[recipes] Fix CORS + JSON-RPC envelope on work-operating-model-activation#329
Draft
drewyd wants to merge 1 commit into
Draft
[recipes] Fix CORS + JSON-RPC envelope on work-operating-model-activation#329drewyd wants to merge 1 commit into
drewyd wants to merge 1 commit into
Conversation
…tion
Browser-based MCP clients (e.g. the Claude.ai web UI) cannot reach this
recipe's Edge Function because:
1. CORS preflight is not handled. OPTIONS requests get no
Access-Control-Allow-* headers, so the browser blocks the POST.
2. The unauthorized path returns a bare { error: "Unauthorized" } at HTTP
401, which is not a valid JSON-RPC 2.0 response. MCP clients that
strictly validate the envelope reject the response before surfacing
the real auth issue.
Fix:
- Add an OPTIONS handler returning the standard CORS allow-list (origin,
methods, headers used by MCP transports including mcp-session-id,
mcp-protocol-version, last-event-id).
- Wrap the unauthorized response in a JSON-RPC 2.0 envelope
({ jsonrpc, error: { code, message }, id }) at HTTP 200, with the
CORS headers attached, and best-effort echo the inbound request id.
- Move the auth gate above the accept-header patching so we never consume
the request body twice on the unauthorized path.
No behaviour change for authorized callers. No refactor of the four MCP
tools or any business logic.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The
work-operating-model-activationrecipe's MCP Edge Function is unreachable from browser-based MCP clients (Claude.ai web UI being the canonical case). Two issues compound:OPTIONShandler. Browsers reject the subsequent POST because noAccess-Control-Allow-Origin/Allow-Headers/Allow-Methodsheaders come back on the preflight.{ error: "Unauthorized" }body at HTTP 401. MCP clients that strictly validate JSON-RPC envelopes ({ jsonrpc: "2.0", id, error: { code, message } }) reject the response before they can surface the real auth issue to the user, and the 401 status code itself makes some browser fetch wrappers throw before the JSON is even parsed.Reproduction
recipes/work-operating-model-activation/README.md.claude.ai-> Settings -> Connectors -> Add custom connector, paste the function URL with?key=<MCP_ACCESS_KEY>.Access-Control-Allow-Originheader and the POST never firing.{ "error": "Unauthorized" }rather than a JSON-RPC error envelope.Fix
Minimal, localized to the Hono app setup and the
app.all("*")catch-all. No changes to the four MCP tools, schemas, or any business logic.app.options("*", ...)returning standard CORS allow-list (origin, methods, and the headers MCP transports actually use:authorization,x-client-info,apikey,content-type,x-brain-key,accept,mcp-session-id,mcp-protocol-version,last-event-id).unauthorizedResponse(id), which returns a JSON-RPC 2.0 envelope ({ jsonrpc: "2.0", error: { code: -32001, message }, id }) at HTTP 200, with CORS headers attached. The inbound request id is best-effort echoed so the client can correlate.transport.handleRequest(c)ownership of the stream.The patched version of this function has been running successfully against the live Claude.ai web UI for ~24h on the contributor's deployment, completing a full five-layer operating-model session end-to-end.
Notes
fix/work-operating-model-corsper the explicit task instruction. Happy to rename tocontrib/drewyd/work-operating-model-cors-fixperCONTRIBUTING.mdconvention if maintainers prefer - just shout.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com