feat: Add CORS configuration for browser-based MCP clients (#1059)
Some checks failed
Main branch checks / checks (push) Has been cancelled
Some checks failed
Main branch checks / checks (push) Has been cancelled
Co-authored-by: Marcelo Trylesinski <marcelotryle@gmail.com> Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
This commit is contained in:
parent
ff02c596a4
commit
09e3a05e13
3 changed files with 46 additions and 0 deletions
26
README.md
26
README.md
|
|
@ -1165,6 +1165,32 @@ The streamable HTTP transport supports:
|
|||
- JSON or SSE response formats
|
||||
- Better scalability for multi-node deployments
|
||||
|
||||
#### CORS Configuration for Browser-Based Clients
|
||||
|
||||
If you'd like your server to be accessible by browser-based MCP clients, you'll need to configure CORS headers. The `Mcp-Session-Id` header must be exposed for browser clients to access it:
|
||||
|
||||
```python
|
||||
from starlette.applications import Starlette
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
|
||||
# Create your Starlette app first
|
||||
starlette_app = Starlette(routes=[...])
|
||||
|
||||
# Then wrap it with CORS middleware
|
||||
starlette_app = CORSMiddleware(
|
||||
starlette_app,
|
||||
allow_origins=["*"], # Configure appropriately for production
|
||||
allow_methods=["GET", "POST", "DELETE"], # MCP streamable HTTP methods
|
||||
expose_headers=["Mcp-Session-Id"],
|
||||
)
|
||||
```
|
||||
|
||||
This configuration is necessary because:
|
||||
|
||||
- The MCP streamable HTTP transport uses the `Mcp-Session-Id` header for session management
|
||||
- Browsers restrict access to response headers unless explicitly exposed via CORS
|
||||
- Without this configuration, browser-based clients won't be able to read the session ID from initialization responses
|
||||
|
||||
### Mounting to an Existing ASGI Server
|
||||
|
||||
By default, SSE servers are mounted at `/sse` and Streamable HTTP servers are mounted at `/mcp`. You can customize these paths using the methods described below.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import mcp.types as types
|
|||
from mcp.server.lowlevel import Server
|
||||
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
||||
from starlette.applications import Starlette
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from starlette.routing import Mount
|
||||
from starlette.types import Receive, Scope, Send
|
||||
|
||||
|
|
@ -123,6 +124,15 @@ def main(
|
|||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# Wrap ASGI application with CORS middleware to expose Mcp-Session-Id header
|
||||
# for browser-based clients (ensures 500 errors get proper CORS headers)
|
||||
starlette_app = CORSMiddleware(
|
||||
starlette_app,
|
||||
allow_origins=["*"], # Allow all origins - adjust as needed for production
|
||||
allow_methods=["GET", "POST", "DELETE"], # MCP streamable HTTP methods
|
||||
expose_headers=["Mcp-Session-Id"],
|
||||
)
|
||||
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(starlette_app, host="127.0.0.1", port=port)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from mcp.server.lowlevel import Server
|
|||
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
|
||||
from pydantic import AnyUrl
|
||||
from starlette.applications import Starlette
|
||||
from starlette.middleware.cors import CORSMiddleware
|
||||
from starlette.routing import Mount
|
||||
from starlette.types import Receive, Scope, Send
|
||||
|
||||
|
|
@ -148,6 +149,15 @@ def main(
|
|||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# Wrap ASGI application with CORS middleware to expose Mcp-Session-Id header
|
||||
# for browser-based clients (ensures 500 errors get proper CORS headers)
|
||||
starlette_app = CORSMiddleware(
|
||||
starlette_app,
|
||||
allow_origins=["*"], # Allow all origins - adjust as needed for production
|
||||
allow_methods=["GET", "POST", "DELETE"], # MCP streamable HTTP methods
|
||||
expose_headers=["Mcp-Session-Id"],
|
||||
)
|
||||
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(starlette_app, host="127.0.0.1", port=port)
|
||||
|
|
|
|||
Loading…
Reference in a new issue