mcp-use 1.6.3-canary.0 → 1.7.0-canary.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/chunk-JQKKMUCT.js +0 -0
  3. package/dist/chunk-PE7UMCVO.js +377 -0
  4. package/dist/{chunk-BWOTID2D.js → chunk-QSLJXXMG.js} +3 -346
  5. package/dist/chunk-R5DJJ4IV.js +942 -0
  6. package/dist/{chunk-SJEHVCPM.js → chunk-XN2PU4PS.js} +100 -23
  7. package/dist/index.cjs +132 -29
  8. package/dist/index.js +8 -5
  9. package/dist/oauth-CNGBFOZW.js +29 -0
  10. package/dist/src/agents/index.js +1 -1
  11. package/dist/src/auth/browser-provider.d.ts +2 -0
  12. package/dist/src/auth/browser-provider.d.ts.map +1 -1
  13. package/dist/src/auth/callback.d.ts.map +1 -1
  14. package/dist/src/auth/index.cjs +396 -0
  15. package/dist/src/auth/index.js +10 -0
  16. package/dist/src/auth/types.d.ts +3 -1
  17. package/dist/src/auth/types.d.ts.map +1 -1
  18. package/dist/src/browser.cjs +36 -8
  19. package/dist/src/browser.js +6 -4
  20. package/dist/src/connectors/http.d.ts.map +1 -1
  21. package/dist/src/react/index.cjs +132 -29
  22. package/dist/src/react/index.js +3 -2
  23. package/dist/src/react/types.d.ts +12 -1
  24. package/dist/src/react/types.d.ts.map +1 -1
  25. package/dist/src/react/useMcp.d.ts.map +1 -1
  26. package/dist/src/server/context-storage.d.ts +54 -0
  27. package/dist/src/server/context-storage.d.ts.map +1 -0
  28. package/dist/src/server/index.cjs +1409 -410
  29. package/dist/src/server/index.d.ts +4 -1
  30. package/dist/src/server/index.d.ts.map +1 -1
  31. package/dist/src/server/index.js +420 -412
  32. package/dist/src/server/mcp-server.d.ts +50 -81
  33. package/dist/src/server/mcp-server.d.ts.map +1 -1
  34. package/dist/src/server/oauth/index.d.ts +13 -0
  35. package/dist/src/server/oauth/index.d.ts.map +1 -0
  36. package/dist/src/server/oauth/middleware.d.ts +19 -0
  37. package/dist/src/server/oauth/middleware.d.ts.map +1 -0
  38. package/dist/src/server/oauth/providers/auth0.d.ts +22 -0
  39. package/dist/src/server/oauth/providers/auth0.d.ts.map +1 -0
  40. package/dist/src/server/oauth/providers/custom.d.ts +19 -0
  41. package/dist/src/server/oauth/providers/custom.d.ts.map +1 -0
  42. package/dist/src/server/oauth/providers/keycloak.d.ts +22 -0
  43. package/dist/src/server/oauth/providers/keycloak.d.ts.map +1 -0
  44. package/dist/src/server/oauth/providers/supabase.d.ts +24 -0
  45. package/dist/src/server/oauth/providers/supabase.d.ts.map +1 -0
  46. package/dist/src/server/oauth/providers/types.d.ts +138 -0
  47. package/dist/src/server/oauth/providers/types.d.ts.map +1 -0
  48. package/dist/src/server/oauth/providers/workos.d.ts +30 -0
  49. package/dist/src/server/oauth/providers/workos.d.ts.map +1 -0
  50. package/dist/src/server/oauth/providers.d.ts +208 -0
  51. package/dist/src/server/oauth/providers.d.ts.map +1 -0
  52. package/dist/src/server/oauth/routes.d.ts +33 -0
  53. package/dist/src/server/oauth/routes.d.ts.map +1 -0
  54. package/dist/src/server/oauth/utils.d.ts +155 -0
  55. package/dist/src/server/oauth/utils.d.ts.map +1 -0
  56. package/dist/src/server/types/common.d.ts +47 -0
  57. package/dist/src/server/types/common.d.ts.map +1 -1
  58. package/dist/src/server/types/context.d.ts +34 -0
  59. package/dist/src/server/types/context.d.ts.map +1 -0
  60. package/dist/src/server/types/index.d.ts +2 -1
  61. package/dist/src/server/types/index.d.ts.map +1 -1
  62. package/dist/src/server/types/tool.d.ts +82 -9
  63. package/dist/src/server/types/tool.d.ts.map +1 -1
  64. package/dist/src/server/utils/index.d.ts +6 -0
  65. package/dist/src/server/utils/index.d.ts.map +1 -0
  66. package/dist/src/server/utils/response-helpers.d.ts +151 -0
  67. package/dist/src/server/utils/response-helpers.d.ts.map +1 -0
  68. package/dist/src/server/utils/runtime.d.ts +25 -0
  69. package/dist/src/server/utils/runtime.d.ts.map +1 -0
  70. package/dist/src/task_managers/streamable_http.d.ts +1 -0
  71. package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
  72. package/dist/tsup.config.d.ts.map +1 -1
  73. package/package.json +14 -5
  74. /package/dist/{chunk-MCF5P6GJ.js → chunk-GVVPUU5K.js} +0 -0
