Skip to content

Commit 213f25e

Browse files
committed
feat: add new exercises for token management and scopes, including problem and solution implementations
1 parent 10e2d27 commit 213f25e

File tree

114 files changed

+37915
-133
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+37915
-133
lines changed

epicshop/epic-me/workers/app.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ export default {
3838
'Access-Control-Allow-Origin': '*',
3939
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
4040
'Access-Control-Allow-Headers': 'mcp-protocol-version',
41-
'Cross-Origin-Resource-Policy': 'cross-origin',
4241
}
4342
}
4443
},

exercises/01.discovery/01.problem.cors/src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { getClient } from './client.ts'
99
import { initializePrompts } from './prompts.ts'
1010
import { initializeResources } from './resources.ts'
1111
import { initializeTools } from './tools.ts'
12+
// 💰 you'll need this:
13+
// import { withCors } from './utils.ts'
1214

1315
type State = { loggingLevel: LoggingLevel }
1416

@@ -55,6 +57,12 @@ You can also help users add tags to their entries and get all tags for an entry.
5557
}
5658

5759
export default {
60+
// 🐨 wrap the fetch handler as the "handler" option in a withCors function call
61+
// 🐨 the getCorsHeaders function should accept the request
62+
// 🐨 if the request url includes '/.well-known' then we want to return an object of headers with the following properties:
63+
// 'Access-Control-Allow-Origin': '*' // <-- we don't know all origins that may want this metadata and we're fine with any origin requesting it
64+
// 'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS' // <-- these methods are the only ones we support for this endpoint
65+
// 'Access-Control-Allow-Headers': 'mcp-protocol-version' // <-- according to the spec, all requests made by clients should include this header, some clients may or may not include it, but it's harmless to allow so we'll do that
5866
fetch: async (request, env, ctx) => {
5967
const url = new URL(request.url)
6068

exercises/01.discovery/01.solution.cors/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ export default {
6363
'Access-Control-Allow-Origin': '*',
6464
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
6565
'Access-Control-Allow-Headers': 'mcp-protocol-version',
66-
'Cross-Origin-Resource-Policy': 'cross-origin',
6766
}
6867
}
6968
},
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// 💰 you'll need this:
2+
// import { EPIC_ME_AUTH_SERVER_URL } from './client.ts'
3+
4+
// 🐨 export an async function called handleOAuthAuthorizationServerRequest
5+
// 🐨 it should construct a URL pointing to `/.well-known/oauth-authorization-server` on the auth server
6+
// 🐨 then make a fetch request to that URL
7+
// 🐨 then return the response body as a JSON object

exercises/01.discovery/02.problem.as/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
type LoggingLevel,
66
} from '@modelcontextprotocol/sdk/types.js'
77
import { McpAgent } from 'agents/mcp'
8+
// 💰 you'll need this:
9+
// import { handleOAuthAuthorizationServerRequest } from './auth.ts'
810
import { getClient } from './client.ts'
911
import { initializePrompts } from './prompts.ts'
1012
import { initializeResources } from './resources.ts'
@@ -63,13 +65,15 @@ export default {
6365
'Access-Control-Allow-Origin': '*',
6466
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
6567
'Access-Control-Allow-Headers': 'mcp-protocol-version',
66-
'Cross-Origin-Resource-Policy': 'cross-origin',
6768
}
6869
}
6970
},
7071
handler: async (request, env, ctx) => {
7172
const url = new URL(request.url)
7273

74+
// 🐨 if the url.pathname is '/.well-known/oauth-authorization-server'
75+
// then call and return the result of handleOAuthAuthorizationServerRequest
76+
7377
if (url.pathname === '/mcp') {
7478
const mcp = EpicMeMCP.serve('/mcp', {
7579
binding: 'EPIC_ME_MCP_OBJECT',

exercises/01.discovery/02.solution.as/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export default {
6464
'Access-Control-Allow-Origin': '*',
6565
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
6666
'Access-Control-Allow-Headers': 'mcp-protocol-version',
67-
'Cross-Origin-Resource-Policy': 'cross-origin',
6867
}
6968
}
7069
},

exercises/01.discovery/03.problem.pr/src/auth.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { EPIC_ME_AUTH_SERVER_URL } from './client.ts'
22

3+
// 🐨 export an async function called handleOAuthProtectedResourceRequest
4+
// 🐨 it should construct a URL pointing to `/mcp` on the current server
5+
// 💰 you can accept a request parameter and use request.url to get the URL of the current server
6+
// 🐨 then return a JSON response (💰 Response.json) with the following properties:
7+
// 🐨 resource: the URL you constructed above
8+
// 🐨 authorization_servers: an array with a single string value of the auth server URL
9+
310
/**
411
* Handles requests for OAuth authorization server metadata.
512
* Fetches the metadata from the auth server and forwards it to the client.

exercises/01.discovery/03.problem.pr/src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@ import {
55
type LoggingLevel,
66
} from '@modelcontextprotocol/sdk/types.js'
77
import { McpAgent } from 'agents/mcp'
8-
import { handleOAuthAuthorizationServerRequest } from './auth.ts'
8+
import {
9+
handleOAuthAuthorizationServerRequest,
10+
// 💰 you'll need this:
11+
// handleOAuthProtectedResourceRequest
12+
} from './auth.ts'
913
import { getClient } from './client.ts'
1014
import { initializePrompts } from './prompts.ts'
1115
import { initializeResources } from './resources.ts'
@@ -64,7 +68,6 @@ export default {
6468
'Access-Control-Allow-Origin': '*',
6569
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
6670
'Access-Control-Allow-Headers': 'mcp-protocol-version',
67-
'Cross-Origin-Resource-Policy': 'cross-origin',
6871
}
6972
}
7073
},
@@ -76,6 +79,9 @@ export default {
7679
return handleOAuthAuthorizationServerRequest()
7780
}
7881

82+
// 🐨 if the url.pathname is '/.well-known/oauth-protected-resource/mcp'
83+
// then call and return the result of handleOAuthProtectedResourceRequest
84+
7985
if (url.pathname === '/mcp') {
8086
const mcp = EpicMeMCP.serve('/mcp', {
8187
binding: 'EPIC_ME_MCP_OBJECT',

exercises/01.discovery/03.solution.pr/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ export default {
6767
'Access-Control-Allow-Origin': '*',
6868
'Access-Control-Allow-Methods': 'GET, HEAD, OPTIONS',
6969
'Access-Control-Allow-Headers': 'mcp-protocol-version',
70-
'Cross-Origin-Resource-Policy': 'cross-origin',
7170
}
7271
}
7372
},

exercises/01.discovery/README.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
# Metadata Discovery
2+
3+
NOTE: Make sure to talk about the relationship between auth server and resource server.

0 commit comments

Comments
 (0)