MCP server
HTTP MCP (Model Context Protocol) server for AI agents — Cursor, Claude Code, Lovable, custom orchestrators. Auth, rate limits, and the public tool surface.
The Brainerce MCP server exposes a small set of read-only documentation and discovery tools over the Model Context Protocol. AI agents (Cursor, Claude Code, Lovable, custom orchestrators) connect to it to fetch SDK docs, integration guides, and runtime store capabilities while generating code against the Brainerce SDK.
It 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 bit about a specific sales-channel's runtime capabilities.
Endpoint
POST https://mcp-docs.brainerce.com/mcp (Streamable HTTP transport)
GET https://mcp-docs.brainerce.com/sse (legacy SSE transport)
GET https://mcp-docs.brainerce.com/health (unauthenticated liveness)For self-hosting, the server lives at packages/mcp-server/src/bin/http.ts and listens on PORT (default 3100).
Connecting clients
Gemini CLI — install the official extension (bundles the endpoint above plus /brainerce:create-store, /brainerce:add-feature, and /brainerce:verify commands):
gemini extensions install https://github.com/brainerce/ai-toolkitClaude Code — add the Brainerce marketplace and install the plugin (bundles the endpoint plus the same /brainerce:* commands):
/plugin marketplace add brainerce/ai-toolkit
/plugin install brainerce@brainerceClaude Desktop — Settings → Connectors → Add custom connector → 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.
Store management (admin): this docs server is read-only. To manage a store from an MCP client, connect the separate Admin MCP at https://api.brainerce.com/api/mcp.
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 also a hard requirement for hosted chat clients — ChatGPT's custom connectors require OAuth and will not accept a bearer token at all.
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. In Gemini CLI, /brainerce:connect-admin sets up the key form.
Compact mode — use it unless you know the client can take a few hundred tools. The Admin MCP's full surface is 524 tool definitions and well over 100k tokens, and it keeps growing as features ship. That is over the tool budget of every hosted client we have measured, and a client that cannot load the list ends up with no tools rather than a truncated set. Compact mode serves 8 definitions (roughly 3,000 tokens) instead: search_tools to find a tool by task, the three call_read_tool / call_write_tool / call_destructive_tool dispatchers to invoke it by name, and the widget-bearing tools listed directly. Every tool on the full surface stays reachable through the dispatchers.
The widget-bearing tools are listed directly for a specific reason: OpenAI reads openai/outputTemplate from a tool's own descriptor, never from a call result, so a card can only render if the tool declaring it appears in tools/list. Behind the dispatchers alone those cards were unreachable. Membership is detected from the descriptor, so a new widget tool joins the compact list automatically. ChatGPT is the only host that renders these cards; every other client is text-only in either mode.
The cards are interactive. The two list cards page through the catalog or the orders inside the card itself, calling the same list tool again through the Apps SDK bridge and carrying the original filters with them, so the second page answers the same question the first one did; all three offer follow-up buttons and a fullscreen toggle. A button never performs a write directly — it posts the request into the conversation and the assistant carries it out, so the tools annotated destructive keep their confirmation step instead of committing on a single click. None of this costs anything in tools/list: the markup is a ui:// resource the host fetches only when a card renders.
Two equivalent ways to select it:
| Form | Endpoint |
|---|---|
| Path (use this when pasting into a form) | https://api.brainerce.com/api/mcp/compact |
| Query param | https://api.brainerce.com/api/mcp?mode=compact |
A third address, https://api.brainerce.com/api/mcp/openai, lists 54 tools by name instead of putting them behind a search step. It carries the store-operations set — products (including per-variant stock, publishing a product to a sales channel and bulk_update_platforms for the whole catalog), categories, tags, orders, fulfilment, customers, coupons, discount rules, product reviews, sales channels and set_sales_channel_live (record the public domain and switch to LIVE), shipping zones and rates, list_tax_rates and create_tax_rate, update_store for the store's name, country, currency, default language and tax flags, a store-setup checklist (get_store_setup_status) and the analytics summaries — and nothing else: no content, media, email, loyalty, app, payment-provider or deletion tools, which stay reachable through compact mode's dispatchers. create_product and update_product also declare openai/fileParams for a photos field, so a picture attached to the ChatGPT conversation becomes a product image. The list is frozen in openai-surface-tools.ts and budget-guarded offline: 54 tools measure 61,109 bytes, roughly 15,277 tokens, against a 62,000-byte ceiling, so it loads in ChatGPT (the 47 of 2026-09-15 were verified against production, including the widget cards; the 54 are measured offline pending deploy). Prefer it there when the actions it carries are the ones you need, with compact mode as the fallback for anything outside that set.
What the full surface added on 2026-09-15 and 2026-09-16, all native and reachable through compact mode's dispatchers, none on the /openai list unless named above: update_store grew to every Settings → General field, plus set_store_languages and activate_store; create_order (a manual order that reserves stock and sends no shopper email) and the order status label, order custom field definition and checkout custom field families; loyalty earning rules, badges, membership plans, referrals, widget settings, tier recalculation and analytics; inquiries (reply_to_inquiry emails the shopper at once) and contact forms; shipping classes, calculate_shipping, check_free_shipping, the ship-from origin, address validation, shipments, manual tracking and buy_shipping_label (quote first, buy with confirm: true); email template create, delete, reset, preview, versions and send_test_email (to the signed-in merchant only), sending domains and the send log; webhook subscriptions (list, update, test, delete; create and secret rotation stay in the dashboard), store exports and the backup schedule (restore stays in the dashboard); marketplace browse, install_app, configure_app (non-secret keys only), suspend, resume, disconnect, uninstall and connector sync, plus per-channel sync, tracking ids and integrations; cohort retention, customer stats, coupon and discount-rule performance, inventory summary, connection health and traffic breakdowns; inventory history, stock velocity, per-channel inventory policies and outbound inventory sync; and set_product_channel_app_visibility, sale-price windows and shipping weight and dimensions on products. There is no analytics:read scope: analytics tools use orders:read or the read scope of the resource they report on.
Prefer the path form 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 stays supported for existing integrations. Anything other than exactly mode=compact is a 400, never a silent fall back to the full list.
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 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.
Abuse is controlled by rate limits and session caps instead (below), plus Cloudflare in front.
Rate limits & abuse protection
- 60 requests / minute / IP, in-memory token bucket keyed by
CF-Connecting-IP. - SSE session caps: 500 concurrent sessions globally, 5 per IP. Above those,
503/429respectively. - 4-hour SSE session lifetime, enforced server-side.
- 100 KB request body cap; oversized payloads get
413. - Header/request reception timeouts guard against slowloris-style connection hoarding.
- The bucket is per-process; if the MCP runs with N replicas the effective limit is N × 60/min.
- Health checks (
GET /health) are exempt from rate limiting.
CORS
Browsers can only call the MCP from origins listed in MCP_ALLOWED_ORIGINS (comma-separated). In development localhost on any port is implicitly allowed.
Tools (public surface)
| Tool | What it does | Outbound call |
|---|---|---|
get-sdk-docs | Static Zod-enum lookup of SDK method shapes | None |
get-type-definitions | Static enum lookup of SDK types | None |
get-code-example | Static map of canonical SDK examples | None |
get-store-info | Fetch public store metadata | GET /api/vc/{salesChannelId}/info |
get-store-capabilities | Fetch what the storefront's connection scope permits | GET /api/vc/{salesChannelId}/capabilities |
get-integration-guide | Fetch the canonical integration guide | GET https://brainerce.com/docs/integration/raw |
get-critical-rules | Mixed — static rules + capabilities | Sometimes outbound |
get-business-flows | Mixed — flows + capabilities | Sometimes outbound |
get-required-features | Mixed — features + capabilities | Sometimes outbound |
get-store-config | Real config for one section (catalog/checkout/customers/merchandising) — how a feature is set up, not just whether it's on | GET /api/vc/{salesChannelId}/{categories,brands,tags,metafield-definitions,payment/providers,shipping/destinations,pickup-locations,tax-classes,regions,oauth/providers,discount-banners} (per section) |
get-product-shape | One product's real option/variant structure and modifier groups (add-ons) | GET /api/vc/{salesChannelId}/products/{productId} or .../products/slug/{slug} |
list-store-products | Orientation list of real products (id/name/slug + hasVariants/hasModifiers) | GET /api/vc/{salesChannelId}/products |
get-store-config / get-product-shape / list-store-products only work against a TEST-mode sales channel — a LIVE channel rejects the request (no browser Origin header from this server) and the affected fields come back explicitly marked unavailable rather than failing the whole call.
Also exposed as MCP resources and prompts:
- Resource
sdk-types— static type catalogue - Prompt
create-store— scaffolding skeleton - Prompt
add-feature— feature-addition skeleton
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
| Variable | Required | Description |
|---|---|---|
BRAINERCE_API_URL | yes | Base URL the MCP fetches from (e.g. https://api.brainerce.com). Must be HTTPS in production — see security note below. |
MCP_ALLOWED_ORIGINS | recommended | Comma-separated CORS allowlist. Empty = no cross-origin browsers. |
MCP_RATE_LIMIT_MAX | no | Requests per window per IP. Defaults to 60. |
MCP_RATE_LIMIT_WINDOW_MS | no | Length of the rate-limit window, in milliseconds. Defaults to 60000 (1 minute). |
MCP_MAX_BODY_BYTES | no | Max JSON request body size in bytes; oversized payloads get 413. Defaults to 102400 (100 KB). |
MCP_MAX_SSE_SESSIONS | no | Global concurrent SSE session cap. Defaults to 500 (MCP_MAX_SSE_SESSIONS_PER_IP caps per-IP, default 5). |
PORT | no | Listen port. Defaults to 3100. |
NODE_ENV | no | When development, falls back to permissive defaults. |
Security note — BRAINERCE_API_URL
If BRAINERCE_API_URL points at an internal address (e.g. http://10.0.0.5) and the MCP is exposed to the public internet, a caller could potentially use the get-store-info / get-store-capabilities tools to probe internal endpoints (SSRF-class). Always set BRAINERCE_API_URL to a public Brainerce host (https://api.brainerce.com) when the MCP itself is publicly reachable.
Trust boundary
- The MCP holds no Brainerce admin credentials.
- Full compromise of the MCP 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 — data already exposed to any storefront browser with that connection ID). This is why running it unauthenticated is safe. - The MCP container runs as non-root, with
--frozen-lockfileinstalls and no baked secrets.
Health
GET /health returns { "status": "ok" } and is exempt from rate limiting (used by deployment health probes).