Skip to content

Commit d09f5e6

Browse files
committed
docs: enhance CORS and authentication server metadata documentation with detailed explanations and examples
1 parent 096320e commit d09f5e6

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,88 @@
11
# 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.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
# CORS
2+
3+
👨‍💼 Excellent work! We've successfully solved a critical problem for our MCP server users: now they can connect to our server from any domain without encountering frustrating CORS policy errors.
4+
5+
This improvement means users get seamless access to our MCP server's capabilities regardless of where they're connecting from. Whether they're using VS Code, a web application, or any other MCP client, the connection just works. This is exactly what users expect from a modern, accessible MCP server.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,56 @@
11
# Auth Server Metadata
2+
3+
👨‍💼 Now that users can connect to our MCP server from any domain, they need to be able to discover how to authenticate with our system. When users want to access protected resources or perform actions that require authentication, they need to know where to go and what methods are available.
4+
5+
The problem is: how do we provide users with the information they need to authenticate with our OAuth server? Without this metadata, users' clients will be stuck because they can't figure out authentication endpoints and supported features.
6+
7+
```ts
8+
// Example: A user trying to discover our OAuth server capabilities
9+
const response = await fetch(
10+
'https://our-mcp-server.com/.well-known/oauth-authorization-server',
11+
)
12+
const metadata = await response.json()
13+
// metadata includes things like:
14+
// - registration_endpoint - how to register a new client for dynamic client registration
15+
// - authorization_endpoint - where to send users to confirm the connection
16+
// - token_endpoint - where to request a token once they have a auth code
17+
// plus more things necessary for the client to set up the connection for the user
18+
```
19+
20+
This metadata endpoint is the gateway that tells users everything they need to know about our authentication system.
21+
22+
To do this, we need to implement the `/.well-known/oauth-authorization-server` endpoint that returns the OAuth server's metadata. This endpoint will fetch the metadata from our actual OAuth server and relay it to users, making our MCP server a complete authentication discovery hub.
23+
24+
<callout-warning class="important">
25+
The OAuth metadata endpoint is a standard that clients expect to find. Without
26+
it, clients won't be able to properly integrate authentication into their
27+
applications.
28+
</callout-warning>
29+
30+
<callout-info>
31+
🔍 Doing this from our resource server is useful because some clients do not
32+
distinguish between the resource server and the auth server and will treat our
33+
resource server as the auth server. So we simply proxy to the auth server to
34+
get the metadata.
35+
</callout-info>
36+
37+
```mermaid
38+
sequenceDiagram
39+
Client->>MCP Server: GET /.well-known/oauth-authorization-server
40+
MCP Server->>OAuth Server: Fetch metadata from localhost:7788
41+
OAuth Server-->>MCP Server: Returns OAuth metadata
42+
MCP Server-->>Client: Returns metadata with CORS headers
43+
```
44+
45+
<callout-muted>
46+
📜 For more details on OAuth authorization server metadata, see the [RFC 8414
47+
specification](https://tools.ietf.org/html/rfc8414).
48+
</callout-muted>
49+
50+
The goal is to make authentication discovery seamless and standards-compliant, so users can easily integrate our OAuth system into their applications without any guesswork.
51+
52+
🧝‍♀️ By the way, I've set up the OAuth server to run on localhost:7788, and you'll need to create a new `auth.ts` file to handle the metadata request. The endpoint should fetch from `http://localhost:7788/.well-known/oauth-authorization-server` and return the response.
53+
54+
👨‍💼 Thanks Kellie!
55+
56+
Now, please implement the metadata endpoint.

0 commit comments

Comments
 (0)