|
1 | 1 | # CORS |
| 2 | + |
| 3 | +👨💼 In our MCP server's case, users will always be accessing us from either a different domain or a desktop application. This means every single request is cross-origin by nature, making CORS headers absolutely essential for our server to function at all. |
| 4 | + |
| 5 | +If we can't handle cross-origin requests properly, users will encounter frustrating errors and won't be able to access the server's capabilities from their preferred applications or domains. The problem is: how do we enable secure cross-origin communication while maintaining the security standards that protect our users and server? |
| 6 | + |
| 7 | +```ts |
| 8 | +// Example: A user trying to access our MCP server from a different domain |
| 9 | +const response = await fetch('https://our-mcp-server.com/mcp', { |
| 10 | + method: 'POST', |
| 11 | + headers: { |
| 12 | + 'Content-Type': 'application/json', |
| 13 | + 'mcp-protocol-version': '2024-11-05', |
| 14 | + }, |
| 15 | + body: JSON.stringify({ |
| 16 | + jsonrpc: '2.0', |
| 17 | + id: 1, |
| 18 | + method: 'tools/list', |
| 19 | + }), |
| 20 | +}) |
| 21 | +``` |
| 22 | + |
| 23 | +Without proper CORS headers, this request would fail with a "CORS policy" error, leaving users unable to connect to our server from their applications. This breaks the fundamental promise of MCP - seamless integration across different tools and platforms. |
| 24 | + |
| 25 | +Whether users are connecting from a web application on a different domain or from a desktop application like VS Code, CORS headers are the gateway that allows these cross-origin requests to succeed. |
| 26 | + |
| 27 | +To solve this, we need to implement CORS support that allows legitimate cross-origin requests while maintaining security. The key is to add the right headers to our responses, especially for the `/.well-known` endpoint which needs to be publicly accessible. |
| 28 | + |
| 29 | +<callout-warning class="important"> |
| 30 | + CORS is not just about adding headers - it's about enabling secure |
| 31 | + cross-origin communication while protecting against malicious requests. The |
| 32 | + `/.well-known` endpoint is particularly important as it's used for service |
| 33 | + discovery. |
| 34 | +</callout-warning> |
| 35 | + |
| 36 | +<callout-info> |
| 37 | + 🚀 The `withCors` utility function will handle the complexity of CORS headers, |
| 38 | + preflight requests, and response modification, so you can focus on the |
| 39 | + business logic. |
| 40 | +</callout-info> |
| 41 | + |
| 42 | +```mermaid |
| 43 | +sequenceDiagram |
| 44 | + Client->>MCP Server: OPTIONS request (preflight) |
| 45 | + MCP Server-->>Client: 204 with CORS headers |
| 46 | + Client->>MCP Server: Actual request |
| 47 | + MCP Server-->>Client: Response with CORS headers |
| 48 | +``` |
| 49 | + |
| 50 | +<callout-muted> |
| 51 | + 📜 For more details on CORS and how it works, see the [MDN documentation on |
| 52 | + CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). |
| 53 | +</callout-muted> |
| 54 | + |
| 55 | +The goal is to make our MCP server accessible from any legitimate client while maintaining the security and reliability that users expect. Users should be able to discover and connect to our server without worrying about origin restrictions. |
| 56 | + |
| 57 | +🧝♀️ By the way, I've prepared a `withCors` utility function in <InlineFile file="src/utils.ts" /> that will handle all the CORS complexity for you. You just need to wrap your existing handler with it and configure the appropriate headers for the `/.well-known` endpoint. |
| 58 | + |
| 59 | +Here's a simple example of how to use it: |
| 60 | + |
| 61 | +```ts |
| 62 | +// Before: Basic handler |
| 63 | +export default { |
| 64 | + fetch: async (request, env, ctx) => { |
| 65 | + // Your existing logic here |
| 66 | + return new Response('Hello World') |
| 67 | + }, |
| 68 | +} |
| 69 | + |
| 70 | +// After: Wrapped with CORS support |
| 71 | +export default { |
| 72 | + fetch: withCors({ |
| 73 | + getCorsHeaders: (request) => { |
| 74 | + // Return CORS headers based on the request |
| 75 | + // 💰 check the request.url property |
| 76 | + // Return null/undefined for no CORS headers |
| 77 | + }, |
| 78 | + handler: async (request, env, ctx) => { |
| 79 | + // Your existing logic here |
| 80 | + return new Response('Hello World') |
| 81 | + }, |
| 82 | + }), |
| 83 | +} |
| 84 | +``` |
| 85 | + |
| 86 | +👨💼 Thanks Kellie! Let's take a look at that. |
| 87 | + |
| 88 | +Now, start by understanding why CORS matters for MCP servers, implement the solution using the provided utility, and test that cross-origin requests work properly. |
0 commit comments