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
@@ -6,6 +6,9 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -16,44 +19,1082 @@ var __copyProps = (to, from, except, desc) => {
16
19
  if (!__hasOwnProp.call(to, key) && key !== except)
17
20
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
21
  }
19
- return to;
20
- };
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
+
34
+ // src/server/utils/runtime.ts
35
+ function getEnv2(key) {
36
+ if (isDeno2) {
37
+ return globalThis.Deno.env.get(key);
38
+ }
39
+ return process.env[key];
40
+ }
41
+ function getCwd() {
42
+ if (isDeno2) {
43
+ return globalThis.Deno.cwd();
44
+ }
45
+ return process.cwd();
46
+ }
47
+ function generateUUID() {
48
+ return globalThis.crypto.randomUUID();
49
+ }
50
+ var isDeno2, fsHelpers, pathHelpers;
51
+ var init_runtime = __esm({
52
+ "src/server/utils/runtime.ts"() {
53
+ "use strict";
54
+ isDeno2 = typeof globalThis.Deno !== "undefined";
55
+ __name(getEnv2, "getEnv");
56
+ __name(getCwd, "getCwd");
57
+ fsHelpers = {
58
+ async readFileSync(path, encoding = "utf8") {
59
+ if (isDeno2) {
60
+ return await globalThis.Deno.readTextFile(path);
61
+ }
62
+ const { readFileSync } = await import("fs");
63
+ const result = readFileSync(path, encoding);
64
+ return typeof result === "string" ? result : result.toString(encoding);
65
+ },
66
+ async readFile(path) {
67
+ if (isDeno2) {
68
+ const data = await globalThis.Deno.readFile(path);
69
+ return data.buffer;
70
+ }
71
+ const { readFileSync } = await import("fs");
72
+ const buffer = readFileSync(path);
73
+ return buffer.buffer.slice(
74
+ buffer.byteOffset,
75
+ buffer.byteOffset + buffer.byteLength
76
+ );
77
+ },
78
+ async existsSync(path) {
79
+ if (isDeno2) {
80
+ try {
81
+ await globalThis.Deno.stat(path);
82
+ return true;
83
+ } catch {
84
+ return false;
85
+ }
86
+ }
87
+ const { existsSync } = await import("fs");
88
+ return existsSync(path);
89
+ },
90
+ async readdirSync(path) {
91
+ if (isDeno2) {
92
+ const entries = [];
93
+ for await (const entry of globalThis.Deno.readDir(path)) {
94
+ entries.push(entry.name);
95
+ }
96
+ return entries;
97
+ }
98
+ const { readdirSync } = await import("fs");
99
+ return readdirSync(path);
100
+ }
101
+ };
102
+ pathHelpers = {
103
+ join(...paths) {
104
+ if (isDeno2) {
105
+ return paths.join("/").replace(/\/+/g, "/");
106
+ }
107
+ return paths.join("/").replace(/\/+/g, "/");
108
+ },
109
+ relative(from, to) {
110
+ const fromParts = from.split("/").filter((p) => p);
111
+ const toParts = to.split("/").filter((p) => p);
112
+ let i = 0;
113
+ while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
114
+ i++;
115
+ }
116
+ const upCount = fromParts.length - i;
117
+ const relativeParts = [...Array(upCount).fill(".."), ...toParts.slice(i)];
118
+ return relativeParts.join("/");
119
+ }
120
+ };
121
+ __name(generateUUID, "generateUUID");
122
+ }
123
+ });
124
+
125
+ // src/server/oauth/providers/supabase.ts
126
+ var import_jose, SupabaseOAuthProvider;
127
+ var init_supabase = __esm({
128
+ "src/server/oauth/providers/supabase.ts"() {
129
+ "use strict";
130
+ import_jose = require("jose");
131
+ SupabaseOAuthProvider = class {
132
+ static {
133
+ __name(this, "SupabaseOAuthProvider");
134
+ }
135
+ config;
136
+ supabaseUrl;
137
+ supabaseAuthUrl;
138
+ issuer;
139
+ jwks = null;
140
+ constructor(config) {
141
+ this.config = config;
142
+ this.supabaseUrl = `https://${config.projectId}.supabase.co`;
143
+ this.supabaseAuthUrl = `${this.supabaseUrl}/auth/v1`;
144
+ this.issuer = `${this.supabaseUrl}/auth/v1`;
145
+ }
146
+ getJWKS() {
147
+ if (!this.jwks) {
148
+ this.jwks = (0, import_jose.createRemoteJWKSet)(
149
+ new URL(`${this.issuer}/.well-known/jwks.json`)
150
+ );
151
+ }
152
+ return this.jwks;
153
+ }
154
+ async verifyToken(token) {
155
+ if (this.config.skipVerification) {
156
+ console.warn(
157
+ "[Supabase OAuth] \u26A0\uFE0F SKIPPING VERIFICATION (DEVELOPMENT MODE)"
158
+ );
159
+ console.warn(
160
+ "[Supabase OAuth] This is NOT secure! Only use for testing!"
161
+ );
162
+ const payload = (0, import_jose.decodeJwt)(token);
163
+ return { payload, protectedHeader: (0, import_jose.decodeProtectedHeader)(token) };
164
+ }
165
+ try {
166
+ const header = (0, import_jose.decodeProtectedHeader)(token);
167
+ if (header.alg === "HS256") {
168
+ if (!this.config.jwtSecret) {
169
+ throw new Error(
170
+ "JWT Secret is required for HS256 tokens. Get it from: Supabase Dashboard \u2192 Project Settings \u2192 API \u2192 JWT Settings"
171
+ );
172
+ }
173
+ const secret = new TextEncoder().encode(this.config.jwtSecret);
174
+ const result = await (0, import_jose.jwtVerify)(token, secret, {
175
+ issuer: this.issuer,
176
+ audience: "authenticated"
177
+ });
178
+ return result;
179
+ } else if (header.alg === "ES256") {
180
+ const result = await (0, import_jose.jwtVerify)(token, this.getJWKS(), {
181
+ issuer: this.issuer,
182
+ audience: "authenticated"
183
+ });
184
+ return result;
185
+ } else {
186
+ throw new Error(`Unsupported algorithm: ${header.alg}`);
187
+ }
188
+ } catch (error2) {
189
+ throw new Error(`Supabase JWT verification failed: ${error2}`);
190
+ }
191
+ }
192
+ getUserInfo(payload) {
193
+ return {
194
+ userId: payload.sub || payload.user_id,
195
+ email: payload.email,
196
+ name: payload.user_metadata?.name || payload.user_metadata?.full_name,
197
+ username: payload.user_metadata?.username,
198
+ picture: payload.user_metadata?.avatar_url,
199
+ roles: payload.role ? [payload.role] : [],
200
+ permissions: payload.aal ? [`aal:${payload.aal}`] : [],
201
+ // Include Supabase-specific claims
202
+ aal: payload.aal,
203
+ // Authentication Assurance Level
204
+ amr: payload.amr,
205
+ // Authentication Methods References
206
+ session_id: payload.session_id
207
+ };
208
+ }
209
+ getIssuer() {
210
+ return this.issuer;
211
+ }
212
+ getAuthEndpoint() {
213
+ return `${this.supabaseAuthUrl}/authorize`;
214
+ }
215
+ getTokenEndpoint() {
216
+ return `${this.supabaseAuthUrl}/token`;
217
+ }
218
+ getScopesSupported() {
219
+ return [];
220
+ }
221
+ getGrantTypesSupported() {
222
+ return ["authorization_code", "refresh_token"];
223
+ }
224
+ };
225
+ }
226
+ });
227
+
228
+ // src/server/oauth/providers/auth0.ts
229
+ var import_jose2, Auth0OAuthProvider;
230
+ var init_auth0 = __esm({
231
+ "src/server/oauth/providers/auth0.ts"() {
232
+ "use strict";
233
+ import_jose2 = require("jose");
234
+ Auth0OAuthProvider = class {
235
+ static {
236
+ __name(this, "Auth0OAuthProvider");
237
+ }
238
+ config;
239
+ issuer;
240
+ jwks = null;
241
+ constructor(config) {
242
+ this.config = config;
243
+ this.issuer = `https://${config.domain}`;
244
+ }
245
+ getJWKS() {
246
+ if (!this.jwks) {
247
+ this.jwks = (0, import_jose2.createRemoteJWKSet)(
248
+ new URL(`${this.issuer}/.well-known/jwks.json`)
249
+ );
250
+ }
251
+ return this.jwks;
252
+ }
253
+ async verifyToken(token) {
254
+ if (this.config.verifyJwt === false) {
255
+ console.warn("[Auth0 OAuth] \u26A0\uFE0F JWT verification is disabled");
256
+ console.warn("[Auth0 OAuth] Enable verifyJwt: true for production");
257
+ const parts = token.split(".");
258
+ if (parts.length !== 3) {
259
+ throw new Error("Invalid JWT format");
260
+ }
261
+ const payload = JSON.parse(
262
+ Buffer.from(parts[1], "base64url").toString("utf8")
263
+ );
264
+ return { payload };
265
+ }
266
+ try {
267
+ const result = await (0, import_jose2.jwtVerify)(token, this.getJWKS(), {
268
+ issuer: this.issuer,
269
+ audience: this.config.audience
270
+ });
271
+ return result;
272
+ } catch (error2) {
273
+ throw new Error(`Auth0 JWT verification failed: ${error2}`);
274
+ }
275
+ }
276
+ getUserInfo(payload) {
277
+ return {
278
+ userId: payload.sub,
279
+ email: payload.email,
280
+ name: payload.name,
281
+ username: payload.username,
282
+ nickname: payload.nickname,
283
+ picture: payload.picture,
284
+ // Auth0 includes permissions directly in the token
285
+ permissions: payload.permissions || [],
286
+ // Auth0 can include roles (if configured)
287
+ roles: payload.roles || payload["https://your-app.com/roles"] || [],
288
+ // Include scope as well
289
+ scopes: payload.scope ? payload.scope.split(" ") : [],
290
+ // Additional Auth0-specific claims
291
+ email_verified: payload.email_verified,
292
+ updated_at: payload.updated_at
293
+ };
294
+ }
295
+ getIssuer() {
296
+ return this.issuer;
297
+ }
298
+ getAuthEndpoint() {
299
+ return `${this.issuer}/authorize`;
300
+ }
301
+ getTokenEndpoint() {
302
+ return `${this.issuer}/oauth/token`;
303
+ }
304
+ getScopesSupported() {
305
+ return ["openid", "profile", "email", "offline_access"];
306
+ }
307
+ getGrantTypesSupported() {
308
+ return ["authorization_code", "refresh_token"];
309
+ }
310
+ };
311
+ }
312
+ });
313
+
314
+ // src/server/oauth/providers/keycloak.ts
315
+ var import_jose3, KeycloakOAuthProvider;
316
+ var init_keycloak = __esm({
317
+ "src/server/oauth/providers/keycloak.ts"() {
318
+ "use strict";
319
+ import_jose3 = require("jose");
320
+ KeycloakOAuthProvider = class {
321
+ static {
322
+ __name(this, "KeycloakOAuthProvider");
323
+ }
324
+ config;
325
+ issuer;
326
+ jwks = null;
327
+ constructor(config) {
328
+ this.config = config;
329
+ const serverUrl = config.serverUrl.replace(/\/$/, "");
330
+ this.issuer = `${serverUrl}/realms/${config.realm}`;
331
+ }
332
+ getJWKS() {
333
+ if (!this.jwks) {
334
+ this.jwks = (0, import_jose3.createRemoteJWKSet)(
335
+ new URL(`${this.issuer}/protocol/openid-connect/certs`)
336
+ );
337
+ }
338
+ return this.jwks;
339
+ }
340
+ async verifyToken(token) {
341
+ if (this.config.verifyJwt === false) {
342
+ console.warn("[Keycloak OAuth] \u26A0\uFE0F JWT verification is disabled");
343
+ console.warn(
344
+ "[Keycloak OAuth] Enable verifyJwt: true for production"
345
+ );
346
+ const parts = token.split(".");
347
+ if (parts.length !== 3) {
348
+ throw new Error("Invalid JWT format");
349
+ }
350
+ const payload = JSON.parse(
351
+ Buffer.from(parts[1], "base64url").toString("utf8")
352
+ );
353
+ return { payload };
354
+ }
355
+ try {
356
+ const result = await (0, import_jose3.jwtVerify)(token, this.getJWKS(), {
357
+ issuer: this.issuer,
358
+ // Don't verify audience if not specified
359
+ ...this.config.clientId && { audience: this.config.clientId }
360
+ });
361
+ return result;
362
+ } catch (error2) {
363
+ throw new Error(`Keycloak JWT verification failed: ${error2}`);
364
+ }
365
+ }
366
+ getUserInfo(payload) {
367
+ const realmRoles = payload.realm_access?.roles || [];
368
+ const clientRoles = this.config.clientId && payload.resource_access?.[this.config.clientId]?.roles || [];
369
+ const allRoles = [...realmRoles, ...clientRoles];
370
+ const permissions = [];
371
+ if (payload.resource_access) {
372
+ Object.entries(payload.resource_access).forEach(
373
+ ([resource2, access]) => {
374
+ if (access.roles) {
375
+ access.roles.forEach((role) => {
376
+ permissions.push(`${resource2}:${role}`);
377
+ });
378
+ }
379
+ }
380
+ );
381
+ }
382
+ return {
383
+ userId: payload.sub,
384
+ email: payload.email,
385
+ name: payload.name,
386
+ username: payload.preferred_username,
387
+ nickname: payload.preferred_username,
388
+ picture: payload.picture,
389
+ roles: allRoles,
390
+ permissions,
391
+ // Include scope as well
392
+ scopes: payload.scope ? payload.scope.split(" ") : [],
393
+ // Keycloak-specific claims
394
+ email_verified: payload.email_verified,
395
+ given_name: payload.given_name,
396
+ family_name: payload.family_name,
397
+ realm_access: payload.realm_access,
398
+ resource_access: payload.resource_access
399
+ };
400
+ }
401
+ getIssuer() {
402
+ return this.issuer;
403
+ }
404
+ getAuthEndpoint() {
405
+ return `${this.issuer}/protocol/openid-connect/auth`;
406
+ }
407
+ getTokenEndpoint() {
408
+ return `${this.issuer}/protocol/openid-connect/token`;
409
+ }
410
+ getScopesSupported() {
411
+ return ["openid", "profile", "email", "offline_access", "roles"];
412
+ }
413
+ getGrantTypesSupported() {
414
+ return ["authorization_code", "refresh_token", "client_credentials"];
415
+ }
416
+ };
417
+ }
418
+ });
419
+
420
+ // src/server/oauth/providers/workos.ts
421
+ var import_jose4, WorkOSOAuthProvider;
422
+ var init_workos = __esm({
423
+ "src/server/oauth/providers/workos.ts"() {
424
+ "use strict";
425
+ import_jose4 = require("jose");
426
+ WorkOSOAuthProvider = class {
427
+ static {
428
+ __name(this, "WorkOSOAuthProvider");
429
+ }
430
+ config;
431
+ issuer;
432
+ jwks = null;
433
+ constructor(config) {
434
+ this.config = config;
435
+ this.issuer = `https://${config.subdomain}.authkit.app`;
436
+ }
437
+ getJWKS() {
438
+ if (!this.jwks) {
439
+ this.jwks = (0, import_jose4.createRemoteJWKSet)(new URL(`${this.issuer}/oauth2/jwks`));
440
+ }
441
+ return this.jwks;
442
+ }
443
+ async verifyToken(token) {
444
+ if (this.config.verifyJwt === false) {
445
+ console.warn("[WorkOS OAuth] \u26A0\uFE0F JWT verification is disabled");
446
+ console.warn("[WorkOS OAuth] Enable verifyJwt: true for production");
447
+ const parts = token.split(".");
448
+ if (parts.length !== 3) {
449
+ throw new Error("Invalid JWT format");
450
+ }
451
+ const payload = (0, import_jose4.decodeJwt)(token);
452
+ return { payload };
453
+ }
454
+ try {
455
+ const result = await (0, import_jose4.jwtVerify)(token, this.getJWKS(), {
456
+ issuer: this.issuer
457
+ });
458
+ return result;
459
+ } catch (error2) {
460
+ throw new Error(`WorkOS JWT verification failed: ${error2}`);
461
+ }
462
+ }
463
+ getUserInfo(payload) {
464
+ return {
465
+ userId: payload.sub,
466
+ email: payload.email,
467
+ name: payload.name,
468
+ username: payload.preferred_username,
469
+ picture: payload.picture,
470
+ // WorkOS includes permissions and roles in token
471
+ permissions: payload.permissions || [],
472
+ roles: payload.roles || [],
473
+ // Include scope as well
474
+ scopes: payload.scope ? payload.scope.split(" ") : [],
475
+ // Additional WorkOS-specific claims
476
+ email_verified: payload.email_verified,
477
+ organization_id: payload.org_id,
478
+ sid: payload.sid
479
+ // Session ID
480
+ };
481
+ }
482
+ getIssuer() {
483
+ return this.issuer;
484
+ }
485
+ getAuthEndpoint() {
486
+ return `${this.issuer}/oauth2/authorize`;
487
+ }
488
+ getTokenEndpoint() {
489
+ return `${this.issuer}/oauth2/token`;
490
+ }
491
+ getScopesSupported() {
492
+ return ["email", "offline_access", "openid", "profile"];
493
+ }
494
+ getGrantTypesSupported() {
495
+ return ["authorization_code", "refresh_token"];
496
+ }
497
+ getMode() {
498
+ if (this.config.clientId) {
499
+ console.log("[WorkOS OAuth] Using proxy mode (pre-registered client)");
500
+ return "proxy";
501
+ }
502
+ console.log(
503
+ "[WorkOS OAuth] Using direct mode (Dynamic Client Registration)"
504
+ );
505
+ return "direct";
506
+ }
507
+ getRegistrationEndpoint() {
508
+ if (this.config.clientId) {
509
+ return void 0;
510
+ }
511
+ return `${this.issuer}/oauth2/register`;
512
+ }
513
+ };
514
+ }
515
+ });
516
+
517
+ // src/server/oauth/providers/custom.ts
518
+ var CustomOAuthProvider;
519
+ var init_custom = __esm({
520
+ "src/server/oauth/providers/custom.ts"() {
521
+ "use strict";
522
+ CustomOAuthProvider = class {
523
+ static {
524
+ __name(this, "CustomOAuthProvider");
525
+ }
526
+ config;
527
+ constructor(config) {
528
+ this.config = config;
529
+ }
530
+ async verifyToken(token) {
531
+ try {
532
+ const result = await this.config.verifyToken(token);
533
+ return { payload: result };
534
+ } catch (error2) {
535
+ throw new Error(`Custom OAuth verification failed: ${error2}`);
536
+ }
537
+ }
538
+ getUserInfo(payload) {
539
+ if (this.config.getUserInfo) {
540
+ return this.config.getUserInfo(payload);
541
+ }
542
+ return {
543
+ userId: payload.sub || payload.user_id || payload.id,
544
+ email: payload.email,
545
+ name: payload.name,
546
+ username: payload.username || payload.preferred_username,
547
+ nickname: payload.nickname,
548
+ picture: payload.picture || payload.avatar_url,
549
+ roles: payload.roles || [],
550
+ permissions: payload.permissions || [],
551
+ scopes: payload.scope ? payload.scope.split(" ") : []
552
+ };
553
+ }
554
+ getIssuer() {
555
+ return this.config.issuer;
556
+ }
557
+ getAuthEndpoint() {
558
+ return this.config.authEndpoint;
559
+ }
560
+ getTokenEndpoint() {
561
+ return this.config.tokenEndpoint;
562
+ }
563
+ getScopesSupported() {
564
+ return this.config.scopesSupported || ["openid", "profile", "email"];
565
+ }
566
+ getGrantTypesSupported() {
567
+ return this.config.grantTypesSupported || ["authorization_code", "refresh_token"];
568
+ }
569
+ };
570
+ }
571
+ });
572
+
573
+ // src/server/oauth/providers.ts
574
+ function oauthSupabaseProvider(config = {}) {
575
+ const projectId = config.projectId ?? getEnv2("MCP_USE_OAUTH_SUPABASE_PROJECT_ID");
576
+ const jwtSecret = config.jwtSecret ?? getEnv2("MCP_USE_OAUTH_SUPABASE_JWT_SECRET");
577
+ if (!projectId) {
578
+ throw new Error(
579
+ "Supabase projectId is required. Set MCP_USE_OAUTH_SUPABASE_PROJECT_ID environment variable or pass projectId in config."
580
+ );
581
+ }
582
+ return new SupabaseOAuthProvider({
583
+ provider: "supabase",
584
+ projectId,
585
+ jwtSecret,
586
+ skipVerification: config.skipVerification
587
+ });
588
+ }
589
+ function oauthAuth0Provider(config = {}) {
590
+ const domain = config.domain ?? getEnv2("MCP_USE_OAUTH_AUTH0_DOMAIN");
591
+ const audience = config.audience ?? getEnv2("MCP_USE_OAUTH_AUTH0_AUDIENCE");
592
+ if (!domain) {
593
+ throw new Error(
594
+ "Auth0 domain is required. Set MCP_USE_OAUTH_AUTH0_DOMAIN environment variable or pass domain in config."
595
+ );
596
+ }
597
+ if (!audience) {
598
+ throw new Error(
599
+ "Auth0 audience is required. Set MCP_USE_OAUTH_AUTH0_AUDIENCE environment variable or pass audience in config."
600
+ );
601
+ }
602
+ return new Auth0OAuthProvider({
603
+ provider: "auth0",
604
+ domain,
605
+ audience,
606
+ verifyJwt: config.verifyJwt
607
+ });
608
+ }
609
+ function oauthKeycloakProvider(config = {}) {
610
+ const serverUrl = config.serverUrl ?? getEnv2("MCP_USE_OAUTH_KEYCLOAK_SERVER_URL");
611
+ const realm = config.realm ?? getEnv2("MCP_USE_OAUTH_KEYCLOAK_REALM");
612
+ const clientId = config.clientId ?? getEnv2("MCP_USE_OAUTH_KEYCLOAK_CLIENT_ID");
613
+ if (!serverUrl) {
614
+ throw new Error(
615
+ "Keycloak serverUrl is required. Set MCP_USE_OAUTH_KEYCLOAK_SERVER_URL environment variable or pass serverUrl in config."
616
+ );
617
+ }
618
+ if (!realm) {
619
+ throw new Error(
620
+ "Keycloak realm is required. Set MCP_USE_OAUTH_KEYCLOAK_REALM environment variable or pass realm in config."
621
+ );
622
+ }
623
+ return new KeycloakOAuthProvider({
624
+ provider: "keycloak",
625
+ serverUrl,
626
+ realm,
627
+ clientId,
628
+ verifyJwt: config.verifyJwt
629
+ });
630
+ }
631
+ function oauthWorkOSProvider(config = {}) {
632
+ const subdomain = config.subdomain ?? getEnv2("MCP_USE_OAUTH_WORKOS_SUBDOMAIN");
633
+ const clientId = config.clientId ?? getEnv2("MCP_USE_OAUTH_WORKOS_CLIENT_ID");
634
+ const apiKey = config.apiKey ?? getEnv2("MCP_USE_OAUTH_WORKOS_API_KEY");
635
+ if (!subdomain) {
636
+ throw new Error(
637
+ "WorkOS subdomain is required. Set MCP_USE_OAUTH_WORKOS_SUBDOMAIN environment variable or pass subdomain in config."
638
+ );
639
+ }
640
+ if (clientId) {
641
+ console.log("[WorkOS OAuth] Using pre-registered OAuth client mode");
642
+ console.log(`[WorkOS OAuth] - Client ID: ${clientId}`);
643
+ console.log(
644
+ "[WorkOS OAuth] - Make sure this client exists in WorkOS Dashboard"
645
+ );
646
+ console.log(
647
+ "[WorkOS OAuth] - Configure redirect URIs to match your MCP client"
648
+ );
649
+ } else {
650
+ console.log("[WorkOS OAuth] Using Dynamic Client Registration (DCR) mode");
651
+ console.log(
652
+ "[WorkOS OAuth] - MCP clients will register themselves automatically"
653
+ );
654
+ console.log(
655
+ "[WorkOS OAuth] - Make sure DCR is enabled in WorkOS Dashboard"
656
+ );
657
+ }
658
+ return new WorkOSOAuthProvider({
659
+ provider: "workos",
660
+ subdomain,
661
+ clientId,
662
+ apiKey,
663
+ verifyJwt: config.verifyJwt
664
+ });
665
+ }
666
+ function oauthCustomProvider(config) {
667
+ return new CustomOAuthProvider({
668
+ provider: "custom",
669
+ ...config
670
+ });
671
+ }
672
+ var init_providers = __esm({
673
+ "src/server/oauth/providers.ts"() {
674
+ "use strict";
675
+ init_supabase();
676
+ init_auth0();
677
+ init_keycloak();
678
+ init_workos();
679
+ init_custom();
680
+ init_runtime();
681
+ __name(oauthSupabaseProvider, "oauthSupabaseProvider");
682
+ __name(oauthAuth0Provider, "oauthAuth0Provider");
683
+ __name(oauthKeycloakProvider, "oauthKeycloakProvider");
684
+ __name(oauthWorkOSProvider, "oauthWorkOSProvider");
685
+ __name(oauthCustomProvider, "oauthCustomProvider");
686
+ }
687
+ });
688
+
689
+ // src/server/oauth/middleware.ts
690
+ function createBearerAuthMiddleware(provider, baseUrl) {
691
+ return async (c, next) => {
692
+ const authHeader = c.req.header("Authorization");
693
+ const getWWWAuthenticateHeader = /* @__PURE__ */ __name(() => {
694
+ const base = baseUrl || new URL(c.req.url).origin;
695
+ const parts = [
696
+ 'Bearer error="unauthorized"',
697
+ 'error_description="Authorization needed"'
698
+ ];
699
+ parts.push(
700
+ `resource_metadata="${base}/.well-known/oauth-protected-resource"`
701
+ );
702
+ return parts.join(", ");
703
+ }, "getWWWAuthenticateHeader");
704
+ if (!authHeader) {
705
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
706
+ return c.json({ error: "Missing Authorization header" }, 401);
707
+ }
708
+ const [type, token] = authHeader.split(" ");
709
+ if (type.toLowerCase() !== "bearer" || !token) {
710
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
711
+ return c.json(
712
+ {
713
+ error: 'Invalid Authorization header format, expected "Bearer TOKEN"'
714
+ },
715
+ 401
716
+ );
717
+ }
718
+ try {
719
+ const result = await provider.verifyToken(token);
720
+ const payload = result.payload;
721
+ const user = provider.getUserInfo(payload);
722
+ const authInfo = {
723
+ user,
724
+ payload,
725
+ accessToken: token,
726
+ // Extract scopes from scope claim (OAuth standard)
727
+ scopes: payload.scope ? payload.scope.split(" ") : [],
728
+ // Extract permissions (Auth0 style, or custom)
729
+ permissions: payload.permissions || []
730
+ };
731
+ c.set("auth", authInfo);
732
+ c.auth = authInfo;
733
+ c.set("user", user);
734
+ c.set("payload", payload);
735
+ c.set("accessToken", token);
736
+ await next();
737
+ } catch (error2) {
738
+ c.header("WWW-Authenticate", getWWWAuthenticateHeader());
739
+ return c.json({ error: `Invalid token: ${error2}` }, 401);
740
+ }
741
+ };
742
+ }
743
+ var init_middleware = __esm({
744
+ "src/server/oauth/middleware.ts"() {
745
+ "use strict";
746
+ __name(createBearerAuthMiddleware, "createBearerAuthMiddleware");
747
+ }
748
+ });
749
+
750
+ // src/server/oauth/routes.ts
751
+ function setupOAuthRoutes(app, provider, baseUrl) {
752
+ const mode = provider.getMode?.() || "proxy";
753
+ app.use(
754
+ "/.well-known/*",
755
+ (0, import_cors.cors)({
756
+ origin: "*",
757
+ // Allow all origins for metadata discovery
758
+ allowMethods: ["GET", "OPTIONS"],
759
+ allowHeaders: ["Content-Type", "Authorization"],
760
+ exposeHeaders: ["Content-Type"],
761
+ maxAge: 86400
762
+ // Cache preflight for 24 hours
763
+ })
764
+ );
765
+ if (mode === "proxy") {
766
+ app.use(
767
+ "/authorize",
768
+ (0, import_cors.cors)({
769
+ origin: "*",
770
+ allowMethods: ["GET", "POST", "OPTIONS"],
771
+ allowHeaders: ["Content-Type", "Authorization"],
772
+ maxAge: 86400
773
+ })
774
+ );
775
+ app.use(
776
+ "/token",
777
+ (0, import_cors.cors)({
778
+ origin: "*",
779
+ allowMethods: ["POST", "OPTIONS"],
780
+ allowHeaders: ["Content-Type", "Authorization"],
781
+ maxAge: 86400
782
+ })
783
+ );
784
+ }
785
+ if (mode === "proxy") {
786
+ const handleAuthorize = /* @__PURE__ */ __name(async (c) => {
787
+ const params = c.req.method === "POST" ? await c.req.parseBody() : c.req.query();
788
+ const clientId = params.client_id;
789
+ const redirectUri = params.redirect_uri;
790
+ const responseType = params.response_type;
791
+ const codeChallenge = params.code_challenge;
792
+ const codeChallengeMethod = params.code_challenge_method;
793
+ const state = params.state;
794
+ const scope = params.scope;
795
+ const audience = params.audience;
796
+ if (!clientId || !redirectUri || !responseType || !codeChallenge) {
797
+ return c.json(
798
+ {
799
+ error: "invalid_request",
800
+ error_description: "Missing required parameters"
801
+ },
802
+ 400
803
+ );
804
+ }
805
+ const authUrl = new URL(provider.getAuthEndpoint());
806
+ authUrl.searchParams.set("client_id", clientId);
807
+ authUrl.searchParams.set("redirect_uri", redirectUri);
808
+ authUrl.searchParams.set("response_type", responseType);
809
+ authUrl.searchParams.set("code_challenge", codeChallenge);
810
+ authUrl.searchParams.set(
811
+ "code_challenge_method",
812
+ codeChallengeMethod || "S256"
813
+ );
814
+ if (state) authUrl.searchParams.set("state", state);
815
+ if (scope) authUrl.searchParams.set("scope", scope);
816
+ if (audience) authUrl.searchParams.set("audience", audience);
817
+ return c.redirect(authUrl.toString(), 302);
818
+ }, "handleAuthorize");
819
+ app.get("/authorize", handleAuthorize);
820
+ app.post("/authorize", handleAuthorize);
821
+ app.post("/token", async (c) => {
822
+ try {
823
+ const body = await c.req.parseBody();
824
+ const response = await fetch(provider.getTokenEndpoint(), {
825
+ method: "POST",
826
+ headers: {
827
+ "Content-Type": "application/x-www-form-urlencoded"
828
+ },
829
+ body: new URLSearchParams(body).toString()
830
+ });
831
+ const data = await response.json();
832
+ if (!response.ok) {
833
+ return c.json(data, response.status);
834
+ }
835
+ return c.json(data);
836
+ } catch (error2) {
837
+ return c.json(
838
+ {
839
+ error: "server_error",
840
+ error_description: `Token exchange failed: ${error2}`
841
+ },
842
+ 500
843
+ );
844
+ }
845
+ });
846
+ }
847
+ const handleAuthorizationServerMetadata = /* @__PURE__ */ __name(async (c) => {
848
+ const requestPath = new URL(c.req.url).pathname;
849
+ console.log(`[OAuth] Metadata request: ${requestPath} (mode: ${mode})`);
850
+ if (mode === "direct") {
851
+ try {
852
+ const metadataUrl = `${provider.getIssuer()}/.well-known/oauth-authorization-server`;
853
+ console.log(`[OAuth] Fetching metadata from provider: ${metadataUrl}`);
854
+ const response = await fetch(metadataUrl);
855
+ if (!response.ok) {
856
+ console.error(
857
+ `[OAuth] Failed to fetch provider metadata: ${response.status}`
858
+ );
859
+ return c.json(
860
+ {
861
+ error: "server_error",
862
+ error_description: `Failed to fetch provider metadata: ${response.status}`
863
+ },
864
+ 500
865
+ );
866
+ }
867
+ const metadata = await response.json();
868
+ const hasRegisteredClient = provider.getRegistrationEndpoint && provider.config?.clientId;
869
+ if (hasRegisteredClient) {
870
+ console.log(
871
+ `[OAuth] Provider has pre-registered client - removing DCR endpoint`
872
+ );
873
+ delete metadata.registration_endpoint;
874
+ }
875
+ console.log(`[OAuth] Provider metadata retrieved successfully`);
876
+ console.log(`[OAuth] - Issuer: ${metadata.issuer}`);
877
+ console.log(
878
+ `[OAuth] - Registration endpoint: ${metadata.registration_endpoint || "not available (using pre-registered client)"}`
879
+ );
880
+ return c.json(metadata);
881
+ } catch (error2) {
882
+ console.error(`[OAuth] Error fetching provider metadata:`, error2);
883
+ return c.json(
884
+ {
885
+ error: "server_error",
886
+ error_description: `Failed to fetch provider metadata: ${error2}`
887
+ },
888
+ 500
889
+ );
890
+ }
891
+ } else {
892
+ console.log(`[OAuth] Returning proxy mode metadata`);
893
+ return c.json({
894
+ issuer: provider.getIssuer(),
895
+ authorization_endpoint: `${baseUrl}/authorize`,
896
+ token_endpoint: `${baseUrl}/token`,
897
+ response_types_supported: ["code"],
898
+ grant_types_supported: provider.getGrantTypesSupported(),
899
+ code_challenge_methods_supported: ["S256"],
900
+ token_endpoint_auth_methods_supported: [
901
+ "client_secret_post",
902
+ "client_secret_basic",
903
+ "none"
904
+ ],
905
+ scopes_supported: provider.getScopesSupported()
906
+ });
907
+ }
908
+ }, "handleAuthorizationServerMetadata");
909
+ app.get(
910
+ "/.well-known/oauth-authorization-server",
911
+ handleAuthorizationServerMetadata
912
+ );
913
+ app.get(
914
+ "/.well-known/openid-configuration",
915
+ handleAuthorizationServerMetadata
916
+ );
917
+ app.get("/.well-known/oauth-protected-resource", (c) => {
918
+ console.log(`[OAuth] Protected resource metadata request (mode: ${mode})`);
919
+ console.log(`[OAuth] - Resource: ${baseUrl}`);
920
+ console.log(`[OAuth] - Authorization server: ${provider.getIssuer()}`);
921
+ return c.json({
922
+ resource: baseUrl,
923
+ authorization_servers: [provider.getIssuer()],
924
+ bearer_methods_supported: ["header"],
925
+ resource_documentation: mode === "direct" ? "This resource uses direct OAuth flow. Clients communicate directly with the authorization server." : void 0
926
+ });
927
+ });
928
+ app.get("/.well-known/oauth-protected-resource/mcp", (c) => {
929
+ return c.json({
930
+ resource: `${baseUrl}/mcp`,
931
+ authorization_servers: [provider.getIssuer()],
932
+ bearer_methods_supported: ["header"]
933
+ });
934
+ });
935
+ }
936
+ var import_cors;
937
+ var init_routes = __esm({
938
+ "src/server/oauth/routes.ts"() {
939
+ "use strict";
940
+ import_cors = require("hono/cors");
941
+ __name(setupOAuthRoutes, "setupOAuthRoutes");
942
+ }
943
+ });
944
+
945
+ // src/server/oauth/utils.ts
946
+ function getAuth(context) {
947
+ return context.get("auth");
948
+ }
949
+ function hasScope(context, needed) {
950
+ const { scopes, permissions } = getAuth(context);
951
+ const requiredScopes = Array.isArray(needed) ? needed : [needed];
952
+ return requiredScopes.every(
953
+ (scope) => scopes.includes(scope) || permissions.includes(scope)
954
+ );
955
+ }
956
+ function hasAnyScope(context, needed) {
957
+ const { scopes, permissions } = getAuth(context);
958
+ return needed.some(
959
+ (scope) => scopes.includes(scope) || permissions.includes(scope)
960
+ );
961
+ }
962
+ function requireScope(needed) {
963
+ return async (c, next) => {
964
+ if (!hasScope(c, needed)) {
965
+ const { scopes, permissions } = getAuth(c);
966
+ const requiredScopes = Array.isArray(needed) ? needed : [needed];
967
+ return c.json(
968
+ {
969
+ error: "insufficient_scope",
970
+ required: requiredScopes,
971
+ granted_scopes: scopes,
972
+ granted_permissions: permissions,
973
+ message: `Missing required scope(s): ${requiredScopes.join(", ")}`
974
+ },
975
+ 403
976
+ );
977
+ }
978
+ await next();
979
+ };
980
+ }
981
+ function requireAnyScope(needed) {
982
+ return async (c, next) => {
983
+ if (!hasAnyScope(c, needed)) {
984
+ const { scopes, permissions } = getAuth(c);
985
+ return c.json(
986
+ {
987
+ error: "insufficient_scope",
988
+ required_any: needed,
989
+ granted_scopes: scopes,
990
+ granted_permissions: permissions,
991
+ message: `Missing at least one required scope from: ${needed.join(", ")}`
992
+ },
993
+ 403
994
+ );
995
+ }
996
+ await next();
997
+ };
998
+ }
999
+ var init_utils = __esm({
1000
+ "src/server/oauth/utils.ts"() {
1001
+ "use strict";
1002
+ __name(getAuth, "getAuth");
1003
+ __name(hasScope, "hasScope");
1004
+ __name(hasAnyScope, "hasAnyScope");
1005
+ __name(requireScope, "requireScope");
1006
+ __name(requireAnyScope, "requireAnyScope");
1007
+ }
1008
+ });
1009
+
1010
+ // src/server/oauth/index.ts
1011
+ var oauth_exports = {};
1012
+ __export(oauth_exports, {
1013
+ createBearerAuthMiddleware: () => createBearerAuthMiddleware,
1014
+ getAuth: () => getAuth,
1015
+ hasAnyScope: () => hasAnyScope,
1016
+ hasScope: () => hasScope,
1017
+ oauthAuth0Provider: () => oauthAuth0Provider,
1018
+ oauthCustomProvider: () => oauthCustomProvider,
1019
+ oauthKeycloakProvider: () => oauthKeycloakProvider,
1020
+ oauthSupabaseProvider: () => oauthSupabaseProvider,
1021
+ oauthWorkOSProvider: () => oauthWorkOSProvider,
1022
+ requireAnyScope: () => requireAnyScope,
1023
+ requireScope: () => requireScope,
1024
+ setupOAuthRoutes: () => setupOAuthRoutes
1025
+ });
1026
+ var init_oauth = __esm({
1027
+ "src/server/oauth/index.ts"() {
1028
+ "use strict";
1029
+ init_providers();
1030
+ init_middleware();
1031
+ init_routes();
1032
+ init_utils();
1033
+ }
1034
+ });
30
1035
 
