Skip to content

[server] Add CORS preflight + Accept header fix for Claude Desktop#94

Merged
justfinethanku merged 1 commit intoNateBJones-Projects:mainfrom
rumbitopi:contrib/rumbitopi/cors-accept-header-fix
Mar 24, 2026
Merged

[server] Add CORS preflight + Accept header fix for Claude Desktop#94
justfinethanku merged 1 commit intoNateBJones-Projects:mainfrom
rumbitopi:contrib/rumbitopi/cors-accept-header-fix

Conversation

@rumbitopi
Copy link
Copy Markdown
Contributor

What does this do?

Adds two fixes to the core server/index.ts that enable Claude Desktop (and other browser/Electron-based clients) to connect to Open Brain MCP servers:

  1. 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.

  2. 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, which StreamableHTTPTransport requires. 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

  • Supabase Edge Function deployment (standard setup)
  • No new dependencies

Testing

Tested on a personal Supabase deployment (rumbrain project):

  • curl OPTIONS → 200 with CORS headers ✅
  • curl POST without Accept header → 200 with valid MCP response ✅
  • curl POST with Accept header → 200 (no regression) ✅
  • Claude Code direct HTTP → tools work ✅
  • Claude Desktop via mcp-remote → tools work ✅
  • Codex via mcp-remote → tools work ✅

Closes #33 (for core server template).

Checklist

  • I have read CONTRIBUTING.md
  • No credentials or API keys in any file
  • Tested on my own Open Brain instance

- 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>
Copy link
Copy Markdown
Collaborator

@justfinethanku justfinethanku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Accept header includes text/event-stream
  • Creates a patched Request object with the required header when missing
  • Properly handles streaming body with duplex: "half"
  • Uses Object.defineProperty to 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.

Copy link
Copy Markdown
Collaborator

@justfinethanku justfinethanku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 Accept header includes text/event-stream
  • Creates a patched Request object with the required header when missing
  • Properly handles streaming body with duplex: "half"
  • Uses Object.defineProperty to 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 justfinethanku merged commit 4c507bc into NateBJones-Projects:main Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Claude Desktop/claude.ai connector fails MCP handshake — Accept header mismatch

2 participants