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

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 (105) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/chunk-3R5PDYIN.js +403 -0
  3. package/dist/{chunk-BWOTID2D.js → chunk-AGKMD2ZM.js} +7 -350
  4. package/dist/{chunk-SJEHVCPM.js → chunk-BG2APH43.js} +120 -26
  5. package/dist/{chunk-YURRUCIM.js → chunk-CPG2WZUL.js} +9 -11
  6. package/dist/chunk-F4UHAA5L.js +854 -0
  7. package/dist/chunk-JQKKMUCT.js +0 -0
  8. package/dist/chunk-MTHLLDCX.js +97 -0
  9. package/dist/{chunk-MCF5P6GJ.js → chunk-S6K5QZBJ.js} +739 -29
  10. package/dist/{display-YIYC6WJE.js → display-A5IEINAP.js} +79 -17
  11. package/dist/index.cjs +1055 -136
  12. package/dist/index.js +14 -10
  13. package/dist/{langfuse-C4HKZ3NL.js → langfuse-N5Y5BSXK.js} +1 -1
  14. package/dist/oauth-U4NNKN4B.js +30 -0
  15. package/dist/src/agents/display.d.ts.map +1 -1
  16. package/dist/src/agents/index.cjs +854 -78
  17. package/dist/src/agents/index.js +3 -2
  18. package/dist/src/auth/browser-provider.d.ts +2 -0
  19. package/dist/src/auth/browser-provider.d.ts.map +1 -1
  20. package/dist/src/auth/callback.d.ts.map +1 -1
  21. package/dist/src/auth/index.cjs +421 -0
  22. package/dist/src/auth/index.js +10 -0
  23. package/dist/src/auth/types.d.ts +3 -1
  24. package/dist/src/auth/types.d.ts.map +1 -1
  25. package/dist/src/browser.cjs +924 -98
  26. package/dist/src/browser.js +8 -5
  27. package/dist/src/connectors/base.d.ts +52 -121
  28. package/dist/src/connectors/base.d.ts.map +1 -1
  29. package/dist/src/connectors/http.d.ts.map +1 -1
  30. package/dist/src/managers/server_manager.d.ts.map +1 -1
  31. package/dist/src/managers/tools/acquire_active_mcp_server.d.ts +2 -2
  32. package/dist/src/managers/tools/acquire_active_mcp_server.d.ts.map +1 -1
  33. package/dist/src/managers/tools/add_server_from_config.d.ts +1 -7
  34. package/dist/src/managers/tools/add_server_from_config.d.ts.map +1 -1
  35. package/dist/src/managers/tools/connect_mcp_server.d.ts +2 -10
  36. package/dist/src/managers/tools/connect_mcp_server.d.ts.map +1 -1
  37. package/dist/src/managers/tools/list_mcp_servers.d.ts +2 -2
  38. package/dist/src/managers/tools/list_mcp_servers.d.ts.map +1 -1
  39. package/dist/src/managers/tools/release_mcp_server_connection.d.ts +2 -2
  40. package/dist/src/managers/tools/release_mcp_server_connection.d.ts.map +1 -1
  41. package/dist/src/observability/langfuse.d.ts +4 -0
  42. package/dist/src/observability/langfuse.d.ts.map +1 -1
  43. package/dist/src/react/McpUseProvider.d.ts.map +1 -1
  44. package/dist/src/react/index.cjs +189 -41
  45. package/dist/src/react/index.js +4 -2
  46. package/dist/src/react/types.d.ts +12 -1
  47. package/dist/src/react/types.d.ts.map +1 -1
  48. package/dist/src/react/useMcp.d.ts.map +1 -1
  49. package/dist/src/server/connect-adapter.d.ts.map +1 -1
  50. package/dist/src/server/context-storage.d.ts +54 -0
  51. package/dist/src/server/context-storage.d.ts.map +1 -0
  52. package/dist/src/server/index.cjs +1413 -418
  53. package/dist/src/server/index.d.ts +4 -1
  54. package/dist/src/server/index.d.ts.map +1 -1
  55. package/dist/src/server/index.js +426 -420
  56. package/dist/src/server/mcp-server.d.ts +50 -81
  57. package/dist/src/server/mcp-server.d.ts.map +1 -1
  58. package/dist/src/server/oauth/index.d.ts +13 -0
  59. package/dist/src/server/oauth/index.d.ts.map +1 -0
  60. package/dist/src/server/oauth/middleware.d.ts +19 -0
  61. package/dist/src/server/oauth/middleware.d.ts.map +1 -0
  62. package/dist/src/server/oauth/providers/auth0.d.ts +22 -0
  63. package/dist/src/server/oauth/providers/auth0.d.ts.map +1 -0
  64. package/dist/src/server/oauth/providers/custom.d.ts +19 -0
  65. package/dist/src/server/oauth/providers/custom.d.ts.map +1 -0
  66. package/dist/src/server/oauth/providers/keycloak.d.ts +22 -0
  67. package/dist/src/server/oauth/providers/keycloak.d.ts.map +1 -0
  68. package/dist/src/server/oauth/providers/supabase.d.ts +24 -0
  69. package/dist/src/server/oauth/providers/supabase.d.ts.map +1 -0
  70. package/dist/src/server/oauth/providers/types.d.ts +138 -0
  71. package/dist/src/server/oauth/providers/types.d.ts.map +1 -0
  72. package/dist/src/server/oauth/providers/workos.d.ts +30 -0
  73. package/dist/src/server/oauth/providers/workos.d.ts.map +1 -0
  74. package/dist/src/server/oauth/providers.d.ts +208 -0
  75. package/dist/src/server/oauth/providers.d.ts.map +1 -0
  76. package/dist/src/server/oauth/routes.d.ts +33 -0
  77. package/dist/src/server/oauth/routes.d.ts.map +1 -0
  78. package/dist/src/server/oauth/utils.d.ts +155 -0
  79. package/dist/src/server/oauth/utils.d.ts.map +1 -0
  80. package/dist/src/server/types/common.d.ts +47 -0
  81. package/dist/src/server/types/common.d.ts.map +1 -1
  82. package/dist/src/server/types/context.d.ts +34 -0
  83. package/dist/src/server/types/context.d.ts.map +1 -0
  84. package/dist/src/server/types/index.d.ts +2 -1
  85. package/dist/src/server/types/index.d.ts.map +1 -1
  86. package/dist/src/server/types/tool.d.ts +82 -9
  87. package/dist/src/server/types/tool.d.ts.map +1 -1
  88. package/dist/src/server/utils/index.d.ts +6 -0
  89. package/dist/src/server/utils/index.d.ts.map +1 -0
  90. package/dist/src/server/utils/response-helpers.d.ts +151 -0
  91. package/dist/src/server/utils/response-helpers.d.ts.map +1 -0
  92. package/dist/src/server/utils/runtime.d.ts +25 -0
  93. package/dist/src/server/utils/runtime.d.ts.map +1 -0
  94. package/dist/src/task_managers/streamable_http.d.ts +1 -0
  95. package/dist/src/task_managers/streamable_http.d.ts.map +1 -1
  96. package/dist/src/utils/json-schema-to-zod/JSONSchemaToZod.d.ts +270 -0
  97. package/dist/src/utils/json-schema-to-zod/JSONSchemaToZod.d.ts.map +1 -0
  98. package/dist/src/utils/json-schema-to-zod/Type.d.ts +24 -0
  99. package/dist/src/utils/json-schema-to-zod/Type.d.ts.map +1 -0
  100. package/dist/src/utils/json-schema-to-zod/index.d.ts +3 -0
  101. package/dist/src/utils/json-schema-to-zod/index.d.ts.map +1 -0
  102. package/dist/src/utils/url-sanitize.d.ts +17 -0
  103. package/dist/src/utils/url-sanitize.d.ts.map +1 -0
  104. package/dist/tsup.config.d.ts.map +1 -1
  105. package/package.json +30 -38
