API ReferenceMCP server

MCP server

The two Brainerce MCP (Model Context Protocol) servers. The public read-only docs server for coding agents (tools, endpoints, rate limits, env), and the Admin MCP for running a store (addresses, tool counts, which client uses which address).

Brainerce runs two separate MCP servers. They share a name and nothing else.

ServerAddressAudienceCarries credentialsWhat it does
Docs serverhttps://mcp-docs.brainerce.com/mcpCoding agents (Cursor, Claude Code, Lovable, custom orchestrators) building a storefrontNo. Public by designRead-only SDK docs, types, business flows, critical rules and live capabilities of one sales channel
Admin MCPhttps://mcp.brainerce.com/api/mcpA merchant's own AI assistant (ChatGPT, Claude, Cursor) running a storeYes: OAuth sign-in or a brainerce_* API keyReads and changes that merchant's store (products, orders, customers, coupons, shipping, content, email and more)

The docs server is intentionally narrow. It does not carry admin credentials, cannot read or mutate merchant data, and is not a substitute for the Public API (v1). Think of it as a documentation oracle that knows a little about one sales channel's runtime capabilities. Everything below until "Admin MCP" describes the docs server.

Endpoint

POST https://mcp-docs.brainerce.com/mcp                  (Streamable HTTP, stateless: a new server instance per request)
GET  https://mcp-docs.brainerce.com/sse                  (legacy SSE transport: opens the stream)
POST https://mcp-docs.brainerce.com/messages?sessionId=  (legacy SSE transport: the client's messages, sessionId from the stream)
GET  https://mcp-docs.brainerce.com/health               (unauthenticated liveness, exempt from rate limiting)

Paste /mcp, not /sse. /sse exists for older clients that cannot speak Streamable HTTP. Any other path answers 404 with { "error": "Not found. Use /mcp (Streamable HTTP), /sse (legacy SSE), or /health." }.

