[server] Add CORS preflight + Accept header fix for Claude Desktop#94
Conversation
- CORS OPTIONS handler for browser/Electron clients (Claude Desktop, claude.ai) - Accept header patch for StreamableHTTPTransport (fixes NateBJones-Projects#33) - 401 responses include CORS headers so preflight errors propagate correctly PR NateBJones-Projects#38 applied the Accept header fix to all 6 extension Edge Functions but not to the core server/index.ts template. This brings the core server in line and adds CORS support that was missing entirely. Tested on a personal Supabase deployment with Claude Code, Claude Desktop, and Codex all connecting successfully. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justfinethanku
left a comment
There was a problem hiding this comment.
Review Summary
This PR addresses two critical compatibility issues that prevent Claude Desktop and browser-based MCP clients from connecting to Open Brain servers. The fixes are well-tested, properly scoped, and directly solve documented problems from issue #33.
What's Good
✅ Addresses real pain points — Issue #33 and the getting-started guide Step 7 have been blockers for new users. This fixes both failure modes (OPTIONS preflight + Accept header).
✅ Minimal, surgical changes — Only touches , which is the right scope. PR #38 fixed the 6 extensions but missed the core template that new users deploy first.
✅ Well-tested — Contributor tested on their own Supabase deployment with multiple clients (curl, Claude Code, Claude Desktop, Codex) and verified both the OPTIONS preflight handler and the Accept header patch work correctly.
✅ Follows established pattern — The Accept header fix is identical to what was merged in PR #38 for the extension edge functions. This brings the core server template into alignment.
✅ CORS headers consistent — The same corsHeaders object is applied to both the OPTIONS preflight response and the 401 auth error response, which is correct for browser-based clients.
✅ Clear documentation — PR description explains both fixes, why both are needed, and how they were tested. The code comments reference issue #33 for future maintainers.
Technical Review
CORS Preflight Handler
The new OPTIONS handler is correct:
- Returns 200 with proper
Access-Control-Allow-*headers - Includes all necessary headers for MCP protocol (
mcp-session-id,x-brain-key, etc.) - Wildcard origin is appropriate for a self-hosted MCP server
Accept Header Patch
The request rewriting logic matches PR #38 exactly:
- Checks if
Acceptheader includestext/event-stream - Creates a patched Request object with the required header when missing
- Properly handles streaming body with
duplex: "half" - Uses
Object.definePropertyto replace the raw request on the Hono context
Auth Flow
Auth check correctly happens after the Accept header patch, which is important — the transport needs the patched request before it processes the MCP handshake.
CORS headers are returned on 401 responses, which is necessary for browser clients to see the error message instead of a CORS failure.
Automated Review Criteria
Since this PR modifies existing infrastructure rather than adding a new contribution, most of the standard automated checks don't apply. Here's what does:
✅ No credentials or secrets — Clean
✅ SQL safety — No SQL changes
✅ No binary blobs — Clean
✅ PR title format — Correct: [server] prefix
✅ Scope — Changes confined to server/index.ts
Note: This PR doesn't require metadata.json or a contribution README because it's a fix to core infrastructure, not a new extension/recipe/etc.
Suggestions (Optional)
1. Consider adding a test edge function
It would be helpful to have a minimal test deployment script or curl-based smoke test that future contributors can run to verify both fixes. Could be added as server/test-cors-and-accept.sh or similar. Not blocking, but would help prevent regression.
2. Update docs/01-getting-started.md
The getting-started guide currently doesn't mention the OPTIONS preflight requirement or the Accept header issue. Consider adding a troubleshooting note in Step 7 explaining that this server template handles both, so users know what to expect if they modify the code.
Verdict: Ready to merge
This is a clean, focused fix that directly solves a documented blocker. The implementation is correct, matches the established pattern from PR #38, and has been properly tested. No changes needed before merge.
Recommendation: Merge and close issue #33.
justfinethanku
left a comment
There was a problem hiding this comment.
Review Summary
This PR addresses two critical compatibility issues that prevent Claude Desktop and browser-based MCP clients from connecting to Open Brain servers. The fixes are well-tested, properly scoped, and directly solve documented problems from issue #33.
What's Good
✅ Addresses real pain points — Issue #33 and the getting-started guide Step 7 have been blockers for new users. This fixes both failure modes (OPTIONS preflight + Accept header).
✅ Minimal, surgical changes — Only touches server/index.ts, which is the right scope. PR #38 fixed the 6 extensions but missed the core template that new users deploy first.
✅ Well-tested — Contributor tested on their own Supabase deployment with multiple clients (curl, Claude Code, Claude Desktop, Codex) and verified both the OPTIONS preflight handler and the Accept header patch work correctly.
✅ Follows established pattern — The Accept header fix is identical to what was merged in PR #38 for the extension edge functions. This brings the core server template into alignment.
✅ CORS headers consistent — The same corsHeaders object is applied to both the OPTIONS preflight response and the 401 auth error response, which is correct for browser-based clients.
✅ Clear documentation — PR description explains both fixes, why both are needed, and how they were tested. The code comments reference issue #33 for future maintainers.
Technical Review
CORS Preflight Handler
The new OPTIONS handler is correct:
- Returns 200 with proper
Access-Control-Allow-*headers - Includes all necessary headers for MCP protocol (
mcp-session-id,x-brain-key, etc.) - Wildcard origin is appropriate for a self-hosted MCP server
Accept Header Patch
The request rewriting logic matches PR #38 exactly:
- Checks if
Acceptheader includestext/event-stream - Creates a patched Request object with the required header when missing
- Properly handles streaming body with
duplex: "half" - Uses
Object.definePropertyto replace the raw request on the Hono context
Auth Flow
Auth check correctly happens after the Accept header patch, which is important — the transport needs the patched request before it processes the MCP handshake.
CORS headers are returned on 401 responses, which is necessary for browser clients to see the error message instead of a CORS failure.
Automated Review Criteria
Since this PR modifies existing infrastructure rather than adding a new contribution, most of the standard automated checks don't apply. Here's what does:
✅ No credentials or secrets — Clean
✅ SQL safety — No SQL changes
✅ No binary blobs — Clean
✅ PR title format — Correct: [server] prefix
✅ Scope — Changes confined to server/index.ts
Note: This PR doesn't require metadata.json or a contribution README because it's a fix to core infrastructure, not a new extension/recipe/etc.
Suggestions (Optional)
1. Consider adding a test edge function
It would be helpful to have a minimal test deployment script or curl-based smoke test that future contributors can run to verify both fixes. Could be added as server/test-cors-and-accept.sh or similar. Not blocking, but would help prevent regression.
2. Update docs/01-getting-started.md
The getting-started guide currently doesn't mention the OPTIONS preflight requirement or the Accept header issue. Consider adding a troubleshooting note in Step 7 explaining that this server template handles both, so users know what to expect if they modify the code.
Verdict: Ready to merge
This is a clean, focused fix that directly solves a documented blocker. The implementation is correct, matches the established pattern from PR #38, and has been properly tested. No changes needed before merge.
Recommendation: Merge and close issue #33.
What does this do?
Adds two fixes to the core
server/index.tsthat enable Claude Desktop (and other browser/Electron-based clients) to connect to Open Brain MCP servers:CORS preflight handler — Claude Desktop sends an OPTIONS preflight before POST. Without CORS headers, the preflight returns 405 and the connection fails silently. This adds an OPTIONS route returning proper
Access-Control-Allow-*headers.Accept header patch — Applies the same fix from PR [extensions][recipes] Fix Claude Desktop connectors + rewrite Gmail import (drop chunking) #38 to the core server template. Claude Desktop doesn't send
Accept: application/json, text/event-stream, whichStreamableHTTPTransportrequires. The patch injects the header before the transport sees the request.Why both fixes?
PR #38 applied the Accept header fix to all 6 extension Edge Functions but not to
server/index.ts. New users deploying from the getting-started guide hit this immediately. The CORS fix was not addressed in #38 or anywhere else — it's a separate failure mode where the OPTIONS preflight is rejected before the Accept header ever matters.Requirements
Testing
Tested on a personal Supabase deployment (
rumbrainproject):curlOPTIONS → 200 with CORS headers ✅curlPOST without Accept header → 200 with valid MCP response ✅curlPOST with Accept header → 200 (no regression) ✅Closes #33 (for core server template).
Checklist