@@ -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,10 @@ 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) {
203
- console.error(
204
- "[WIDGETS] node-mocks-http not available. Install connect and node-mocks-http for Vite middleware support."
1243
+ } catch (error2) {
1244
+ throw new Error(
1245
+ "\u274C Widget middleware dependencies not installed!\n\nTo use Connect middleware adapters with MCP widgets, you need to install:\n\n npm install node-mocks-http\n # or\n pnpm add node-mocks-http\n\nThis dependency is automatically included in projects created with 'create-mcp-use-app'."
205
1246
  );
206
- throw error;
207
1247
  }
208
1248
  let normalizedPath = middlewarePath;
209
1249
  if (normalizedPath.endsWith("*")) {
@@ -416,7 +1456,7 @@ async function requestLogger(c, next) {
416
1456
  } else {
417
1457
  console.log("\x1B[33mResponse Body:\x1B[0m (no body)");
418
1458
  }
419
- } catch (error) {
1459
+ } catch (error2) {
420
1460
  console.log("\x1B[33mResponse Body:\x1B[0m (unable to read)");
421
1461
  }
422
1462
  console.log("\x1B[36m" + "=".repeat(80) + "\x1B[0m\n");
@@ -425,90 +1465,8 @@ async function requestLogger(c, next) {
425
1465
  __name(requestLogger, "requestLogger");
426
1466
 
427
1467
  // src/server/mcp-server.ts
428
- function generateUUID() {
429
- return globalThis.crypto.randomUUID();
430
- }
431
- __name(generateUUID, "generateUUID");
1468
+ init_runtime();
432
1469
  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
1470
  var McpServer = class {
513
1471
  static {
514
1472
  __name(this, "McpServer");
@@ -527,6 +1485,13 @@ var McpServer = class {
527
1485
  buildId;
528
1486
  sessions = /* @__PURE__ */ new Map();
529
1487
  idleCleanupInterval;
1488
+ oauthProvider;
1489
+ // OAuthProvider from oauth/index.js
1490
+ oauthMiddleware;
1491
+ // Bearer auth middleware
1492
+ oauthConfig;
1493
+ // Store OAuth config for lazy initialization
1494
+ oauthSetupComplete = false;
530
1495
  /**
531
1496
  * Creates a new MCP server instance with Hono integration
532
1497
  *
@@ -548,7 +1513,7 @@ var McpServer = class {
548
1513
  this.app = new import_hono.Hono();
549
1514
  this.app.use(
550
1515
  "*",
551
- (0, import_cors.cors)({
1516
+ (0, import_cors2.cors)({
552
1517
  origin: "*",
553
1518
  allowMethods: ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"],
554
1519
  allowHeaders: [
@@ -565,6 +1530,9 @@ var McpServer = class {
565
1530
  })
566
1531
  );
567
1532
  this.app.use("*", requestLogger);
1533
+ if (config.oauth) {
1534
+ this.oauthConfig = config.oauth;
1535
+ }
568
1536
  return new Proxy(this, {
569
1537
  get(target, prop) {
570
1538
  if (prop === "use") {
@@ -645,6 +1613,42 @@ var McpServer = class {
645
1613
  console.log("[CSP] Parsed CSP URLs:", urls);
646
1614
  return urls;
647
1615
  }
1616
+ /**
1617
+ * Setup OAuth authentication
1618
+ *
1619
+ * Initializes OAuth provider, creates bearer auth middleware,
1620
+ * sets up OAuth routes, and applies auth to /mcp endpoints.
1621
+ *
1622
+ * @private
1623
+ */
1624
+ async setupOAuth(oauthProvider) {
1625
+ if (this.oauthSetupComplete) {
1626
+ return;
1627
+ }
1628
+ const { setupOAuthRoutes: setupOAuthRoutes2, createBearerAuthMiddleware: createBearerAuthMiddleware2 } = await Promise.resolve().then(() => (init_oauth(), oauth_exports));
1629
+ this.oauthProvider = oauthProvider;
1630
+ console.log(`[OAuth] OAuth provider initialized`);
1631
+ const baseUrl = this.getServerBaseUrl();
1632
+ this.oauthMiddleware = createBearerAuthMiddleware2(
1633
+ this.oauthProvider,
1634
+ baseUrl
1635
+ );
1636
+ setupOAuthRoutes2(this.app, this.oauthProvider, baseUrl);
1637
+ const mode = this.oauthProvider.getMode?.() || "proxy";
1638
+ if (mode === "direct") {
1639
+ console.log(
1640
+ "[OAuth] Direct mode: Clients will authenticate with provider directly"
1641
+ );
1642
+ console.log("[OAuth] Metadata endpoints: /.well-known/*");
1643
+ } else {
1644
+ console.log(
1645
+ "[OAuth] Proxy mode: Routes at /authorize, /token, /.well-known/*"
1646
+ );
1647
+ }
1648
+ this.app.use("/mcp/*", this.oauthMiddleware);
1649
+ console.log("[OAuth] Bearer authentication enabled on /mcp routes");
1650
+ this.oauthSetupComplete = true;
1651
+ }
648
1652
  /**
649
1653
  * Define a static resource that can be accessed by clients
650
1654
  *
@@ -771,46 +1775,22 @@ var McpServer = class {
771
1775
  this.registeredResources.push(resourceTemplateDefinition.name);
772
1776
  return this;
773
1777
  }
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 || []);
1778
+ // Implementation
1779
+ tool(toolDefinition, callback) {
1780
+ const actualCallback = callback || toolDefinition.cb;
1781
+ if (!actualCallback) {
1782
+ throw new Error(
1783
+ `Tool '${toolDefinition.name}' must have either a cb property or a callback parameter`
1784
+ );
1785
+ }
1786
+ let inputSchema;
1787
+ if (toolDefinition.schema) {
1788
+ inputSchema = this.convertZodSchemaToParams(toolDefinition.schema);
1789
+ } else if (toolDefinition.inputs && toolDefinition.inputs.length > 0) {
1790
+ inputSchema = this.createParamsSchema(toolDefinition.inputs);
1791
+ } else {
1792
+ inputSchema = {};
1793
+ }
814
1794
  this.server.registerTool(
815
1795
  toolDefinition.name,
816
1796
  {
@@ -821,101 +1801,95 @@ var McpServer = class {
821
1801
  _meta: toolDefinition._meta
822
1802
  },
823
1803
  async (params, extra) => {
1804
+ let requestContext = getRequestContext();
1805
+ if (!requestContext) {
1806
+ for (const [, session] of this.sessions.entries()) {
1807
+ if (session.context) {
1808
+ requestContext = session.context;
1809
+ break;
1810
+ }
1811
+ }
1812
+ }
824
1813
  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
- }
1814
+ const enhancedContext = requestContext ? Object.create(requestContext) : {};
1815
+ enhancedContext.sample = async (sampleParams, options) => {
1816
+ const {
1817
+ timeout,
1818
+ progressIntervalMs = 5e3,
1819
+ onProgress
1820
+ } = options ?? {};
1821
+ let progressCount = 0;
1822
+ let completed = false;
1823
+ let progressInterval = null;
1824
+ if (progressToken && extra?.sendNotification) {
1825
+ progressInterval = setInterval(async () => {
1826
+ if (completed) return;
1827
+ progressCount++;
1828
+ const progressData = {
1829
+ progress: progressCount,
1830
+ total: void 0,
1831
+ message: `Waiting for LLM response... (${progressCount * Math.round(progressIntervalMs / 1e3)}s elapsed)`
1832
+ };
1833
+ if (onProgress) {
864
1834
  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
- });
1835
+ onProgress(progressData);
874
1836
  } catch {
875
1837
  }
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
1838
  }
891
- return await samplePromise;
892
- } finally {
893
- completed = true;
894
- if (progressInterval) {
895
- clearInterval(progressInterval);
1839
+ try {
1840
+ await extra.sendNotification({
1841
+ method: "notifications/progress",
1842
+ params: {
1843
+ progressToken,
1844
+ progress: progressData.progress,
1845
+ total: progressData.total,
1846
+ message: progressData.message
1847
+ }
1848
+ });
1849
+ } catch {
896
1850
  }
1851
+ }, progressIntervalMs);
1852
+ }
1853
+ try {
1854
+ const samplePromise = this.createMessage(sampleParams);
1855
+ if (timeout && timeout !== Infinity) {
1856
+ const timeoutPromise = new Promise((_, reject) => {
1857
+ setTimeout(
1858
+ () => reject(new Error(`Sampling timed out after ${timeout}ms`)),
1859
+ timeout
1860
+ );
1861
+ });
1862
+ return await Promise.race([samplePromise, timeoutPromise]);
897
1863
  }
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
1864
+ return await samplePromise;
1865
+ } finally {
1866
+ completed = true;
1867
+ if (progressInterval) {
1868
+ clearInterval(progressInterval);
1869
+ }
1870
+ }
914
1871
  };
915
- if (toolDefinition.cb.length >= 2) {
916
- return await toolDefinition.cb(params, context);
1872
+ enhancedContext.reportProgress = progressToken && extra?.sendNotification ? async (progress, total, message) => {
1873
+ await extra.sendNotification({
1874
+ method: "notifications/progress",
1875
+ params: {
1876
+ progressToken,
1877
+ progress,
1878
+ total,
1879
+ message
1880
+ }
1881
+ });
1882
+ } : void 0;
1883
+ const executeCallback = /* @__PURE__ */ __name(async () => {
1884
+ if (actualCallback.length >= 2) {
1885
+ return await actualCallback(params, enhancedContext);
1886
+ }
1887
+ return await actualCallback(params);
1888
+ }, "executeCallback");
1889
+ if (requestContext) {
1890
+ return await runWithContext(requestContext, executeCallback);
917
1891
  }
918
- return await toolDefinition.cb(params);
1892
+ return await executeCallback();
919
1893
  }
920
1894
  );
921
1895
  this.registeredTools.push(toolDefinition.name);
@@ -963,6 +1937,7 @@ var McpServer = class {
963
1937
  title: promptDefinition.title,
964
1938
  description: promptDefinition.description ?? "",
965
1939
  argsSchema
1940
+ // Type assertion for Zod v4 compatibility
966
1941
  },
967
1942
  async (params) => {
968
1943
  return await promptDefinition.cb(params);
@@ -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,14 +2408,10 @@ var McpServer = class {
1462
2408
  'return import("@tailwindcss/vite")'
1463
2409
  )();
1464
2410
  tailwindcss = tailwindModule.default;
1465
- } catch (error) {
1466
- console.error(
1467
- "[WIDGETS] Dev dependencies not available. Install vite, @vitejs/plugin-react, and @tailwindcss/vite for widget development."
1468
- );
1469
- console.error(
1470
- "[WIDGETS] For production, use 'mcp-use build' to pre-build widgets."
2411
+ } catch (error2) {
2412
+ throw new Error(
2413
+ "\u274C Widget dependencies not installed!\n\nTo use MCP widgets with resources folder, you need to install the required dependencies:\n\n npm install vite @vitejs/plugin-react @tailwindcss/vite\n # or\n pnpm add vite @vitejs/plugin-react @tailwindcss/vite\n\nThese dependencies are automatically included in projects created with 'create-mcp-use-app'.\nFor production, pre-build your widgets using 'mcp-use build'."
1471
2414
  );
1472
- return;
1473
2415
  }
1474
2416
  const widgets = entries.map((entry) => {
1475
2417
  return {
@@ -1478,8 +2420,8 @@ var McpServer = class {
1478
2420
  entry: entry.path
1479
2421
  };
1480
2422
  });
1481
- for (const widget of widgets) {
1482
- const widgetTempDir = pathHelpers.join(tempDir, widget.name);
2423
+ for (const widget2 of widgets) {
2424
+ const widgetTempDir = pathHelpers.join(tempDir, widget2.name);
1483
2425
  await fs.mkdir(widgetTempDir, { recursive: true });
1484
2426
  const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
1485
2427
  const relativeResourcesPath = pathHelpers.relative(widgetTempDir, resourcesPath).replace(/\\/g, "/");
@@ -1496,7 +2438,7 @@ var McpServer = class {
1496
2438
  const entryContent = `import React from 'react'
1497
2439
  import { createRoot } from 'react-dom/client'
1498
2440
  import './styles.css'
1499
- import Component from '${widget.entry}'
2441
+ import Component from '${widget2.entry}'
1500
2442
 
1501
2443
  const container = document.getElementById('widget-root')
1502
2444
  if (container && Component) {
@@ -1509,11 +2451,11 @@ if (container && Component) {
1509
2451
  <head>
1510
2452
  <meta charset="UTF-8" />
1511
2453
  <meta name="viewport" content="width=device-width,initial-scale=1" />
1512
- <title>${widget.name} Widget</title>
2454
+ <title>${widget2.name} Widget</title>
1513
2455
  </head>
1514
2456
  <body>
1515
2457
  <div id="widget-root"></div>
1516
- <script type="module" src="${baseRoute}/${widget.name}/entry.tsx"></script>
2458
+ <script type="module" src="${baseRoute}/${widget2.name}/entry.tsx"></script>
1517
2459
  </body>
1518
2460
  </html>`;
1519
2461
  await fs.writeFile(
@@ -1603,8 +2545,8 @@ if (container && Component) {
1603
2545
  const widgetMatch = pathname.replace(baseRoute, "").match(/^\/([^/]+)/);
1604
2546
  if (widgetMatch) {
1605
2547
  const widgetName = widgetMatch[1];
1606
- const widget = widgets.find((w) => w.name === widgetName);
1607
- if (widget) {
2548
+ const widget2 = widgets.find((w) => w.name === widgetName);
2549
+ if (widget2) {
1608
2550
  const relativePath = pathname.replace(baseRoute, "");
1609
2551
  if (relativePath === `/${widgetName}` || relativePath === `/${widgetName}/`) {
1610
2552
  const newUrl = new URL(c.req.url);
@@ -1655,42 +2597,42 @@ if (container && Component) {
1655
2597
  const message = isAsset ? "Widget asset not found" : "Widget not found";
1656
2598
  return c.text(message, 404);
1657
2599
  });
1658
- widgets.forEach((widget) => {
2600
+ widgets.forEach((widget2) => {
1659
2601
  console.log(
1660
- `[WIDGET] ${widget.name} mounted at ${baseRoute}/${widget.name}`
2602
+ `[WIDGET] ${widget2.name} mounted at ${baseRoute}/${widget2.name}`
1661
2603
  );
1662
2604
  });
1663
- for (const widget of widgets) {
2605
+ for (const widget2 of widgets) {
1664
2606
  const type = "appsSdk";
1665
2607
  let metadata = {};
1666
2608
  let props = {};
1667
- let description = widget.description;
2609
+ let description = widget2.description;
1668
2610
  try {
1669
- const mod = await viteServer.ssrLoadModule(widget.entry);
2611
+ const mod = await viteServer.ssrLoadModule(widget2.entry);
1670
2612
  if (mod.widgetMetadata) {
1671
2613
  metadata = mod.widgetMetadata;
1672
- description = metadata.description || widget.description;
2614
+ description = metadata.description || widget2.description;
1673
2615
  if (metadata.inputs) {
1674
2616
  try {
1675
2617
  props = metadata.inputs.shape || {};
1676
- } catch (error) {
2618
+ } catch (error2) {
1677
2619
  console.warn(
1678
- `[WIDGET] Failed to extract props schema for ${widget.name}:`,
1679
- error
2620
+ `[WIDGET] Failed to extract props schema for ${widget2.name}:`,
2621
+ error2
1680
2622
  );
1681
2623
  }
1682
2624
  }
1683
2625
  }
1684
- } catch (error) {
2626
+ } catch (error2) {
1685
2627
  console.warn(
1686
- `[WIDGET] Failed to load metadata for ${widget.name}:`,
1687
- error
2628
+ `[WIDGET] Failed to load metadata for ${widget2.name}:`,
2629
+ error2
1688
2630
  );
1689
2631
  }
1690
2632
  let html = "";
1691
2633
  try {
1692
2634
  html = await fsHelpers.readFileSync(
1693
- pathHelpers.join(tempDir, widget.name, "index.html"),
2635
+ pathHelpers.join(tempDir, widget2.name, "index.html"),
1694
2636
  "utf8"
1695
2637
  );
1696
2638
  const mcpUrl = this.getServerBaseUrl();
@@ -1728,25 +2670,25 @@ if (container && Component) {
1728
2670
  html = html.replace(
1729
2671
  /<head[^>]*>/i,
1730
2672
  `<head>
1731
- <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget.name}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
2673
+ <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget2.name}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
1732
2674
  );
1733
- } catch (error) {
2675
+ } catch (error2) {
1734
2676
  console.error(
1735
- `Failed to read html template for widget ${widget.name}`,
1736
- error
2677
+ `Failed to read html template for widget ${widget2.name}`,
2678
+ error2
1737
2679
  );
1738
2680
  }
1739
2681
  const mcp_connect_domain = this.getServerBaseUrl() ? new URL(this.getServerBaseUrl() || "").origin : null;
1740
2682
  this.uiResource({
1741
- name: widget.name,
1742
- title: metadata.title || widget.name,
2683
+ name: widget2.name,
2684
+ title: metadata.title || widget2.name,
1743
2685
  description,
1744
2686
  type,
1745
2687
  props,
1746
2688
  _meta: {
1747
2689
  "mcp-use/widget": {
1748
- name: widget.name,
1749
- title: metadata.title || widget.name,
2690
+ name: widget2.name,
2691
+ title: metadata.title || widget2.name,
1750
2692
  description,
1751
2693
  type,
1752
2694
  props,
@@ -1758,8 +2700,8 @@ if (container && Component) {
1758
2700
  htmlTemplate: html,
1759
2701
  appsSdkMetadata: {
1760
2702
  "openai/widgetDescription": description,
1761
- "openai/toolInvocation/invoking": `Loading ${widget.name}...`,
1762
- "openai/toolInvocation/invoked": `${widget.name} ready`,
2703
+ "openai/toolInvocation/invoking": `Loading ${widget2.name}...`,
2704
+ "openai/toolInvocation/invoked": `${widget2.name} ready`,
1763
2705
  "openai/widgetAccessible": true,
1764
2706
  "openai/resultCanProduceWidget": true,
1765
2707
  ...metadata.appsSdkMetadata || {},
@@ -1832,10 +2774,10 @@ if (container && Component) {
1832
2774
  } else {
1833
2775
  console.log("[WIDGETS] No widgets found in manifest");
1834
2776
  }
1835
- } catch (error) {
2777
+ } catch (error2) {
1836
2778
  console.log(
1837
2779
  "[WIDGETS] Could not read manifest file, falling back to directory listing:",
1838
- error
2780
+ error2
1839
2781
  );
1840
2782
  try {
1841
2783
  const allEntries = await fsHelpers.readdirSync(widgetsDir);
@@ -1900,10 +2842,10 @@ if (container && Component) {
1900
2842
  <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widgetName}/"+filename }; window.__mcpPublicUrl = "${baseUrl}/mcp-use/public";</script>`
1901
2843
  );
1902
2844
  }
1903
- } catch (error) {
2845
+ } catch (error2) {
1904
2846
  console.error(
1905
2847
  `[WIDGET] Failed to read ${widgetName}/index.html:`,
1906
- error
2848
+ error2
1907
2849
  );
1908
2850
  continue;
1909
2851
  }
@@ -2030,7 +2972,7 @@ if (container && Component) {
2030
2972
  if (closeOldSessionId && this.sessions.has(closeOldSessionId)) {
2031
2973
  try {
2032
2974
  this.sessions.get(closeOldSessionId).transport.close();
2033
- } catch (error) {
2975
+ } catch (error2) {
2034
2976
  }
2035
2977
  this.sessions.delete(closeOldSessionId);
2036
2978
  }
@@ -2161,7 +3103,7 @@ if (container && Component) {
2161
3103
  if (now - session.lastAccessedAt > idleTimeoutMs) {
2162
3104
  try {
2163
3105
  session.transport.close();
2164
- } catch (error) {
3106
+ } catch (error2) {
2165
3107
  }
2166
3108
  this.sessions.delete(sessionId);
2167
3109
  }
@@ -2317,19 +3259,23 @@ if (container && Component) {
2317
3259
  }
2318
3260
  }
2319
3261
  if (sessionId && this.sessions.has(sessionId)) {
2320
- this.sessions.get(sessionId).lastAccessedAt = Date.now();
3262
+ const session = this.sessions.get(sessionId);
3263
+ session.lastAccessedAt = Date.now();
3264
+ session.context = c;
2321
3265
  }
2322
3266
  if (expressRes._closeHandler) {
2323
3267
  c.req.raw.signal?.addEventListener("abort", () => {
2324
3268
  transport.close();
2325
3269
  });
2326
3270
  }
2327
- await this.waitForRequestComplete(
2328
- transport,
2329
- expressReq,
2330
- expressRes,
2331
- expressReq.body
2332
- );
3271
+ await runWithContext(c, async () => {
3272
+ await this.waitForRequestComplete(
3273
+ transport,
3274
+ expressReq,
3275
+ expressRes,
3276
+ expressReq.body
3277
+ );
3278
+ });
2333
3279
  const response = getResponse();
2334
3280
  if (response) {
2335
3281
  return response;
@@ -2573,6 +3519,9 @@ if (container && Component) {
2573
3519
  if (hostEnv) {
2574
3520
  this.serverHost = hostEnv;
2575
3521
  }
3522
+ if (this.oauthConfig && !this.oauthSetupComplete) {
3523
+ await this.setupOAuth(this.oauthConfig);
3524
+ }
2576
3525
  await this.mountWidgets({
2577
3526
  baseRoute: "/mcp-use/widgets",
2578
3527
  resourcesDir: "resources"
@@ -2681,6 +3630,9 @@ if (container && Component) {
2681
3630
  * ```
2682
3631
  */
2683
3632
  async getHandler(options) {
3633
+ if (this.oauthConfig && !this.oauthSetupComplete) {
3634
+ await this.setupOAuth(this.oauthConfig);
3635
+ }
2684
3636
  console.log("[MCP] Mounting widgets");
2685
3637
  await this.mountWidgets({
2686
3638
  baseRoute: "/mcp-use/widgets",
@@ -2784,10 +3736,10 @@ if (container && Component) {
2784
3736
  for (const [sessionId, session] of this.sessions.entries()) {
2785
3737
  try {
2786
3738
  await session.transport.send(notification);
2787
- } catch (error) {
3739
+ } catch (error2) {
2788
3740
  console.warn(
2789
3741
  `[MCP] Failed to send notification to session ${sessionId}:`,
2790
- error
3742
+ error2
2791
3743
  );
2792
3744
  }
2793
3745
  }
@@ -2832,10 +3784,10 @@ if (container && Component) {
2832
3784
  try {
2833
3785
  await session.transport.send(notification);
2834
3786
  return true;
2835
- } catch (error) {
3787
+ } catch (error2) {
2836
3788
  console.warn(
2837
3789
  `[MCP] Failed to send notification to session ${sessionId}:`,
2838
- error
3790
+ error2
2839
3791
  );
2840
3792
  return false;
2841
3793
  }
@@ -2903,10 +3855,10 @@ if (container && Component) {
2903
3855
  return response.roots;
2904
3856
  }
2905
3857
  return [];
2906
- } catch (error) {
3858
+ } catch (error2) {
2907
3859
  console.warn(
2908
3860
  `[MCP] Failed to list roots from session ${sessionId}:`,
2909
- error
3861
+ error2
2910
3862
  );
2911
3863
  return null;
2912
3864
  }
@@ -2984,14 +3936,14 @@ if (container && Component) {
2984
3936
  */
2985
3937
  setupWidgetRoutes() {
2986
3938
  this.app.get("/mcp-use/widgets/:widget/assets/*", async (c) => {
2987
- const widget = c.req.param("widget");
3939
+ const widget2 = c.req.param("widget");
2988
3940
  const assetFile = c.req.path.split("/assets/")[1];
2989
3941
  const assetPath = pathHelpers.join(
2990
3942
  getCwd(),
2991
3943
  "dist",
2992
3944
  "resources",
2993
3945
  "widgets",
2994
- widget,
3946
+ widget2,
2995
3947
  "assets",
2996
3948
  assetFile
2997
3949
  );
@@ -3020,10 +3972,10 @@ if (container && Component) {
3020
3972
  );
3021
3973
  try {
3022
3974
  const widgets = await fsHelpers.readdirSync(widgetsDir);
3023
- for (const widget of widgets) {
3975
+ for (const widget2 of widgets) {
3024
3976
  const assetPath = pathHelpers.join(
3025
3977
  widgetsDir,
3026
- widget,
3978
+ widget2,
3027
3979
  "assets",
3028
3980
  assetFile
3029
3981
  );
@@ -3043,13 +3995,13 @@ if (container && Component) {
3043
3995
  }
3044
3996
  });
3045
3997
  this.app.get("/mcp-use/widgets/:widget", async (c) => {
3046
- const widget = c.req.param("widget");
3998
+ const widget2 = c.req.param("widget");
3047
3999
  const filePath = pathHelpers.join(
3048
4000
  getCwd(),
3049
4001
  "dist",
3050
4002
  "resources",
3051
4003
  "widgets",
3052
- widget,
4004
+ widget2,
3053
4005
  "index.html"
3054
4006
  );
3055
4007
  try {
@@ -3066,7 +4018,7 @@ if (container && Component) {
3066
4018
  html = html.replace(
3067
4019
  /<head[^>]*>/i,
3068
4020
  `<head>
3069
- <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget}/"+filename }</script>`
4021
+ <script>window.__getFile = (filename) => { return "${baseUrl}/mcp-use/widgets/${widget2}/"+filename }</script>`
3070
4022
  );
3071
4023
  return c.html(html);
3072
4024
  } catch {
@@ -3093,28 +4045,21 @@ if (container && Component) {
3093
4045
  });
3094
4046
  }
3095
4047
  /**
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.
4048
+ * Convert a Zod object schema to the internal Record<string, z.ZodSchema> format
3101
4049
  *
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
- * ```
4050
+ * @param zodSchema - Zod object schema to convert
4051
+ * @returns Object mapping parameter names to Zod validation schemas
3110
4052
  */
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;
4053
+ convertZodSchemaToParams(zodSchema) {
4054
+ if (!(zodSchema instanceof import_zod.z.ZodObject)) {
4055
+ throw new Error("schema must be a Zod object schema (z.object({...}))");
4056
+ }
4057
+ const shape = zodSchema.shape;
4058
+ const params = {};
4059
+ for (const [key, value] of Object.entries(shape)) {
4060
+ params[key] = value;
4061
+ }
4062
+ return params;
3118
4063
  }
3119
4064
  /**
3120
4065
  * Create input schema for tools
@@ -3168,75 +4113,6 @@ if (container && Component) {
3168
4113
  });
3169
4114
  return schema;
3170
4115
  }
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
4116
  /**
3241
4117
  * Parse parameter values from a URI based on a template
3242
4118
  *
@@ -3279,8 +4155,127 @@ function createMCPServer(name, config = {}) {
3279
4155
  host: config.host,
3280
4156
  baseUrl: config.baseUrl,
3281
4157
  allowedOrigins: config.allowedOrigins,
3282
- sessionIdleTimeoutMs: config.sessionIdleTimeoutMs
4158
+ sessionIdleTimeoutMs: config.sessionIdleTimeoutMs,
4159
+ autoCreateSessionOnInvalidId: config.autoCreateSessionOnInvalidId,
4160
+ oauth: config.oauth
3283
4161
  });
3284
4162
  return instance;
3285
4163
  }
3286
4164
  __name(createMCPServer, "createMCPServer");
4165
+
4166
+ // src/server/utils/response-helpers.ts
4167
+ function text(content) {
4168
+ return {
4169
+ content: [
4170
+ {
4171
+ type: "text",
4172
+ text: content
4173
+ }
4174
+ ]
4175
+ };
4176
+ }
4177
+ __name(text, "text");
4178
+ function image(data, mimeType = "image/png") {
4179
+ return {
4180
+ content: [
4181
+ {
4182
+ type: "image",
4183
+ data,
4184
+ mimeType
4185
+ }
4186
+ ]
4187
+ };
4188
+ }
4189
+ __name(image, "image");
4190
+ function resource(uri, mimeType, text2) {
4191
+ const resourceContent = {
4192
+ type: "resource",
4193
+ resource: {
4194
+ uri,
4195
+ ...mimeType && { mimeType },
4196
+ ...text2 && { text: text2 }
4197
+ }
4198
+ };
4199
+ return {
4200
+ content: [resourceContent]
4201
+ };
4202
+ }
4203
+ __name(resource, "resource");
4204
+ function error(message) {
4205
+ return {
4206
+ isError: true,
4207
+ content: [
4208
+ {
4209
+ type: "text",
4210
+ text: message
4211
+ }
4212
+ ]
4213
+ };
4214
+ }
4215
+ __name(error, "error");
4216
+ function object(data) {
4217
+ return Array.isArray(data) ? array(data) : {
4218
+ content: [
4219
+ {
4220
+ type: "text",
4221
+ text: JSON.stringify(data, null, 2)
4222
+ }
4223
+ ],
4224
+ structuredContent: data
4225
+ };
4226
+ }
4227
+ __name(object, "object");
4228
+ function array(data) {
4229
+ return {
4230
+ content: [
4231
+ {
4232
+ type: "text",
4233
+ text: JSON.stringify(data, null, 2)
4234
+ }
4235
+ ],
4236
+ structuredContent: { data }
4237
+ };
4238
+ }
4239
+ __name(array, "array");
4240
+ function widget(config) {
4241
+ const {
4242
+ name,
4243
+ data,
4244
+ message,
4245
+ invoking,
4246
+ invoked,
4247
+ widgetAccessible = true,
4248
+ resultCanProduceWidget = true,
4249
+ buildId
4250
+ } = config;
4251
+ const randomId = Math.random().toString(36).substring(2, 15);
4252
+ const buildIdPart = buildId ? `-${buildId}` : "";
4253
+ const uniqueUri = `ui://widget/${name}${buildIdPart}-${randomId}.html`;
4254
+ const metadata = {
4255
+ "openai/outputTemplate": uniqueUri,
4256
+ "openai/widgetAccessible": widgetAccessible,
4257
+ "openai/resultCanProduceWidget": resultCanProduceWidget
4258
+ };
4259
+ if (invoking) {
4260
+ metadata["openai/toolInvocation/invoking"] = invoking;
4261
+ }
4262
+ if (invoked) {
4263
+ metadata["openai/toolInvocation/invoked"] = invoked;
4264
+ }
4265
+ const displayMessage = message || `Displaying ${name}`;
4266
+ return {
4267
+ _meta: metadata,
4268
+ content: [
4269
+ {
4270
+ type: "text",
4271
+ text: displayMessage
4272
+ }
4273
+ ],
4274
+ // structuredContent will be injected as window.openai.toolOutput by Apps SDK
4275
+ structuredContent: data
4276
+ };
4277
+ }
4278
+ __name(widget, "widget");
4279
+
4280
+ // src/server/index.ts
4281
+ init_oauth();