For self-hosting, the HTTP server lives at packages/mcp-server/src/bin/http.ts and listens on PORT (default 3100). A local stdio server is npx -y @brainerce/mcp-server (the package's bin is brainerce-mcp).

Connecting clients

Gemini CLI. Install the official extension. It bundles the endpoint above plus five commands: /brainerce:create-store, /brainerce:connect-storefront, /brainerce:add-feature, /brainerce:verify and /brainerce:connect-admin.

gemini extensions install https://github.com/brainerce/ai-toolkit

Claude Code. Add the Brainerce marketplace and install the plugin. It bundles the endpoint plus the same /brainerce:* commands.

/plugin marketplace add brainerce/ai-toolkit
/plugin install brainerce@brainerce

Claude Desktop. Settings, then Connectors, then Add custom connector, and paste https://mcp-docs.brainerce.com/mcp.

Any other MCP client. Paste the Streamable HTTP endpoint (https://mcp-docs.brainerce.com/mcp) into the client's MCP settings, or run the server locally over stdio with npx -y @brainerce/mcp-server.

Telemetry. Each MCP initialize logs the connecting client's self-reported name, version and User-Agent (adoption metrics). Queries, tool arguments and content are never recorded.

Authentication

None. The docs server is public by design. Everything behind it is public data: static SDK docs and a handful of public /api/vc/* endpoints that any storefront browser can already call. Paste the URL into your AI tool and it works; no token, no registration. An Authorization header, if sent, is ignored (and so is a MCP_AUTH_TOKENS environment variable on a self-hosted instance).

Abuse is controlled by rate limits and session caps instead (below), plus Cloudflare in front.

Rate limits and abuse protection

  • 60 requests per minute per IP, an in-memory token bucket keyed by CF-Connecting-IP (falling back to the rightmost X-Forwarded-For entry, then the socket address). Over the limit: 429 with Retry-After.
  • SSE session caps: 500 concurrent sessions globally (503 above that) and 5 per IP (429 above that).
  • 4-hour SSE session lifetime, enforced server-side, with a keep-alive comment every 10 seconds.
  • 100 KB request body cap. An oversized payload gets 413 ({ "error": "Payload too large" }). A body that is not valid JSON gets 400.
  • Slowloris guards: request headers must arrive within 15 seconds and the whole request within 60 seconds.
  • The bucket is per process. If the MCP runs with N replicas the effective limit is N times 60 per minute.
  • Health checks (GET /health) are exempt from rate limiting.

CORS

Browsers can only call the docs server from origins listed in MCP_ALLOWED_ORIGINS (comma-separated). When NODE_ENV is development (the default when it is unset) localhost and 127.0.0.1 on any port are also allowed. Responses never allow credentials (there are no cookies on this surface). Allowed methods are GET, POST, DELETE, OPTIONS, and Mcp-Session-Id is exposed.

Tools (public surface)

Thirteen tools. All are read-only.

ToolArgumentsWhat it doesOutbound call
get-sdk-docstopic (enum, required), salesChannelId?, currency?SDK reference for one topic: setup, products, cart, checkout, checkout-custom-fields, shipping-app, payment, saved-payment-methods, auth, order-confirmation, inventory, discounts, loyalty, recommendations, reviews, product-customization-fields, modifier-groups, tax, critical-rules, type-reference, i18n, multilingual-seo, admin, inquiries, newsletter, stock-alerts, wishlist, donations, store-events, content, blog, seo, storefront-bot, analytics, marketing-tags, connect-existing-frontend, or all. A set of aliases (for example saved-items, events, retrofit, gtm, ga4) resolves to the topic above it.None (static)
get-type-definitionsdomain (enum, required)TypeScript types by domain: products, cart, checkout, orders, customers, payments, helpers, inquiries, newsletter, stock-alerts, wishlist, reviews, modifier-groups, content, regions, loyalty, donations, gift-cards-admin, allNone (static)
get-code-exampleoperation (enum, required)A canonical SDK snippet for one operation (SDK init, checkout steps, auth, coupons, reservations, search, i18n, modifiers, newsletter popup, back-in-stock, wishlist heart and more)None (static)
get-critical-rulestopics? (array of sdk, state, auth, checkout, tokens, i18n, types, all; default all)The do and don't rules that cause production incidentsNone (static)
get-business-flowsflow (enum, required)The non-negotiable sequences: checkout, auth-register, auth-login, password-reset, oauth, order-confirmation, cart-persistence, inventory-reservation, product-customization, content-bootstrap, donation, store-event-registration, or allNone (static)
get-required-featuressalesChannelId?The functional coverage checklist. With a salesChannelId it is tuned to that channel's capabilities; without one it returns the generic complete-store checklistGET /api/vc/{salesChannelId}/capabilities (only when an id is given)
get-store-infosalesChannelIdPublic store metadata (name, currency, language)GET /api/vc/{salesChannelId}/info
get-store-capabilitiessalesChannelIdWhat the channel's scope permits and which conditional features are onGET /api/vc/{salesChannelId}/capabilities
get-integration-guidepart (core, optional or rules)The canonical integration guideGET https://brainerce.com/docs/integration/raw?part={part}
search-docsquery (min 2 chars), limit? (1 to 20, default 8)Full-text search over brainerce.com/docs. Returns titles, URLs and snippets, never whole pages. A fallback for what the fixed topic lists do not coverGET https://brainerce.com/api/search?query=
get-store-configsalesChannelId, section (catalog, checkout, customers or merchandising; there is deliberately no all)How one area is actually configured, not just whether it is onGET /api/vc/{salesChannelId}/{path} where path is categories, brands, tags, metafield-definitions (catalog); payment/providers, shipping/destinations, pickup-locations, tax-classes, regions (checkout); oauth/providers (customers); discount-banners (merchandising)
get-product-shapesalesChannelId, productId or slugOne product's real option and variant structure and modifier groups (add-ons)GET /api/vc/{salesChannelId}/products/{productId} or .../products/slug/{slug}
list-store-productssalesChannelId, search?, limit? (default 20, hard cap 50)Orientation list of real products (id, name, slug, hasVariants, hasModifiers)GET /api/vc/{salesChannelId}/products

connectionId is accepted on every tool that takes salesChannelId as a deprecated alias.

get-store-config, get-product-shape and list-store-products only work against a TEST-mode sales channel. A LIVE channel is locked to its own registered domain and rejects the request (this server sends a localhost Origin, the ladder it tries is http://localhost:3000 then http://localhost), and the affected fields come back explicitly marked unavailable instead of failing the whole call. A TEST channel with a Domain set that matches neither origin refuses too; clear the Domain field or add your dev origin to Allowed Origins.

Also exposed as MCP resources and prompts:

  • Resource brainerce://sdk/types ("Brainerce SDK Types"): the static type catalogue.
  • Prompt create-store (connectionId, storeName, storeType, currency? default USD, storeStyle?): a framework-agnostic brief for building a storefront.
  • Prompt add-feature (feature one of products, cart, checkout, payment, auth, order-confirmation, inventory, discounts, recommendations, search, tax; connectionId?, currency?): a focused prompt for adding one feature to an existing store.

All outbound calls hit public Brainerce endpoints. The MCP does not forward the caller's Authorization header: every call is unauthenticated and returns only public, sales-channel-scoped data.

Configuration env (docs server)

VariableRequiredDescription
BRAINERCE_API_URLnoBase URL the tools fetch /api/vc/* from (for example https://api.brainerce.com). When unset the server tries production (https://api.brainerce.com) and then staging (https://api-staging.brainerce.com). When set it is the only URL tried. Use a public HTTPS host if the server is reachable from the internet (see the security note)
MCP_ALLOWED_ORIGINSrecommendedComma-separated CORS allowlist. Empty means no cross-origin browsers
MCP_RATE_LIMIT_MAXnoRequests per window per IP. Defaults to 60
MCP_RATE_LIMIT_WINDOW_MSnoLength of the rate-limit window in milliseconds. Defaults to 60000
MCP_RATE_BUCKETS_MAXnoCap on tracked IPs; when hit, the counters reset. Defaults to 20000
MCP_MAX_BODY_BYTESnoMax JSON request body in bytes; oversized payloads get 413. Defaults to 102400 (100 KB)
MCP_MAX_SSE_SESSIONSnoGlobal concurrent SSE session cap. Defaults to 500
MCP_MAX_SSE_SESSIONS_PER_IPnoPer-IP SSE session cap. Defaults to 5
PORTnoListen port. Defaults to 3100
NODE_ENVnoDefaults to development, which additionally allows localhost and 127.0.0.1 origins

Security note: BRAINERCE_API_URL

If BRAINERCE_API_URL points at an internal address (for example http://10.0.0.5) and the MCP is exposed to the public internet, a caller could use the get-store-info and get-store-capabilities tools to probe internal endpoints (SSRF class). Set it to a public Brainerce host (https://api.brainerce.com) when the MCP itself is publicly reachable, or leave it unset. The server does not enforce HTTPS itself.

Trust boundary

  • The docs server holds no Brainerce admin credentials.
  • Full compromise of it grants nothing tenant-scoped. At worst an attacker can make rate-limited requests to the public /api/vc/<id>/* read endpoints the tools above call (info, capabilities, catalog, checkout config, OAuth providers, products), which is data already exposed to any storefront browser with that connection ID. This is why running it unauthenticated is safe.
  • The container runs as non-root, with --frozen-lockfile installs and no baked secrets.

Health

GET /health returns { "status": "ok", "server": "brainerce-mcp", "activeSessions": <number of open SSE sessions> } and is exempt from rate limiting (used by deployment health probes).


Admin MCP (store management)

The Admin MCP lets a merchant's AI assistant read and run one store: products, variants and stock, orders and fulfilment, customers, coupons and discount rules, shipping, tax, content, email, loyalty, analytics and more. The docs server above cannot do any of this.

https://mcp.brainerce.com/api/mcp

The host is mcp.brainerce.com, the same address for every merchant. The OAuth grant decides which store a session is bound to, so there is no per-store URL to look up or hand out. Use this host rather than api.brainerce.com: the OAuth protected-resource metadata declares https://mcp.brainerce.com/... as the canonical resource, and a client that connects to a host the metadata does not name can fail the resource check during authorization.

Signing in

Signing in is the primary way in, not an API key. The Admin MCP is an OAuth 2.1 authorization server with dynamic client registration, so a client you have never registered can connect on its own: it opens a browser, the merchant signs in, chooses which store to bind the grant to, approves the scopes, and nothing is copied or pasted. That flow is a hard requirement for hosted chat clients, because ChatGPT's custom connectors require OAuth and will not accept a bearer token at all.

Redirect URIs a client may register: https URLs, reverse-DNS custom schemes (com.example.app:/callback) and http loopback URLs (127.0.0.1, [::1], localhost). For an http loopback redirect the port is not compared (RFC 8252 section 7.3), so a desktop client that binds a different free port on each run keeps working with the URI it registered once. The host, path and query still have to match exactly, and every other redirect is matched exactly as registered.

A brainerce_* API key as the Authorization: Bearer header still works and is the right choice for a headless client that cannot open a browser. Keys are created in the dashboard under Settings, then API keys. In Gemini CLI, /brainerce:connect-admin sets up the key form.

Many tools are OAuth only. Tools that act as the signed-in person (categories, tags, brands, product options, custom-field values, shipping zones and rates, loyalty tiers, store settings, publishing a product to a channel, switching a channel live, and roughly a third of all tools) are refused on an API key with "This tool requires OAuth authentication and is not available via API key". That is the connection, not the store. Tools scoped by key permission (products:write, tax:write and so on) work on either.

Scopes. Each tool declares the scope it needs (for example orders:read, products:write, settings:write). There is no analytics:read scope: analytics tools use orders:read or the read scope of the resource they report on.

Which address for which client

All four addresses reach the same store with the same permissions. They differ in which tools the tools/list answer contains, because hosted clients have a tool budget and a client that cannot load the list ends up with no tools at all rather than a truncated set.

Addresstools/list answersUse it for
https://mcp.brainerce.com/api/mcp (native)580 tool definitions, roughly 930 KB (well over 200,000 tokens)Claude Code, Cursor, Claude Desktop and any client that can take a few hundred tools. Every tool is listed directly. A request with no credential is answered 401 with a WWW-Authenticate header, so a client that signs in on its own opens its sign-in window at connect time. It offers no GET event stream (405); everything runs over POST
https://mcp.brainerce.com/api/mcp/compact (or /api/mcp?mode=compact)9 definitions, roughly 18 KB (about 4,500 tokens)Any other client with a small tool budget
https://mcp.brainerce.com/api/mcp/openai48 definitions, roughly 63 KB (held under a 16,000 token budget)ChatGPT
https://mcp.brainerce.com/api/mcp/claude77 definitions, roughly 106 KBThe Brainerce Claude plugin, which points Claude Code here for you

Do not use compact mode with Claude Code. Compact hides every tool behind a search step, and a model that cannot see a write tool may substitute a different one rather than say it is blocked (a request to create a tag once created a product). Claude Code and Cursor connect to the native address, or through the Claude plugin to /api/mcp/claude.

Which doors answer an anonymous request. The native address answers 401 first, because Cursor, Claude Code and Claude's connector dialog start OAuth only on a 401 (the MCP authorization specification asks for exactly that). The ChatGPT address (/api/mcp/openai) and the compact address do not: ChatGPT signs in inline from a 200 that carries the challenge in its result, and a 401 there would replace a working sign-in with a dead connector. The Claude address (/api/mcp/claude) answers 401 only to a call of a protected tool, as Anthropic's connector documentation requires. /api/mcp/ide is an older alias of the native address and behaves the same.

Sessions last. An access token is valid for 1 hour. A refresh token is issued with it, is replaced on every use and is valid for 365 days from that use, so a connection you keep using does not ask you to sign in again. Two refreshes of the same token that arrive within 30 seconds of each other (two editor windows) are both served; a rotated token presented after that window revokes the whole family.

Compact mode: 9 definitions

search_tools finds a tool by task. The three dispatchers call_read_tool, call_write_tool and call_destructive_tool invoke it by name. Five read tools are listed directly so the questions a merchant asks first ("show me my products", "my orders", "how is the store doing") need no search step: list_products, get_product, show_product_gallery, list_orders and get_store_analytics_summary. Every tool on the full surface stays reachable through the dispatchers, except the ones listed under "What the dispatchers refuse" below.

  • search_tools({ query, top_k? }): query is 1 to 200 characters of short English keywords naming an action and its object ("create product", "set stock"); top_k is 1 to 20, default 8. Matching is on keywords, not meaning, so translate the merchant's words into the platform's nouns first (a "three for two" is a bundle offer, a "VIP club" a loyalty tier, "toppings" a modifier group, a "newsletter" a campaign). Tools already in the listing are excluded from the results by design.
  • call_read_tool, call_write_tool, call_destructive_tool each take { tool_name, arguments?, store? }. A dispatcher refuses a tool of another category: the category comes from the target tool's own annotations (read-only, non-destructive write, or destructive), not from the caller. Arguments are validated against that tool's own schema, and are capped at 20,000 characters of JSON. Three separate dispatchers exist so a host's per-tool approval prompt can tell reading a product from cancelling an order.

Compact has no custom cards: ChatGPT presents the data itself and every client gets the same text result. Prefer the path form (/api/mcp/compact) anywhere the URL is stored and replayed by someone else (an app-directory submission, a connector registry, a config UI), because a query string may not survive the round trip. The query form ?mode=compact stays supported (?mode=openai and ?mode=claude pin the other two surfaces the same way). Any other mode value is a 400, never a silent fall back to the full list.

The /openai surface: 48 definitions

It lists 43 tools by name, plus list_capabilities, plus the same search step and three dispatchers compact mode uses, so most of the full registry stays reachable from it. It is both a flat list and a door.

The 43 named tools:

  • Products: list_products, get_product, count_products, show_product_gallery, create_product, update_product, duplicate_product
  • Variants and stock: create_variant, update_variant, set_product_stock, set_variant_stock
  • Publishing: bulk_update_platforms (the whole catalog to a channel), publish_product_to_channel
  • Taxonomy: list_categories, create_category, list_tags, create_tag
  • Orders: list_orders, get_order, update_order_status, cancel_order, fulfill_order
  • Customers: list_customers, get_customer, get_customer_orders
  • Discounts: list_coupons, create_coupon (a code the shopper types), list_discount_rules, create_discount_rule (automatic, no code)
  • Sales channels: list_sales_channels, create_sales_channel, set_sales_channel_live (record the public domain and switch to LIVE)
  • Store and setup: get_store, update_store, get_store_setup_status, get_store_analytics_summary
  • Shipping, tax, loyalty, email: list_shipping_zones, create_shipping_zone, create_shipping_rate, list_tax_rates, create_tax_rate, create_loyalty_tier, update_email_template

The list is frozen in openai-surface-tools.ts and held to a combined token budget by openai-surface-budget.spec.ts. A name is added only with a written justification, because a write tool the model cannot reach makes it substitute the nearest one it can see.

Specific to this surface:

  • Attaching a photo to the ChatGPT conversation does not reach a product: openai/fileParams was withdrawn on 2026-09-23 after the submission portal refused the whole tool scan over it, and the photos field went with it. Send an image as a direct file URL in images. Both are still on the native surface.
  • Digital downloads (ingest_download_file, set_product_download_files) and the store-events tools are not reachable through the dispatchers here either (ChatGPT's commerce category covers physical goods). Claude and the native surface reach them.

The /claude surface: 77 definitions

73 named tools plus the same search step and three dispatchers. It carries the /openai list except show_product_gallery (a ChatGPT-only visual) and adds 30 tools: the other half of each lifecycle (list_variants, bulk_save_variants, update_category, update_tag, the custom-field definition and value tools, update_coupon, preview_coupon_for_order, update_discount_rule, toggle_discount_rule, update_shipping_zone, list_shipping_rates, update_shipping_rate, update_tax_rate), inventory reads (get_product_inventory, get_variant_stock), the order and sales reports (get_recent_orders, get_orders_stats, get_orders_by_status, get_top_selling_products, get_average_order_value), product reviews (list_product_reviews, get_product_review_stats), create_blog_post, search_help and search_docs. Digital downloads and the store-events tools are reachable through the dispatchers here. The frozen list lives in claude-surface-tools.ts.

What the dispatchers refuse

On every surface the dispatchers reach every registered tool except a small denylist in door-policy.ts, applied to search_tools results and to execution alike, so the surface never recommends something it would then refuse:

  • Payment-provider configuration: set_region_payment_providers (it replaces a region's whole provider set, and provider credentials must not cross a conversation).
  • Money movement: create_refund, mark_order_paid, update_order_payment_method, refund_donation, refund_event_registration, cancel_event.
  • On /openai only: ingest_download_file, set_product_download_files and the store-events tools.

Deletion tools and gift cards are not on that list: they are reachable through call_destructive_tool, where a host's approval prompt applies. Connecting a payment provider, entering provider credentials and switching a provider between TEST and LIVE are dashboard tasks on every surface; configure_app refuses credential-shaped keys by name.

What the full surface covers

The native list is derived from the registry, so it grows as features ship; read the live tools/list for the authority, never this page. By family it includes: products, variants, stock per variant and per channel, publishing to sales channels, categories, tags, brands, attributes, modifier groups, custom fields, pricing formulas, bundle offers and order bumps; orders (create, status, fulfilment, shipments and labels, tracking, notes, custom fields, status labels), refunds and donations; customers, segments, addresses and inquiries; coupons and discount rules; shipping classes, zones, rates, pickup and address validation; tax classes, rates, registrations and reports; regions and regional prices; loyalty (tiers, rewards, badges, earning rules, referrals); gift cards; recurring plans and subscriptions; events and registrations; content, blog and contact forms; email (settings, templates, sending domains, sequences, campaigns, send log); translations; webhooks (subscriptions, deliveries, health, resend and replay; creating a subscription and rotating its secret stay in the dashboard), store exports and the backup schedule (restore stays in the dashboard); apps and connectors (browse, install, configure non-secret keys, suspend, resume, disconnect, uninstall, sync); the store team and its invitations; SEO audits; analytics and reports (revenue, series, cohorts, coupon and discount-rule performance, inventory, traffic, connection health); and the store setup checklist (get_store_setup_status).

create_order makes a manual order that reserves stock and sends no shopper email; reply_to_inquiry emails the shopper at once; buy_shipping_label quotes first and buys only with confirm: true; send_test_email sends to the signed-in merchant only; configure_app takes non-secret keys only.