MCP CORS preflight: headers Sume allows for a browser client
Sume answers an MCP OPTIONS preflight with 204 and lists authorization, content-type, idempotency-key, mcp-session-id and x-api-key for listed origins.

A browser MCP client that sends an OPTIONS preflight to the hosted MCP endpoint gets 204. If its Origin is on the server's allow-list, the reply lists authorization, content-type, idempotency-key, mcp-protocol-version, mcp-session-id and x-api-key as allowed request headers. Any other origin gets the 204 with no CORS headers, and the browser blocks the call.
This is read from the hosted MCP server source and the API server's CORS setup in the repository, 2026-10-01, plus the OAuth and API keys page for the endpoint URL (https://mcp.sume.com/mcp). I did not run a live preflight, so test your own origin.
What does the preflight response contain?
The MCP server's explicit OPTIONS handler (registered on the MCP host root, /) sets the CORS headers only when the request has an origin and that origin passes the allow check, and sets allow either way. The API server's CORS plugin separately lists the same six allowed request headers for GET, POST and OPTIONS; its origin check is its own and I did not read it in full.
| Header | Value |
|---|---|
| Status | 204, empty body |
allow | POST, OPTIONS |
access-control-allow-origin | The request's own origin, only if listed |
access-control-allow-headers | authorization, content-type, idempotency-key, mcp-protocol-version, mcp-session-id, x-api-key |
access-control-allow-methods | GET, POST, OPTIONS |
vary | Origin |
Which origins are allowed?
The check passes a request with no Origin header at all, which is the normal case for server-side and desktop clients. For a browser request, the origin must be in a set built from the server's configured CORS origins, its own public base URL, and a remote-MCP allow-list. The sources I read do not publish that list, so a new web app origin has to be confirmed with Sume rather than guessed.
Why is mcp-session-id in the allowed headers?
It is only an allowance: a browser may include that header without failing preflight. In the MCP server package, that allowlist is the only place the string mcp-session-id appears; the API server's CORS config lists it too, as an allowed and an exposed header. Sume's GET /mcp answers 405 with allow: POST, so the endpoint is POST JSON-RPC only. The MCP server code does not read that header, so your client has no session id to store; if a library sends one, preflight will not reject it.
Which headers should my browser client actually send?
Send Authorization: Bearer ... (or x-api-key) and content-type: application/json. Paid and write tools also need an idempotency_key argument, as described in MCP tools and gates; the idempotency-key header is allowed by preflight as well. Do not ship an API key in a public web page, since anything the browser can read, a visitor can read. For a user-facing app, prefer the OAuth flow, and see the Sume API CORS error for the REST side.
Sources
Related posts
More in Developers
- MCP DPoP sender-constrained tokens: Sume is bearer-only today
The MCP roadmap lists DPoP finalization, but Sume's hosted MCP issues mcp_at_ bearer tokens sent in the Authorization header, valid for one hour.
- MCP DCR application_type: what Sume's register endpoint reads
The 2026-07-28 MCP spec asks clients to send application_type in dynamic registration. Sume's /oauth/register reads redirect_uris and other named fields.
- MCP server URL trailing slash 404: use mcp.sume.com/mcp
Sume's hosted MCP URL is https://mcp.sume.com/mcp with no trailing slash. The server registers that exact path, so write it as documented; skip redirect flags.
- MCP error -32000 connection closed: what Sume's -32000 means
MCP error -32000 is implementation-defined. Sume returns it only when its MCP work budget is full; a client's own connection closed text is a different thing.
Written by Sume