31
1036
  // src/server/index.ts
32
1037
  var server_exports = {};
33
1038
  __export(server_exports, {
34
1039
  adaptConnectMiddleware: () => adaptConnectMiddleware,
35
1040
  adaptMiddleware: () => adaptMiddleware,
1041
+ array: () => array,
36
1042
  buildWidgetUrl: () => buildWidgetUrl,
37
1043
  createExternalUrlResource: () => createExternalUrlResource,
38
1044
  createMCPServer: () => createMCPServer,
39
1045
  createRawHtmlResource: () => createRawHtmlResource,
40
1046
  createRemoteDomResource: () => createRemoteDomResource,
41
1047
  createUIResourceFromDefinition: () => createUIResourceFromDefinition,
42
- isExpressMiddleware: () => isExpressMiddleware
1048
+ error: () => error,
1049
+ getAuth: () => getAuth,
1050
+ getRequestContext: () => getRequestContext,
1051
+ hasAnyScope: () => hasAnyScope,
1052
+ hasRequestContext: () => hasRequestContext,
1053
+ hasScope: () => hasScope,
1054
+ image: () => image,
1055
+ isExpressMiddleware: () => isExpressMiddleware,
1056
+ oauthAuth0Provider: () => oauthAuth0Provider,
1057
+ oauthCustomProvider: () => oauthCustomProvider,
1058
+ oauthKeycloakProvider: () => oauthKeycloakProvider,
1059
+ oauthSupabaseProvider: () => oauthSupabaseProvider,
1060
+ oauthWorkOSProvider: () => oauthWorkOSProvider,
1061
+ object: () => object,
1062
+ requireAnyScope: () => requireAnyScope,
1063
+ requireScope: () => requireScope,
1064
+ resource: () => resource,
1065
+ runWithContext: () => runWithContext,
1066
+ text: () => text,
1067
+ widget: () => widget
43
1068
  });
