Ebay MCP Remote Edition
Remote + Local MCP server for eBay APIs - provides access to eBay developer functionality through MCP (Model Context Protocol)
Ask AI about Ebay MCP Remote Edition
Powered by Claude Β· Grounded in docs
I know everything about Ebay MCP Remote Edition. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
eBay MCP β Remote Edition
A Model Context Protocol (MCP) server providing AI assistants with comprehensive access to eBay's Sell APIs. 325+ tools covering inventory management, order fulfillment, marketing campaigns, analytics, developer tools, and more.
API Coverage: 100% of eBay Sell APIs (270+ unique endpoints)
Overview
This project extends Yosef Hayim's eBay MCP with a full hosted, multi-user deployment mode while keeping the original local STDIO mode intact. The key additions are:
- Hosted Streamable HTTP mode β deploy to Render (or any Node.js host) and serve multiple users from one instance
- MCP OAuth 2.1 authorization server β full browser-based eBay login with automatic token management; Cline and other OAuth-aware clients connect with zero manual token pasting
- Environment-scoped route trees β
/sandbox/mcpand/production/mcphard-bind their eBay environment; no query param needed - Cloudflare KV / Upstash Redis token and session storage for persistent multi-user auth
- Admin session management β inspect, revoke, or delete sessions via authenticated endpoints
- TTL-aligned records β every stored record (OAuth state, auth code, session, user token) carries an
expiresAttimestamp and a matching KV/Redis TTL so storage and application expiry are always in sync - Env-selected eBay Research session persistence β the first-party research bootstrap/runtime can persist Playwright storage state to Cloudflare KV, Upstash KV, or explicit filesystem mode via
EBAY_RESEARCH_SESSION_STORE - QStash-triggered Telegram alerts for eBay Research session expiry β bootstrap can schedule version-aware expiry callbacks that notify operators before first-party research auth silently degrades
- Alert-safe scheduling guardrails β expiry callbacks are only scheduled when the callback URL is externally reachable and the research session store supports shared alert locks (
upstash-redisorfilesystem)
β οΈ Disclaimer
This is an open-source project provided "as is" without warranty of any kind. The authors accept no responsibility or liability for any damages arising from use of this software. This project is not affiliated with, endorsed by, or sponsored by eBay Inc. Test thoroughly in eBay's sandbox before using in production.
Table of Contents
- Choose a runtime mode
- Prerequisites
- Local mode setup
- Hosted mode setup
- Available tools
- Development
- Testing & validation
- Troubleshooting
- Resources
Choose a runtime mode
| Mode | Transport | Best for |
|---|---|---|
| Local STDIO | stdin/stdout | Single-user local AI client (Claude Desktop, Cline, Cursor, etc.) |
| Hosted HTTP | Streamable HTTP | Multi-user server deployment; remote MCP clients |
Both modes use the same eBay tools. The local mode reads credentials from environment variables or a .env file. The hosted mode handles multi-user OAuth server-side and authenticates clients with session tokens.
Prerequisites
All modes:
- Node.js β₯ 18.0.0
- pnpm (or npm β
npm install -g pnpm) - An eBay Developer Account
Getting eBay credentials:
- Log in to the eBay Developer Portal
- Create an application and copy your App ID (Client ID) and Cert ID (Client Secret)
- Under User Tokens β Add RuName, register your OAuth callback URL and copy the generated RuName string
EBAY_RUNAMEis the RuName string eBay generates, not the callback URL itself. It looks likeYourApp-YourApp-SBX-abcdefghi. The callback URL is set separately (see below).
HTTPS callback URL (required by eBay)
eBay requires an HTTPS callback URL for OAuth. For local development, use mkcert:
brew install mkcert nss
mkcert -install
mkcert ebay-local.test
echo "127.0.0.1 ebay-local.test" | sudo tee -a /etc/hosts
Register https://ebay-local.test:3000/oauth/callback in the eBay Developer Portal as your Accept URL. Then add to .env:
PUBLIC_BASE_URL=https://ebay-local.test:3000
EBAY_LOCAL_TLS_CERT_PATH=/path/to/ebay-local.test.pem
EBAY_LOCAL_TLS_KEY_PATH=/path/to/ebay-local.test-key.pem
β οΈ Trust the mkcert CA in Node.js (required for MCP clients like Cline)
VS Code's extension host (where Cline runs) uses Node.js for outbound HTTPS requests. Node.js does not automatically read macOS's system keychain, so the ebay-local.test certificate is not trusted by default. This causes the OAuth token exchange (POST /sandbox/token) to fail silently β the browser flow completes, the "Open in VS Code" page appears, but Cline never receives a session token.
Fix β run these two commands once, then fully quit and reopen VS Code:
# 1. Set for the current macOS session (affects all Dock/Spotlight-launched apps):
launchctl setenv NODE_EXTRA_CA_CERTS "$(mkcert -CAROOT)/rootCA.pem"
# 2. Create a LaunchAgent so it persists across reboots:
cat > ~/Library/LaunchAgents/com.local.mkcert-node-trust.plist <<'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key><string>com.local.mkcert-node-trust</string>
<key>ProgramArguments</key>
<array>
<string>launchctl</string><string>setenv</string>
<string>NODE_EXTRA_CA_CERTS</string>
<string>/Users/YOUR_USERNAME/Library/Application Support/mkcert/rootCA.pem</string>
</array>
<key>RunAtLoad</key><true/>
</dict>
</plist>
EOF
launchctl load ~/Library/LaunchAgents/com.local.mkcert-node-trust.plist
# 3. For terminal-launched VS Code β add to ~/.zshrc:
echo 'export NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem"' >> ~/.zshrc
Replace
YOUR_USERNAMEwith your actual macOS username in the plist, or use the full path printed bymkcert -CAROOT.
After running these commands and fully quitting VS Code (Cmd+Q on macOS) and reopening it, Cline's extension host will trust the ebay-local.test certificate and the MCP OAuth flow will complete successfully.
Verify the fix works (without restarting VS Code):
NODE_EXTRA_CA_CERTS="$(mkcert -CAROOT)/rootCA.pem" node -e "
require('https').get('https://ebay-local.test:3000/health', r => console.log('TLS OK β status:', r.statusCode)).on('error', e => console.error('TLS FAIL:', e.message));
"
# Expected: TLS OK β status: 200
For hosted deployments, register your server's public HTTPS URL instead (e.g. https://your-server.com/oauth/callback).
Local mode setup
Install
Option A β pnpm global install (no build step):
pnpm install -g ebay-mcp-remote-edition
Option B β clone and build (for contributors or self-hosting):
git clone https://github.com/mrnajiboy/ebay-mcp-remote-edition.git
cd ebay-mcp-remote-edition
pnpm install
pnpm run build
Configure credentials
Create a .env file in the project root (see .env.example):
EBAY_CLIENT_ID=your_client_id
EBAY_CLIENT_SECRET=your_client_secret
EBAY_RUNAME=your_runame_string
EBAY_ENVIRONMENT=sandbox # or production
EBAY_MARKETPLACE_ID=EBAY_US # optional, defaults to EBAY_US
EBAY_CONTENT_LANGUAGE=en-US # optional, defaults to en-US
# Populated by the setup wizard:
EBAY_USER_REFRESH_TOKEN=
Authentication tiers:
| Method | Rate limit | How |
|---|---|---|
| Client credentials (default) | 1,000 req/day | Just set EBAY_CLIENT_ID + EBAY_CLIENT_SECRET |
| User tokens (recommended) | 10,000β50,000 req/day | Run the setup wizard to complete OAuth and populate EBAY_USER_REFRESH_TOKEN |
Run the setup wizard
The interactive wizard guides you through environment selection, credential entry, OAuth login, and MCP client configuration:
pnpm run setup
Options:
--quickβ skip optional steps--diagnoseβ run connectivity and token checks only
After completing OAuth, the wizard writes EBAY_USER_REFRESH_TOKEN to .env and optionally configures Claude Desktop automatically.
Local client configuration
For direct STDIO usage, configure your MCP client to launch the server as a subprocess. All clients use the same JSON pattern:
Using npm (no clone needed):
{
"mcpServers": {
"ebay": {
"command": "npx",
"args": ["-y", "ebay-mcp-remote-edition"],
"env": {
"EBAY_CLIENT_ID": "YOUR_CLIENT_ID",
"EBAY_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
"EBAY_ENVIRONMENT": "sandbox",
"EBAY_RUNAME": "YOUR_RUNAME",
"EBAY_USER_REFRESH_TOKEN": "YOUR_REFRESH_TOKEN"
}
}
}
}
Using a local build:
{
"mcpServers": {
"ebay": {
"command": "node",
"args": ["/absolute/path/to/ebay-mcp-remote-edition/build/index.js"],
"env": {
"EBAY_CLIENT_ID": "YOUR_CLIENT_ID",
"EBAY_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
"EBAY_ENVIRONMENT": "sandbox",
"EBAY_RUNAME": "YOUR_RUNAME",
"EBAY_USER_REFRESH_TOKEN": "YOUR_REFRESH_TOKEN"
}
}
}
}
Config file locations by client:
| Client | Config file |
|---|---|
| Cline | ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json |
| Claude Desktop (macOS) | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Claude Desktop (Windows) | %APPDATA%\Claude\claude_desktop_config.json |
| Cursor (global) | ~/.cursor/mcp.json |
| Cursor (project) | .cursor/mcp.json |
Zed, Windsurf, Continue.dev, Roo Code, and Amazon Q follow the same mcpServers JSON shape.
Hosted mode setup
The hosted HTTP server exposes environment-scoped MCP and OAuth endpoints, handles eBay OAuth server-side, and issues session tokens to MCP clients.
Hosted environment variables
# Server
PORT=3000
MCP_HOST=0.0.0.0
PUBLIC_BASE_URL=https://your-server.com
# eBay credentials (prefer secret file below instead of raw env)
EBAY_DEFAULT_ENVIRONMENT=production # sandbox or production
# Persistent token/session storage backend (required for multi-user hosted mode)
EBAY_TOKEN_STORE_BACKEND=cloudflare-kv # cloudflare-kv | upstash-redis | memory
# Cloudflare KV (when EBAY_TOKEN_STORE_BACKEND=cloudflare-kv)
CLOUDFLARE_ACCOUNT_ID=
CLOUDFLARE_KV_NAMESPACE_ID=
CLOUDFLARE_API_TOKEN=
# Upstash Redis (when EBAY_TOKEN_STORE_BACKEND=upstash-redis)
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
# eBay Research session-expiry alerts (optional but recommended when using
# first-party research in hosted mode)
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=1574052684
QSTASH_URL=
QSTASH_TOKEN=
QSTASH_CURRENT_SIGNING_KEY=
QSTASH_NEXT_SIGNING_KEY=
EBAY_RESEARCH_SESSION_ALERTS_ENABLED=true
EBAY_RESEARCH_SESSION_ALERT_WINDOW_24H=true
EBAY_RESEARCH_SESSION_ALERT_WINDOW_6H=true
EBAY_RESEARCH_SESSION_ALERT_ON_EXPIRED=true
EBAY_RESEARCH_SESSION_ALERT_CALLBACK_URL=
# Alert scheduling additionally requires:
# - PUBLIC_BASE_URL or EBAY_RESEARCH_SESSION_ALERT_CALLBACK_URL to be externally reachable
# - EBAY_RESEARCH_SESSION_STORE=upstash-redis or filesystem
# Security
ADMIN_API_KEY= # required for admin session endpoints
OAUTH_START_KEY= # optional; protects /oauth/start with a shared secret
# Validation runner identity (required for hosted /validation/* routes)
# Reuses a stored refresh-token-backed user in the existing multi-user auth store.
# Use the env-specific values when sandbox and production need different runner users.
VALIDATION_RUNNER_USER_ID=
VALIDATION_RUNNER_USER_ID_SANDBOX=
VALIDATION_RUNNER_USER_ID_PRODUCTION=
# Temporary sold-data enrichment provider for validation.
# This is an interim external abstraction and will be replaced by an internal
# sales-data implementation without changing the validation orchestration route.
SOLD_ITEMS_API_URL=
SOLD_ITEMS_API_KEY=
# Future orchestration-side historical research provider.
# Currently only used to enable the placeholder research contract.
PERPLEXITY_API_KEY=
# Optional phase-1 social-signal providers used by hosted validation.
# These signals are supportive only and should not be treated as authoritative
# automated buy triggers on their own.
TWITTER_BEARER_TOKEN=
YOUTUBE_API_KEY=
REDDIT_CLIENT_ID=
REDDIT_CLIENT_SECRET=
REDDIT_USER_AGENT=
# Session TTL (optional; default 30 days)
SESSION_TTL_SECONDS=2592000
# Logging
EBAY_LOG_LEVEL=info
EBAY_MARKETPLACE_ID=EBAY_US
EBAY_CONTENT_LANGUAGE=en-US
# Path to secret file (see below)
EBAY_CONFIG_FILE=/etc/secrets/ebay-config.json
Use
EBAY_TOKEN_STORE_BACKEND=memoryonly for local development or tests. All OAuth state, session tokens, and user tokens are lost on restart.
Secret file
Store eBay credentials in a mounted secret file rather than raw environment variables. On Render, create a Secret File named ebay-config.json mounted at /etc/secrets/ebay-config.json:
{
"production": {
"clientId": "PROD_CLIENT_ID",
"clientSecret": "PROD_CLIENT_SECRET",
"redirectUri": "YOUR_PRODUCTION_RUNAME"
},
"sandbox": {
"clientId": "SANDBOX_CLIENT_ID",
"clientSecret": "SANDBOX_CLIENT_SECRET",
"redirectUri": "YOUR_SANDBOX_RUNAME"
}
}
Deploy to Render / Railway / other Nixpacks hosts
- Connect your repo to Render as a Web Service
- Set Build command:
pnpm install && pnpm run build - Set Start command:
pnpm run start:http - Add the environment variables listed above
- Add the
ebay-config.jsonsecret file
The server starts on the port Render assigns via $PORT and logs the active KV backend on startup.
For Nixpacks-based platforms such as Railway and Coolify:
- The repository now includes
nixpacks.tomlso the generated image usespnpm install --frozen-lockfile, runspnpm run build, installs Chromium for the Playwright-backed validation paths, and starts withpnpm run start:http. - Runtime secrets should be configured in the platform dashboard as runtime environment variables or mounted secret files. Do not bake secrets into Docker build arguments or
ENVlayers. - Keep
pnpm-lock.yamlcommitted and in sync withpackage.json; Nixpacks installs with a frozen lockfile.
OAuth flows
eBay requires a single registered callback URL per application. The hosted server registers /oauth/callback at the root and recovers the environment from the stored OAuth state record.
Start an OAuth flow (browser):
GET /sandbox/oauth/start # always sandbox
GET /production/oauth/start # always production
If OAUTH_START_KEY is set, include it as a query parameter or header:
GET /sandbox/oauth/start?key=YOUR_OAUTH_START_KEY
# or header: X-OAuth-Start-Key: YOUR_OAUTH_START_KEY
After a successful login, the callback page displays your session token, eBay access token, and eBay refresh token with one-click copy buttons.
Session token TTL schedule:
| Record | expiresAt field | Backend TTL |
|---|---|---|
| OAuth state | 15 minutes | 15 minutes |
| MCP auth code | 10 minutes | 10 minutes |
| Session | 30 days (configurable) | Matches SESSION_TTL_SECONDS |
| User token record | eBay refresh token expiry (fallback: 18 months) | Matches token expiry |
MCP endpoints
Environment-scoped (recommended):
POST/GET/DELETE /sandbox/mcp
POST/GET/DELETE /production/mcp
Each scoped path includes its own OAuth 2.1 discovery document:
GET /sandbox/.well-known/oauth-authorization-server
GET /production/.well-known/oauth-authorization-server
Legacy auto-detect (backward-compatible):
POST/GET/DELETE /mcp # resolves environment from ?env= or EBAY_DEFAULT_ENVIRONMENT
Authentication behavior:
GET /mcp(or scoped variant) without a valid Bearer token redirects the browser to the matchingoauth/startURLPOST /mcpwithout a valid Bearer token returns a structured401JSON with anauthorization_urlfield- All requests supply a session token via
Authorization: Bearer <session-token>
Other utility endpoints:
GET /health # Server health check (no auth required)
GET /whoami # Session identity; requires Bearer session token
GET /admin/session/:sessionToken # View session; requires X-Admin-API-Key
POST /admin/session/:sessionToken/revoke # Revoke session
DELETE /admin/session/:sessionToken # Delete session
/whoami response:
{
"userId": "...",
"environment": "sandbox",
"createdAt": "2026-03-23T08:00:00.000Z",
"expiresAt": "2026-04-22T08:00:00.000Z",
"lastUsedAt": "2026-03-23T09:30:00.000Z",
"revokedAt": null
}
/whoami is the quickest hosted-session debugging check when an MCP client appears authenticated but requests still fail. It confirms which stored user session is active, which environment it is bound to, and whether the session has expired or been revoked.
Validation architecture
The hosted backend now includes a deployment-oriented validation pipeline for non-MCP server-side execution. The route handlers live in src/server-http.ts, while the validation module lives under src/validation/.
Current module layout:
src/validation/types.tsβ request/response contracts for validation runs, decision payloads, debug payloads, and provider signal typessrc/validation/effective-context.tsβ source-aware normalization layer that converts raw request payloads into a first-class effective validation context for item and event runssrc/validation/run-validation.tsβ orchestration entrypoint that validates input, queries providers, merges signals, and returns writes/decision/debug outputsrc/validation/recommendation.tsβ recommendation and automation decision logicsrc/validation/providers/ebay.tsβ live eBay browse-market snapshot provider using the server's existing user-scoped eBay API clientsrc/validation/providers/ebay-sold.tsβ temporary sold-data provider backed by an external API viaSOLD_ITEMS_API_URLandSOLD_ITEMS_API_KEYsrc/validation/providers/terapeak.tsβ authenticated eBay Research provider orchestration for current-market and previous-POB metrics, including candidate scoring, fallback diagnostics, and sold-velocity bucketingsrc/validation/providers/ebay-research.tsβ low-level authenticated eBay Research fetcher with session-cookie sourcing, response parsing, and auth-aware cache invalidationsrc/validation/providers/query-utils.tsβ shared multi-tier query candidate and fallback helpers used by browse and sold providerssrc/validation/providers/social.tsβ phase-1 social provider for recent Twitter/X activity, YouTube view-rate proxy data, and Reddit recent-post counts with graceful degradationsrc/validation/providers/chart.tsβ chart-signal stub reserved for later implementationsrc/validation/providers/research.tsβ stable previous-comeback research contract provider for orchestration-side historical inference; currently a placeholder contract with optional futurePERPLEXITY_API_KEYsupport
Current provider domains called by runValidation():
- browse/current-market via
src/validation/providers/ebay.ts - sold enrichment via
src/validation/providers/ebay-sold.ts - Terapeak / eBay research contract via
src/validation/providers/terapeak.ts - social support signals via
src/validation/providers/social.ts - chart support signals via
src/validation/providers/chart.ts - previous comeback research inference via
src/validation/providers/research.ts
Architecturally, the validation stack is split into two practical classes of providers:
- Server-side authenticated providers β these run with the hosted backend's stored eBay user context and are the right place for authenticated marketplace retrieval. Today that means the live browse/current-market provider in
src/validation/providers/ebay.ts, the sold enrichment layer insrc/validation/providers/ebay-sold.ts, and the Terapeak/eBay research contract insrc/validation/providers/terapeak.ts. - Orchestration-side research providers β these run as supporting inference layers inside orchestration rather than as part of the user-scoped eBay API client surface. Today that means previous comeback resolution and external historical-research inference in
src/validation/providers/research.ts, plus non-authoritative support providers such assrc/validation/providers/social.tsandsrc/validation/providers/chart.ts.
Operationally, validation works like this:
- An admin caller invokes an environment-scoped validation route.
- The server resolves the environment (
sandboxorproduction) from the mounted route tree. - The route looks up the configured validation runner user ID for that environment.
- The server loads that user's stored refresh-token-backed credentials from the existing hosted auth store.
- The validation orchestrator calls all six provider domains and gathers browse/current-market, sold enrichment, Terapeak/research contract data, social support signals, chart stub output, and previous-comeback research output.
- Before provider execution,
runValidation()builds a normalizedeffectiveContextso downstream logic consumes a source-aware model (itemorevent) instead of relying on empty item placeholders. runValidation()deterministically merges the provider outputs into normalized field writes.- The response returns those writes, a conservative buy/track decision block, and provider debug metadata for downstream systems.
Effective validation context
Validation runs now normalize incoming request data into an internal effective context before provider query planning and recommendation logic execute.
- Item-scope runs normalize to an item-oriented context with the resolved artist, album/item phrase, location, and resolved search query.
- Event-scope runs normalize to an event-oriented context with
searchArtist,searchEvent,searchItem,searchLocation, timing metadata, and a derivedeffectiveSearchQuerywhen no direct resolved query is present. - Providers and recommendation logic consume that normalized context rather than reasoning about blank
item.recordIdoritem.namefields. - Debug output now exposes
effectiveSourceType,effectiveContextMode,effectiveSearchQuery,hasItem, andhasEventso operators can confirm whether an event run was normalized correctly.
The request schema also now accepts source-aware query-context fields for hosted validation runs:
resolvedSearchArtistresolvedSearchItemresolvedSearchEventresolvedSearchLocationresolvedSearchQuery
The validation contract is intentionally split between stable route orchestration and swappable providers. That is why the current sold-data source can be replaced later without changing downstream orchestration or the hosted route contract implemented in src/validation/run-validation.ts.
Deterministic merge precedence
The current merge order is fixed in runValidation() so downstream systems can treat the writes as predictable rather than provider-order dependent:
- Watchers / preorder count / shipping / competition prefer Terapeak contract output when available, then fall back to the browse/current-market provider.
- Market price prefers Terapeak contract output, then the sold provider's median sold price, then the browse/current-market provider.
- Sold day buckets (
day1Soldthroughday5Sold, plusdaysTracked) prefer the sold provider, then authenticated eBay Research sold-row bucketing, then the browse/current-market provider. - Previous POB metrics (
previousPobAvgPriceUsd,previousPobSellThroughPct) are written from the Terapeak contract output when available. - Previous comeback first-week sales (
previousComebackFirstWeekSales) is written from the orchestration-side research provider when available. - Supportive social fields are only written when a value is actually resolved, so the pipeline avoids blanking previously stored downstream data.
The validation signal contracts in TerapeakValidationSignals and PreviousComebackResearchSignals also back the new write fields in ValidationWrites: previousPobAvgPriceUsd, previousPobSellThroughPct, and previousComebackFirstWeekSales.
Validation endpoints and auth model
Use the environment-scoped hosted routes for validation:
POST /sandbox/validation/run
POST /production/validation/run
GET /sandbox/validation/health
GET /production/validation/health
Both routes require the admin key:
X-Admin-API-Key: YOUR_ADMIN_API_KEY
Auth model summary:
- Validation routes are hosted HTTP backend routes, not MCP tool endpoints.
- They do not use MCP client auth for execution.
- They reuse the existing stored refresh-token-backed hosted user architecture.
- The caller authenticates with
X-Admin-API-Key, and the server then impersonates the configured validation runner user for the target environment. - Validation runner identity comes from
VALIDATION_RUNNER_USER_ID,VALIDATION_RUNNER_USER_ID_SANDBOX, orVALIDATION_RUNNER_USER_ID_PRODUCTION. - The validation runner must already have stored hosted tokens in the configured token store backend.
POST /validation/run
Runs the validation pipeline for the target environment.
- Uses the configured validation runner user ID for that environment
- Requires that stored refresh-token-backed eBay credentials already exist for that user
- Returns either:
status: "ok"withwrites,decision, anddebug, orstatus: "error"witherrorCode,message,retryable, andnextCheckAt
The request/response contract is defined in src/validation/types.ts, and the orchestration behavior is implemented in src/validation/run-validation.ts.
The writes payload is intentionally non-destructive for supportive and optional fields: if a social, authenticated eBay Research, or previous-comeback research provider cannot resolve data, the orchestration omits those optional writes instead of overwriting existing downstream values with empty placeholders.
GET /validation/health
Checks whether the validation runner is operational in the target environment.
This endpoint is intended for deployment diagnostics and returns:
- configured environment
- configured validation runner user ID
- whether stored tokens are present
- whether token refresh/authentication succeeded
- token status from the user-scoped eBay API client
authDebugdiagnostics including token endpoint resolution and credential presence- provider availability summary
The diagnostics are especially useful after the OAuth token endpoint fix in getOAuthTokenBaseUrl() and the debug additions in getAuthDebugInfo(). If the validation runner cannot refresh tokens, /validation/health shows the resolved token endpoint and any captured upstream response status/body excerpt.
Diagnostics and health endpoints
Use these endpoints together when validating a hosted deployment:
GET /health
GET /whoami
GET /sandbox/validation/health
GET /production/validation/health
POST /internal/ebay-research/check-session-expiry
Recommended debugging flow:
- Call
/healthto confirm the HTTP service is up. - Call
/whoamiwith a Bearer hosted session token to confirm the active hosted user session, bound environment, expiry, and revocation status. - Call the matching env-scoped
/validation/healthroute withX-Admin-API-Keyto confirm the validation runner user is configured, stored tokens exist, and token refresh succeeds. - The internal
POST /internal/ebay-research/check-session-expiryroute is reserved for signed QStash callbacks and should not be used as an unauthenticated public endpoint.
/whoami is especially useful when an operator wants to verify which hosted session is currently active before registering or troubleshooting the validation runner user. Validation routes themselves still authenticate with the admin key and a stored hosted runner identity, not with MCP auth.
The validation health response is also the main place to verify the OAuth token-endpoint derivation fix from getOAuthTokenBaseUrl(). If a refresh fails, the authDebug block exposes the resolved endpoint, credential-presence flags, and captured upstream response excerpts.
Validation provider behavior and limitations
Current backend status:
- eBay live market snapshot support is implemented and wired into orchestration.
- Sold-data enrichment is implemented through a temporary external provider abstraction.
- Authenticated eBay Research is wired into orchestration for current-market and previous-POB retrieval, while previous-comeback research remains a separate placeholder contract.
- Social support signals are implemented in phase 1.
- Chart data remains a stub.
- Validation is currently an admin-operated hosted backend workflow, not an MCP tool surface.
- Event-scope validations are now handled as first-class normalized runs instead of as item-shaped requests with null item identity tolerated for compatibility.
Provider behavior:
- Browse/eBay provider:
src/validation/providers/ebay.tsuses the eBay Browse API plus shared query fallback logic fromsrc/validation/providers/query-utils.ts. It walks multiple query candidates, records the selected query and tier in debug output, and uses heuristic matching rather than a strict catalog identity join. Event-driven runs now build those fallback queries from normalized event context instead of raw item title assumptions. - Browse debug semantics: validation debug now keeps browse candidate generation, selected query/tier, browse-specific sample size, and per-candidate result counts separate from sold-provider result counts so operators can tell whether the browse layer contributed a field, fell back to a weaker query, or returned no usable match.
- Sold provider:
src/validation/providers/ebay-sold.tsuses a temporary external sold-data source configured bySOLD_ITEMS_API_URLandSOLD_ITEMS_API_KEY. It uses the same query-fallback strategy as the browse provider and returns sold-price ranges, sample sold items, and recent sold-velocity buckets when available. - Terapeak / eBay research provider:
src/validation/providers/terapeak.tsnow evaluates authenticated eBay Research candidates for both current-market and previous-POB contexts, scores them against title alignment and subtype coverage, preserves per-candidate diagnostics in debug output, and derives sold-day buckets from sold-row timestamps when available. - Authenticated research session source:
src/validation/providers/ebay-research.tsnow prefers KV-backed Playwright storage state first, then environment-provided storage state / cookie fallbacks, then local storage-state/profile fallbacks for local development only. Parsed ACTIVE and SOLD tab responses are cached, automatically invalidated when the authenticated cookie fingerprint changes, and emit explicit auth-resolution debug fields includingsessionSource, KV/env/filesystem attempt status, and fallback reasons. - Social provider:
src/validation/providers/social.tssupports phase-1 Twitter/X recent activity, YouTube average-daily-views proxy data exposed through theyoutubeViews24hMillionsfield, and Reddit recent post counts. These signals degrade gracefully on provider/API failure and are used as supportive indicators rather than authoritative demand truth. - Chart provider:
src/validation/providers/chart.tsis still a stub and does not currently contribute chart-based metrics. - Previous comeback research provider:
src/validation/providers/research.tsnow performs Perplexity-backed historical research whenPERPLEXITY_API_KEYis configured. It attempts to resolve the prior comeback, normalize previous first-week sales when support exists, assign aperplexityHistoricalContextScore, generate concisehistoricalContextNotes, and emit debug diagnostics covering the research query, citations/snippets, resolved prior release, confidence, and score reasoning.
Recommendation behavior:
src/validation/recommendation.tsnow accepts Terapeak and research inputs alongside browse, sold, social, and chart signals.- Recommendation generation also consumes the normalized effective context so event runs can carry source-aware monitoring notes and avoid item-only assumptions when no usable item identity exists.
- Automatic tracking now pauses when the validation is still nominally in a watch state but the required source context or a usable derived query is missing.
- The decisioning remains intentionally conservative: Terapeak and research data can improve monitoring notes and confidence context, but the system still avoids aggressive automatic buy-state changes from partial or proxy signals alone.
Known limitations in the current implementation:
- The sold-data provider depends on external configuration via
SOLD_ITEMS_API_URLandSOLD_ITEMS_API_KEY. - If those sold-data variables are missing, validation still runs but sold enrichment degrades to an unavailable/error state rather than providing full historical-sales signals.
- The sold-data provider is temporary and intended to be replaced by an internal implementation later.
- Authenticated eBay Research requires a valid session source such as KV-backed Playwright storage state,
EBAY_RESEARCH_STORAGE_STATE_JSON,EBAY_RESEARCH_COOKIES_JSON, a local Playwright storage-state file, or a local browser profile directory; without one, the provider degrades to diagnostic-only output with explicit structured auth-resolution debug.
eBay Research bootstrap and hosted runtime notes
- Install Chromium for hosted runtimes with
package.jsonscriptplaywright:install(pnpm run playwright:install). - The Docker deployment path now provisions Chromium during image build in
Dockerfile. - Canonical production session source of truth is KV-backed Playwright storage-state JSON stored under
ebay_research_storage_state_jsonwith companion metadata inebay_research_storage_state_meta, includingupdatedAt,expiresAt,ttlSeconds,marketplace,sessionStore, andsessionVersion. - Bootstrap a signed-in eBay Research storage state into KV with
src/scripts/bootstrap-ebay-research-session.tsvia the packaged/runtime-safepackage.jsonscriptresearch:bootstrap(pnpm run build && pnpm run research:bootstrap). - Inspect canonical eBay Research session persistence and fresh-client readback diagnostics with
src/scripts/inspect-ebay-research-session.tsvia the packaged/runtime-safepackage.jsonscriptresearch:inspect-session(pnpm run build && pnpm run research:inspect-session). - Verify headless Chromium launchability with
src/scripts/check-playwright.tsvia the packaged/runtime-safepackage.jsonscriptresearch:check-browser(pnpm run build && pnpm run research:check-browser). - Runtime precedence is: KV storage state β
EBAY_RESEARCH_STORAGE_STATE_JSONβEBAY_RESEARCH_COOKIES_JSONβ local storage-state file β local Playwright profile β explicit auth-missing fallback. - Every candidate session source is validated against the first-party ACTIVE endpoint before the provider reports
authState = loaded; failed validation is surfaced through debug fields includingkvStorageStateBytes,authValidationAttempted, andauthValidationSucceeded. - Once a validated session is loaded, ACTIVE and SOLD endpoint fetches automatically become the preferred first-party research source while legacy active/sold fallbacks remain intact when auth is missing or invalid.
- Successful bootstrap also schedules signed QStash callbacks for 24 hours before expiry, 6 hours before expiry, and at expiry. Those callbacks target
POST /internal/ebay-research/check-session-expiry, which verifies QStash signatures, suppresses stale reminders bysessionVersion, and sends Telegram alerts toTELEGRAM_CHAT_ID. - Alert scheduling is intentionally skipped when the callback URL resolves to localhost/loopback or when
EBAY_RESEARCH_SESSION_STOREuses a backend without shared lock support, because those configurations cannot safely deliver or deduplicate hosted reminders. - Session refresh is manual by design for now: rerun
pnpm run build && pnpm run research:bootstrapwhenever eBay expires the stored session, then redeploy or restart the hosted service if your platform does not hot-reload env/KV-backed state. - The previous-comeback research provider depends on grounded external research and therefore degrades to low-confidence notes with a zero historical score when
PERPLEXITY_API_KEYis missing, the response cannot be normalized, or reliable evidence is not found. - The browse provider still relies on heuristic query selection and fallback matching.
- The YouTube-backed
youtubeViews24hMillionsfield is currently an average daily views proxy, not a true trailing 24-hour delta. - Social signals are supportive/proxy data only and should not be presented as decisive automated buy logic.
- eBay-derived metrics are intentionally practical rather than exhaustive, but authenticated ACTIVE research rows now populate watcher-derived metrics whenever watcher counts are present in the first-party response.
Roadmap note: provider maturation
- The current sold-data implementation is explicitly interim. It is isolated behind
src/validation/providers/ebay-sold.tsso we can replace the external-provider-backed implementation with our own internal sales-data system later without changing downstream validation orchestration or the hosted validation route contract. - The Terapeak/eBay research layer is intentionally isolated behind
src/validation/providers/terapeak.tsso a future authenticated research integration can drop in without changing the route contract or downstream writes. - The orchestration-side historical research layer is intentionally isolated behind
src/validation/providers/research.tsso future previous-comeback resolution or external inference providers can be added without rewriting the validation runner.
Remote client configuration
Replace https://your-server.com with your actual PUBLIC_BASE_URL.
Cline (automatic OAuth β no manual token needed)
Cline supports MCP OAuth 2.1 discovery natively. It fetches the discovery document, registers itself, opens the eBay browser login, exchanges the auth code for a session token, and stores it β all automatically.
{
"mcpServers": {
"ebay-sandbox": {
"url": "https://your-server.com/sandbox/mcp"
},
"ebay-production": {
"url": "https://your-server.com/production/mcp"
}
}
}
What Cline does automatically:
- Fetches
/.well-known/oauth-authorization-serverfor the scoped path - Registers at
POST /sandbox/register(or/production/register) - Your browser opens
GET /sandbox/authorize, which redirects to eBay login - After you grant access, eBay redirects to
/oauth/callback, which issues an auth code - Cline exchanges the code at
POST /sandbox/tokenfor a session token and stores it - All subsequent
/sandbox/mcprequests authenticate automatically
Claude Desktop and Cursor (Bearer token)
Claude Desktop and most other remote MCP clients require a pre-obtained session token. Complete the browser OAuth flow first:
- Open
https://your-server.com/sandbox/oauth/start(or/production/oauth/start) in a browser - Log in with your eBay account
- Copy the session token from the confirmation page
Then configure your client:
{
"mcpServers": {
"ebay-sandbox": {
"url": "https://your-server.com/sandbox/mcp",
"headers": {
"Authorization": "Bearer YOUR_SESSION_TOKEN"
}
}
}
}
Make / Zapier / TypingMind and similar platforms
- Open
https://your-server.com/sandbox/oauth/startin a browser and complete eBay login - Copy the session token from the confirmation page
- Paste it as the API Key / Bearer token in the platform's MCP connector settings
- Set the MCP endpoint URL to
https://your-server.com/sandbox/mcp
Available tools
325+ tools across all eBay Sell API categories:
- Account Management
- Inventory Management
- Order Fulfillment
- Marketing & Promotions
- Analytics & Reporting
- Communication (messages, feedback, notifications, negotiation)
- Metadata & Taxonomy
- Developer Tools (key management, analytics)
- Auth / Token helper tools
Full tool source: src/tools/definitions/
Development
Commands reference
| Command | Description |
|---|---|
pnpm run build | Compile TypeScript to JavaScript |
pnpm start | Run local STDIO MCP server |
pnpm run start:http | Run hosted HTTP MCP server |
pnpm run dev | Local STDIO server with hot reload |
pnpm run dev:http | Hosted HTTP server with hot reload |
pnpm test | Run test suite |
pnpm run setup | Interactive local setup wizard |
pnpm run sync | Download latest eBay OpenAPI specs and regenerate types |
pnpm run diagnose | Check configuration and connectivity |
pnpm run typecheck | Run TypeScript type checking |
pnpm run check | Typecheck + lint + format check |
pnpm run fix | Auto-fix lint and format issues |
pnpm run sync
Downloads the latest eBay OpenAPI specs, regenerates TypeScript types, and reports implemented vs missing endpoints. Run this when you want to pick up new eBay API surface:
pnpm run sync
pnpm run typecheck
pnpm run build
Review the diff, commit the generated changes you want to keep, and deploy.
Local env management
For local development, standard runtime scripts load .env via dotenvx only when a real local .env file is present. Hosted platforms should provide environment variables directly β the server skips dotenvx for hosted/runtime environments (including Nixpacks-style deployments, which set DISABLE_DOTENVX) and whenever no local .env file exists.
pnpm run env:encrypt # encrypt .env for safe sharing
pnpm run env:decrypt # decrypt
Logging
EBAY_LOG_LEVEL=debug # error | warn | info | debug
EBAY_ENABLE_FILE_LOGGING=true # write logs to files
Testing & validation
# Build and type check
pnpm run build
pnpm run typecheck
# Run the test suite
pnpm test
# Check connectivity and token status
pnpm run diagnose
# Verify hosted server health
curl https://your-server.com/health
# Verify a session token
curl -H "Authorization: Bearer <session-token>" https://your-server.com/whoami
# Verify validation runner health for sandbox
curl https://your-server.com/sandbox/validation/health \
-H "X-Admin-API-Key: YOUR_ADMIN_API_KEY"
# Run a hosted validation job
curl -X POST https://your-server.com/sandbox/validation/run \
-H "Content-Type: application/json" \
-H "X-Admin-API-Key: YOUR_ADMIN_API_KEY" \
-d '{"validationId":"example-123","runType":"manual","cadence":"Daily","timestamp":"2026-03-31T00:00:00.000Z","item":{"recordId":"1","name":"Example Item","variation":[],"itemType":[],"releaseType":[],"releaseDate":null,"releasePeriod":[],"availability":[],"wholesalePrice":null,"supplierNames":[],"canonicalArtists":[],"relatedAlbums":[]},"validation":{"validationType":"default","buyDecision":"Hold","automationStatus":"Manual","autoCheckEnabled":false,"dDay":null,"artistTier":"unknown","initialBudget":null,"reserveBudget":null,"currentMetrics":{"avgWatchersPerListing":null,"preOrderListingsCount":null,"twitterTrending":false,"youtubeViews24hMillions":null,"redditPostsCount7d":null,"marketPriceUsd":null,"avgShippingCostUsd":null,"competitionLevel":null,"marketPriceTrend":"Stable","day1Sold":null,"day2Sold":null,"day3Sold":null,"day4Sold":null,"day5Sold":null,"daysTracked":null}}}'
# Test MCP endpoint returns auth challenge when no token is provided
curl -X POST https://your-server.com/sandbox/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# β should return 401 with authorization_url
Troubleshooting
Hosted MCP returns 406
Include the correct Accept header in your MCP client:
Accept: application/json, text/event-stream
OAuth callback: "Invalid or expired OAuth state"
OAuth state records expire in 15 minutes. If you see this error, restart the browser OAuth flow.
Token verification fails on existing refresh token
Refresh tokens expire after ~18 months or can be revoked by eBay (password changes, etc.). Run the setup wizard again to obtain a new one:
pnpm run setup
In hosted mode, start a new browser OAuth flow at /sandbox/oauth/start or /production/oauth/start.
Session token no longer works in hosted mode
Check whether the session was revoked or expired:
curl -H "Authorization: Bearer <token>" https://your-server.com/whoami
Revoke exposed session tokens via the admin endpoint:
curl -X POST https://your-server.com/admin/session/<token>/revoke \
-H "X-Admin-API-Key: YOUR_ADMIN_API_KEY"
Validation health is degraded
Start with the environment-scoped health endpoint:
curl https://your-server.com/sandbox/validation/health \
-H "X-Admin-API-Key: YOUR_ADMIN_API_KEY"
Common causes:
VALIDATION_RUNNER_USER_IDor the env-specific override is missing- the validation runner user has no stored refresh-token-backed credentials in the hosted token store
- the refresh token is expired or revoked upstream
SOLD_ITEMS_API_URLorSOLD_ITEMS_API_KEYis missing, causing sold enrichment to degrade- one or more social-provider credentials are absent, which causes the related supportive signal to degrade gracefully instead of failing the entire run
eBay Research debug shows authState = missing or sessionStrategy = none
This means the first-party research provider could not load a validated authenticated session and validation is intentionally falling back to browse and/or the temporary sold provider.
Run this checklist:
pnpm run playwright:install
pnpm run build
pnpm run research:check-browser
pnpm run research:bootstrap
Expected post-bootstrap debug characteristics from src/validation/providers/ebay-research.ts:
authState = loadedsessionStrategy = storage_statesessionSource = kvkvLoadAttempted = truekvLoadSucceeded = trueauthValidationAttempted = trueauthValidationSucceeded = true
If the provider still reports missing, verify that your hosted deployment can reach the configured KV backend, that Chromium is available in the runtime image, and that the stored eBay session has not expired. Refresh the session by rerunning pnpm run research:bootstrap.
If authDebug.tokenEndpoint or the captured upstream response looks wrong, verify the environment-specific OAuth configuration and token-base resolution.
Security checklist
- Do not commit
.envor session tokens to version control - Protect
/oauth/startand/admin/*withOAUTH_START_KEYandADMIN_API_KEY - Keep
/oauth/callbackpublicly reachable (eBay redirects to it after login) - Keep
/healthreachable if Render uses it for health checks - For production-grade isolation, optionally place
/,/oauth/start, and/admin/*behind Cloudflare Access - Rotate exposed eBay client secrets and update your secret file
Resources
- eBay Developer Portal
- MCP Documentation
- Auth Configuration Guide
- OAuth Quick Reference
- API Status
- Changelog
- Contributing Guidelines
- Security Policy
License
MIT β see LICENSE
