Shopping MCP Server
The server provides an authenticated, eBay-backed shopping MCP server for product discovery, cart management, checkout quotes, and order handling.
Search the eBay catalog with
search_products(text query, category, sort, pagination).Read item details with
get_product.Browse taxonomy with
get_categories(full tree or subtree).Manage a user cart with
add_to_cart,view_cart, andupdate_cart_item(server-side pricing; quantities can be set to 0 to remove).Create checkout quotes with
checkout, including live price/availability verification and a shipping address.Place orders from an unexpired quote with
place_order, which clears the cart and is idempotent.View and manage orders with
get_order,order_history, andcancel_order(orders are user-scoped).Access resources and widgets such as
shopping://featured-products,shopping://categories,health://checks,metrics://shopping, and theshopping_assistantprompt.Enforce JWT authentication and scopes (
shopping:read,shopping:write) for all protected operations.
Provides access to eBay's catalog via Browse and Taxonomy APIs, enabling product search, item detail retrieval, and marketplace category tree exploration for the shopping server.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Shopping MCP Server search for wireless headphones under $100 and add the top result to my cart"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Shopping MCP Server
A production-oriented shopping MCP server built with NitroStack. It exposes an eBay-backed product catalog, authenticated carts and orders, health resources, prompts, and seven static-export widgets.
place_orderrecords an order in this service. It does not charge a payment method or create an eBay fulfillment order. Add a payment/fulfillment provider before using it for real commerce.
Features
eBay Browse search, item details, and Taxonomy category trees
Offline demo catalog for local development (
EBAY_MOCK=true)JWT authentication compatible with a Better Auth JWT plugin
User-scoped cart and order persistence
Postgres/Neon in production, atomic JSON-file storage locally, and
:memory:test modeLive price and availability verification during checkout
Expiring checkout quotes, order history, and cancellation
Zod input validation, normalized inputs, typed domain errors, structured responses, logging, caching, and eBay quota protection
Database, eBay, and system health checks exposed as
health://checksProduct, cart, and order resources plus the
shopping_assistantpromptProduct, search-results, category-tree, cart-summary, confirmation, order-summary, and cancellation widgets
Related MCP server: ingrammicro-mcp
Requirements
Node.js 22+
pnpm 11+
eBay application credentials for live catalog access (optional for demo mode)
Postgres/Neon
DATABASE_URLfor multi-instance production persistence
Quick start
pnpm install:all
cp .env.example .env
pnpm verify
pnpm devpnpm verify builds the server and widgets, starts an isolated stdio MCP server, and exercises tool schemas, resources, prompt execution, JWT authorization, catalog lookup, cart updates, checkout, order placement, history, cancellation, and cart isolation.
Configuration
Copy .env.example and set values for the deployment. Important settings:
Variable | Purpose |
| Explicit signing algorithm and Better Auth JWKS endpoint ( |
| Current and temporary previous HMAC secrets; required only for HS* verification and at least 32 bytes outside development |
| Required JWT claim validation values ( |
| Issuer token lifetime and maximum accepted |
| Maximum age of cached public keys before refresh (default |
| Postgres/Neon connection string; required outside development and takes precedence over file storage |
| Single-process local JSON store, or |
| eBay keyset for live Browse/Taxonomy calls |
| eBay marketplace, default |
| Set |
|
|
| HTTP listener settings; production defaults to |
| CORS opt-in and exact comma-separated HTTP(S) origin allowlist; wildcard origins are rejected |
| Decimal tax rate used in checkout, for example |
| Must be set explicitly outside development; only |
| Checkout quote lifetime, default |
| Curated item list, or the fixed query used by |
| Bounded exponential backoff for transient eBay failures only |
| Bound a taxonomy response so a full tree cannot overflow a client |
|
|
| Reverse-proxy header policy; an |
| Include storage mode and applied migrations in |
| Advertise OAuth 2.1 discovery metadata for external MCP clients |
In development, missing eBay credentials are allowed for the offline demo. Outside development, set EBAY_MOCK=true to explicitly allow demo mode, or set EBAY_MOCK=false and provide both eBay credentials. A production configuration never silently falls back to the demo catalog. Monitor health://checks for the configured eBay status.
MCP surface
Tools
Tool | Auth | Description |
| Public | Search the eBay catalog |
| Public | Read current item details |
| Public | Read the marketplace category tree or subtree |
| JWT + | Add or increment a user cart item |
| JWT + | Read the authenticated user cart |
| JWT + | Set quantity; |
| JWT + | Create a ten-minute quote with live price/availability checks |
| JWT + | Persist an order from an unexpired quote and clear the cart |
| JWT + | Read one order owned by the authenticated user |
| JWT + | List the authenticated user’s orders |
| JWT + | Cancel an order owned by the authenticated user |
Protected calls use a Bearer token. For MCP clients, provide it as _meta.authorization: "Bearer <token>"; for Streamable HTTP clients, send the normal Authorization header. The verified JWT sub is the user ID—no tool accepts a caller-supplied userId. Tokens must contain a non-empty sub, iss, aud, and unexpired exp claim.
Authentication configuration
The selected strategy is a Better Auth JWT bridge for a trusted first-party frontend. The supported clients are that frontend and MCP clients that can forward bearer credentials. Better Auth must issue a signed JWT with a stable application-user sub claim. The recommended Better Auth JWT plugin configuration uses its JWKS endpoint and EdDSA; this server also supports explicitly configured RS*, PS*, ES*, and HS* algorithms. The server expects the following token contract from .env.example:
JWT_ALGORITHM=EdDSAandJWT_JWKS_URI=https://<frontend>/api/auth/jwks(recommended)Or
JWT_ALGORITHM=HS256andJWT_SECRETwhen the issuer is explicitly configured to mint HMAC tokensJWT_AUDIENCE=amazon-mcpJWT_ISSUER=better-authJWT_EXPIRES_IN=1h(the issuer controls the actualexpclaim)
The guard verifies the signature against the configured HMAC secret or cached remote JWKS, requires an explicit algorithm allowlist, validates expiration, issuer, audience, and non-empty sub, and fails closed when JWKS cannot validate a token. It accepts Authorization: Bearer <token> from HTTP requests and the equivalent MCP _meta.authorization metadata. Protected reads require shopping:read; cart, checkout, placement, and cancellation writes require shopping:write. A token with both scopes is needed for the complete recommended flow.
The corresponding Better Auth configuration should make these values explicit (the scopes should come from the application's authorization policy):
jwt({
jwks: {
keyPairConfig: { alg: 'EdDSA', crv: 'Ed25519' },
rotationInterval: 60 * 60 * 24 * 30,
gracePeriod: 60 * 60 * 24 * 30,
},
jwt: {
issuer: process.env.JWT_ISSUER,
audience: process.env.JWT_AUDIENCE,
expirationTime: process.env.JWT_EXPIRES_IN,
getSubject: (session) => session.user.id,
definePayload: ({ user }) => ({
sub: user.id,
scopes: ['shopping:read', 'shopping:write'],
}),
},
})Key rotation
For HMAC mode, JWT verification supports a current secret and one temporary previous secret. To rotate without logging out active users:
Generate a new random secret and deploy it as
JWT_SECRET.Move the old value to
JWT_SECRET_PREVIOUSin the same deployment.Keep the previous value for at least the maximum token lifetime (and any clock-skew/rollout buffer).
Remove
JWT_SECRET_PREVIOUSin a later deployment after that window.
For the recommended JWKS mode, configure Better Auth's rotationInterval and gracePeriod; the server caches the JWKS, refreshes on key IDs, and never falls back to an old or unsigned key when verification fails. Never log secrets or tokens. A token signed by any other key/secret, with the wrong issuer/audience, malformed claims, wrong signature, or expired exp is rejected.
OAuth discovery is intentionally not enabled by default because this deployment targets a trusted first-party frontend. If external OAuth authorization-server clients are required, configure NitroStack's OAuth module and discovery endpoints before exposing the HTTP transport to them.
Recommended flow:
search_products → get_product → add_to_cart → view_cart
→ checkout → confirm quote → place_order → get_orderResources and prompt
shopping://catalog-guideshopping://featured-productsshopping://categoriesshopping://cart-guideshopping://order-guideshopping://order-statusesmetrics://shoppinghealth://checkswidget://examplesshopping_assistantprompt for guided product research
Widget resources are automatically registered for every tool decorated with @Widget. pnpm build runs the Next.js static export and places the seven bundles in src/widgets/out/.
Commands
pnpm dev # development stdio server
pnpm build # widget export + TypeScript build
pnpm test # build + unit tests + MCP protocol tests
pnpm test:unit # unit and persistence tests only
pnpm test:coverage # unit tests with coverage thresholds
pnpm test:postgres # persistence tests against TEST_DATABASE_URL
pnpm verify # build + lint + typecheck + unit tests + protocol tests
pnpm verify:mcp # stdio, HTTP, dual, JWKS, and widget-mode protocol tests
pnpm verify:live # live eBay checks; skips without EBAY_APP_ID/EBAY_CERT_ID
pnpm lint # repository lint and formatting checks
pnpm typecheck # TypeScript only
pnpm start # build, then start
pnpm start:prod # start an existing dist buildPostgres coverage is opt-in and truncates every shopping table, so point it only at a disposable database:
TEST_DATABASE_URL=postgresql://user@localhost:5432/amazon_mcp_test pnpm test:postgresCorrectness guarantees
Cart contents come from the server.
add_to_cartaccepts onlyitem_idandquantity; the title, price, currency, URL, and availability are fetched from eBay. A forged price or a nonexistent item cannot enter a cart.Cart writes are atomic. Every mutation is a locked read-modify-write (a per-user advisory lock plus row lock on Postgres, a serialized write queue for the file adapter), so concurrent
add_to_cartcalls cannot lose an update.Quotes are durable and cart-bound. A checkout quote is persisted and fingerprinted against the cart it was priced from. If the cart changes afterwards,
place_orderreturns a conflict and the newer cart is left intact.Placement re-validates and is idempotent. Prices and availability are re-read immediately before placement, and the
checkout_idacts as the idempotency key: a retry returns the original order (alreadyPlaced: true), and two replicas cannot both consume one quote.The eBay budget is shared. With
DATABASE_URLthe daily application quota is an atomic Postgres counter that survives restarts and is shared by every replica. It counts eBay requests, not tool calls, because@Cachewraps@RateLimit.Failures stay quiet. Upstream messages are redacted before they reach tool output, logs, or metrics, and unexpected errors are replaced with a generic message.
Observability
metrics://shopping reports tool invocations, failures and error codes, eBay request counts, latency, retries and failure categories, catalog cache hit rate, quota usage, storage mode, applied migrations, and evaluated alerts (sustained eBay failures, a low or exhausted daily budget, an unreachable quota counter). It contains names, counts, and durations only — never tokens, credentials, or shopper data.
Over HTTP, /healthz is liveness (process only, so a dependency outage never triggers a restart) and /readyz is readiness (fails when persistence is unusable; a degraded eBay dependency is reported but does not remove the replica from service). health://checks remains the MCP-facing view.
Persistence and deployment
The Postgres adapter applies versioned, forward-only migrations at startup (shopping_schema_migrations), each inside a transaction under an advisory lock so concurrent replicas cannot apply the same version twice. It creates shopping_carts, shopping_orders, shopping_quotes, and ebay_quota, and scopes every read by the authenticated user.
Postgres is required for more than one replica. Carts, checkout quotes, orders, and the eBay quota counter all live there. The JSON adapter keeps its state in one process and is for a single local/demo instance only.
Before deployment:
Set
NODE_ENV=productionand explicitly chooseMCP_TRANSPORT_TYPE=http(ordualonly when stdio is intentionally needed).Set
HOST=0.0.0.0,DATABASE_URL, TLS settings,JWT_SECRET, and live eBay credentials through the secret manager.Set
SHOPPING_FULFILLMENT_MODE=demoexplicitly; startup fails without it outside development.Keep
EBAY_MOCK=falsefor live access and verifyhealth://checksreports the database and eBay asup.Run
pnpm verify, andpnpm verify:liveonce against the eBay sandbox with real credentials.Put the HTTP transport behind TLS. Set
TRUSTED_FORWARDED_HOSTSto the public host andREQUIRE_HTTPS=truewhen a proxy terminates TLS. Leave CORS disabled for non-browser clients, or setENABLE_CORS=truewith an exactCORS_ALLOWED_ORIGINSallowlist; wildcard CORS is not supported.Load
JWT_*,DATABASE_URL, and eBay credentials from the platform's secret store. Never commit a.env.
Logging and retention
Log records carry a request ID, tool name, authenticated subject, duration, and error code. Tool input is never logged, because it can contain a shipping address and _meta.authorization carries a bearer token; upstream eBay messages are redacted before they are logged. Treat the subject claim as personal data and keep operational logs to the shortest retention your incident process allows.
Not a real commerce backend
place_order records an order in this server's database. There is no payment authorization or capture, no inventory reservation, no eBay order or fulfilment integration, and no refund handling — the eBay Browse and Taxonomy APIs are read-only under an application token and cannot reserve stock. Orders therefore have exactly two states, placed and cancelled, any un-cancelled order is eligible for cancellation, and every order reports fulfillment: "demo". SHOPPING_FULFILLMENT_MODE=external is rejected at startup so a deployment cannot appear to be something it is not.
Available Tools
11 toolsadd_to_cartAdd to cartC
Add a product to the authenticated user cart. Never pass a user ID; it comes from the JWT subject.
Inputs: item_id (required), quantity (required), title, currency, +4 more.
cancel_orderCancel orderA
Cancel an order belonging to the authenticated user when it has not already been cancelled.
Inputs: order_id (required).
checkoutPreview checkoutA
Create a short-lived checkout quote using live eBay prices and availability. This does not place an order.
Inputs: shipping_address.
get_categoriesGet product categoriesA
Retrieve the eBay category tree, or a category subtree when category_id is supplied.
Inputs: category_id.
get_orderGet orderB
Retrieve one order belonging to the authenticated user.
Inputs: order_id (required).
get_productGet productA
Retrieve current details and pricing for one eBay item.
Inputs: item_id (required).
order_historyOrder historyA
List orders belonging only to the authenticated user, newest first.
Inputs: limit, status.
place_orderPlace orderA
Place an authenticated user order from an unexpired checkout quote and clear the cart.
Inputs: checkout_id (required), shipping_address.
search_productsSearch productsB
Search the eBay catalog for products matching a text query and optional category.
Inputs: query (required), sort, limit, offset, +1 more.
update_cart_itemUpdate cart itemA
Set an item quantity in the authenticated user cart; quantity 0 removes it.
Inputs: item_id (required), quantity (required).
view_cartView cartA
View the authenticated user cart and its current item subtotal.
Inputs: no named parameters.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 11 tools
Each tool targets a distinct action or resource: search vs. specific product vs. category tree vs. cart operations vs. checkout vs. order lifecycle. No overlap in purpose, and descriptions clearly differentiate them.
Most tools follow a verb_noun pattern (search_products, get_product, get_categories, view_cart, update_cart_item, add_to_cart, place_order, cancel_order), but 'checkout' and 'order_history' deviate (single verb, noun phrase without a verb). The inconsistency is noticeable but not chaotic.
11 tools is well-scoped for a shopping domain, covering discovery, cart, checkout, and order management without unnecessary redundancy or bloat.
The tool surface covers the full shopping lifecycle: product discovery, cart, immediate cart actions, checkout, order placement, order retrieval, and cancellation. Minor gap: no direct 'get all categories' without subtree tree logic, but other methods query properly.
Related MCP Connectors
Search multi-merchant supply, checkout, and track orders via MCP.
E-commerce MCP gateway: live product deals, attributed buy links, order tracking, flights.
Remote MCP connector for eBay, Shopify, Best Buy & Etsy marketplace data via the Commerce API
Unified MCP server for 70+ eCommerce platforms: products, orders, customers, and more.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for eBay buyer-side workflows enabling search, watch, bid, buy, and management of MyeBay via a hybrid REST and Trading API stack.151Apache 2.0
- AlicenseAqualityBmaintenanceEnables the full Ingram Micro Reseller purchasing lifecycle through a single stateless HTTP MCP service, covering catalog and pricing, quotes, quote-to-order, order placement/modification/cancellation/lookup, invoices, renewals, special deals, returns, and freight estimates with one set of credentials.24Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables searching active eBay listings, retrieving full item details, and browsing eBay category taxonomies through MCP tools.115 npm1MIT
- AlicenseNot gradedqualityCmaintenanceEnables searching eBay listings, inspecting item details, monitoring price drops, placing auction bids, and buying fixed-price items via guest checkout through eBay's Buy APIs.MIT