Skip to content

Commit a3b644c

Browse files
Update mcp server oauth integration tests (#2)
Co-authored-by: me <[email protected]> Co-authored-by: Cursor Agent <[email protected]>
1 parent 560059e commit a3b644c

File tree

8 files changed

+7894
-6449
lines changed

8 files changed

+7894
-6449
lines changed

epicshop/epic-me/app/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ export default [
66
route('/healthcheck', 'routes/healthcheck.tsx'),
77
route('/db-api', 'routes/db-api.tsx'),
88
route('/introspect', 'routes/introspect.tsx'),
9+
route('/test-auth', 'routes/test-auth.tsx'),
910
] satisfies RouteConfig
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { z } from 'zod'
2+
import { type Route } from './+types/test-auth'
3+
4+
const requestParamsSchema = z
5+
.object({
6+
response_type: z.string().default('code'),
7+
client_id: z.string(),
8+
code_challenge: z.string(),
9+
code_challenge_method: z.string(),
10+
redirect_uri: z.string(),
11+
scope: z
12+
.string()
13+
.optional()
14+
.default('')
15+
.transform((s) => (s ? s.split(' ') : [])),
16+
state: z.string().optional().default(''),
17+
user_id: z.string().optional(), // For programmatic testing
18+
})
19+
.passthrough()
20+
.transform(
21+
({
22+
response_type: responseType,
23+
client_id: clientId,
24+
code_challenge: codeChallenge,
25+
code_challenge_method: codeChallengeMethod,
26+
redirect_uri: redirectUri,
27+
user_id: userId,
28+
...val
29+
}) => ({
30+
responseType,
31+
clientId,
32+
codeChallenge,
33+
codeChallengeMethod,
34+
redirectUri,
35+
userId,
36+
...val,
37+
}),
38+
)
39+
40+
export async function loader({ request, context }: Route.LoaderArgs) {
41+
const url = new URL(request.url)
42+
43+
try {
44+
const requestParams = requestParamsSchema.parse(
45+
Object.fromEntries(url.searchParams),
46+
)
47+
48+
// Default to first user for testing if no user_id specified
49+
let userId = requestParams.userId
50+
if (!userId) {
51+
const users = await context.db.getAllUsers()
52+
if (users.length === 0) {
53+
return Response.json({ error: 'No users available' }, { status: 400 })
54+
}
55+
userId = String(users[0].id)
56+
}
57+
58+
const user = await context.db.getUserById(Number(userId))
59+
if (!user) {
60+
return Response.json({ error: 'User not found' }, { status: 404 })
61+
}
62+
63+
const { redirectTo } =
64+
await context.cloudflare.env.OAUTH_PROVIDER.completeAuthorization({
65+
request: requestParams,
66+
userId: String(user.id),
67+
metadata: {
68+
label: user.email,
69+
},
70+
scope: requestParams.scope || [],
71+
props: {
72+
userId: String(user.id),
73+
userEmail: user.email,
74+
},
75+
})
76+
77+
return Response.json({ redirectTo, userId: user.id })
78+
} catch (error) {
79+
console.error('Error in test-auth:', error)
80+
return Response.json(
81+
{
82+
error: 'Failed to complete authorization',
83+
details: error instanceof Error ? error.message : String(error),
84+
},
85+
{ status: 500 },
86+
)
87+
}
88+
}

0 commit comments

Comments
 (0)