44
1069
  module.exports = __toCommonJS(server_exports);
45
1070
 
46
1071
  // src/server/mcp-server.ts
47
1072
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
48
- var import_hono = require("hono");
49
- var import_cors = require("hono/cors");
50
1073
  var import_zod = require("zod");
1074
+ var import_hono = require("hono");
1075
+ var import_cors2 = require("hono/cors");
1076
+
1077
+ // src/server/context-storage.ts
1078
+ var import_node_async_hooks = require("async_hooks");
1079
+ var requestContextStorage = new import_node_async_hooks.AsyncLocalStorage();
1080
+ async function runWithContext(context, fn) {
1081
+ return requestContextStorage.run(context, fn);
1082
+ }
1083
+ __name(runWithContext, "runWithContext");
1084
+ function getRequestContext() {
1085
+ return requestContextStorage.getStore();
1086
+ }
1087
+ __name(getRequestContext, "getRequestContext");
1088
+ function hasRequestContext() {
1089
+ return requestContextStorage.getStore() !== void 0;
1090
+ }
1091
+ __name(hasRequestContext, "hasRequestContext");
51
1092
 
52
1093
  // src/server/adapters/mcp-ui-adapter.ts
53
1094
  var import_server = require("@mcp-ui/server");
54
- function buildWidgetUrl(widget, props, config) {
1095
+ function buildWidgetUrl(widget2, props, config) {
55
1096
  const url = new URL(
56
- `/mcp-use/widgets/${widget}`,
1097
+ `/mcp-use/widgets/${widget2}`,
57
1098
  `${config.baseUrl}:${config.port}`
58
1099
  );
59
1100
  if (props && Object.keys(props).length > 0) {
@@ -93,17 +1134,17 @@ function createRemoteDomResource(uri, script, framework = "react", encoding = "t
93
1134
  }
94
1135
  __name(createRemoteDomResource, "createRemoteDomResource");
95
1136
  function createAppsSdkResource(uri, htmlTemplate, metadata) {
96
- const resource = {
1137
+ const resource2 = {
97
1138
  uri,
98
1139
  mimeType: "text/html+skybridge",
99
1140
  text: htmlTemplate
100
1141
  };
101
1142
  if (metadata && Object.keys(metadata).length > 0) {
102
- resource._meta = metadata;
1143
+ resource2._meta = metadata;
103
1144
  }
104
1145
  return {
105
1146
  type: "resource",
106
- resource
1147
+ resource: resource2
107
1148
  };
108
1149
  }
109
1150
  __name(createAppsSdkResource, "createAppsSdkResource");
@@ -199,11 +1240,11 @@ async function adaptConnectMiddleware(connectMiddleware, middlewarePath) {
199
1240
  const httpMocks = await import("node-mocks-http");
200
1241
  createRequest = httpMocks.createRequest;
201
1242
  createResponse = httpMocks.createResponse;
202
- } catch (error) {
1243
+ } catch (error2) {
203
1244
  console.error(
204
1245
  "[WIDGETS] node-mocks-http not available. Install connect and node-mocks-http for Vite middleware support."
205
1246
  );
206
- throw error;
1247
+ throw error2;
207
1248
  }
208
1249
  let normalizedPath = middlewarePath;
209
1250
  if (normalizedPath.endsWith("*")) {
@@ -416,7 +1457,7 @@ async function requestLogger(c, next) {
416
1457
  } else {
417
1458
  console.log("\x1B[33mResponse Body:\x1B[0m (no body)");
418
1459
  }
419
- } catch (error) {
1460
+ } catch (error2) {
420
1461
  console.log("\x1B[33mResponse Body:\x1B[0m (unable to read)");
421
1462
  }
422
1463
  console.log("\x1B[36m" + "=".repeat(80) + "\x1B[0m\n");
@@ -425,90 +1466,8 @@ async function requestLogger(c, next) {
425
1466
  __name(requestLogger, "requestLogger");
426
1467
 
427
1468
  // src/server/mcp-server.ts
428
- function generateUUID() {
429
- return globalThis.crypto.randomUUID();
430
- }
431
- __name(generateUUID, "generateUUID");
1469
+ init_runtime();
432
1470
  var TMP_MCP_USE_DIR = ".mcp-use";
433
- var isDeno2 = typeof globalThis.Deno !== "undefined";
434
- function getEnv2(key) {
435
- if (isDeno2) {
436
- return globalThis.Deno.env.get(key);
437
- }
438
- return process.env[key];
439
- }
440
- __name(getEnv2, "getEnv");
441
- function getCwd() {
442
- if (isDeno2) {
443
- return globalThis.Deno.cwd();
444
- }
445
- return process.cwd();
446
- }
447
- __name(getCwd, "getCwd");
448
- var fsHelpers = {
449
- async readFileSync(path, encoding = "utf8") {
450
- if (isDeno2) {
451
- return await globalThis.Deno.readTextFile(path);
452
- }
453
- const { readFileSync } = await import("fs");
454
- const result = readFileSync(path, encoding);
455
- return typeof result === "string" ? result : result.toString(encoding);
456
- },
457
- async readFile(path) {
458
- if (isDeno2) {
459
- const data = await globalThis.Deno.readFile(path);
460
- return data.buffer;
461
- }
462
- const { readFileSync } = await import("fs");
463
- const buffer = readFileSync(path);
464
- return buffer.buffer.slice(
465
- buffer.byteOffset,
466
- buffer.byteOffset + buffer.byteLength
467
- );
468
- },
469
- async existsSync(path) {
470
- if (isDeno2) {
471
- try {
472
- await globalThis.Deno.stat(path);
473
- return true;
474
- } catch {
475
- return false;
476
- }
477
- }
478
- const { existsSync } = await import("fs");
479
- return existsSync(path);
480
- },
481
- async readdirSync(path) {
482
- if (isDeno2) {
483
- const entries = [];
484
- for await (const entry of globalThis.Deno.readDir(path)) {
485
- entries.push(entry.name);
486
- }
487
- return entries;
488
- }
489
- const { readdirSync } = await import("fs");
490
- return readdirSync(path);
491
- }
492
- };
493
- var pathHelpers = {
494
- join(...paths) {
495
- if (isDeno2) {
496
- return paths.join("/").replace(/\/+/g, "/");
497
- }
498
- return paths.join("/").replace(/\/+/g, "/");
499
- },
500
- relative(from, to) {
501
- const fromParts = from.split("/").filter((p) => p);
502
- const toParts = to.split("/").filter((p) => p);
503
- let i = 0;
504
- while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
505
- i++;
506
- }
507
- const upCount = fromParts.length - i;
508
- const relativeParts = [...Array(upCount).fill(".."), ...toParts.slice(i)];
509
- return relativeParts.join("/");
510
- }
511
- };
512
1471
  var McpServer = class {
513
1472
  static {
514
1473
  __name(this, "McpServer");
@@ -527,6 +1486,13 @@ var McpServer = class {
527
1486
  buildId;
528
1487
  sessions = /* @__PURE__ */ new Map();
529
1488
  idleCleanupInterval;
1489
+ oauthProvider;
1490
+ // OAuthProvider from oauth/index.js
1491
+ oauthMiddleware;
1492
+ // Bearer auth middleware
1493
+ oauthConfig;
1494
+ // Store OAuth config for lazy initialization
1495
+ oauthSetupComplete = false;
530
1496
  /**
531
1497
  * Creates a new MCP server instance with Hono integration
532
1498
  *
@@ -548,7 +1514,7 @@ var McpServer = class {
548
1514
  this.app = new import_hono.Hono();
549
1515
  this.app.use(
550
1516
  "*",
551
- (0, import_cors.cors)({
1517
+ (0, import_cors2.cors)({
552
1518
  origin: "*",
553
1519
  allowMethods: ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"],
554
1520
  allowHeaders: [
@@ -565,6 +1531,9 @@ var McpServer = class {
565
1531
  })
566
1532
  );
567
1533
  this.app.use("*", requestLogger);
1534
+ if (config.oauth) {
1535
+ this.oauthConfig = config.oauth;
1536
+ }
568
1537
  return new Proxy(this, {
569
1538
  get(target, prop) {
570
1539
  if (prop === "use") {
@@ -645,6 +1614,42 @@ var McpServer = class {
645
1614
  console.log("[CSP] Parsed CSP URLs:", urls);
646
1615
  return urls;
647
1616
  }
1617
+ /**
1618
+ * Setup OAuth authentication
1619
+ *
1620
+ * Initializes OAuth provider, creates bearer auth middleware,
1621
+ * sets up OAuth routes, and applies auth to /mcp endpoints.
1622
+ *
1623
+ * @private
1624
+ */
1625
+ async setupOAuth(oauthProvider) {
1626
+ if (this.oauthSetupComplete) {
1627
+ return;
1628
+ }
1629
+ const { setupOAuthRoutes: setupOAuthRoutes2, createBearerAuthMiddleware: createBearerAuthMiddleware2 } = await Promise.resolve().then(() => (init_oauth(), oauth_exports));
1630
+ this.oauthProvider = oauthProvider;
1631
+ console.log(`[OAuth] OAuth provider initialized`);
1632
+ const baseUrl = this.getServerBaseUrl();
1633
+ this.oauthMiddleware = createBearerAuthMiddleware2(
1634
+ this.oauthProvider,
1635
+ baseUrl
1636
+ );
1637
+ setupOAuthRoutes2(this.app, this.oauthProvider, baseUrl);
1638
+ const mode = this.oauthProvider.getMode?.() || "proxy";
1639
+ if (mode === "direct") {
1640
+ console.log(
1641
+ "[OAuth] Direct mode: Clients will authenticate with provider directly"
1642
+ );
1643
+ console.log("[OAuth] Metadata endpoints: /.well-known/*");
1644
+ } else {
1645
+ console.log(
1646
+ "[OAuth] Proxy mode: Routes at /authorize, /token, /.well-known/*"
1647
+ );
1648
+ }
1649
+ this.app.use("/mcp/*", this.oauthMiddleware);
1650
+ console.log("[OAuth] Bearer authentication enabled on /mcp routes");
1651
+ this.oauthSetupComplete = true;
1652
+ }
648
1653
  /**
649
1654
  * Define a static resource that can be accessed by clients
650
1655
  *
@@ -771,46 +1776,22 @@ var McpServer = class {
771
1776
  this.registeredResources.push(resourceTemplateDefinition.name);
772
1777
  return this;
773
1778
  }
774
- /**
775
- * Define a tool that can be called by clients
776
- *
777
- * Registers a tool with the MCP server that clients can invoke with parameters.
778
- * Tools are functions that perform actions, computations, or operations and
779
- * return results. They accept structured input parameters and return structured output.
780
- *
781
- * Supports Apps SDK metadata for ChatGPT integration via the _meta field.
782
- *
783
- * @param toolDefinition - Configuration object containing tool metadata and handler function
784
- * @param toolDefinition.name - Unique identifier for the tool
785
- * @param toolDefinition.description - Human-readable description of what the tool does
786
- * @param toolDefinition.inputs - Array of input parameter definitions with types and validation
787
- * @param toolDefinition.cb - Async callback function that executes the tool logic with provided parameters
788
- * @param toolDefinition._meta - Optional metadata for the tool (e.g. Apps SDK metadata)
789
- * @returns The server instance for method chaining
790
- *
791
- * @example
792
- * ```typescript
793
- * server.tool({
794
- * name: 'calculate',
795
- * description: 'Performs mathematical calculations',
796
- * inputs: [
797
- * { name: 'expression', type: 'string', required: true },
798
- * { name: 'precision', type: 'number', required: false }
799
- * ],
800
- * cb: async ({ expression, precision = 2 }) => {
801
- * const result = eval(expression)
802
- * return { result: Number(result.toFixed(precision)) }
803
- * },
804
- * _meta: {
805
- * 'openai/outputTemplate': 'ui://widgets/calculator',
806
- * 'openai/toolInvocation/invoking': 'Calculating...',
807
- * 'openai/toolInvocation/invoked': 'Calculation complete'
808
- * }
809
- * })
810
- * ```
811
- */
812
- tool(toolDefinition) {
813
- const inputSchema = this.createParamsSchema(toolDefinition.inputs || []);
1779
+ // Implementation
1780
+ tool(toolDefinition, callback) {
1781
+ const actualCallback = callback || toolDefinition.cb;
1782
+ if (!actualCallback) {
1783
+ throw new Error(
1784
+ `Tool '${toolDefinition.name}' must have either a cb property or a callback parameter`
1785
+ );
1786
+ }
1787
+ let inputSchema;
1788
+ if (toolDefinition.schema) {
1789
+ inputSchema = this.convertZodSchemaToParams(toolDefinition.schema);
1790
+ } else if (toolDefinition.inputs && toolDefinition.inputs.length > 0) {
1791
+ inputSchema = this.createParamsSchema(toolDefinition.inputs);
1792
+ } else {
1793
+ inputSchema = {};
1794
+ }
814
1795
  this.server.registerTool(
815
1796
  toolDefinition.name,
816
1797
  {
@@ -821,101 +1802,95 @@ var McpServer = class {
821
1802
  _meta: toolDefinition._meta
822
1803
  },
823
1804
  async (params, extra) => {
1805
+ let requestContext = getRequestContext();
1806
+ if (!requestContext) {
1807
+ for (const [, session] of this.sessions.entries()) {
1808
+ if (session.context) {
1809
+ requestContext = session.context;
1810
+ break;
1811
+ }
1812
+ }
1813
+ }
824
1814
  const progressToken = extra?._meta?.progressToken;
825
- const context = {
826
- /**
827
- * Request sampling from the client's LLM with automatic progress notifications.
828
- *
829
- * Progress notifications are sent every 5 seconds (configurable) while waiting
830
- * for the sampling response. This prevents client-side timeouts when
831
- * resetTimeoutOnProgress is enabled.
832
- *
833
- * @param params - Sampling parameters (messages, model preferences, etc.)
834
- * @param options - Optional configuration
835
- * @param options.timeout - Timeout in milliseconds (default: no timeout / Infinity)
836
- * @param options.progressIntervalMs - Interval between progress notifications (default: 5000ms)
837
- * @param options.onProgress - Optional callback called each time progress is reported
838
- * @returns The sampling result from the client's LLM
839
- */
840
- sample: /* @__PURE__ */ __name(async (sampleParams, options) => {
841
- const {
842
- timeout,
843
- progressIntervalMs = 5e3,
844
- onProgress
845
- } = options ?? {};
846
- let progressCount = 0;
847
- let completed = false;
848
- let progressInterval = null;
849
- if (progressToken && extra?.sendNotification) {
850
- progressInterval = setInterval(async () => {
851
- if (completed) return;
852
- progressCount++;
853
- const progressData = {
854
- progress: progressCount,
855
- total: void 0,
856
- message: `Waiting for LLM response... (${progressCount * Math.round(progressIntervalMs / 1e3)}s elapsed)`
857
- };
858
- if (onProgress) {
859
- try {
860
- onProgress(progressData);
861
- } catch {
862
- }
863
- }
1815
+ const enhancedContext = requestContext ? Object.create(requestContext) : {};
1816
+ enhancedContext.sample = async (sampleParams, options) => {
1817
+ const {
1818
+ timeout,
1819
+ progressIntervalMs = 5e3,
1820
+ onProgress
1821
+ } = options ?? {};
1822
+ let progressCount = 0;
1823
+ let completed = false;
1824
+ let progressInterval = null;
1825
+ if (progressToken && extra?.sendNotification) {
1826
+ progressInterval = setInterval(async () => {
1827
+ if (completed) return;
1828
+ progressCount++;
1829
+ const progressData = {
1830
+ progress: progressCount,
1831
+ total: void 0,
1832
+ message: `Waiting for LLM response... (${progressCount * Math.round(progressIntervalMs / 1e3)}s elapsed)`
1833
+ };
1834
+ if (onProgress) {
864
1835
  try {
865
- await extra.sendNotification({
866
- method: "notifications/progress",
867
- params: {
868
- progressToken,
869
- progress: progressData.progress,
870
- total: progressData.total,
871
- message: progressData.message
872
- }
873
- });
1836
+ onProgress(progressData);
874
1837
  } catch {
875
1838
  }
876
- }, progressIntervalMs);
877
- }
878
- try {
879
- const samplePromise = this.createMessage(sampleParams);
880
- if (timeout && timeout !== Infinity) {
881
- const timeoutPromise = new Promise((_, reject) => {
882
- setTimeout(
883
- () => reject(
884
- new Error(`Sampling timed out after ${timeout}ms`)
885
- ),
886
- timeout
887
- );
888
- });
889
- return await Promise.race([samplePromise, timeoutPromise]);
890
1839
  }
891
- return await samplePromise;
892
- } finally {
893
- completed = true;
894
- if (progressInterval) {
895
- clearInterval(progressInterval);
1840
+ try {
1841
+ await extra.sendNotification({
1842
+ method: "notifications/progress",
1843
+ params: {
1844
+ progressToken,
1845
+ progress: progressData.progress,
1846
+ total: progressData.total,
1847
+ message: progressData.message
1848
+ }
1849
+ });
1850
+ } catch {
896
1851
  }
1852
+ }, progressIntervalMs);
1853
+ }
1854
+ try {
1855
+ const samplePromise = this.createMessage(sampleParams);
1856
+ if (timeout && timeout !== Infinity) {
1857
+ const timeoutPromise = new Promise((_, reject) => {
1858
+ setTimeout(
1859
+ () => reject(new Error(`Sampling timed out after ${timeout}ms`)),
1860
+ timeout
1861
+ );
1862
+ });
1863
+ return await Promise.race([samplePromise, timeoutPromise]);
897
1864
  }
898
- }, "sample"),
899
- /**
900
- * Send a progress notification to the client.
901
- * Only works if the client requested progress updates for this tool call.
902
- */
903
- reportProgress: progressToken && extra?.sendNotification ? async (progress, total, message) => {
904
- await extra.sendNotification({
905
- method: "notifications/progress",
906
- params: {
907
- progressToken,
908
- progress,
909
- total,
910
- message
911
- }
912
- });
913
- } : void 0
1865
+ return await samplePromise;
1866
+ } finally {
1867
+ completed = true;
1868
+ if (progressInterval) {
1869
+ clearInterval(progressInterval);
1870
+ }
1871
+ }
914
1872
  };
915
- if (toolDefinition.cb.length >= 2) {
916
- return await toolDefinition.cb(params, context);
1873
+ enhancedContext.reportProgress = progressToken && extra?.sendNotification ? async (progress, total, message) => {
1874
+ await extra.sendNotification({
1875
+ method: "notifications/progress",
1876
+ params: {
1877
+ progressToken,
1878
+ progress,
1879
+ total,
1880
+ message
1881
+ }
1882
+ });
1883
+ } : void 0;
1884
+ const executeCallback = /* @__PURE__ */ __name(async () => {
1885
+ if (actualCallback.length >= 2) {
1886
+ return await actualCallback(params, enhancedContext);
1887
+ }
1888
+ return await actualCallback(params);
1889
+ }, "executeCallback");
1890
+ if (requestContext) {
1891
+ return await runWithContext(requestContext, executeCallback);
917
1892
  }
918
- return await toolDefinition.cb(params);
1893
+ return await executeCallback();
919
1894
  }
920
1895
  );
921
1896
  this.registeredTools.push(toolDefinition.name);
@@ -1266,35 +2241,6 @@ var McpServer = class {
1266
2241
  }
1267
2242
  return `ui://widget/${parts.join("-")}${extension}`;
1268
2243
  }
1269
- /**
1270
- * Build a complete URL for a widget including query parameters
1271
- *
1272
- * Constructs the full URL to access a widget's iframe, encoding any provided
1273
- * parameters as query string parameters. Complex objects are JSON-stringified
1274
- * for transmission.
1275
- *
1276
- * @private
1277
- * @param widget - Widget name/identifier
1278
- * @param params - Parameters to encode in the URL
1279
- * @returns Complete URL with encoded parameters
1280
- */
1281
- buildWidgetUrl(widget, params) {
1282
- const baseUrl = `http://${this.serverHost}:${this.serverPort}/mcp-use/widgets/${widget}`;
1283
- if (Object.keys(params).length === 0) {
1284
- return baseUrl;
1285
- }
1286
- const queryParams = new URLSearchParams();
1287
- for (const [key, value] of Object.entries(params)) {
1288
- if (value !== void 0 && value !== null) {
1289
- if (typeof value === "object") {
1290
- queryParams.append(key, JSON.stringify(value));
1291
- } else {
1292
- queryParams.append(key, String(value));
1293
- }
1294
- }
1295
- }
1296
- return `${baseUrl}?${queryParams.toString()}`;
1297
- }
1298
2244
  /**
1299
2245
  * Convert widget props definition to tool input schema
1300
2246
  *
@@ -1403,7 +2349,7 @@ var McpServer = class {
1403
2349
  const srcDir = pathHelpers.join(getCwd(), resourcesDir);
1404
2350
  try {
1405
2351
  await fs.access(srcDir);
1406
- } catch (error) {
2352
+ } catch (error2) {
1407
2353
  console.log(
1408
2354
  `[WIDGETS] No ${resourcesDir}/ directory found - skipping widget serving`
1409
2355
  );
@@ -1437,7 +2383,7 @@ var McpServer = class {
1437
2383
  }
1438
2384
  }
1439
2385
  }
1440
- } catch (error) {
2386
+ } catch (error2) {
1441
2387
  console.log(`[WIDGETS] No widgets found in ${resourcesDir}/ directory`);
1442
2388
  return;
1443
2389
  }
@@ -1462,7 +2408,7 @@ var McpServer = class {
1462
2408
  'return import("@tailwindcss/vite")'
1463
2409
  )();
1464
2410
  tailwindcss = tailwindModule.default;
1465
- } catch (error) {
2411
+ } catch (error2) {
1466
2412
  console.error(
1467
2413
  "[WIDGETS] Dev dependencies not available. Install vite, @vitejs/plugin-react, and @tailwindcss/vite for widget development."
1468
2414
  );
@@ -1478,8 +2424,8 @@ var McpServer = class {
1478
2424
  entry: entry.path
1479
2425
  };
1480
2426
  });
1481
- for (const widget of widgets) {
1482
- const widgetTempDir = pathHelpers.join(tempDir, widget.name);
2427
+ for (const widget2 of widgets) {
2428
+ const widgetTempDir = pathHelpers.join(tempDir, widget2.name);
1483
2429
  await fs.mkdir(widgetTempDir, { recursive: true });
1484
2430
  const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
1485
2431
  const relativeResourcesPath = pathHelpers.relative(widgetTempDir, resourcesPath).replace(/\\/g, "/");
@@ -1496,7 +2442,7 @@ var McpServer = class {
1496
2442
  const entryContent = `import React from 'react'
1497
2443
  import { createRoot } from 'react-dom/client'
1498
2444
  import './styles.css'
1499
- import Component from '${widget.entry}'
2445
+ import Component from '${widget2.entry}'
1500
2446
 
1501
2447
  const container = document.getElementById('widget-root')
1502
2448
  if (container && Component) {
@@ -1509,11 +2455,11 @@ if (container && Component) {
1509
2455
  <head>
1510
2456
  <meta charset="UTF-8" />
1511
2457
  <meta name="viewport" content="width=device-width,initial-scale=1" />
1512
- <title>${widget.name} Widget</title>
2458
+ <title>${widget2.name} Widget</title>
1513
2459
  </head>
1514
2460
  <body>
1515
2461
  <div id="widget-root"></div>
1516
- <script type="module" src="${baseRoute}/${widget.name}/entry.tsx"></script>
2462
+ <script type="module" src="${baseRoute}/${widget2.name}/entry.tsx"></script>
1517
2463
  </body>
1518
2464
  </html>`;
1519
2465
  await fs.writeFile(
@@ -1603,8 +2549,8 @@ if (container && Component) {
1603
2549
  const widgetMatch = pathname.replace(baseRoute, "").match(/^\/([^/]+)/);
1604
2550
  if (widgetMatch) {
1605
2551
  const widgetName = widgetMatch[1];
1606
- const widget = widgets.find((w) => w.name === widgetName);
1607
- if (widget) {
2552
+ const widget2 = widgets.find((w) => w.name === widgetName);
2553
+ if (widget2) {
1608
2554
  const relativePath = pathname.replace(baseRoute, "");
1609
2555
  if (relativePath === `/${widgetName}` || relativePath === `/${widgetName}/`) {
1610
2556
  const newUrl = new URL(c.req.url);
@@ -1655,42 +2601,42 @@ if (container && Component) {
1655
2601
  const message = isAsset ? "Widget asset not found" : "Widget not found";
1656
2602
  return c.text(message, 404);
1657
2603
  });
1658
- widgets.forEach((widget) => {
2604
+ widgets.forEach((widget2) => {
1659
2605
  console.log(
1660
- `[WIDGET] ${widget.name} mounted at ${baseRoute}/${widget.name}`
2606
+ `[WIDGET] ${widget2.name} mounted at ${baseRoute}/${widget2.name}`
1661
2607
  );
1662
2608
  });
1663
- for (const widget of widgets) {
2609
+ for (const widget2 of widgets) {
1664
2610
  const type = "appsSdk";
1665
2611
  let metadata = {};
1666
2612
  let props = {};
1667
- let description = widget.description;
2613
+ let description = widget2.description;
1668
2614
  try {
1669
- const mod = await viteServer.ssrLoadModule(widget.entry);
2615
+ const mod = await viteServer.ssrLoadModule(widget2.entry);
1670
2616
  if (mod.widgetMetadata) {
1671
2617
  metadata = mod.widgetMetadata;
1672
- description = metadata.description || widget.description;
2618
+ description = metadata.description || widget2.description;
1673
2619
  if (metadata.inputs) {
1674
2620
  try {
1675
2621
  props = metadata.inputs.shape || {};
1676
- } catch (error) {
2622
+ } catch (error2) {
1677
2623
  console.warn(
1678
- `[WIDGET] Failed to extract props schema for ${widget.name}:`,
1679
- error
2624
+ `[WIDGET] Failed to extract props schema for ${widget2.name}:`,
2625
+ error2
1680
2626
  );
1681
2627
  }
1682
2628
  }
1683
2629
  }
1684
- } catch (error) {
2630
+ } catch (error2) {
1685
2631
  console.warn(
1686
- `[WIDGET] Failed to load metadata for ${widget.name}:`,
1687
- error
2632
+ `[WIDGET] Failed to load metadata for ${widget2.name}:`,
2633
+ error2
1688
2634
  );
1689
2635
  }
1690
2636
  let html = "";
1691
2637
  try {
1692
2638
  html = await fsHelpers.readFileSync(
1693
- pathHelpers.join(tempDir, widget.name, "index.html"),
2639
+ pathHelpers.join(tempDir, widget2.name, "index.html"),
1694
2640
  "utf8"
1695
2641
  );
1696
2642
  const mcpUrl = this.getServerBaseUrl();
@@ -1728,25 +2674,25 @@ if (container && Component) {
1728
2674
  html = html.replace(
1729
2675
  /<head[^>]*>/i,
1730
2676
  `<head>
1731
- <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget.name}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
2677
+ <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget2.name}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
1732
2678
  );
1733
- } catch (error) {
2679
+ } catch (error2) {
1734
2680
  console.error(
1735
- `Failed to read html template for widget ${widget.name}`,
1736
- error
2681
+ `Failed to read html template for widget ${widget2.name}`,
2682
+ error2
1737
2683
  );
1738
2684
  }
1739
2685
  const mcp_connect_domain = this.getServerBaseUrl() ? new URL(this.getServerBaseUrl() || "").origin : null;
1740
2686
  this.uiResource({
1741
- name: widget.name,
1742
- title: metadata.title || widget.name,
2687
+ name: widget2.name,
2688
+ title: metadata.title || widget2.name,
1743
2689
  description,
1744
2690
  type,
1745
2691
  props,
1746
2692
  _meta: {
1747
2693
  "mcp-use/widget": {
1748
- name: widget.name,
1749
- title: metadata.title || widget.name,
2694
+ name: widget2.name,
2695
+ title: metadata.title || widget2.name,
1750
2696
  description,
1751
2697
  type,
1752
2698
  props,
@@ -1758,8 +2704,8 @@ if (container && Component) {
1758
2704
  htmlTemplate: html,
1759
2705
  appsSdkMetadata: {
1760
2706
  "openai/widgetDescription": description,
1761
- "openai/toolInvocation/invoking": `Loading ${widget.name}...`,
1762
- "openai/toolInvocation/invoked": `${widget.name} ready`,
2707
+ "openai/toolInvocation/invoking": `Loading ${widget2.name}...`,
2708
+ "openai/toolInvocation/invoked": `${widget2.name} ready`,
1763
2709
  "openai/widgetAccessible": true,
1764
2710
  "openai/resultCanProduceWidget": true,
1765
2711
  ...metadata.appsSdkMetadata || {},
@@ -1832,10 +2778,10 @@ if (container && Component) {
1832
2778
  } else {
1833
2779
  console.log("[WIDGETS] No widgets found in manifest");
1834
2780
  }
1835
- } catch (error) {
2781
+ } catch (error2) {
1836
2782
  console.log(
1837
2783
  "[WIDGETS] Could not read manifest file, falling back to directory listing:",
1838
- error
2784
+ error2
1839
2785
  );
1840
2786
  try {
1841
2787
  const allEntries = await fsHelpers.readdirSync(widgetsDir);
@@ -1900,10 +2846,10 @@ if (container && Component) {
1900
2846
  <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widgetName}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
1901
2847
  );
1902
2848
  }
1903
- } catch (error) {
2849
+ } catch (error2) {
1904
2850
  console.error(
1905
2851
  `[WIDGET] Failed to read ${widgetName}/index.html:`,
1906
- error
2852
+ error2
1907
2853
  );
1908
2854
  continue;
1909
2855
  }
@@ -2030,7 +2976,7 @@ if (container && Component) {
2030
2976
  if (closeOldSessionId && this.sessions.has(closeOldSessionId)) {
2031
2977
  try {
2032
2978
  this.sessions.get(closeOldSessionId).transport.close();
2033
- } catch (error) {
2979
+ } catch (error2) {
2034
2980
  }
2035
2981
  this.sessions.delete(closeOldSessionId);
2036
2982
  }
@@ -2161,7 +3107,7 @@ if (container && Component) {
2161
3107
  if (now - session.lastAccessedAt > idleTimeoutMs) {
2162
3108
  try {
2163
3109
  session.transport.close();
2164
- } catch (error) {
3110
+ } catch (error2) {
2165
3111
  }
2166
3112
  this.sessions.delete(sessionId);
2167
3113
  }
@@ -2317,19 +3263,23 @@ if (container && Component) {
2317
3263
  }
2318
3264
  }
2319
3265
  if (sessionId && this.sessions.has(sessionId)) {
2320
- this.sessions.get(sessionId).lastAccessedAt = Date.now();
3266
+ const session = this.sessions.get(sessionId);
3267
+ session.lastAccessedAt = Date.now();
3268
+ session.context = c;
2321
3269
  }
2322
3270
  if (expressRes._closeHandler) {
2323
3271
  c.req.raw.signal?.addEventListener("abort", () => {
2324
3272
  transport.close();
2325
3273
  });
2326
3274
  }
2327
- await this.waitForRequestComplete(
2328
- transport,
2329
- expressReq,
2330
- expressRes,
2331
- expressReq.body
2332
- );
3275
+ await runWithContext(c, async () => {
3276
+ await this.waitForRequestComplete(
3277
+ transport,
3278
+ expressReq,
3279
+ expressRes,
3280
+ expressReq.body
3281
+ );
3282
+ });
2333
3283
  const response = getResponse();
2334
3284
  if (response) {
2335
3285
  return response;
@@ -2573,6 +3523,9 @@ if (container && Component) {
2573
3523
  if (hostEnv) {
2574
3524
  this.serverHost = hostEnv;
2575
3525
  }
3526
+ if (this.oauthConfig && !this.oauthSetupComplete) {
3527
+ await this.setupOAuth(this.oauthConfig);
3528
+ }
2576
3529
  await this.mountWidgets({
2577
3530
  baseRoute: "/mcp-use/widgets",
2578
3531
  resourcesDir: "resources"
@@ -2681,6 +3634,9 @@ if (container && Component) {
2681
3634
  * ```
2682
3635
  */
2683
3636
  async getHandler(options) {
3637
+ if (this.oauthConfig && !this.oauthSetupComplete) {
3638
+ await this.setupOAuth(this.oauthConfig);
3639
+ }
2684
3640
  console.log("[MCP] Mounting widgets");
2685
3641
  await this.mountWidgets({
2686
3642
  baseRoute: "/mcp-use/widgets",
@@ -2784,10 +3740,10 @@ if (container && Component) {
2784
3740
  for (const [sessionId, session] of this.sessions.entries()) {
2785
3741
  try {
2786
3742
  await session.transport.send(notification);
2787
- } catch (error) {
3743
+ } catch (error2) {
2788
3744
  console.warn(
2789
3745
  `[MCP] Failed to send notification to session ${sessionId}:`,
2790
- error
3746
+ error2
2791
3747
  );
2792
3748
  }
2793
3749
  }
@@ -2832,10 +3788,10 @@ if (container && Component) {
2832
3788
  try {
2833
3789
  await session.transport.send(notification);
2834
3790
  return true;
2835
- } catch (error) {
3791
+ } catch (error2) {
2836
3792
  console.warn(
2837
3793
  `[MCP] Failed to send notification to session ${sessionId}:`,
2838
- error
3794
+ error2
2839
3795
  );
2840
3796
  return false;
2841
3797
  }
@@ -2903,10 +3859,10 @@ if (container && Component) {
2903
3859
  return response.roots;
2904
3860
  }
2905
3861
  return [];
2906
- } catch (error) {
3862
+ } catch (error2) {
2907
3863
  console.warn(
2908
3864
  `[MCP] Failed to list roots from session ${sessionId}:`,
2909
- error
3865
+ error2
2910
3866
  );
2911
3867
  return null;
2912
3868
  }
@@ -2984,14 +3940,14 @@ if (container && Component) {
2984
3940
  */
2985
3941
  setupWidgetRoutes() {
2986
3942
  this.app.get("/mcp-use/widgets/:widget/assets/*", async (c) => {
2987
- const widget = c.req.param("widget");
3943
+ const widget2 = c.req.param("widget");
2988
3944
  const assetFile = c.req.path.split("/assets/")[1];
2989
3945
  const assetPath = pathHelpers.join(
2990
3946
  getCwd(),
2991
3947
  "dist",
2992
3948
  "resources",
2993
3949
  "widgets",
2994
- widget,
3950
+ widget2,
2995
3951
  "assets",
2996
3952
  assetFile
2997
3953
  );
@@ -3020,10 +3976,10 @@ if (container && Component) {
3020
3976
  );
3021
3977
  try {
3022
3978
  const widgets = await fsHelpers.readdirSync(widgetsDir);
3023
- for (const widget of widgets) {
3979
+ for (const widget2 of widgets) {
3024
3980
  const assetPath = pathHelpers.join(
3025
3981
  widgetsDir,
3026
- widget,
3982
+ widget2,
3027
3983
  "assets",
3028
3984
  assetFile
3029
3985
  );
@@ -3043,13 +3999,13 @@ if (container && Component) {
3043
3999
  }
3044
4000
  });
3045
4001
  this.app.get("/mcp-use/widgets/:widget", async (c) => {
3046
- const widget = c.req.param("widget");
4002
+ const widget2 = c.req.param("widget");
3047
4003
  const filePath = pathHelpers.join(
3048
4004
  getCwd(),
3049
4005
  "dist",
3050
4006
  "resources",
3051
4007
  "widgets",
3052
- widget,
4008
+ widget2,
3053
4009
  "index.html"
3054
4010
  );
3055
4011
  try {
@@ -3066,7 +4022,7 @@ if (container && Component) {
3066
4022
  html = html.replace(
3067
4023
  /<head[^>]*>/i,
3068
4024
  `<head>
3069
- <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget}/"+filename }</script>`
4025
+ <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget2}/"+filename }</script>`
3070
4026
  );
3071
4027
  return c.html(html);
3072
4028
  } catch {
@@ -3093,28 +4049,21 @@ if (container && Component) {
3093
4049
  });
3094
4050
  }
3095
4051
  /**
3096
- * Create input schema for resource templates
3097
- *
3098
- * Parses a URI template string to extract parameter names and generates a Zod
3099
- * validation schema for those parameters. Used internally for validating resource
3100
- * template parameters before processing requests.
4052
+ * Convert a Zod object schema to the internal Record<string, z.ZodSchema> format
3101
4053
  *
3102
- * @param uriTemplate - URI template string with parameter placeholders (e.g., "/users/{id}/posts/{postId}")
3103
- * @returns Object mapping parameter names to Zod string schemas
3104
- *
3105
- * @example
3106
- * ```typescript
3107
- * const schema = this.createInputSchema("/users/{id}/posts/{postId}")
3108
- * // Returns: { id: z.string(), postId: z.string() }
3109
- * ```
4054
+ * @param zodSchema - Zod object schema to convert
4055
+ * @returns Object mapping parameter names to Zod validation schemas
3110
4056
  */
3111
- createInputSchema(uriTemplate) {
3112
- const params = this.extractTemplateParams(uriTemplate);
3113
- const schema = {};
3114
- params.forEach((param) => {
3115
- schema[param] = import_zod.z.string();
3116
- });
3117
- return schema;
4057
+ convertZodSchemaToParams(zodSchema) {
4058
+ if (!(zodSchema instanceof import_zod.z.ZodObject)) {
4059
+ throw new Error("schema must be a Zod object schema (z.object({...}))");
4060
+ }
4061
+ const shape = zodSchema.shape;
4062
+ const params = {};
4063
+ for (const [key, value] of Object.entries(shape)) {
4064
+ params[key] = value;
4065
+ }
4066
+ return params;
3118
4067
  }
3119
4068
  /**
3120
4069
  * Create input schema for tools
@@ -3168,75 +4117,6 @@ if (container && Component) {
3168
4117
  });
3169
4118
  return schema;
3170
4119
  }
3171
- /**
3172
- * Create arguments schema for prompts
3173
- *
3174
- * Converts prompt argument definitions into Zod validation schemas for runtime validation.
3175
- * Supports common data types (string, number, boolean, object, array) and optional
3176
- * parameters. Used internally when registering prompt templates with the MCP server.
3177
- *
3178
- * @param inputs - Array of argument definitions with name, type, and optional flag
3179
- * @returns Object mapping argument names to Zod validation schemas
3180
- *
3181
- * @example
3182
- * ```typescript
3183
- * const schema = this.createPromptArgsSchema([
3184
- * { name: 'topic', type: 'string', required: true },
3185
- * { name: 'style', type: 'string', required: false }
3186
- * ])
3187
- * // Returns: { topic: z.string(), style: z.string().optional() }
3188
- * ```
3189
- */
3190
- createPromptArgsSchema(inputs) {
3191
- const schema = {};
3192
- inputs.forEach((input) => {
3193
- let zodType;
3194
- switch (input.type) {
3195
- case "string":
3196
- zodType = import_zod.z.string();
3197
- break;
3198
- case "number":
3199
- zodType = import_zod.z.number();
3200
- break;
3201
- case "boolean":
3202
- zodType = import_zod.z.boolean();
3203
- break;
3204
- case "object":
3205
- zodType = import_zod.z.object({});
3206
- break;
3207
- case "array":
3208
- zodType = import_zod.z.array(import_zod.z.any());
3209
- break;
3210
- default:
3211
- zodType = import_zod.z.any();
3212
- }
3213
- if (!input.required) {
3214
- zodType = zodType.optional();
3215
- }
3216
- schema[input.name] = zodType;
3217
- });
3218
- return schema;
3219
- }
3220
- /**
3221
- * Extract parameter names from URI template
3222
- *
3223
- * Parses a URI template string to extract parameter names enclosed in curly braces.
3224
- * Used internally to identify dynamic parameters in resource templates and generate
3225
- * appropriate validation schemas.
3226
- *
3227
- * @param uriTemplate - URI template string with parameter placeholders (e.g., "/users/{id}/posts/{postId}")
3228
- * @returns Array of parameter names found in the template
3229
- *
3230
- * @example
3231
- * ```typescript
3232
- * const params = this.extractTemplateParams("/users/{id}/posts/{postId}")
3233
- * // Returns: ["id", "postId"]
3234
- * ```
3235
- */
3236
- extractTemplateParams(uriTemplate) {
3237
- const matches = uriTemplate.match(/\{([^}]+)\}/g);
3238
- return matches ? matches.map((match) => match.slice(1, -1)) : [];
3239
- }
3240
4120
  /**
3241
4121
  * Parse parameter values from a URI based on a template
3242
4122
  *
@@ -3279,8 +4159,127 @@ function createMCPServer(name, config = {}) {
3279
4159
  host: config.host,
3280
4160
  baseUrl: config.baseUrl,
3281
4161
  allowedOrigins: config.allowedOrigins,
3282
- sessionIdleTimeoutMs: config.sessionIdleTimeoutMs
4162
+ sessionIdleTimeoutMs: config.sessionIdleTimeoutMs,
4163
+ autoCreateSessionOnInvalidId: config.autoCreateSessionOnInvalidId,
4164
+ oauth: config.oauth
3283
4165
  });
3284
4166
  return instance;
3285
4167
  }
3286
4168
  __name(createMCPServer, "createMCPServer");
4169
+
4170
+ // src/server/utils/response-helpers.ts
4171
+ function text(content) {
4172
+ return {
4173
+ content: [
4174
+ {
4175
+ type: "text",
4176
+ text: content
4177
+ }
4178
+ ]
4179
+ };
4180
+ }
4181
+ __name(text, "text");
4182
+ function image(data, mimeType = "image/png") {
4183
+ return {
4184
+ content: [
4185
+ {
4186
+ type: "image",
4187
+ data,
4188
+ mimeType
4189
+ }
4190
+ ]
4191
+ };
4192
+ }
4193
+ __name(image, "image");
4194
+ function resource(uri, mimeType, text2) {
4195
+ const resourceContent = {
4196
+ type: "resource",
4197
+ resource: {
4198
+ uri,
4199
+ ...mimeType && { mimeType },
4200
+ ...text2 && { text: text2 }
4201
+ }
4202
+ };
4203
+ return {
4204
+ content: [resourceContent]
4205
+ };
4206
+ }
4207
+ __name(resource, "resource");
4208
+ function error(message) {
4209
+ return {
4210
+ isError: true,
4211
+ content: [
4212
+ {
4213
+ type: "text",
4214
+ text: message
4215
+ }
4216
+ ]
4217
+ };
4218
+ }
4219
+ __name(error, "error");
4220
+ function object(data) {
4221
+ return Array.isArray(data) ? array(data) : {
4222
+ content: [
4223
+ {
4224
+ type: "text",
4225
+ text: JSON.stringify(data, null, 2)
4226
+ }
4227
+ ],
4228
+ structuredContent: data
4229
+ };
4230
+ }
4231
+ __name(object, "object");
4232
+ function array(data) {
4233
+ return {
4234
+ content: [
4235
+ {
4236
+ type: "text",
4237
+ text: JSON.stringify(data, null, 2)
4238
+ }
4239
+ ],
4240
+ structuredContent: { data }
4241
+ };
4242
+ }
4243
+ __name(array, "array");
4244
+ function widget(config) {
4245
+ const {
4246
+ name,
4247
+ data,
4248
+ message,
4249
+ invoking,
4250
+ invoked,
4251
+ widgetAccessible = true,
4252
+ resultCanProduceWidget = true,
4253
+ buildId
4254
+ } = config;
4255
+ const randomId = Math.random().toString(36).substring(2, 15);
4256
+ const buildIdPart = buildId ? `-${buildId}` : "";
4257
+ const uniqueUri = `ui://widget/${name}${buildIdPart}-${randomId}.html`;
4258
+ const metadata = {
4259
+ "openai/outputTemplate": uniqueUri,
4260
+ "openai/widgetAccessible": widgetAccessible,
4261
+ "openai/resultCanProduceWidget": resultCanProduceWidget
4262
+ };
4263
+ if (invoking) {
4264
+ metadata["openai/toolInvocation/invoking"] = invoking;
4265
+ }
4266
+ if (invoked) {
4267
+ metadata["openai/toolInvocation/invoked"] = invoked;
4268
+ }
4269
+ const displayMessage = message || `Displaying ${name}`;
4270
+ return {
4271
+ _meta: metadata,
4272
+ content: [
4273
+ {
4274
+ type: "text",
4275
+ text: displayMessage
4276
+ }
4277
+ ],
4278
+ // structuredContent will be injected as window.openai.toolOutput by Apps SDK
4279
+ structuredContent: data
4280
+ };
4281
+ }
4282
+ __name(widget, "widget");
4283
+
4284
+ // src/server/index.ts
4285
+ init_oauth();