@@ -0,0 +1,942 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-3GQAWCBQ.js";
4
+
5
+ // src/server/oauth/providers/supabase.ts
6
+ import {
7
+ jwtVerify,
8
+ createRemoteJWKSet,
9
+ decodeProtectedHeader,
10
+ decodeJwt
11
+ } from "jose";
12
+ var SupabaseOAuthProvider = class {
13
+ static {
14
+ __name(this, "SupabaseOAuthProvider");
15
+ }
16
+ config;
17
+ supabaseUrl;
18
+ supabaseAuthUrl;
19
+ issuer;
20
+ jwks = null;
21
+ constructor(config) {
22
+ this.config = config;
23
+ this.supabaseUrl = `https://${config.projectId}.supabase.co`;
24
+ this.supabaseAuthUrl = `${this.supabaseUrl}/auth/v1`;
25
+ this.issuer = `${this.supabaseUrl}/auth/v1`;
26
+ }
27
+ getJWKS() {
28
+ if (!this.jwks) {
29
+ this.jwks = createRemoteJWKSet(
30
+ new URL(`${this.issuer}/.well-known/jwks.json`)
31
+ );
32
+ }
33
+ return this.jwks;
34
+ }
35
+ async verifyToken(token) {
36
+ if (this.config.skipVerification) {
37
+ console.warn(
38
+ "[Supabase OAuth] \u26A0\uFE0F SKIPPING VERIFICATION (DEVELOPMENT MODE)"
39
+ );
40
+ console.warn(
41
+ "[Supabase OAuth] This is NOT secure! Only use for testing!"
42
+ );
43
+ const payload = decodeJwt(token);
44
+ return { payload, protectedHeader: decodeProtectedHeader(token) };
45
+ }
46
+ try {
47
+ const header = decodeProtectedHeader(token);
48
+ if (header.alg === "HS256") {
49
+ if (!this.config.jwtSecret) {
50
+ throw new Error(
51
+ "JWT Secret is required for HS256 tokens. Get it from: Supabase Dashboard \u2192 Project Settings \u2192 API \u2192 JWT Settings"
52
+ );
53
+ }
54
+ const secret = new TextEncoder().encode(this.config.jwtSecret);
55
+ const result = await jwtVerify(token, secret, {
56
+ issuer: this.issuer,
57
+ audience: "authenticated"
58
+ });
59
+ return result;
60
+ } else if (header.alg === "ES256") {
61
+ const result = await jwtVerify(token, this.getJWKS(), {
62
+ issuer: this.issuer,
63
+ audience: "authenticated"
64
+ });
65
+ return result;
66
+ } else {
67
+ throw new Error(`Unsupported algorithm: ${header.alg}`);
68
+ }
69
+ } catch (error) {
70
+ throw new Error(`Supabase JWT verification failed: ${error}`);
71
+ }
72
+ }
73
+ getUserInfo(payload) {
74
+ return {
75
+ userId: payload.sub || payload.user_id,
76
+ email: payload.email,
77
+ name: payload.user_metadata?.name || payload.user_metadata?.full_name,
78
+ username: payload.user_metadata?.username,
79
+ picture: payload.user_metadata?.avatar_url,
80
+ roles: payload.role ? [payload.role] : [],
81
+ permissions: payload.aal ? [`aal:${payload.aal}`] : [],
82
+ // Include Supabase-specific claims
83
+ aal: payload.aal,
84
+ // Authentication Assurance Level
85
+ amr: payload.amr,
86
+ // Authentication Methods References
87
+ session_id: payload.session_id
88
+ };
89
+ }
90
+ getIssuer() {
91
+ return this.issuer;
92
+ }
93
+ getAuthEndpoint() {
94
+ return `${this.supabaseAuthUrl}/authorize`;
95
+ }
96
+ getTokenEndpoint() {
97
+ return `${this.supabaseAuthUrl}/token`;
98
+ }
99
+ getScopesSupported() {
100
+ return [];
101
+ }
102
+ getGrantTypesSupported() {
103
+ return ["authorization_code", "refresh_token"];
104
+ }
105
+ };
106
+
107
+ // src/server/oauth/providers/auth0.ts
108
+ import { jwtVerify as jwtVerify2, createRemoteJWKSet as createRemoteJWKSet2 } from "jose";
109
+ var Auth0OAuthProvider = class {
110
+ static {
111
+ __name(this, "Auth0OAuthProvider");
112
+ }
113
+ config;
114
+ issuer;
115
+ jwks = null;
116
+ constructor(config) {
117
+ this.config = config;
118
+ this.issuer = `https://${config.domain}`;
119
+ }
120
+ getJWKS() {
121
+ if (!this.jwks) {
122
+ this.jwks = createRemoteJWKSet2(
123
+ new URL(`${this.issuer}/.well-known/jwks.json`)
124
+ );
125
+ }
126
+ return this.jwks;
127
+ }
128
+ async verifyToken(token) {
129
+ if (this.config.verifyJwt === false) {
130
+ console.warn("[Auth0 OAuth] \u26A0\uFE0F JWT verification is disabled");
131
+ console.warn("[Auth0 OAuth] Enable verifyJwt: true for production");
132
+ const parts = token.split(".");
133
+ if (parts.length !== 3) {
134
+ throw new Error("Invalid JWT format");
135
+ }
136
+ const payload = JSON.parse(
137
+ Buffer.from(parts[1], "base64url").toString("utf8")
138
+ );
139
+ return { payload };
140
+ }
141
+ try {
142
+ const result = await jwtVerify2(token, this.getJWKS(), {
143
+ issuer: this.issuer,
144
+ audience: this.config.audience
145
+ });
146
+ return result;
147
+ } catch (error) {
148
+ throw new Error(`Auth0 JWT verification failed: ${error}`);
149
+ }
150
+ }
151
+ getUserInfo(payload) {
152
+ return {
153
+ userId: payload.sub,
154
+ email: payload.email,
155
+ name: payload.name,
156
+ username: payload.username,
157
+ nickname: payload.nickname,
158
+ picture: payload.picture,
159
+ // Auth0 includes permissions directly in the token
160
+ permissions: payload.permissions || [],
161
+ // Auth0 can include roles (if configured)
162
+ roles: payload.roles || payload["https://your-app.com/roles"] || [],
163
+ // Include scope as well
164
+ scopes: payload.scope ? payload.scope.split(" ") : [],
165
+ // Additional Auth0-specific claims
166
+ email_verified: payload.email_verified,
167
+ updated_at: payload.updated_at
168
+ };
169
+ }
170
+ getIssuer() {
171
+ return this.issuer;
172
+ }
173
+ getAuthEndpoint() {
174
+ return `${this.issuer}/authorize`;
175
+ }
176
+ getTokenEndpoint() {
177
+ return `${this.issuer}/oauth/token`;
178
+ }
179
+ getScopesSupported() {
180
+ return ["openid", "profile", "email", "offline_access"];
181
+ }
182
+ getGrantTypesSupported() {
183
+ return ["authorization_code", "refresh_token"];
184
+ }
185
+ };
186
+
187
+ // src/server/oauth/providers/keycloak.ts
188
+ import { jwtVerify as jwtVerify3, createRemoteJWKSet as createRemoteJWKSet3 } from "jose";
189
+ var KeycloakOAuthProvider = class {
190
+ static {
191
+ __name(this, "KeycloakOAuthProvider");
192
+ }
193
+ config;
194
+ issuer;
195
+ jwks = null;
196
+ constructor(config) {
197
+ this.config = config;
198
+ const serverUrl = config.serverUrl.replace(/\/$/, "");
199
+ this.issuer = `${serverUrl}/realms/${config.realm}`;
200
+ }
201
+ getJWKS() {
202
+ if (!this.jwks) {
203
+ this.jwks = createRemoteJWKSet3(
204
+ new URL(`${this.issuer}/protocol/openid-connect/certs`)
205
+ );
206
+ }
207
+ return this.jwks;
208
+ }
209
+ async verifyToken(token) {
210
+ if (this.config.verifyJwt === false) {
211
+ console.warn("[Keycloak OAuth] \u26A0\uFE0F JWT verification is disabled");
212
+ console.warn(
213
+ "[Keycloak OAuth] Enable verifyJwt: true for production"
214
+ );
215
+ const parts = token.split(".");
216
+ if (parts.length !== 3) {
217
+ throw new Error("Invalid JWT format");
218
+ }
219
+ const payload = JSON.parse(
220
+ Buffer.from(parts[1], "base64url").toString("utf8")
221
+ );
222
+ return { payload };
223
+ }
224
+ try {
225
+ const result = await jwtVerify3(token, this.getJWKS(), {
226
+ issuer: this.issuer,
227
+ // Don't verify audience if not specified
228
+ ...this.config.clientId && { audience: this.config.clientId }
229
+ });
230
+ return result;
231
+ } catch (error) {
232
+ throw new Error(`Keycloak JWT verification failed: ${error}`);
233
+ }
234
+ }
235
+ getUserInfo(payload) {
236
+ const realmRoles = payload.realm_access?.roles || [];
237
+ const clientRoles = this.config.clientId && payload.resource_access?.[this.config.clientId]?.roles || [];
238
+ const allRoles = [...realmRoles, ...clientRoles];
239
+ const permissions = [];
240
+ if (payload.resource_access) {
241
+ Object.entries(payload.resource_access).forEach(
242
+ ([resource, access]) => {
243
+ if (access.roles) {
244
+ access.roles.forEach((role) => {
245
+ permissions.push(`${resource}:${role}`);
246
+ });
247
+ }
248
+ }
249
+ );
250
+ }
251
+ return {
252
+ userId: payload.sub,
253
+ email: payload.email,
254
+ name: payload.name,
255
+ username: payload.preferred_username,
256
+ nickname: payload.preferred_username,
257
+ picture: payload.picture,
258
+ roles: allRoles,
259
+ permissions,
260
+ // Include scope as well
261
+ scopes: payload.scope ? payload.scope.split(" ") : [],
262
+ // Keycloak-specific claims
263
+ email_verified: payload.email_verified,
264
+ given_name: payload.given_name,
265
+ family_name: payload.family_name,
266
+ realm_access: payload.realm_access,
267
+ resource_access: payload.resource_access
268
+ };
269
+ }
270
+ getIssuer() {
271
+ return this.issuer;
272
+ }
273
+ getAuthEndpoint() {
274
+ return `${this.issuer}/protocol/openid-connect/auth`;
275
+ }
276
+ getTokenEndpoint() {
277
+ return `${this.issuer}/protocol/openid-connect/token`;
278
+ }
279
+ getScopesSupported() {
280
+ return ["openid", "profile", "email", "offline_access", "roles"];
281
+ }
282
+ getGrantTypesSupported() {
283
+ return ["authorization_code", "refresh_token", "client_credentials"];
284
+ }
285
+ };
286
+
287
+ // src/server/oauth/providers/workos.ts
288
+ import { jwtVerify as jwtVerify4, createRemoteJWKSet as createRemoteJWKSet4, decodeJwt as decodeJwt2 } from "jose";
289
+ var WorkOSOAuthProvider = class {
290
+ static {
291
+ __name(this, "WorkOSOAuthProvider");
292
+ }
293
+ config;
294
+ issuer;
295
+ jwks = null;
296
+ constructor(config) {
297
+ this.config = config;
298
+ this.issuer = `https://${config.subdomain}.authkit.app`;
299
+ }
300
+ getJWKS() {
301
+ if (!this.jwks) {
302
+ this.jwks = createRemoteJWKSet4(new URL(`${this.issuer}/oauth2/jwks`));
303
+ }
304
+ return this.jwks;
305
+ }
306
+ async verifyToken(token) {
307
+ if (this.config.verifyJwt === false) {
308
+ console.warn("[WorkOS OAuth] \u26A0\uFE0F JWT verification is disabled");
309
+ console.warn("[WorkOS OAuth] Enable verifyJwt: true for production");
310
+ const parts = token.split(".");
311
+ if (parts.length !== 3) {
312
+ throw new Error("Invalid JWT format");
313
+ }
314
+ const payload = decodeJwt2(token);
315
+ return { payload };
316
+ }
317
+ try {
318
+ const result = await jwtVerify4(token, this.getJWKS(), {
319
+ issuer: this.issuer
320
+ });
321
+ return result;
322
+ } catch (error) {
323
+ throw new Error(`WorkOS JWT verification failed: ${error}`);
324
+ }
325
+ }
326
+ getUserInfo(payload) {
327
+ return {
328
+ userId: payload.sub,
329
+ email: payload.email,
330
+ name: payload.name,
331
+ username: payload.preferred_username,
332
+ picture: payload.picture,
333
+ // WorkOS includes permissions and roles in token
334
+ permissions: payload.permissions || [],
335
+ roles: payload.roles || [],
336
+ // Include scope as well
337
+ scopes: payload.scope ? payload.scope.split(" ") : [],
338
+ // Additional WorkOS-specific claims
339
+ email_verified: payload.email_verified,
340
+ organization_id: payload.org_id,
341
+ sid: payload.sid
342
+ // Session ID
343
+ };
344
+ }
345
+ getIssuer() {
346
+ return this.issuer;
347
+ }
348
+ getAuthEndpoint() {
349
+ return `${this.issuer}/oauth2/authorize`;
350
+ }
351
+ getTokenEndpoint() {
352
+ return `${this.issuer}/oauth2/token`;
353
+ }
354
+ getScopesSupported() {
355
+ return ["email", "offline_access", "openid", "profile"];
356
+ }
357
+ getGrantTypesSupported() {
358
+ return ["authorization_code", "refresh_token"];
359
+ }
360
+ getMode() {
361
+ if (this.config.clientId) {
362
+ console.log("[WorkOS OAuth] Using proxy mode (pre-registered client)");
363
+ return "proxy";
364
+ }
365
+ console.log(
366
+ "[WorkOS OAuth] Using direct mode (Dynamic Client Registration)"
367
+ );
368
+ return "direct";
369
+ }
370
+ getRegistrationEndpoint() {
371
+ if (this.config.clientId) {
372
+ return void 0;
373
+ }
374
+ return `${this.issuer}/oauth2/register`;
375
+ }
376
+ };
377
+
378
+ // src/server/oauth/providers/custom.ts
379
+ var CustomOAuthProvider = class {
380
+ static {
381
+ __name(this, "CustomOAuthProvider");
382
+ }
383
+ config;
384
+ constructor(config) {
385
+ this.config = config;
386
+ }
387
+ async verifyToken(token) {
388
+ try {
389
+ const result = await this.config.verifyToken(token);
390
+ return { payload: result };
391
+ } catch (error) {
392
+ throw new Error(`Custom OAuth verification failed: ${error}`);
393
+ }
394
+ }
395
+ getUserInfo(payload) {
396
+ if (this.config.getUserInfo) {
397
+ return this.config.getUserInfo(payload);
398
+ }
399
+ return {
400
+ userId: payload.sub || payload.user_id || payload.id,
401
+ email: payload.email,
402
+ name: payload.name,
403
+ username: payload.username || payload.preferred_username,
404
+ nickname: payload.nickname,
405
+ picture: payload.picture || payload.avatar_url,
406
+ roles: payload.roles || [],
407
+ permissions: payload.permissions || [],
408
+ scopes: payload.scope ? payload.scope.split(" ") : []
409
+ };
410
+ }
411
+ getIssuer() {
412
+ return this.config.issuer;
413
+ }
414
+ getAuthEndpoint() {
415
+ return this.config.authEndpoint;
416
+ }
417
+ getTokenEndpoint() {
418
+ return this.config.tokenEndpoint;
419
+ }
420
+ getScopesSupported() {
421
+ return this.config.scopesSupported || ["openid", "profile", "email"];
422
+ }
423
+ getGrantTypesSupported() {
424
+ return this.config.grantTypesSupported || ["authorization_code", "refresh_token"];
425
+ }
426
+ };
427
+
428
+ // src/server/utils/runtime.ts
429
+ var isDeno = typeof globalThis.Deno !== "undefined";
430
+ function getEnv(key) {
431
+ if (isDeno) {
432
+ return globalThis.Deno.env.get(key);
433
+ }
434
+ return process.env[key];
435
+ }
436
+ __name(getEnv, "getEnv");
437
+ function getCwd() {
438
+ if (isDeno) {
439
+ return globalThis.Deno.cwd();
440
+ }
441
+ return process.cwd();
442
+ }
443
+ __name(getCwd, "getCwd");
444
+ var fsHelpers = {
445
+ async readFileSync(path, encoding = "utf8") {
446
+ if (isDeno) {
447
+ return await globalThis.Deno.readTextFile(path);
448
+ }
449
+ const { readFileSync } = await import("fs");
450
+ const result = readFileSync(path, encoding);
451
+ return typeof result === "string" ? result : result.toString(encoding);
452
+ },
453
+ async readFile(path) {
454
+ if (isDeno) {
455
+ const data = await globalThis.Deno.readFile(path);
456
+ return data.buffer;
457
+ }
458
+ const { readFileSync } = await import("fs");
459
+ const buffer = readFileSync(path);
460
+ return buffer.buffer.slice(
461
+ buffer.byteOffset,
462
+ buffer.byteOffset + buffer.byteLength
463
+ );
464
+ },
465
+ async existsSync(path) {
466
+ if (isDeno) {
467
+ try {
468
+ await globalThis.Deno.stat(path);
469
+ return true;
470
+ } catch {
471
+ return false;
472
+ }
473
+ }
474
+ const { existsSync } = await import("fs");
475
+ return existsSync(path);
476
+ },
477
+ async readdirSync(path) {
478
+ if (isDeno) {
479
+ const entries = [];
480
+ for await (const entry of globalThis.Deno.readDir(path)) {
481
+ entries.push(entry.name);
482
+ }
483
+ return entries;
484
+ }
485
+ const { readdirSync } = await import("fs");
486
+ return readdirSync(path);
487
+ }
488
+ };
489
+ var pathHelpers = {
490
+ join(...paths) {
491
+ if (isDeno) {
492
+ return paths.join("/").replace(/\/+/g, "/");
493
+ }
494
+ return paths.join("/").replace(/\/+/g, "/");
495
+ },
496
+ relative(from, to) {
497
+ const fromParts = from.split("/").filter((p) => p);
498
+ const toParts = to.split("/").filter((p) => p);
499
+ let i = 0;
500
+ while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
501
+ i++;
502
+ }
503
+ const upCount = fromParts.length - i;
504
+ const relativeParts = [...Array(upCount).fill(".."), ...toParts.slice(i)];
505
+ return relativeParts.join("/");
506
+ }
507
+ };
508
+ function generateUUID() {
509
+ return globalThis.crypto.randomUUID();
510
+ }
511
+ __name(generateUUID, "generateUUID");
512
+
513
+ // src/server/oauth/providers.ts
514
+ function oauthSupabaseProvider(config = {}) {
515
+ const projectId = config.projectId ?? getEnv("MCP_USE_OAUTH_SUPABASE_PROJECT_ID");
516
+ const jwtSecret = config.jwtSecret ?? getEnv("MCP_USE_OAUTH_SUPABASE_JWT_SECRET");
517
+ if (!projectId) {
518
+ throw new Error(
519
+ "Supabase projectId is required. Set MCP_USE_OAUTH_SUPABASE_PROJECT_ID environment variable or pass projectId in config."
520
+ );
521
+ }
522
+ return new SupabaseOAuthProvider({
523
+ provider: "supabase",
524
+ projectId,
525
+ jwtSecret,
526
+ skipVerification: config.skipVerification
527
+ });
528
+ }
529
+ __name(oauthSupabaseProvider, "oauthSupabaseProvider");
530
+ function oauthAuth0Provider(config = {}) {
531
+ const domain = config.domain ?? getEnv("MCP_USE_OAUTH_AUTH0_DOMAIN");
532
+ const audience = config.audience ?? getEnv("MCP_USE_OAUTH_AUTH0_AUDIENCE");
533
+ if (!domain) {
534
+ throw new Error(
535
+ "Auth0 domain is required. Set MCP_USE_OAUTH_AUTH0_DOMAIN environment variable or pass domain in config."
536
+ );
537
+ }
538
+ if (!audience) {
539
+ throw new Error(
540
+ "Auth0 audience is required. Set MCP_USE_OAUTH_AUTH0_AUDIENCE environment variable or pass audience in config."
541
+ );
542
+ }
543
+ return new Auth0OAuthProvider({
544
+ provider: "auth0",
545
+ domain,
546
+ audience,
547
+ verifyJwt: config.verifyJwt
548
+ });
549
+ }
550
+ __name(oauthAuth0Provider, "oauthAuth0Provider");
551
+ function oauthKeycloakProvider(config = {}) {
552
+ const serverUrl = config.serverUrl ?? getEnv("MCP_USE_OAUTH_KEYCLOAK_SERVER_URL");
553
+ const realm = config.realm ?? getEnv("MCP_USE_OAUTH_KEYCLOAK_REALM");
554
+ const clientId = config.clientId ?? getEnv("MCP_USE_OAUTH_KEYCLOAK_CLIENT_ID");
555
+ if (!serverUrl) {
556
+ throw new Error(
557
+ "Keycloak serverUrl is required. Set MCP_USE_OAUTH_KEYCLOAK_SERVER_URL environment variable or pass serverUrl in config."
558
+ );
559
+ }
560
+ if (!realm) {
561
+ throw new Error(
562
+ "Keycloak realm is required. Set MCP_USE_OAUTH_KEYCLOAK_REALM environment variable or pass realm in config."
563
+ );
564
+ }
565
+ return new KeycloakOAuthProvider({
566
+ provider: "keycloak",
567
+ serverUrl,
568
+ realm,
569
+ clientId,
570
+ verifyJwt: config.verifyJwt
571
+ });
572
+ }
573
+ __name(oauthKeycloakProvider, "oauthKeycloakProvider");
574
+ function oauthWorkOSProvider(config = {}) {
575
+ const subdomain = config.subdomain ?? getEnv("MCP_USE_OAUTH_WORKOS_SUBDOMAIN");
576
+ const clientId = config.clientId ?? getEnv("MCP_USE_OAUTH_WORKOS_CLIENT_ID");
577
+ const apiKey = config.apiKey ?? getEnv("MCP_USE_OAUTH_WORKOS_API_KEY");
578
+ if (!subdomain) {
579
+ throw new Error(
580
+ "WorkOS subdomain is required. Set MCP_USE_OAUTH_WORKOS_SUBDOMAIN environment variable or pass subdomain in config."
581
+ );
582
+ }
583
+ if (clientId) {
584
+ console.log("[WorkOS OAuth] Using pre-registered OAuth client mode");
585
+ console.log(`[WorkOS OAuth] - Client ID: ${clientId}`);
586
+ console.log(
587
+ "[WorkOS OAuth] - Make sure this client exists in WorkOS Dashboard"
588
+ );
589
+ console.log(
590
+ "[WorkOS OAuth] - Configure redirect URIs to match your MCP client"
591
+ );
592
+ } else {
593
+ console.log("[WorkOS OAuth] Using Dynamic Client Registration (DCR) mode");
594
+ console.log(
595
+ "[WorkOS OAuth] - MCP clients will register themselves automatically"
596
+ );
597
+ console.log(
598
+ "[WorkOS OAuth] - Make sure DCR is enabled in WorkOS Dashboard"
599
+ );
600
+ }
601
+ return new WorkOSOAuthProvider({
602
+ provider: "workos",
603
+ subdomain,
604
+ clientId,
605
+ apiKey,
606
+ verifyJwt: config.verifyJwt
607
+ });
608
+ }
609
+ __name(oauthWorkOSProvider, "oauthWorkOSProvider");
610
+ function oauthCustomProvider(config) {
611
+ return new CustomOAuthProvider({
612
+ provider: "custom",
613
+ ...config
614
+ });
615
+ }
616
+ __name(oauthCustomProvider, "oauthCustomProvider");
617
+
618
+ // src/server/oauth/middleware.ts
619
+ function createBearerAuthMiddleware(provider, baseUrl) {
620
+ return async (c, next) => {
621
+ const authHeader = c.req.header("Authorization");
622
+ const getWWWAuthenticateHeader = /* @__PURE__ */ __name(() => {
623
+ const base = baseUrl || new URL(c.req.url).origin;
624
+ const parts = [
625
+ 'Bearer error="unauthorized"',
626
+ 'error_description="Authorization needed"'
627
+ ];
628
+ parts.push(
629
+ `resource_metadata="${base}/.well-known/oauth-protected-resource"`
630
+ );
631
+ return parts.join(", ");
632
+ }, "getWWWAuthenticateHeader");
633
+ if (!authHeader) {
634
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
635
+ return c.json({ error: "Missing Authorization header" }, 401);
636
+ }
637
+ const [type, token] = authHeader.split(" ");
638
+ if (type.toLowerCase() !== "bearer" || !token) {
639
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
640
+ return c.json(
641
+ {
642
+ error: 'Invalid Authorization header format, expected "Bearer TOKEN"'
643
+ },
644
+ 401
645
+ );
646
+ }
647
+ try {
648
+ const result = await provider.verifyToken(token);
649
+ const payload = result.payload;
650
+ const user = provider.getUserInfo(payload);
651
+ const authInfo = {
652
+ user,
653
+ payload,
654
+ accessToken: token,
655
+ // Extract scopes from scope claim (OAuth standard)
656
+ scopes: payload.scope ? payload.scope.split(" ") : [],
657
+ // Extract permissions (Auth0 style, or custom)
658
+ permissions: payload.permissions || []
659
+ };
660
+ c.set("auth", authInfo);
661
+ c.auth = authInfo;
662
+ c.set("user", user);
663
+ c.set("payload", payload);
664
+ c.set("accessToken", token);
665
+ await next();
666
+ } catch (error) {
667
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
668
+ return c.json({ error: `Invalid token: ${error}` }, 401);
669
+ }
670
+ };
671
+ }
672
+ __name(createBearerAuthMiddleware, "createBearerAuthMiddleware");
673
+
674
+ // src/server/oauth/routes.ts
675
+ import { cors } from "hono/cors";
676
+ function setupOAuthRoutes(app, provider, baseUrl) {
677
+ const mode = provider.getMode?.() || "proxy";
678
+ app.use(
679
+ "/.well-known/*",
680
+ cors({
681
+ origin: "*",
682
+ // Allow all origins for metadata discovery
683
+ allowMethods: ["GET", "OPTIONS"],
684
+ allowHeaders: ["Content-Type", "Authorization"],
685
+ exposeHeaders: ["Content-Type"],
686
+ maxAge: 86400
687
+ // Cache preflight for 24 hours
688
+ })
689
+ );
690
+ if (mode === "proxy") {
691
+ app.use(
692
+ "/authorize",
693
+ cors({
694
+ origin: "*",
695
+ allowMethods: ["GET", "POST", "OPTIONS"],
696
+ allowHeaders: ["Content-Type", "Authorization"],
697
+ maxAge: 86400
698
+ })
699
+ );
700
+ app.use(
701
+ "/token",
702
+ cors({
703
+ origin: "*",
704
+ allowMethods: ["POST", "OPTIONS"],
705
+ allowHeaders: ["Content-Type", "Authorization"],
706
+ maxAge: 86400
707
+ })
708
+ );
709
+ }
710
+ if (mode === "proxy") {
711
+ const handleAuthorize = /* @__PURE__ */ __name(async (c) => {
712
+ const params = c.req.method === "POST" ? await c.req.parseBody() : c.req.query();
713
+ const clientId = params.client_id;
714
+ const redirectUri = params.redirect_uri;
715
+ const responseType = params.response_type;
716
+ const codeChallenge = params.code_challenge;
717
+ const codeChallengeMethod = params.code_challenge_method;
718
+ const state = params.state;
719
+ const scope = params.scope;
720
+ const audience = params.audience;
721
+ if (!clientId || !redirectUri || !responseType || !codeChallenge) {
722
+ return c.json(
723
+ {
724
+ error: "invalid_request",
725
+ error_description: "Missing required parameters"
726
+ },
727
+ 400
728
+ );
729
+ }
730
+ const authUrl = new URL(provider.getAuthEndpoint());
731
+ authUrl.searchParams.set("client_id", clientId);
732
+ authUrl.searchParams.set("redirect_uri", redirectUri);
733
+ authUrl.searchParams.set("response_type", responseType);
734
+ authUrl.searchParams.set("code_challenge", codeChallenge);
735
+ authUrl.searchParams.set(
736
+ "code_challenge_method",
737
+ codeChallengeMethod || "S256"
738
+ );
739
+ if (state) authUrl.searchParams.set("state", state);
740
+ if (scope) authUrl.searchParams.set("scope", scope);
741
+ if (audience) authUrl.searchParams.set("audience", audience);
742
+ return c.redirect(authUrl.toString(), 302);
743
+ }, "handleAuthorize");
744
+ app.get("/authorize", handleAuthorize);
745
+ app.post("/authorize", handleAuthorize);
746
+ app.post("/token", async (c) => {
747
+ try {
748
+ const body = await c.req.parseBody();
749
+ const response = await fetch(provider.getTokenEndpoint(), {
750
+ method: "POST",
751
+ headers: {
752
+ "Content-Type": "application/x-www-form-urlencoded"
753
+ },
754
+ body: new URLSearchParams(body).toString()
755
+ });
756
+ const data = await response.json();
757
+ if (!response.ok) {
758
+ return c.json(data, response.status);
759
+ }
760
+ return c.json(data);
761
+ } catch (error) {
762
+ return c.json(
763
+ {
764
+ error: "server_error",
765
+ error_description: `Token exchange failed: ${error}`
766
+ },
767
+ 500
768
+ );
769
+ }
770
+ });
771
+ }
772
+ const handleAuthorizationServerMetadata = /* @__PURE__ */ __name(async (c) => {
773
+ const requestPath = new URL(c.req.url).pathname;
774
+ console.log(`[OAuth] Metadata request: ${requestPath} (mode: ${mode})`);
775
+ if (mode === "direct") {
776
+ try {
777
+ const metadataUrl = `${provider.getIssuer()}/.well-known/oauth-authorization-server`;
778
+ console.log(`[OAuth] Fetching metadata from provider: ${metadataUrl}`);
779
+ const response = await fetch(metadataUrl);
780
+ if (!response.ok) {
781
+ console.error(
782
+ `[OAuth] Failed to fetch provider metadata: ${response.status}`
783
+ );
784
+ return c.json(
785
+ {
786
+ error: "server_error",
787
+ error_description: `Failed to fetch provider metadata: ${response.status}`
788
+ },
789
+ 500
790
+ );
791
+ }
792
+ const metadata = await response.json();
793
+ const hasRegisteredClient = provider.getRegistrationEndpoint && provider.config?.clientId;
794
+ if (hasRegisteredClient) {
795
+ console.log(
796
+ `[OAuth] Provider has pre-registered client - removing DCR endpoint`
797
+ );
798
+ delete metadata.registration_endpoint;
799
+ }
800
+ console.log(`[OAuth] Provider metadata retrieved successfully`);
801
+ console.log(`[OAuth] - Issuer: ${metadata.issuer}`);
802
+ console.log(
803
+ `[OAuth] - Registration endpoint: ${metadata.registration_endpoint || "not available (using pre-registered client)"}`
804
+ );
805
+ return c.json(metadata);
806
+ } catch (error) {
807
+ console.error(`[OAuth] Error fetching provider metadata:`, error);
808
+ return c.json(
809
+ {
810
+ error: "server_error",
811
+ error_description: `Failed to fetch provider metadata: ${error}`
812
+ },
813
+ 500
814
+ );
815
+ }
816
+ } else {
817
+ console.log(`[OAuth] Returning proxy mode metadata`);
818
+ return c.json({
819
+ issuer: provider.getIssuer(),
820
+ authorization_endpoint: `${baseUrl}/authorize`,
821
+ token_endpoint: `${baseUrl}/token`,
822
+ response_types_supported: ["code"],
823
+ grant_types_supported: provider.getGrantTypesSupported(),
824
+ code_challenge_methods_supported: ["S256"],
825
+ token_endpoint_auth_methods_supported: [
826
+ "client_secret_post",
827
+ "client_secret_basic",
828
+ "none"
829
+ ],
830
+ scopes_supported: provider.getScopesSupported()
831
+ });
832
+ }
833
+ }, "handleAuthorizationServerMetadata");
834
+ app.get(
835
+ "/.well-known/oauth-authorization-server",
836
+ handleAuthorizationServerMetadata
837
+ );
838
+ app.get(
839
+ "/.well-known/openid-configuration",
840
+ handleAuthorizationServerMetadata
841
+ );
842
+ app.get("/.well-known/oauth-protected-resource", (c) => {
843
+ console.log(`[OAuth] Protected resource metadata request (mode: ${mode})`);
844
+ console.log(`[OAuth] - Resource: ${baseUrl}`);
845
+ console.log(`[OAuth] - Authorization server: ${provider.getIssuer()}`);
846
+ return c.json({
847
+ resource: baseUrl,
848
+ authorization_servers: [provider.getIssuer()],
849
+ bearer_methods_supported: ["header"],
850
+ resource_documentation: mode === "direct" ? "This resource uses direct OAuth flow. Clients communicate directly with the authorization server." : void 0
851
+ });
852
+ });
853
+ app.get("/.well-known/oauth-protected-resource/mcp", (c) => {
854
+ return c.json({
855
+ resource: `${baseUrl}/mcp`,
856
+ authorization_servers: [provider.getIssuer()],
857
+ bearer_methods_supported: ["header"]
858
+ });
859
+ });
860
+ }
861
+ __name(setupOAuthRoutes, "setupOAuthRoutes");
862
+
863
+ // src/server/oauth/utils.ts
864
+ function getAuth(context) {
865
+ return context.get("auth");
866
+ }
867
+ __name(getAuth, "getAuth");
868
+ function hasScope(context, needed) {
869
+ const { scopes, permissions } = getAuth(context);
870
+ const requiredScopes = Array.isArray(needed) ? needed : [needed];
871
+ return requiredScopes.every(
872
+ (scope) => scopes.includes(scope) || permissions.includes(scope)
873
+ );
874
+ }
875
+ __name(hasScope, "hasScope");
876
+ function hasAnyScope(context, needed) {
877
+ const { scopes, permissions } = getAuth(context);
878
+ return needed.some(
879
+ (scope) => scopes.includes(scope) || permissions.includes(scope)
880
+ );
881
+ }
882
+ __name(hasAnyScope, "hasAnyScope");
883
+ function requireScope(needed) {
884
+ return async (c, next) => {
885
+ if (!hasScope(c, needed)) {
886
+ const { scopes, permissions } = getAuth(c);
887
+ const requiredScopes = Array.isArray(needed) ? needed : [needed];
888
+ return c.json(
889
+ {
890
+ error: "insufficient_scope",
891
+ required: requiredScopes,
892
+ granted_scopes: scopes,
893
+ granted_permissions: permissions,
894
+ message: `Missing required scope(s): ${requiredScopes.join(", ")}`
895
+ },
896
+ 403
897
+ );
898
+ }
899
+ await next();
900
+ };
901
+ }
902
+ __name(requireScope, "requireScope");
903
+ function requireAnyScope(needed) {
904
+ return async (c, next) => {
905
+ if (!hasAnyScope(c, needed)) {
906
+ const { scopes, permissions } = getAuth(c);
907
+ return c.json(
908
+ {
909
+ error: "insufficient_scope",
910
+ required_any: needed,
911
+ granted_scopes: scopes,
912
+ granted_permissions: permissions,
913
+ message: `Missing at least one required scope from: ${needed.join(", ")}`
914
+ },
915
+ 403
916
+ );
917
+ }
918
+ await next();
919
+ };
920
+ }
921
+ __name(requireAnyScope, "requireAnyScope");
922
+
923
+ export {
924
+ isDeno,
925
+ getEnv,
926
+ getCwd,
927
+ fsHelpers,
928
+ pathHelpers,
929
+ generateUUID,
930
+ oauthSupabaseProvider,
931
+ oauthAuth0Provider,
932
+ oauthKeycloakProvider,
933
+ oauthWorkOSProvider,
934
+ oauthCustomProvider,
935
+ createBearerAuthMiddleware,
936
+ setupOAuthRoutes,
937
+ getAuth,
938
+ hasScope,
939
+ hasAnyScope,
940
+ requireScope,
941
+ requireAnyScope
942
+ };