mcp-use 2.0.0-beta.35 → 2.0.0-beta.37

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 (44) hide show
  1. package/dist/bin.js +1 -3
  2. package/dist/chunk-5Z6KY5ON.js +2 -0
  3. package/dist/{chunk-PPQL2WHL.js → chunk-GX6PGIEO.js} +32 -142
  4. package/dist/chunk-JMDHTN6N.js +1 -0
  5. package/dist/chunk-OJF6B5EU.js +1 -0
  6. package/dist/chunk-PSKSL567.js +1 -0
  7. package/dist/chunk-WYBJYZJB.js +1 -0
  8. package/dist/chunk-Y26DNVWA.js +3 -0
  9. package/dist/chunk-ZMU5USAZ.js +1 -0
  10. package/dist/index.js +9 -3100
  11. package/dist/internal/resource-completion.js +1 -6
  12. package/dist/internal/usage.js +1 -0
  13. package/dist/landing-handler-TG6LVQBI.js +1 -0
  14. package/dist/landing.js +1 -6
  15. package/dist/mcp-proxy-NETCUGUD.js +2 -0
  16. package/dist/mcp-proxy.d.ts +6 -0
  17. package/dist/next/index.js +1 -171
  18. package/dist/node-bridge.js +1 -150
  19. package/dist/oauth/auth0.js +1 -60
  20. package/dist/oauth/better-auth.js +1 -75
  21. package/dist/oauth/clerk.js +1 -69
  22. package/dist/oauth/index.js +1 -26
  23. package/dist/oauth/keycloak.js +1 -93
  24. package/dist/oauth/supabase.js +1 -100
  25. package/dist/oauth/workos.js +1 -76
  26. package/dist/openapi/index.js +1 -6
  27. package/dist/public-route-DAQJGS6K.js +1 -0
  28. package/dist/react/components/model-context.d.ts +9 -14
  29. package/dist/react/hooks/use-view-state.d.ts +23 -0
  30. package/dist/react/index.d.ts +1 -0
  31. package/dist/react/index.js +215 -81
  32. package/dist/react/runtime/model-context-store.d.ts +34 -68
  33. package/dist/react/runtime/view-runtime.d.ts +2 -2
  34. package/dist/usage.d.ts +11 -0
  35. package/package.json +6 -5
  36. package/dist/chunk-DFFP6QPR.js +0 -37
  37. package/dist/chunk-HDV7K2TE.js +0 -97
  38. package/dist/chunk-HNNQJLD5.js +0 -383
  39. package/dist/chunk-QCIREWRS.js +0 -64
  40. package/dist/chunk-QKJJ6DWK.js +0 -184
  41. package/dist/chunk-YF5X7FYF.js +0 -517
  42. package/dist/landing-handler-QEH2ATIR.js +0 -36
  43. package/dist/mcp-proxy-JK7IC5CR.js +0 -281
  44. package/dist/public-route-BAMZRI4R.js +0 -8
package/dist/index.js CHANGED
@@ -1,1388 +1,8 @@
1
- import {
2
- hasExplicitAssetsBase,
3
- originFromAssetsBase,
4
- resolveAssetsBase,
5
- resolveServerOrigin
6
- } from "./chunk-HDV7K2TE.js";
7
- import {
8
- registerOpenAPITools
9
- } from "./chunk-HNNQJLD5.js";
10
- import {
11
- completable,
12
- normalizeCompletions
13
- } from "./chunk-DFFP6QPR.js";
14
- import {
15
- resolvePublicFilePath,
16
- servePublicFile
17
- } from "./chunk-QCIREWRS.js";
18
- import {
19
- authInfoFromRequest,
20
- composeFetch,
21
- getOAuthProtectedResourceMetadataUrl,
22
- getRequestBag,
23
- hostValidationMiddleware,
24
- isHtmlNavigationRequest,
25
- jsonBodyMiddleware,
26
- matchesPath,
27
- matchesPathPrefix,
28
- oauthMetadata,
29
- originValidationMiddleware,
30
- pathUnderBase,
31
- pathnameOf,
32
- requireBearerAuth
33
- } from "./chunk-QKJJ6DWK.js";
34
- import {
35
- getOAuthProviderOptions,
36
- resolveConfiguredOAuthResource,
37
- resolveLocalOAuthResource,
38
- wrapOAuthTokenVerifier
39
- } from "./chunk-YF5X7FYF.js";
40
-
41
- // src/server.ts
42
- import {
43
- localhostAllowedHostnames,
44
- localhostAllowedOrigins,
45
- McpServer as SdkMcpServer,
46
- ResourceTemplate,
47
- isInputRequiredResult as isInputRequiredResult2
48
- } from "@modelcontextprotocol/server";
49
- import { Hono } from "hono";
50
-
51
- // src/branding.ts
52
- var FAVICON_CACHE_CONTROL = "public, max-age=31536000, immutable";
53
- var FAVICON_REDIRECT_CACHE_CONTROL = "public, max-age=300";
54
- function protocolOf(value) {
55
- const match = /^([a-z][a-z\d+.-]*):/i.exec(value);
56
- return match?.[1]?.toLowerCase();
57
- }
58
- function publicAssetPath(basePath, source) {
59
- const prefix = basePath === "/" ? "" : basePath;
60
- return `${prefix}/_mcp-use/public/${source.split("/").map((segment) => encodeURIComponent(segment)).join("/")}`;
61
- }
62
- function isLocalPublicSource(source) {
63
- return protocolOf(source) === void 0;
64
- }
65
- function selectFaviconFromIcons(icons) {
66
- return icons[0];
67
- }
68
- function assertLocalPublicSource(source, field) {
69
- if (source.startsWith("/") || source.includes("\\") || source.includes("?") || source.includes("#") || source.split("/").some((segment) => segment === "" || segment === "..")) {
70
- throw new TypeError(
71
- `${field} must be an http(s) URL, image data URL, or safe path relative to public/`
72
- );
73
- }
74
- }
75
- function parseDataImage(source, field) {
76
- const comma = source.indexOf(",");
77
- if (comma < 0) {
78
- throw new TypeError(`${field} must be a valid image data URL`);
79
- }
80
- const metadata = source.slice(5, comma);
81
- const payload = source.slice(comma + 1);
82
- const parts = metadata.split(";");
83
- const mimeType = parts[0]?.toLowerCase() ?? "";
84
- if (!mimeType.startsWith("image/")) {
85
- throw new TypeError(`${field} data URL must use an image MIME type`);
86
- }
87
- try {
88
- if (parts.includes("base64")) {
89
- const binary2 = atob(payload);
90
- return {
91
- mimeType,
92
- bytes: Uint8Array.from(binary2, (character) => character.charCodeAt(0))
93
- };
94
- }
95
- return {
96
- mimeType,
97
- bytes: new TextEncoder().encode(decodeURIComponent(payload))
98
- };
99
- } catch {
100
- throw new TypeError(`${field} must be a valid image data URL`);
101
- }
102
- }
103
- function assertBrandingSource(source, field) {
104
- if (typeof source !== "string" || source.length === 0) {
105
- throw new TypeError(`${field} must be a non-empty string`);
106
- }
107
- const protocol = protocolOf(source);
108
- if (protocol === void 0) {
109
- assertLocalPublicSource(source, field);
110
- return source;
111
- }
112
- if (protocol === "data") {
113
- parseDataImage(source, field);
114
- return source;
115
- }
116
- if (protocol !== "http" && protocol !== "https") {
117
- throw new TypeError(
118
- `${field} must be an http(s) URL, image data URL, or safe path relative to public/`
119
- );
120
- }
121
- try {
122
- new URL(source);
123
- } catch {
124
- throw new TypeError(`${field} must be a valid absolute http(s) URL`);
125
- }
126
- return source;
127
- }
128
- function normalizeServerBranding(config) {
129
- let websiteUrl;
130
- if (config.websiteUrl !== void 0) {
131
- if (typeof config.websiteUrl !== "string" || config.websiteUrl.length === 0) {
132
- throw new TypeError(
133
- "websiteUrl must be a non-empty absolute http(s) URL"
134
- );
135
- }
136
- let parsed;
137
- try {
138
- parsed = new URL(config.websiteUrl);
139
- } catch {
140
- throw new TypeError(
141
- "websiteUrl must be a non-empty absolute http(s) URL"
142
- );
143
- }
144
- if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
145
- throw new TypeError(
146
- "websiteUrl must be a non-empty absolute http(s) URL"
147
- );
148
- }
149
- websiteUrl = config.websiteUrl;
150
- }
151
- let icons;
152
- if (config.icons !== void 0) {
153
- if (!Array.isArray(config.icons)) {
154
- throw new TypeError("icons must be an array of MCP Icon objects");
155
- }
156
- icons = Object.freeze(
157
- config.icons.map((value, index) => {
158
- if (typeof value !== "object" || value === null) {
159
- throw new TypeError(`icons[${index}] must be an MCP Icon object`);
160
- }
161
- const icon = value;
162
- const src = assertBrandingSource(icon["src"], `icons[${index}].src`);
163
- const mimeType = icon["mimeType"];
164
- if (mimeType !== void 0 && (typeof mimeType !== "string" || !mimeType.toLowerCase().startsWith("image/"))) {
165
- throw new TypeError(
166
- `icons[${index}].mimeType must be an image MIME type when provided`
167
- );
168
- }
169
- const sizes = icon["sizes"];
170
- if (sizes !== void 0 && (!Array.isArray(sizes) || sizes.some((size) => typeof size !== "string" || size.length === 0))) {
171
- throw new TypeError(
172
- `icons[${index}].sizes must be an array of non-empty strings when provided`
173
- );
174
- }
175
- const normalizedSizes = sizes === void 0 ? void 0 : sizes.map((size) => size);
176
- const theme = icon["theme"];
177
- if (theme !== void 0 && theme !== "light" && theme !== "dark") {
178
- throw new TypeError(
179
- `icons[${index}].theme must be "light" or "dark" when provided`
180
- );
181
- }
182
- return Object.freeze({
183
- src,
184
- ...mimeType !== void 0 && { mimeType },
185
- ...normalizedSizes !== void 0 && {
186
- sizes: Object.freeze(normalizedSizes)
187
- },
188
- ...theme !== void 0 && { theme }
189
- });
190
- })
191
- );
192
- }
193
- const explicitFavicon = config.favicon === void 0 ? void 0 : assertBrandingSource(config.favicon, "favicon");
194
- const inferred = explicitFavicon === void 0 ? selectFaviconFromIcons(icons ?? []) : void 0;
195
- const favicon = explicitFavicon ?? inferred?.src;
196
- const faviconMimeType = inferred?.mimeType ?? icons?.find((icon) => icon.src === explicitFavicon)?.mimeType;
197
- return Object.freeze({
198
- ...favicon !== void 0 && { favicon },
199
- ...faviconMimeType !== void 0 && { faviconMimeType },
200
- ...icons !== void 0 && { icons },
201
- ...websiteUrl !== void 0 && { websiteUrl }
202
- });
203
- }
204
- function resolveImplementationIcons(icons, request, basePath) {
205
- if (icons === void 0) {
206
- return void 0;
207
- }
208
- return icons.map((icon) => ({
209
- ...icon,
210
- src: request !== void 0 && isLocalPublicSource(icon.src) ? `${resolveAssetsBase(request)}${publicAssetPath(basePath, icon.src)}` : icon.src,
211
- ...icon.sizes !== void 0 && { sizes: [...icon.sizes] }
212
- }));
213
- }
214
- function hasLocalBrandingAsset(branding) {
215
- return branding.favicon !== void 0 && isLocalPublicSource(branding.favicon) || branding.icons?.some((icon) => isLocalPublicSource(icon.src)) === true;
216
- }
217
- function createFaviconHandler(branding, options) {
218
- const source = branding.favicon;
219
- if (source === void 0) {
220
- return void 0;
221
- }
222
- return async (request) => {
223
- if (request.method !== "GET" && request.method !== "HEAD") {
224
- return new Response("Method Not Allowed", {
225
- status: 405,
226
- headers: { Allow: "GET, HEAD" }
227
- });
228
- }
229
- if (new URL(request.url).pathname !== "/favicon.ico") {
230
- return new Response("Not Found", { status: 404 });
231
- }
232
- const protocol = protocolOf(source);
233
- if (protocol === "http" || protocol === "https") {
234
- return new Response(null, {
235
- status: 307,
236
- headers: {
237
- Location: source,
238
- "Cache-Control": FAVICON_REDIRECT_CACHE_CONTROL
239
- }
240
- });
241
- }
242
- if (protocol === "data") {
243
- const data = parseDataImage(source, "favicon");
244
- return new Response(
245
- request.method === "HEAD" ? null : data.bytes.buffer,
246
- {
247
- status: 200,
248
- headers: {
249
- "Content-Type": branding.faviconMimeType ?? data.mimeType,
250
- "Cache-Control": FAVICON_CACHE_CONTROL,
251
- "X-Content-Type-Options": "nosniff"
252
- }
253
- }
254
- );
255
- }
256
- const { join } = await import("path");
257
- const publicRoot = options.dev ? join(options.projectRoot, "public") : join(options.projectRoot, ".mcp-use/build/views/public");
258
- const diskPath = await resolvePublicFilePath(publicRoot, source);
259
- if (diskPath === null) {
260
- return new Response("Not Found", {
261
- status: 404,
262
- headers: { "Cache-Control": "no-store" }
263
- });
264
- }
265
- const response = await servePublicFile(diskPath, {
266
- ...options.deferCors === true && { deferCors: true },
267
- ...request.method === "HEAD" && { head: true }
268
- });
269
- response.headers.set("Cache-Control", FAVICON_CACHE_CONTROL);
270
- response.headers.set("X-Content-Type-Options", "nosniff");
271
- if (branding.faviconMimeType !== void 0) {
272
- response.headers.set("Content-Type", branding.faviconMimeType);
273
- }
274
- return response;
275
- };
276
- }
277
-
278
- // src/config.ts
279
- function assertServerConfig(config) {
280
- if (config.basePath !== void 0) {
281
- if (typeof config.basePath !== "string") {
282
- throw new TypeError(
283
- "basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace"
284
- );
285
- }
286
- const { basePath } = config;
287
- if (!basePath.startsWith("/") || basePath.includes("?") || basePath.includes("#") || /\s/.test(basePath) || basePath.includes("//") || basePath.length > 1 && basePath.endsWith("/")) {
288
- throw new TypeError(
289
- "basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace"
290
- );
291
- }
292
- }
293
- if (config.port !== void 0 && (typeof config.port !== "number" || !Number.isInteger(config.port) || config.port < 0 || config.port > 65535)) {
294
- throw new TypeError("port must be an integer between 0 and 65535");
295
- }
296
- }
297
-
298
- // src/listen-address.ts
299
- var DEFAULT_LISTEN_HOST = "127.0.0.1";
300
- var DEFAULT_LISTEN_PORT = 3e3;
301
- function resolveListenHost(explicitHost, configuredHost, env = process.env) {
302
- if (explicitHost !== void 0) return explicitHost;
303
- const envHost = env.HOST?.trim();
304
- if (envHost !== void 0 && envHost !== "") return envHost;
305
- return configuredHost ?? DEFAULT_LISTEN_HOST;
306
- }
307
- function resolveListenPort(explicitPort, configuredPort, env = process.env) {
308
- if (explicitPort !== void 0) return explicitPort;
309
- const envPort = parsePort(env.PORT);
310
- if (envPort !== void 0) return envPort;
311
- return configuredPort ?? DEFAULT_LISTEN_PORT;
312
- }
313
- function parsePort(value) {
314
- if (value === void 0 || value.trim() === "") return void 0;
315
- const port = Number(value);
316
- return Number.isInteger(port) && port >= 0 && port <= 65535 ? port : void 0;
317
- }
318
-
319
- // src/context.ts
320
- import {
321
- CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY2,
322
- CLIENT_INFO_META_KEY,
323
- inputRequired,
324
- inputResponse
325
- } from "@modelcontextprotocol/server";
326
- import { HonoRequest } from "hono/request";
327
-
328
- // src/views/capabilities.ts
329
- import {
330
- CLIENT_CAPABILITIES_META_KEY
331
- } from "@modelcontextprotocol/server";
332
-
333
- // src/views/constants.ts
334
- var UI_EXTENSION_ID = "io.modelcontextprotocol/ui";
335
- var UI_MIME_TYPE = "text/html;profile=mcp-app";
336
- var UI_RESOURCE_URI_PREFIX = "ui://views/";
337
- var UI_META_KEY = "ui";
338
- var UI_RESOURCE_URI_META_KEY = "ui/resourceUri";
339
- function viewResourceUri(viewName) {
340
- return `${UI_RESOURCE_URI_PREFIX}${viewName}.html`;
341
- }
342
-
343
- // src/views/capabilities.ts
344
- var clientCapabilitiesByRequest = /* @__PURE__ */ new WeakMap();
345
- function stashClientCapabilities(request, capabilities) {
346
- clientCapabilitiesByRequest.set(request, capabilities);
347
- }
348
- function extractClientCapabilitiesFromBody(body) {
349
- if (typeof body !== "object" || body === null) {
350
- return void 0;
351
- }
352
- const params = body["params"];
353
- if (typeof params !== "object" || params === null) {
354
- return void 0;
355
- }
356
- const meta = params["_meta"];
357
- if (typeof meta !== "object" || meta === null) {
358
- return void 0;
359
- }
360
- const capabilities = meta[CLIENT_CAPABILITIES_META_KEY];
361
- if (typeof capabilities !== "object" || capabilities === null) {
362
- return void 0;
363
- }
364
- return capabilities;
365
- }
366
- function supportsViews(capabilities) {
367
- const extensions = capabilities?.extensions;
368
- if (extensions === void 0) {
369
- return false;
370
- }
371
- const uiExtension = extensions[UI_EXTENSION_ID];
372
- if (typeof uiExtension !== "object" || uiExtension === null) {
373
- return false;
374
- }
375
- const mimeTypes = uiExtension["mimeTypes"];
376
- if (!Array.isArray(mimeTypes)) {
377
- return false;
378
- }
379
- return mimeTypes.includes(UI_MIME_TYPE);
380
- }
381
-
382
- // src/context.ts
383
- function requireOAuthAuthInfo(authInfo) {
384
- if (authInfo === void 0 || authInfo.extra === void 0 || authInfo.expiresAt === void 0) {
385
- throw new Error("OAuth callback did not receive mapped AuthInfo.extra");
386
- }
387
- }
388
- function stringValue(value) {
389
- return typeof value === "string" ? value : void 0;
390
- }
391
- function coordinateValue(value) {
392
- if (typeof value === "string") return value;
393
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
394
- }
395
- function normalizeUserContext(meta) {
396
- if (meta === void 0) return void 0;
397
- const locale = stringValue(meta["openai/locale"]) ?? stringValue(meta["webplus/i18n"]);
398
- const userAgent = stringValue(meta["openai/userAgent"]);
399
- const subject = stringValue(meta["openai/subject"]);
400
- const conversationId = stringValue(meta["openai/session"]);
401
- const organizationId = stringValue(meta["openai/organization"]);
402
- const rawLocation = meta["openai/userLocation"];
403
- let location;
404
- if (typeof rawLocation === "object" && rawLocation !== null && !Array.isArray(rawLocation)) {
405
- const values = rawLocation;
406
- const normalized = {
407
- city: stringValue(values.city),
408
- region: stringValue(values.region),
409
- country: stringValue(values.country),
410
- timezone: stringValue(values.timezone),
411
- latitude: coordinateValue(values.latitude),
412
- longitude: coordinateValue(values.longitude)
413
- };
414
- const entries = Object.entries(normalized).filter(
415
- (entry) => entry[1] !== void 0
416
- );
417
- if (entries.length > 0) {
418
- location = Object.fromEntries(entries);
419
- }
420
- }
421
- if (locale === void 0 && userAgent === void 0 && location === void 0 && subject === void 0 && conversationId === void 0 && organizationId === void 0) {
422
- return void 0;
423
- }
424
- return {
425
- ...locale !== void 0 && { locale },
426
- ...userAgent !== void 0 && { userAgent },
427
- ...location !== void 0 && { location },
428
- ...subject !== void 0 && { subject },
429
- ...conversationId !== void 0 && { conversationId },
430
- ...organizationId !== void 0 && { organizationId }
431
- };
432
- }
433
- function toClientContext(ctx) {
434
- const envelope = ctx.mcpReq.envelope;
435
- const capabilities = {
436
- ...envelope?.[CLIENT_CAPABILITIES_META_KEY2] ?? {}
437
- };
438
- const info = {
439
- ...envelope?.[CLIENT_INFO_META_KEY] ?? {}
440
- };
441
- const user = normalizeUserContext(ctx.mcpReq._meta);
442
- return {
443
- can(capability) {
444
- return Object.hasOwn(capabilities, capability);
445
- },
446
- capabilities() {
447
- return { ...capabilities };
448
- },
449
- extension(id) {
450
- const settings = capabilities.extensions?.[id];
451
- return settings === void 0 ? void 0 : { ...settings };
452
- },
453
- info() {
454
- return { ...info };
455
- },
456
- user() {
457
- return user === void 0 ? void 0 : {
458
- ...user,
459
- ...user.location !== void 0 && {
460
- location: { ...user.location }
461
- }
462
- };
463
- },
464
- supportsViews() {
465
- return supportsViews(capabilities);
466
- }
467
- };
468
- }
469
- function createElicit(inputResponses) {
470
- return async function elicit(key, message, schemaOrUrl) {
471
- let request;
472
- let formSchema;
473
- if (typeof schemaOrUrl === "string") {
474
- request = inputRequired.elicitUrl({
475
- message,
476
- url: schemaOrUrl
477
- });
478
- } else if (schemaOrUrl !== void 0) {
479
- formSchema = schemaOrUrl;
480
- request = inputRequired.elicit({
481
- message,
482
- requestedSchema: schemaOrUrl
483
- });
484
- } else {
485
- throw new TypeError(
486
- "ctx.elicit(key, message, value) requires a form schema or URL string"
487
- );
488
- }
489
- const response = inputResponse(inputResponses, key);
490
- if (response.kind === "elicit") {
491
- if (response.action !== "accept") {
492
- return { status: response.action };
493
- }
494
- if (formSchema === void 0) {
495
- return { status: "accept" };
496
- }
497
- if (response.content !== void 0) {
498
- const outcome = await formSchema["~standard"].validate(
499
- response.content
500
- );
501
- if (outcome.issues === void 0) {
502
- return { status: "accept", data: outcome.value };
503
- }
504
- }
505
- }
506
- return {
507
- status: "required",
508
- result: inputRequired({ inputRequests: { [key]: request } })
509
- };
510
- };
511
- }
512
- function toRequestContext(ctx) {
513
- const rawRequest = ctx.http?.req;
514
- const http = rawRequest === void 0 ? void 0 : getRequestBag(rawRequest).honoContext;
515
- const request = http?.req ?? (rawRequest === void 0 ? void 0 : new HonoRequest(rawRequest));
516
- const additions = {
517
- signal: ctx.mcpReq.signal,
518
- ...request !== void 0 && { request },
519
- ...ctx.mcpReq.inputResponses !== void 0 && {
520
- inputResponses: ctx.mcpReq.inputResponses
521
- },
522
- client: toClientContext(ctx),
523
- elicit: createElicit(ctx.mcpReq.inputResponses),
524
- requestState: () => ctx.mcpReq.requestState(),
525
- async sendNotification(method, params) {
526
- await ctx.mcpReq.notify({
527
- method,
528
- ...params !== void 0 && { params }
529
- });
530
- },
531
- async reportProgress(progress, total, message) {
532
- const progressToken = ctx.mcpReq._meta?.progressToken;
533
- if (progressToken === void 0) return false;
534
- await ctx.mcpReq.notify({
535
- method: "notifications/progress",
536
- params: {
537
- progressToken,
538
- progress,
539
- ...total !== void 0 && { total },
540
- ...message !== void 0 && { message }
541
- }
542
- });
543
- return true;
544
- },
545
- async sendLog(level, data, logger) {
546
- await ctx.mcpReq.notify({
547
- method: "notifications/message",
548
- params: {
549
- level,
550
- data,
551
- ...logger !== void 0 && { logger }
552
- }
553
- });
554
- }
555
- };
556
- if (http !== void 0) {
557
- return Object.assign(http, additions);
558
- }
559
- return {
560
- ...additions,
561
- ...request !== void 0 && { req: request }
562
- };
563
- }
564
- function toAuthenticatedRequestContext(ctx) {
565
- const authInfo = ctx.http?.authInfo;
566
- requireOAuthAuthInfo(authInfo);
567
- return Object.assign(toRequestContext(ctx), {
568
- auth: {
569
- user: authInfo.extra.user,
570
- payload: authInfo.extra.payload,
571
- accessToken: authInfo.token,
572
- scopes: [...authInfo.scopes],
573
- permissions: [...authInfo.extra.permissions],
574
- ...authInfo.clientId.length > 0 && { clientId: authInfo.clientId },
575
- expiresAt: authInfo.expiresAt,
576
- ...authInfo.resource !== void 0 && { resource: authInfo.resource }
577
- }
578
- });
579
- }
580
-
581
- // src/response-conversion.ts
582
- function isReadResourceResult(result) {
583
- return "contents" in result && Array.isArray(result.contents);
584
- }
585
- function isGetPromptResult(result) {
586
- return "messages" in result && Array.isArray(result.messages);
587
- }
588
- function toResourceResult(result, uri) {
589
- if (isReadResourceResult(result)) {
590
- return result;
591
- }
592
- const mime = result._meta && typeof result._meta === "object" && typeof result._meta.mimeType === "string" ? result._meta.mimeType : void 0;
593
- const contents = [];
594
- for (const block of result.content ?? []) {
595
- const mapped = contentBlockToResourceContents(block, uri, mime);
596
- if (mapped !== void 0) {
597
- contents.push(mapped);
598
- }
599
- }
600
- if (contents.length === 0 && result.structuredContent !== void 0) {
601
- contents.push({
602
- uri,
603
- mimeType: "application/json",
604
- text: JSON.stringify(result.structuredContent)
605
- });
606
- }
607
- if (contents.length === 0) {
608
- contents.push({ uri, mimeType: "text/plain", text: "" });
609
- }
610
- return { contents };
611
- }
612
- function contentBlockToResourceContents(block, uri, mimeHint) {
613
- if (block.type === "text") {
614
- return {
615
- uri,
616
- mimeType: mimeHint ?? "text/plain",
617
- text: block.text
618
- };
619
- }
620
- if (block.type === "image" || block.type === "audio") {
621
- return {
622
- uri,
623
- mimeType: block.mimeType,
624
- blob: block.data
625
- };
626
- }
627
- if (block.type === "resource") {
628
- return { ...block.resource };
629
- }
630
- return void 0;
631
- }
632
- function toPromptResult(result) {
633
- if (isGetPromptResult(result)) {
634
- return result;
635
- }
636
- const messages = (result.content ?? []).map((content) => ({
637
- role: "user",
638
- content
639
- }));
640
- if (messages.length === 0 && result.structuredContent !== void 0) {
641
- messages.push({
642
- role: "user",
643
- content: {
644
- type: "text",
645
- text: JSON.stringify(result.structuredContent)
646
- }
647
- });
648
- }
649
- if (messages.length === 0) {
650
- messages.push({
651
- role: "user",
652
- content: { type: "text", text: "" }
653
- });
654
- }
655
- return { messages };
656
- }
657
-
658
- // src/middleware/cors.ts
659
- var DEFAULT_METHODS = ["GET", "HEAD", "POST", "OPTIONS"];
660
- var DEFAULT_ALLOWED_HEADERS = [
661
- "Content-Type",
662
- "Authorization",
663
- "mcp-protocol-version",
664
- "mcp-method",
665
- "mcp-name"
666
- ];
667
- function resolveAllowedOrigin(origin, requestOrigin) {
668
- if (origin === void 0) {
669
- return requestOrigin;
670
- }
671
- if (typeof origin === "function") {
672
- return origin(requestOrigin);
673
- }
674
- if (origin === "*") {
675
- return "*";
676
- }
677
- if (Array.isArray(origin)) {
678
- if (requestOrigin !== null && origin.includes(requestOrigin)) {
679
- return requestOrigin;
680
- }
681
- return null;
682
- }
683
- return origin;
684
- }
685
- function corsHeaders(options, request) {
686
- if (request.headers.has("Access-Control-Allow-Origin")) {
687
- return void 0;
688
- }
689
- const requestOrigin = request.headers.get("Origin");
690
- const allowedOrigin = resolveAllowedOrigin(options.origin, requestOrigin);
691
- if (allowedOrigin === null) {
692
- return void 0;
693
- }
694
- const headers = {
695
- "Access-Control-Allow-Origin": allowedOrigin,
696
- "Access-Control-Allow-Methods": options.methods.join(", "),
697
- "Access-Control-Allow-Headers": options.allowedHeaders.join(", ")
698
- };
699
- if (options.credentials) {
700
- headers["Access-Control-Allow-Credentials"] = "true";
701
- }
702
- if (allowedOrigin !== "*") {
703
- headers.Vary = "Origin";
704
- }
705
- return headers;
706
- }
707
- function mergeCorsHeaders(response, headers) {
708
- if (response.headers.has("Access-Control-Allow-Origin")) {
709
- return response;
710
- }
711
- const merged = new Headers(response.headers);
712
- const corsHeaders2 = new Headers(headers);
713
- corsHeaders2.forEach((value, key) => {
714
- merged.set(key, value);
715
- });
716
- return new Response(response.body, {
717
- status: response.status,
718
- statusText: response.statusText,
719
- headers: merged
720
- });
721
- }
722
- function corsFetchMiddleware(options) {
723
- const enabled = options.enabled !== false;
724
- if (!enabled) {
725
- return async (_request, next) => next();
726
- }
727
- const resolved = {
728
- ...options.origin !== void 0 && { origin: options.origin },
729
- methods: options.methods ?? DEFAULT_METHODS,
730
- allowedHeaders: options.allowedHeaders ?? DEFAULT_ALLOWED_HEADERS,
731
- credentials: options.credentials ?? false
732
- };
733
- return async (request, next) => {
734
- const headers = corsHeaders(resolved, request);
735
- if (headers === void 0) {
736
- return next();
737
- }
738
- if (request.method === "OPTIONS") {
739
- return new Response(null, { status: 204, headers });
740
- }
741
- const response = await next();
742
- return mergeCorsHeaders(response, headers);
743
- };
744
- }
745
- function isGlobalCorsEnabled(cors) {
746
- return cors !== void 0 && cors.enabled !== false;
747
- }
748
-
749
- // src/middleware/mcp-middleware.ts
750
- import {
751
- CallToolResultSchema,
752
- GetPromptResultSchema,
753
- ListPromptsResultSchema,
754
- ListResourcesResultSchema,
755
- ListToolsResultSchema,
756
- ReadResourceResultSchema
757
- } from "@modelcontextprotocol/core";
758
- import { isInputRequiredResult } from "@modelcontextprotocol/server";
759
- var MCP_MIDDLEWARE_METHODS = [
760
- "tools/call",
761
- "tools/list",
762
- "resources/read",
763
- "resources/list",
764
- "prompts/get",
765
- "prompts/list"
766
- ];
767
- function withMcpMiddlewareParams(request, params) {
768
- if (typeof request !== "object" || request === null || Array.isArray(request)) {
769
- throw new TypeError(
770
- "[mcp-use] MCP middleware received an invalid downstream request"
771
- );
772
- }
773
- return { ...request, params };
774
- }
775
- function createMcpMiddlewareEntry(pattern, handler) {
776
- const normalizedPattern = normalizeMcpMiddlewarePattern(pattern);
777
- const invoke = handler;
778
- if (normalizedPattern !== "*" && !isMcpMiddlewareMethod(normalizedPattern)) {
779
- throw new TypeError(
780
- `Unsupported MCP middleware pattern "${pattern}". Use an exact MCP method or "mcp:*".`
781
- );
782
- }
783
- if (normalizedPattern === "*") {
784
- return {
785
- pattern: normalizedPattern,
786
- handler: async (ctx, next) => {
787
- let downstreamCalled = false;
788
- let downstreamResult;
789
- await invoke(ctx, async () => {
790
- downstreamResult = await next();
791
- downstreamCalled = true;
792
- });
793
- if (!downstreamCalled) {
794
- throw new Error(
795
- `Wildcard MCP middleware "${normalizedPattern}" must call next()`
796
- );
797
- }
798
- return downstreamResult;
799
- }
800
- };
801
- }
802
- return {
803
- pattern: normalizedPattern,
804
- handler: (ctx, next) => invoke(ctx, next)
805
- };
806
- }
807
- function createMcpEventListenerEntry(pattern, handler) {
808
- const { pattern: normalizedPattern, phase } = parseMcpPattern(pattern);
809
- const invoke = handler;
810
- return {
811
- pattern: normalizedPattern,
812
- phase,
813
- handler: (ctx, result) => invoke(ctx, result)
814
- };
815
- }
816
- function matchesPattern(pattern, method) {
817
- if (pattern === "*") return true;
818
- if (pattern.endsWith("/*")) {
819
- const prefix = pattern.slice(0, -1);
820
- return method.startsWith(prefix);
821
- }
822
- return pattern === method;
823
- }
824
- function isMcpMiddlewareMethod(value) {
825
- return MCP_MIDDLEWARE_METHODS.some((method) => method === value);
826
- }
827
- function composeMiddleware(entries, method, innerFn) {
828
- const matching = entries.filter(
829
- (entry) => matchesPattern(entry.pattern, method)
830
- );
831
- if (matching.length === 0) {
832
- return (_ctx) => innerFn();
833
- }
834
- return (ctx) => {
835
- let index = -1;
836
- const dispatch = (i) => {
837
- if (i <= index) {
838
- return Promise.reject(new Error("next() called multiple times"));
839
- }
840
- index = i;
841
- if (i === matching.length) {
842
- return innerFn();
843
- }
844
- const entry = matching[i];
845
- return entry.handler(
846
- ctx,
847
- () => dispatch(i + 1)
848
- );
849
- };
850
- return dispatch(0);
851
- };
852
- }
853
- function freezeMiddlewareContext(ctx) {
854
- return Object.freeze({
855
- method: ctx.method,
856
- params: Object.freeze({ ...ctx.params }),
857
- ...ctx.request !== void 0 && { request: ctx.request },
858
- ...ctx.req !== void 0 && { req: ctx.req },
859
- ...ctx.session !== void 0 && {
860
- session: Object.freeze({ ...ctx.session })
861
- },
862
- ...ctx.auth !== void 0 && { auth: ctx.auth },
863
- state: new Map(ctx.state)
864
- });
865
- }
866
- async function runMcpOperation(middlewares, events, method, ctx, innerFn) {
867
- dispatchMcpEvents(events, method, "before", ctx);
868
- const chained = composeMiddleware(middlewares, method, innerFn);
869
- const result = await chained(ctx);
870
- assertValidMiddlewareResult(method, result);
871
- dispatchMcpEvents(events, method, "complete", ctx, result);
872
- return result;
873
- }
874
- function assertValidMiddlewareResult(method, result) {
875
- if ((method === "tools/call" || method === "resources/read" || method === "prompts/get") && isInputRequiredResult(result)) {
876
- return;
877
- }
878
- const validation = (() => {
879
- switch (method) {
880
- case "tools/call":
881
- assertArrayProperty(method, result, "content");
882
- return CallToolResultSchema.safeParse(result);
883
- case "tools/list":
884
- assertArrayResult(method, result);
885
- return ListToolsResultSchema.safeParse({ tools: result });
886
- case "resources/read":
887
- assertArrayProperty(method, result, "contents");
888
- return ReadResourceResultSchema.safeParse(result);
889
- case "resources/list":
890
- assertArrayResult(method, result);
891
- return ListResourcesResultSchema.safeParse({ resources: result });
892
- case "prompts/get":
893
- assertArrayProperty(method, result, "messages");
894
- return GetPromptResultSchema.safeParse(result);
895
- case "prompts/list":
896
- assertArrayResult(method, result);
897
- return ListPromptsResultSchema.safeParse({ prompts: result });
898
- default:
899
- throw new TypeError(`Unsupported MCP middleware method "${method}"`);
900
- }
901
- })();
902
- if (!validation.success) {
903
- throw new TypeError(
904
- `[mcp-use] ${method} middleware returned an invalid result: ${validation.error.message}`
905
- );
906
- }
907
- }
908
- function assertArrayResult(method, result) {
909
- if (!Array.isArray(result)) {
910
- throw new TypeError(
911
- `[mcp-use] ${method} middleware returned an invalid result: expected an array`
912
- );
913
- }
914
- }
915
- function assertArrayProperty(method, result, property) {
916
- if (typeof result !== "object" || result === null || !Array.isArray(result[property])) {
917
- throw new TypeError(
918
- `[mcp-use] ${method} middleware returned an invalid result: expected a ${property} array`
919
- );
920
- }
921
- }
922
- function dispatchMcpEvents(events, method, phase, ctx, result) {
923
- const frozen = freezeMiddlewareContext(ctx);
924
- for (const entry of events) {
925
- if (entry.phase !== phase || !matchesPattern(entry.pattern, method)) {
926
- continue;
927
- }
928
- try {
929
- entry.handler(frozen, result);
930
- } catch (error2) {
931
- console.error(
932
- `[mcp-use] MCP event listener for "${entry.pattern}" (${phase}) threw:`,
933
- error2
934
- );
935
- }
936
- }
937
- }
938
- function parseMcpPattern(raw) {
939
- const pattern = raw.startsWith("mcp:") ? raw.slice(4) : raw;
940
- if (pattern.endsWith(":complete")) {
941
- return {
942
- pattern: pattern.slice(0, -":complete".length),
943
- phase: "complete"
944
- };
945
- }
946
- return { pattern, phase: "before" };
947
- }
948
- function normalizeMcpMiddlewarePattern(raw) {
949
- return raw.startsWith("mcp:") ? raw.slice(4) : raw;
950
- }
951
-
952
- // src/logging.ts
953
- import {
954
- CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY2,
955
- isJSONRPCRequest
956
- } from "@modelcontextprotocol/server";
957
- function colorsEnabled() {
958
- if (typeof process === "undefined") return false;
959
- if (process.env?.["NO_COLOR"] !== void 0) return false;
960
- return process.stdout?.isTTY === true;
961
- }
962
- function ansi(open, close) {
963
- return (text2) => colorsEnabled() ? `\x1B[${open}m${text2}\x1B[${close}m` : text2;
964
- }
965
- var bold = ansi(1, 22);
966
- var dim = ansi(2, 22);
967
- var red = ansi(31, 39);
968
- var green = ansi(32, 39);
969
- var yellow = ansi(33, 39);
970
- var blue = ansi(34, 39);
971
- var magenta = ansi(35, 39);
972
- var cyan = ansi(36, 39);
973
- var gray = ansi(90, 39);
974
- function resolveLogLevel(configured) {
975
- const raw = typeof process === "undefined" ? void 0 : process.env?.["MCP_USE_LOG_LEVEL"]?.toLowerCase();
976
- if (raw === "info" || raw === "debug" || raw === "trace") return raw;
977
- return configured ?? "info";
978
- }
979
- function formatClientInfo(info) {
980
- if (info === void 0) return void 0;
981
- return typeof info.version === "string" && info.version !== "" ? `${info.name}/${info.version}` : info.name;
982
- }
983
- var detailFormatters = {
984
- initialize: (p) => ({ subject: formatClientInfo(p.clientInfo) }),
985
- ping: () => ({}),
986
- "server/discover": () => ({}),
987
- "completion/complete": (p) => ({
988
- subject: p.ref.type === "ref/prompt" ? p.ref.name : p.ref.uri,
989
- input: p.argument
990
- }),
991
- "logging/setLevel": (p) => ({ subject: p.level }),
992
- "prompts/get": (p) => ({ subject: p.name, input: p.arguments }),
993
- "prompts/list": () => ({}),
994
- "resources/list": () => ({}),
995
- "resources/templates/list": () => ({}),
996
- "resources/read": (p) => ({ subject: p.uri }),
997
- "resources/subscribe": (p) => ({ subject: p.uri }),
998
- "resources/unsubscribe": (p) => ({ subject: p.uri }),
999
- "subscriptions/listen": () => ({}),
1000
- "tools/call": (p) => ({ subject: p.name, input: p.arguments }),
1001
- "tools/list": () => ({}),
1002
- "sampling/createMessage": () => ({}),
1003
- "elicitation/create": () => ({}),
1004
- "roots/list": () => ({})
1005
- };
1006
- function isKnownMethod(method) {
1007
- return Object.prototype.hasOwnProperty.call(detailFormatters, method);
1008
- }
1009
- function formatDetail(message) {
1010
- if (!isKnownMethod(message.method)) return {};
1011
- try {
1012
- const formatter = detailFormatters[message.method];
1013
- const detail = formatter(message.params);
1014
- return typeof detail.subject === "string" || detail.subject === void 0 ? detail : {};
1015
- } catch {
1016
- return {};
1017
- }
1018
- }
1019
- var INLINE_JSON_MAX_LENGTH = 80;
1020
- function inlineJson(value) {
1021
- let text2;
1022
- try {
1023
- text2 = JSON.stringify(value) ?? String(value);
1024
- } catch {
1025
- text2 = String(value);
1026
- }
1027
- return text2.length > INLINE_JSON_MAX_LENGTH ? `${text2.slice(0, INLINE_JSON_MAX_LENGTH)}...` : text2;
1028
- }
1029
- function formatClientIdentity(message) {
1030
- const meta = message.params?._meta;
1031
- if (meta === void 0) return void 0;
1032
- const info = meta[CLIENT_INFO_META_KEY2];
1033
- if (typeof info !== "object" || info === null || typeof info.name !== "string") {
1034
- return void 0;
1035
- }
1036
- return formatClientInfo(info);
1037
- }
1038
- function sanitize(text2) {
1039
- return text2.replace(/[\u0000-\u001F\u007F-\u009F]+/g, " ");
1040
- }
1041
- function methodStyle(method) {
1042
- if (method.startsWith("tools/")) return cyan;
1043
- if (method.startsWith("resources/")) return green;
1044
- if (method.startsWith("prompts/")) return magenta;
1045
- if (method === "initialize" || method === "ping") return gray;
1046
- return blue;
1047
- }
1048
- var REDACTED_HEADERS = /* @__PURE__ */ new Set([
1049
- "authorization",
1050
- "proxy-authorization",
1051
- "cookie",
1052
- "set-cookie",
1053
- "x-api-key"
1054
- ]);
1055
- function redactHeaders(headers) {
1056
- return Object.fromEntries(
1057
- Object.entries(headers).map(([name, value]) => [
1058
- name,
1059
- REDACTED_HEADERS.has(name.toLowerCase()) ? "[REDACTED]" : value
1060
- ])
1061
- );
1062
- }
1063
- async function extractResponseOutcome(res) {
1064
- if (!res.body) return { errorMessage: null };
1065
- let text2;
1066
- try {
1067
- text2 = await res.clone().text();
1068
- } catch {
1069
- return { errorMessage: null };
1070
- }
1071
- if (!text2) return { errorMessage: null };
1072
- const isSse = (res.headers.get("content-type") ?? "").includes(
1073
- "text/event-stream"
1074
- );
1075
- const payloads = [];
1076
- const tryParse = (raw) => {
1077
- try {
1078
- payloads.push(JSON.parse(raw));
1079
- } catch {
1080
- }
1081
- };
1082
- if (isSse) {
1083
- for (const line of text2.split(/\r?\n/)) {
1084
- if (line.startsWith("data:")) {
1085
- const data = line.slice(5).trim();
1086
- if (data) tryParse(data);
1087
- }
1088
- }
1089
- } else {
1090
- tryParse(text2);
1091
- }
1092
- let result;
1093
- for (const payload of payloads) {
1094
- if (payload === null || typeof payload !== "object") continue;
1095
- const message = payload;
1096
- if (typeof message.error?.message === "string") {
1097
- return { errorMessage: message.error.message };
1098
- }
1099
- if (message.result?.isError === true) {
1100
- const blocks = Array.isArray(message.result.content) ? message.result.content : [];
1101
- const textBlock = blocks.find(
1102
- (b) => b?.type === "text" && typeof b.text === "string"
1103
- );
1104
- return {
1105
- errorMessage: textBlock ? String(textBlock.text) : "tool error"
1106
- };
1107
- }
1108
- if ("result" in message) result = message.result;
1109
- }
1110
- return { errorMessage: null, result };
1111
- }
1112
- function compactToolResult(result) {
1113
- if (result === null || typeof result !== "object") return result;
1114
- const { structuredContent, content } = result;
1115
- if (structuredContent !== void 0) return structuredContent;
1116
- if (Array.isArray(content)) {
1117
- const [block] = content;
1118
- if (content.length === 1 && block?.type === "text") return block.text;
1119
- }
1120
- return content;
1121
- }
1122
- function formatForDump(value) {
1123
- function truncate(val) {
1124
- if (typeof val === "string" && val.length > 100) {
1125
- return `${val.slice(0, 100)}...`;
1126
- }
1127
- if (Array.isArray(val)) return val.map(truncate);
1128
- if (val !== null && typeof val === "object") {
1129
- return Object.fromEntries(
1130
- Object.entries(val).map(([k, v]) => [
1131
- k,
1132
- truncate(v)
1133
- ])
1134
- );
1135
- }
1136
- return val;
1137
- }
1138
- try {
1139
- return JSON.stringify(truncate(value), null, 2);
1140
- } catch {
1141
- return String(value);
1142
- }
1143
- }
1144
- var DUMP_BODY_MAX_LENGTH = 1e4;
1145
- async function printTraceDump(response, requestHeaders, requestBody, readResponseBody) {
1146
- console.log(`
1147
- ${cyan("=".repeat(80))}`);
1148
- console.log(bold(cyan("[TRACE] Request Details")));
1149
- console.log(cyan("-".repeat(80)));
1150
- if (Object.keys(requestHeaders).length > 0) {
1151
- console.log(yellow("Request Headers:"));
1152
- console.log(formatForDump(redactHeaders(requestHeaders)));
1153
- }
1154
- if (requestBody !== void 0) {
1155
- console.log(yellow("Request Body:"));
1156
- console.log(
1157
- typeof requestBody === "string" ? requestBody : formatForDump(requestBody)
1158
- );
1159
- }
1160
- const responseHeaders = {};
1161
- response.headers.forEach((value, key) => {
1162
- responseHeaders[key] = value;
1163
- });
1164
- if (Object.keys(responseHeaders).length > 0) {
1165
- console.log(yellow("Response Headers:"));
1166
- console.log(formatForDump(redactHeaders(responseHeaders)));
1167
- }
1168
- if (!readResponseBody) {
1169
- console.log(`${yellow("Response Body:")} (streaming \u2014 not dumped)`);
1170
- } else if (response.body === null) {
1171
- console.log(`${yellow("Response Body:")} (no body)`);
1172
- } else {
1173
- try {
1174
- const text2 = await response.clone().text();
1175
- if (text2.length === 0) {
1176
- console.log(`${yellow("Response Body:")} (empty)`);
1177
- } else {
1178
- console.log(yellow("Response Body:"));
1179
- try {
1180
- console.log(formatForDump(JSON.parse(text2)));
1181
- } catch {
1182
- console.log(
1183
- text2.length > DUMP_BODY_MAX_LENGTH ? `${text2.slice(0, DUMP_BODY_MAX_LENGTH)}
1184
- ... (truncated, ${text2.length - DUMP_BODY_MAX_LENGTH} more characters)` : text2
1185
- );
1186
- }
1187
- }
1188
- } catch {
1189
- console.log(`${yellow("Response Body:")} (unable to read)`);
1190
- }
1191
- }
1192
- console.log(`${cyan("=".repeat(80))}
1193
- `);
1194
- }
1195
- function styleStatus(status) {
1196
- const text2 = String(status);
1197
- if (status >= 500) return magenta(text2);
1198
- if (status >= 400) return red(text2);
1199
- if (status >= 300) return yellow(text2);
1200
- return green(text2);
1201
- }
1202
- function isNoisyRequest(httpMethod, pathname) {
1203
- if (httpMethod !== "GET" && httpMethod !== "HEAD") return false;
1204
- return pathname.endsWith("/favicon.ico");
1205
- }
1206
- function requestLogger(options = {}) {
1207
- if (options.enabled === false) {
1208
- return (_request, next) => next();
1209
- }
1210
- return async (request, next) => {
1211
- const level = resolveLogLevel(options.level);
1212
- const startedAt = Date.now();
1213
- const httpMethod = request.method;
1214
- const pathname = new URL(request.url).pathname;
1215
- if (isNoisyRequest(httpMethod, pathname)) {
1216
- return next();
1217
- }
1218
- const requestHeaders = {};
1219
- if (level === "trace") {
1220
- request.headers.forEach((value, key) => {
1221
- requestHeaders[key] = value;
1222
- });
1223
- }
1224
- let requestBody;
1225
- if (httpMethod !== "GET" && httpMethod !== "HEAD") {
1226
- const parsedBody = getRequestBag(request).parsedBody;
1227
- if (parsedBody !== void 0) {
1228
- requestBody = parsedBody;
1229
- } else {
1230
- try {
1231
- requestBody = await request.clone().json();
1232
- } catch {
1233
- }
1234
- }
1235
- }
1236
- const response = await next();
1237
- const durationMs = Date.now() - startedAt;
1238
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 19);
1239
- const mcpRequest = isJSONRPCRequest(requestBody) ? requestBody : void 0;
1240
- const isStreamingMethod = mcpRequest?.method === "subscriptions/listen";
1241
- const lines = [
1242
- [
1243
- dim(timestamp),
1244
- bold(httpMethod),
1245
- pathname,
1246
- styleStatus(response.status),
1247
- dim(`in ${durationMs}ms`)
1248
- ].join(" ")
1249
- ];
1250
- if (mcpRequest !== void 0) {
1251
- const method = sanitize(mcpRequest.method);
1252
- const parts = [` ${methodStyle(method)(method)}`];
1253
- const detail = formatDetail(mcpRequest);
1254
- if (detail.subject !== void 0) {
1255
- parts.push(bold(sanitize(detail.subject)));
1256
- }
1257
- const echoPayloads = level !== "info";
1258
- if (echoPayloads && detail.input !== void 0) {
1259
- parts.push(inlineJson(detail.input));
1260
- }
1261
- const outcome = isStreamingMethod ? { errorMessage: null } : await extractResponseOutcome(response);
1262
- if (echoPayloads && mcpRequest.method === "tools/call" && outcome.errorMessage === null && outcome.result !== void 0) {
1263
- parts.push(dim("->"), inlineJson(compactToolResult(outcome.result)));
1264
- }
1265
- if (mcpRequest.method !== "initialize") {
1266
- const client = formatClientIdentity(mcpRequest);
1267
- if (client !== void 0) parts.push(dim(sanitize(client)));
1268
- }
1269
- if (outcome.errorMessage !== null) {
1270
- parts.push(red(`ERROR ${sanitize(outcome.errorMessage)}`));
1271
- } else if (response.status >= 400) {
1272
- parts.push(red(`ERROR (HTTP ${response.status})`));
1273
- }
1274
- lines.push(parts.join(" "));
1275
- }
1276
- console.log(lines.join("\n"));
1277
- if (level === "trace") {
1278
- await printTraceDump(
1279
- response,
1280
- requestHeaders,
1281
- requestBody,
1282
- !isStreamingMethod
1283
- );
1284
- }
1285
- return response;
1286
- };
1287
- }
1288
-
1289
- // src/mount-mcp.ts
1290
- import {
1291
- createMcpHandler
1292
- } from "@modelcontextprotocol/server";
1293
- function createMcpMount(factory, options = {}) {
1294
- const {
1295
- path = "/mcp",
1296
- handler: handlerOptions,
1297
- authInfo: getAuthInfo
1298
- } = options;
1299
- const legacyMode = handlerOptions?.legacy ?? "stateless";
1300
- const handler = createMcpHandler(factory, {
1301
- legacy: "stateless",
1302
- ...handlerOptions
1303
- });
1304
- const fetch = async (request) => {
1305
- if (!matchesPath(request, path)) {
1306
- return new Response("Not Found", { status: 404 });
1307
- }
1308
- if (legacyMode === "stateless") {
1309
- const method = request.method.toUpperCase();
1310
- if (method === "GET" || method === "DELETE" || method === "HEAD") {
1311
- return new Response(null, { status: 204 });
1312
- }
1313
- }
1314
- const bag = getRequestBag(request);
1315
- let parsedBody = bag.parsedBody;
1316
- if (parsedBody === void 0) {
1317
- try {
1318
- parsedBody = await request.clone().json();
1319
- } catch {
1320
- }
1321
- }
1322
- const capabilities = extractClientCapabilitiesFromBody(parsedBody);
1323
- if (capabilities !== void 0) {
1324
- stashClientCapabilities(request, capabilities);
1325
- }
1326
- const authInfo = getAuthInfo?.(request) ?? bag.authInfo;
1327
- return handler.fetch(request, {
1328
- ...parsedBody !== void 0 && { parsedBody },
1329
- ...authInfo !== void 0 && { authInfo }
1330
- });
1331
- };
1332
- return { handler, fetch };
1333
- }
1334
-
1335
- // src/tools.ts
1336
- function resolveToolInputSchema(definition) {
1337
- return definition.inputSchema ?? definition.schema;
1338
- }
1339
-
1340
- // src/views/register.ts
1341
- var registerViews = /* @__PURE__ */ Symbol("mcp-use/registerViews");
1342
-
1343
- // src/views/document.ts
1344
- function resolveAssetUrl(assetPath, origin) {
1345
- if (!assetPath.startsWith("/")) {
1346
- throw new Error(
1347
- `View manifest asset path must be origin-absolute (start with "/"); got ${JSON.stringify(assetPath)}`
1348
- );
1349
- }
1350
- return `${origin}${assetPath}`;
1351
- }
1352
- function viewAssetsBasePath(basePath, viewName) {
1353
- return `${pathUnderBase(basePath, `_mcp-use/views/${viewName}`)}/`;
1354
- }
1355
- function resolveExternalAssetUrl(assetPath, assetsBase, basePath, viewName) {
1356
- if (assetPath.startsWith("http://") || assetPath.startsWith("https://") || assetPath.startsWith("data:")) {
1357
- return assetPath;
1358
- }
1359
- if (assetPath.startsWith("/")) {
1360
- return resolveAssetUrl(assetPath, assetsBase);
1361
- }
1362
- return `${assetsBase}${viewAssetsBasePath(basePath, viewName)}${assetPath.replace(/^\/+/, "")}`;
1363
- }
1364
- function resolvePublicBase(assetsBase, basePath) {
1365
- return `${assetsBase}${pathUnderBase(basePath, "_mcp-use/public")}/`;
1366
- }
1367
- function escapeInlineScript(code) {
1368
- return code.replaceAll(/<\/script/gi, "<\\/script").replaceAll("<!--", "\\x3C!--");
1369
- }
1370
- function escapeInlineStyle(css2) {
1371
- return css2.replaceAll(/<\/style/gi, "<\\/style");
1372
- }
1373
- function escapeHtml(value) {
1374
- return value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
1375
- }
1376
- var TRANSPARENT_IFRAME_STYLE = "<style>html,body,#root{background:transparent}</style>";
1377
- function synthesizeViewDocument(entry, assetsBase, basePath, viewName) {
1378
- const viewConfig = {
1379
- publicBase: resolvePublicBase(assetsBase, basePath)
1380
- };
1381
- const configScript = `<script>globalThis.__mcpUseViewConfig=${JSON.stringify(viewConfig)};</script>`;
1382
- if (entry.kind === "inline") {
1383
- const styleTag = entry.css.length > 0 ? `<style>${escapeInlineStyle(entry.css)}</style>` : "";
1384
- const moduleScript = `<script type="module">${escapeInlineScript(entry.js)}</script>`;
1385
- return `<!doctype html>
1
+ import{hasExplicitAssetsBase,originFromAssetsBase,resolveAssetsBase,resolveServerOrigin}from"./chunk-PSKSL567.js";import{registerOpenAPITools}from"./chunk-Y26DNVWA.js";import{completable,normalizeCompletions}from"./chunk-OJF6B5EU.js";import{recordUsage}from"./chunk-5Z6KY5ON.js";import{resolvePublicFilePath,servePublicFile}from"./chunk-ZMU5USAZ.js";import{authInfoFromRequest,composeFetch,getOAuthProtectedResourceMetadataUrl,getRequestBag,hostValidationMiddleware,isHtmlNavigationRequest,jsonBodyMiddleware,matchesPath,matchesPathPrefix,oauthMetadata,originValidationMiddleware,pathUnderBase,pathnameOf,requireBearerAuth}from"./chunk-WYBJYZJB.js";import{getOAuthProviderOptions,resolveConfiguredOAuthResource,resolveLocalOAuthResource,wrapOAuthTokenVerifier}from"./chunk-JMDHTN6N.js";import{localhostAllowedHostnames,localhostAllowedOrigins,McpServer as SdkMcpServer,ResourceTemplate,CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY3,CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY3,PROTOCOL_VERSION_META_KEY,isJSONRPCRequest as isJSONRPCRequest2,isInputRequiredResult as isInputRequiredResult2}from"@modelcontextprotocol/server";import{Hono}from"hono";var FAVICON_CACHE_CONTROL="public, max-age=31536000, immutable",FAVICON_REDIRECT_CACHE_CONTROL="public, max-age=300";function protocolOf(value){return/^([a-z][a-z\d+.-]*):/i.exec(value)?.[1]?.toLowerCase()}function publicAssetPath(basePath,source){return`${basePath==="/"?"":basePath}/_mcp-use/public/${source.split("/").map(segment=>encodeURIComponent(segment)).join("/")}`}function isLocalPublicSource(source){return protocolOf(source)===void 0}function selectFaviconFromIcons(icons){return icons[0]}function assertLocalPublicSource(source,field){if(source.startsWith("/")||source.includes("\\")||source.includes("?")||source.includes("#")||source.split("/").some(segment=>segment===""||segment===".."))throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`)}function parseDataImage(source,field){let comma=source.indexOf(",");if(comma<0)throw new TypeError(`${field} must be a valid image data URL`);let metadata=source.slice(5,comma),payload=source.slice(comma+1),parts=metadata.split(";"),mimeType=parts[0]?.toLowerCase()??"";if(!mimeType.startsWith("image/"))throw new TypeError(`${field} data URL must use an image MIME type`);try{if(parts.includes("base64")){let binary2=atob(payload);return{mimeType,bytes:Uint8Array.from(binary2,character=>character.charCodeAt(0))}}return{mimeType,bytes:new TextEncoder().encode(decodeURIComponent(payload))}}catch{throw new TypeError(`${field} must be a valid image data URL`)}}function assertBrandingSource(source,field){if(typeof source!="string"||source.length===0)throw new TypeError(`${field} must be a non-empty string`);let protocol=protocolOf(source);if(protocol===void 0)return assertLocalPublicSource(source,field),source;if(protocol==="data")return parseDataImage(source,field),source;if(protocol!=="http"&&protocol!=="https")throw new TypeError(`${field} must be an http(s) URL, image data URL, or safe path relative to public/`);try{new URL(source)}catch{throw new TypeError(`${field} must be a valid absolute http(s) URL`)}return source}function normalizeServerBranding(config){let websiteUrl;if(config.websiteUrl!==void 0){if(typeof config.websiteUrl!="string"||config.websiteUrl.length===0)throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");let parsed;try{parsed=new URL(config.websiteUrl)}catch{throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL")}if(parsed.protocol!=="http:"&&parsed.protocol!=="https:")throw new TypeError("websiteUrl must be a non-empty absolute http(s) URL");websiteUrl=config.websiteUrl}let icons;if(config.icons!==void 0){if(!Array.isArray(config.icons))throw new TypeError("icons must be an array of MCP Icon objects");icons=Object.freeze(config.icons.map((value,index)=>{if(typeof value!="object"||value===null)throw new TypeError(`icons[${index}] must be an MCP Icon object`);let icon=value,src=assertBrandingSource(icon.src,`icons[${index}].src`),mimeType=icon.mimeType;if(mimeType!==void 0&&(typeof mimeType!="string"||!mimeType.toLowerCase().startsWith("image/")))throw new TypeError(`icons[${index}].mimeType must be an image MIME type when provided`);let sizes=icon.sizes;if(sizes!==void 0&&(!Array.isArray(sizes)||sizes.some(size=>typeof size!="string"||size.length===0)))throw new TypeError(`icons[${index}].sizes must be an array of non-empty strings when provided`);let normalizedSizes=sizes===void 0?void 0:sizes.map(size=>size),theme=icon.theme;if(theme!==void 0&&theme!=="light"&&theme!=="dark")throw new TypeError(`icons[${index}].theme must be "light" or "dark" when provided`);return Object.freeze({src,...mimeType!==void 0&&{mimeType},...normalizedSizes!==void 0&&{sizes:Object.freeze(normalizedSizes)},...theme!==void 0&&{theme}})}))}let explicitFavicon=config.favicon===void 0?void 0:assertBrandingSource(config.favicon,"favicon"),inferred=explicitFavicon===void 0?selectFaviconFromIcons(icons??[]):void 0,favicon=explicitFavicon??inferred?.src,faviconMimeType=inferred?.mimeType??icons?.find(icon=>icon.src===explicitFavicon)?.mimeType;return Object.freeze({...favicon!==void 0&&{favicon},...faviconMimeType!==void 0&&{faviconMimeType},...icons!==void 0&&{icons},...websiteUrl!==void 0&&{websiteUrl}})}function resolveImplementationIcons(icons,request,basePath){if(icons!==void 0)return icons.map(icon=>({...icon,src:request!==void 0&&isLocalPublicSource(icon.src)?`${resolveAssetsBase(request)}${publicAssetPath(basePath,icon.src)}`:icon.src,...icon.sizes!==void 0&&{sizes:[...icon.sizes]}}))}function hasLocalBrandingAsset(branding){return branding.favicon!==void 0&&isLocalPublicSource(branding.favicon)||branding.icons?.some(icon=>isLocalPublicSource(icon.src))===!0}function createFaviconHandler(branding,options){let source=branding.favicon;if(source!==void 0)return async request=>{if(request.method!=="GET"&&request.method!=="HEAD")return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, HEAD"}});if(new URL(request.url).pathname!=="/favicon.ico")return new Response("Not Found",{status:404});let protocol=protocolOf(source);if(protocol==="http"||protocol==="https")return new Response(null,{status:307,headers:{Location:source,"Cache-Control":FAVICON_REDIRECT_CACHE_CONTROL}});if(protocol==="data"){let data=parseDataImage(source,"favicon");return new Response(request.method==="HEAD"?null:data.bytes.buffer,{status:200,headers:{"Content-Type":branding.faviconMimeType??data.mimeType,"Cache-Control":FAVICON_CACHE_CONTROL,"X-Content-Type-Options":"nosniff"}})}let{join}=await import("path"),publicRoot=options.dev?join(options.projectRoot,"public"):join(options.projectRoot,".mcp-use/build/views/public"),diskPath=await resolvePublicFilePath(publicRoot,source);if(diskPath===null)return new Response("Not Found",{status:404,headers:{"Cache-Control":"no-store"}});let response=await servePublicFile(diskPath,{...options.deferCors===!0&&{deferCors:!0},...request.method==="HEAD"&&{head:!0}});return response.headers.set("Cache-Control",FAVICON_CACHE_CONTROL),response.headers.set("X-Content-Type-Options","nosniff"),branding.faviconMimeType!==void 0&&response.headers.set("Content-Type",branding.faviconMimeType),response}}function assertServerConfig(config){if(config.basePath!==void 0){if(typeof config.basePath!="string")throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace");let{basePath}=config;if(!basePath.startsWith("/")||basePath.includes("?")||basePath.includes("#")||/\s/.test(basePath)||basePath.includes("//")||basePath.length>1&&basePath.endsWith("/"))throw new TypeError("basePath must be an absolute URL pathname without empty segments, trailing slash, query, fragment, or whitespace")}if(config.port!==void 0&&(typeof config.port!="number"||!Number.isInteger(config.port)||config.port<0||config.port>65535))throw new TypeError("port must be an integer between 0 and 65535")}var DEFAULT_LISTEN_HOST="127.0.0.1";function resolveListenHost(explicitHost,configuredHost,env=process.env){if(explicitHost!==void 0)return explicitHost;let envHost=env.HOST?.trim();return envHost!==void 0&&envHost!==""?envHost:configuredHost??DEFAULT_LISTEN_HOST}function resolveListenPort(explicitPort,configuredPort,env=process.env){if(explicitPort!==void 0)return explicitPort;let envPort=parsePort(env.PORT);return envPort!==void 0?envPort:configuredPort??3e3}function parsePort(value){if(value===void 0||value.trim()==="")return;let port=Number(value);return Number.isInteger(port)&&port>=0&&port<=65535?port:void 0}import{CLIENT_CAPABILITIES_META_KEY as CLIENT_CAPABILITIES_META_KEY2,CLIENT_INFO_META_KEY,inputRequired,inputResponse}from"@modelcontextprotocol/server";import{HonoRequest}from"hono/request";import{CLIENT_CAPABILITIES_META_KEY}from"@modelcontextprotocol/server";var UI_EXTENSION_ID="io.modelcontextprotocol/ui",UI_MIME_TYPE="text/html;profile=mcp-app",UI_RESOURCE_URI_PREFIX="ui://views/";var UI_RESOURCE_URI_META_KEY="ui/resourceUri";function viewResourceUri(viewName){return`${UI_RESOURCE_URI_PREFIX}${viewName}.html`}var clientCapabilitiesByRequest=new WeakMap;function stashClientCapabilities(request,capabilities){clientCapabilitiesByRequest.set(request,capabilities)}function extractClientCapabilitiesFromBody(body){if(typeof body!="object"||body===null)return;let params=body.params;if(typeof params!="object"||params===null)return;let meta=params._meta;if(typeof meta!="object"||meta===null)return;let capabilities=meta[CLIENT_CAPABILITIES_META_KEY];if(!(typeof capabilities!="object"||capabilities===null))return capabilities}function supportsViews(capabilities){let extensions=capabilities?.extensions;if(extensions===void 0)return!1;let uiExtension=extensions[UI_EXTENSION_ID];if(typeof uiExtension!="object"||uiExtension===null)return!1;let mimeTypes=uiExtension.mimeTypes;return Array.isArray(mimeTypes)?mimeTypes.includes(UI_MIME_TYPE):!1}function requireOAuthAuthInfo(authInfo){if(authInfo===void 0||authInfo.extra===void 0||authInfo.expiresAt===void 0)throw new Error("OAuth callback did not receive mapped AuthInfo.extra")}function stringValue(value){return typeof value=="string"?value:void 0}function coordinateValue(value){return typeof value=="string"||typeof value=="number"&&Number.isFinite(value)?value:void 0}function normalizeUserContext(meta){if(meta===void 0)return;let locale=stringValue(meta["openai/locale"])??stringValue(meta["webplus/i18n"]),userAgent=stringValue(meta["openai/userAgent"]),subject=stringValue(meta["openai/subject"]),conversationId=stringValue(meta["openai/session"]),organizationId=stringValue(meta["openai/organization"]),rawLocation=meta["openai/userLocation"],location;if(typeof rawLocation=="object"&&rawLocation!==null&&!Array.isArray(rawLocation)){let values=rawLocation,normalized={city:stringValue(values.city),region:stringValue(values.region),country:stringValue(values.country),timezone:stringValue(values.timezone),latitude:coordinateValue(values.latitude),longitude:coordinateValue(values.longitude)},entries=Object.entries(normalized).filter(entry=>entry[1]!==void 0);entries.length>0&&(location=Object.fromEntries(entries))}if(!(locale===void 0&&userAgent===void 0&&location===void 0&&subject===void 0&&conversationId===void 0&&organizationId===void 0))return{...locale!==void 0&&{locale},...userAgent!==void 0&&{userAgent},...location!==void 0&&{location},...subject!==void 0&&{subject},...conversationId!==void 0&&{conversationId},...organizationId!==void 0&&{organizationId}}}function toClientContext(ctx){let envelope=ctx.mcpReq.envelope,capabilities={...envelope?.[CLIENT_CAPABILITIES_META_KEY2]??{}},info={...envelope?.[CLIENT_INFO_META_KEY]??{}},user=normalizeUserContext(ctx.mcpReq._meta);return{can(capability){return Object.hasOwn(capabilities,capability)},capabilities(){return{...capabilities}},extension(id){let settings=capabilities.extensions?.[id];return settings===void 0?void 0:{...settings}},info(){return{...info}},user(){return user===void 0?void 0:{...user,...user.location!==void 0&&{location:{...user.location}}}},supportsViews(){return supportsViews(capabilities)}}}function createElicit(inputResponses){return async function(key,message,schemaOrUrl){let request,formSchema;if(typeof schemaOrUrl=="string")request=inputRequired.elicitUrl({message,url:schemaOrUrl});else if(schemaOrUrl!==void 0)formSchema=schemaOrUrl,request=inputRequired.elicit({message,requestedSchema:schemaOrUrl});else throw new TypeError("ctx.elicit(key, message, value) requires a form schema or URL string");let response=inputResponse(inputResponses,key);if(response.kind==="elicit"){if(response.action!=="accept")return{status:response.action};if(formSchema===void 0)return{status:"accept"};if(response.content!==void 0){let outcome=await formSchema["~standard"].validate(response.content);if(outcome.issues===void 0)return{status:"accept",data:outcome.value}}}return{status:"required",result:inputRequired({inputRequests:{[key]:request}})}}}function toRequestContext(ctx){let rawRequest=ctx.http?.req,http=rawRequest===void 0?void 0:getRequestBag(rawRequest).honoContext,request=http?.req??(rawRequest===void 0?void 0:new HonoRequest(rawRequest)),additions={signal:ctx.mcpReq.signal,...request!==void 0&&{request},...ctx.mcpReq.inputResponses!==void 0&&{inputResponses:ctx.mcpReq.inputResponses},client:toClientContext(ctx),elicit:createElicit(ctx.mcpReq.inputResponses),requestState:()=>ctx.mcpReq.requestState(),async sendNotification(method,params){await ctx.mcpReq.notify({method,...params!==void 0&&{params}})},async reportProgress(progress,total,message){let progressToken=ctx.mcpReq._meta?.progressToken;return progressToken===void 0?!1:(await ctx.mcpReq.notify({method:"notifications/progress",params:{progressToken,progress,...total!==void 0&&{total},...message!==void 0&&{message}}}),!0)},async sendLog(level,data,logger){await ctx.mcpReq.notify({method:"notifications/message",params:{level,data,...logger!==void 0&&{logger}}})}};return http!==void 0?Object.assign(http,additions):{...additions,...request!==void 0&&{req:request}}}function toAuthenticatedRequestContext(ctx){let authInfo=ctx.http?.authInfo;return requireOAuthAuthInfo(authInfo),Object.assign(toRequestContext(ctx),{auth:{user:authInfo.extra.user,payload:authInfo.extra.payload,accessToken:authInfo.token,scopes:[...authInfo.scopes],permissions:[...authInfo.extra.permissions],...authInfo.clientId.length>0&&{clientId:authInfo.clientId},expiresAt:authInfo.expiresAt,...authInfo.resource!==void 0&&{resource:authInfo.resource}}})}function isReadResourceResult(result){return"contents"in result&&Array.isArray(result.contents)}function isGetPromptResult(result){return"messages"in result&&Array.isArray(result.messages)}function toResourceResult(result,uri){if(isReadResourceResult(result))return result;let mime=result._meta&&typeof result._meta=="object"&&typeof result._meta.mimeType=="string"?result._meta.mimeType:void 0,contents=[];for(let block of result.content??[]){let mapped=contentBlockToResourceContents(block,uri,mime);mapped!==void 0&&contents.push(mapped)}return contents.length===0&&result.structuredContent!==void 0&&contents.push({uri,mimeType:"application/json",text:JSON.stringify(result.structuredContent)}),contents.length===0&&contents.push({uri,mimeType:"text/plain",text:""}),{contents}}function contentBlockToResourceContents(block,uri,mimeHint){if(block.type==="text")return{uri,mimeType:mimeHint??"text/plain",text:block.text};if(block.type==="image"||block.type==="audio")return{uri,mimeType:block.mimeType,blob:block.data};if(block.type==="resource")return{...block.resource}}function toPromptResult(result){if(isGetPromptResult(result))return result;let messages=(result.content??[]).map(content=>({role:"user",content}));return messages.length===0&&result.structuredContent!==void 0&&messages.push({role:"user",content:{type:"text",text:JSON.stringify(result.structuredContent)}}),messages.length===0&&messages.push({role:"user",content:{type:"text",text:""}}),{messages}}var DEFAULT_METHODS=["GET","HEAD","POST","OPTIONS"],DEFAULT_ALLOWED_HEADERS=["Content-Type","Authorization","mcp-protocol-version","mcp-method","mcp-name"];function resolveAllowedOrigin(origin,requestOrigin){return origin===void 0?requestOrigin:typeof origin=="function"?origin(requestOrigin):origin==="*"?"*":Array.isArray(origin)?requestOrigin!==null&&origin.includes(requestOrigin)?requestOrigin:null:origin}function corsHeaders(options,request){if(request.headers.has("Access-Control-Allow-Origin"))return;let requestOrigin=request.headers.get("Origin"),allowedOrigin=resolveAllowedOrigin(options.origin,requestOrigin);if(allowedOrigin===null)return;let headers={"Access-Control-Allow-Origin":allowedOrigin,"Access-Control-Allow-Methods":options.methods.join(", "),"Access-Control-Allow-Headers":options.allowedHeaders.join(", ")};return options.credentials&&(headers["Access-Control-Allow-Credentials"]="true"),allowedOrigin!=="*"&&(headers.Vary="Origin"),headers}function mergeCorsHeaders(response,headers){if(response.headers.has("Access-Control-Allow-Origin"))return response;let merged=new Headers(response.headers);return new Headers(headers).forEach((value,key)=>{merged.set(key,value)}),new Response(response.body,{status:response.status,statusText:response.statusText,headers:merged})}function corsFetchMiddleware(options){if(!(options.enabled!==!1))return async(_request,next)=>next();let resolved={...options.origin!==void 0&&{origin:options.origin},methods:options.methods??DEFAULT_METHODS,allowedHeaders:options.allowedHeaders??DEFAULT_ALLOWED_HEADERS,credentials:options.credentials??!1};return async(request,next)=>{let headers=corsHeaders(resolved,request);if(headers===void 0)return next();if(request.method==="OPTIONS")return new Response(null,{status:204,headers});let response=await next();return mergeCorsHeaders(response,headers)}}function isGlobalCorsEnabled(cors){return cors!==void 0&&cors.enabled!==!1}import{CallToolResultSchema,GetPromptResultSchema,ListPromptsResultSchema,ListResourcesResultSchema,ListToolsResultSchema,ReadResourceResultSchema}from"@modelcontextprotocol/core";import{isInputRequiredResult}from"@modelcontextprotocol/server";var MCP_MIDDLEWARE_METHODS=["tools/call","tools/list","resources/read","resources/list","prompts/get","prompts/list"];function withMcpMiddlewareParams(request,params){if(typeof request!="object"||request===null||Array.isArray(request))throw new TypeError("[mcp-use] MCP middleware received an invalid downstream request");return{...request,params}}function createMcpMiddlewareEntry(pattern,handler){let normalizedPattern=normalizeMcpMiddlewarePattern(pattern),invoke=handler;if(normalizedPattern!=="*"&&!isMcpMiddlewareMethod(normalizedPattern))throw new TypeError(`Unsupported MCP middleware pattern "${pattern}". Use an exact MCP method or "mcp:*".`);return normalizedPattern==="*"?{pattern:normalizedPattern,handler:async(ctx,next)=>{let downstreamCalled=!1,downstreamResult;if(await invoke(ctx,async()=>{downstreamResult=await next(),downstreamCalled=!0}),!downstreamCalled)throw new Error(`Wildcard MCP middleware "${normalizedPattern}" must call next()`);return downstreamResult}}:{pattern:normalizedPattern,handler:(ctx,next)=>invoke(ctx,next)}}function createMcpEventListenerEntry(pattern,handler){let{pattern:normalizedPattern,phase}=parseMcpPattern(pattern),invoke=handler;return{pattern:normalizedPattern,phase,handler:(ctx,result)=>invoke(ctx,result)}}function matchesPattern(pattern,method){if(pattern==="*")return!0;if(pattern.endsWith("/*")){let prefix=pattern.slice(0,-1);return method.startsWith(prefix)}return pattern===method}function isMcpMiddlewareMethod(value){return MCP_MIDDLEWARE_METHODS.some(method=>method===value)}function composeMiddleware(entries,method,innerFn){let matching=entries.filter(entry=>matchesPattern(entry.pattern,method));return matching.length===0?_ctx=>innerFn():ctx=>{let index=-1,dispatch=i=>i<=index?Promise.reject(new Error("next() called multiple times")):(index=i,i===matching.length?innerFn():matching[i].handler(ctx,()=>dispatch(i+1)));return dispatch(0)}}function freezeMiddlewareContext(ctx){return Object.freeze({method:ctx.method,params:Object.freeze({...ctx.params}),...ctx.request!==void 0&&{request:ctx.request},...ctx.req!==void 0&&{req:ctx.req},...ctx.session!==void 0&&{session:Object.freeze({...ctx.session})},...ctx.auth!==void 0&&{auth:ctx.auth},state:new Map(ctx.state)})}async function runMcpOperation(middlewares,events,method,ctx,innerFn){dispatchMcpEvents(events,method,"before",ctx);let result=await composeMiddleware(middlewares,method,innerFn)(ctx);return assertValidMiddlewareResult(method,result),dispatchMcpEvents(events,method,"complete",ctx,result),result}function assertValidMiddlewareResult(method,result){if((method==="tools/call"||method==="resources/read"||method==="prompts/get")&&isInputRequiredResult(result))return;let validation=(()=>{switch(method){case"tools/call":return assertArrayProperty(method,result,"content"),CallToolResultSchema.safeParse(result);case"tools/list":return assertArrayResult(method,result),ListToolsResultSchema.safeParse({tools:result});case"resources/read":return assertArrayProperty(method,result,"contents"),ReadResourceResultSchema.safeParse(result);case"resources/list":return assertArrayResult(method,result),ListResourcesResultSchema.safeParse({resources:result});case"prompts/get":return assertArrayProperty(method,result,"messages"),GetPromptResultSchema.safeParse(result);case"prompts/list":return assertArrayResult(method,result),ListPromptsResultSchema.safeParse({prompts:result});default:throw new TypeError(`Unsupported MCP middleware method "${method}"`)}})();if(!validation.success)throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: ${validation.error.message}`)}function assertArrayResult(method,result){if(!Array.isArray(result))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected an array`)}function assertArrayProperty(method,result,property){if(typeof result!="object"||result===null||!Array.isArray(result[property]))throw new TypeError(`[mcp-use] ${method} middleware returned an invalid result: expected a ${property} array`)}function dispatchMcpEvents(events,method,phase,ctx,result){let frozen=freezeMiddlewareContext(ctx);for(let entry of events)if(!(entry.phase!==phase||!matchesPattern(entry.pattern,method)))try{entry.handler(frozen,result)}catch(error2){console.error(`[mcp-use] MCP event listener for "${entry.pattern}" (${phase}) threw:`,error2)}}function parseMcpPattern(raw){let pattern=raw.startsWith("mcp:")?raw.slice(4):raw;return pattern.endsWith(":complete")?{pattern:pattern.slice(0,-9),phase:"complete"}:{pattern,phase:"before"}}function normalizeMcpMiddlewarePattern(raw){return raw.startsWith("mcp:")?raw.slice(4):raw}import{CLIENT_INFO_META_KEY as CLIENT_INFO_META_KEY2,isJSONRPCRequest}from"@modelcontextprotocol/server";function colorsEnabled(){return typeof process>"u"||process.env?.NO_COLOR!==void 0?!1:process.stdout?.isTTY===!0}function ansi(open,close){return text2=>colorsEnabled()?`\x1B[${open}m${text2}\x1B[${close}m`:text2}var bold=ansi(1,22),dim=ansi(2,22),red=ansi(31,39),green=ansi(32,39),yellow=ansi(33,39),blue=ansi(34,39),magenta=ansi(35,39),cyan=ansi(36,39),gray=ansi(90,39);function resolveLogLevel(configured){let raw=typeof process>"u"?void 0:process.env?.MCP_USE_LOG_LEVEL?.toLowerCase();return raw==="info"||raw==="debug"||raw==="trace"?raw:configured??"info"}function formatClientInfo(info){if(info!==void 0)return typeof info.version=="string"&&info.version!==""?`${info.name}/${info.version}`:info.name}var detailFormatters={initialize:p=>({subject:formatClientInfo(p.clientInfo)}),ping:()=>({}),"server/discover":()=>({}),"completion/complete":p=>({subject:p.ref.type==="ref/prompt"?p.ref.name:p.ref.uri,input:p.argument}),"logging/setLevel":p=>({subject:p.level}),"prompts/get":p=>({subject:p.name,input:p.arguments}),"prompts/list":()=>({}),"resources/list":()=>({}),"resources/templates/list":()=>({}),"resources/read":p=>({subject:p.uri}),"resources/subscribe":p=>({subject:p.uri}),"resources/unsubscribe":p=>({subject:p.uri}),"subscriptions/listen":()=>({}),"tools/call":p=>({subject:p.name,input:p.arguments}),"tools/list":()=>({}),"sampling/createMessage":()=>({}),"elicitation/create":()=>({}),"roots/list":()=>({})};function isKnownMethod(method){return Object.prototype.hasOwnProperty.call(detailFormatters,method)}function formatDetail(message){if(!isKnownMethod(message.method))return{};try{let formatter=detailFormatters[message.method],detail=formatter(message.params);return typeof detail.subject=="string"||detail.subject===void 0?detail:{}}catch{return{}}}var INLINE_JSON_MAX_LENGTH=80;function inlineJson(value){let text2;try{text2=JSON.stringify(value)??String(value)}catch{text2=String(value)}return text2.length>INLINE_JSON_MAX_LENGTH?`${text2.slice(0,INLINE_JSON_MAX_LENGTH)}...`:text2}function formatClientIdentity(message){let meta=message.params?._meta;if(meta===void 0)return;let info=meta[CLIENT_INFO_META_KEY2];if(!(typeof info!="object"||info===null||typeof info.name!="string"))return formatClientInfo(info)}function sanitize(text2){return text2.replace(/[\u0000-\u001F\u007F-\u009F]+/g," ")}function methodStyle(method){return method.startsWith("tools/")?cyan:method.startsWith("resources/")?green:method.startsWith("prompts/")?magenta:method==="initialize"||method==="ping"?gray:blue}var REDACTED_HEADERS=new Set(["authorization","proxy-authorization","cookie","set-cookie","x-api-key"]);function redactHeaders(headers){return Object.fromEntries(Object.entries(headers).map(([name,value])=>[name,REDACTED_HEADERS.has(name.toLowerCase())?"[REDACTED]":value]))}async function extractResponseOutcome(res){if(!res.body)return{errorMessage:null};let text2;try{text2=await res.clone().text()}catch{return{errorMessage:null}}if(!text2)return{errorMessage:null};let isSse=(res.headers.get("content-type")??"").includes("text/event-stream"),payloads=[],tryParse=raw=>{try{payloads.push(JSON.parse(raw))}catch{}};if(isSse){for(let line of text2.split(/\r?\n/))if(line.startsWith("data:")){let data=line.slice(5).trim();data&&tryParse(data)}}else tryParse(text2);let result;for(let payload of payloads){if(payload===null||typeof payload!="object")continue;let message=payload;if(typeof message.error?.message=="string")return{errorMessage:message.error.message};if(message.result?.isError===!0){let textBlock=(Array.isArray(message.result.content)?message.result.content:[]).find(b=>b?.type==="text"&&typeof b.text=="string");return{errorMessage:textBlock?String(textBlock.text):"tool error"}}"result"in message&&(result=message.result)}return{errorMessage:null,result}}function compactToolResult(result){if(result===null||typeof result!="object")return result;let{structuredContent,content}=result;if(structuredContent!==void 0)return structuredContent;if(Array.isArray(content)){let[block]=content;if(content.length===1&&block?.type==="text")return block.text}return content}function formatForDump(value){function truncate(val){return typeof val=="string"&&val.length>100?`${val.slice(0,100)}...`:Array.isArray(val)?val.map(truncate):val!==null&&typeof val=="object"?Object.fromEntries(Object.entries(val).map(([k,v])=>[k,truncate(v)])):val}try{return JSON.stringify(truncate(value),null,2)}catch{return String(value)}}var DUMP_BODY_MAX_LENGTH=1e4;async function printTraceDump(response,requestHeaders,requestBody,readResponseBody){console.log(`
2
+ ${cyan("=".repeat(80))}`),console.log(bold(cyan("[TRACE] Request Details"))),console.log(cyan("-".repeat(80))),Object.keys(requestHeaders).length>0&&(console.log(yellow("Request Headers:")),console.log(formatForDump(redactHeaders(requestHeaders)))),requestBody!==void 0&&(console.log(yellow("Request Body:")),console.log(typeof requestBody=="string"?requestBody:formatForDump(requestBody)));let responseHeaders={};if(response.headers.forEach((value,key)=>{responseHeaders[key]=value}),Object.keys(responseHeaders).length>0&&(console.log(yellow("Response Headers:")),console.log(formatForDump(redactHeaders(responseHeaders)))),!readResponseBody)console.log(`${yellow("Response Body:")} (streaming \u2014 not dumped)`);else if(response.body===null)console.log(`${yellow("Response Body:")} (no body)`);else try{let text2=await response.clone().text();if(text2.length===0)console.log(`${yellow("Response Body:")} (empty)`);else{console.log(yellow("Response Body:"));try{console.log(formatForDump(JSON.parse(text2)))}catch{console.log(text2.length>DUMP_BODY_MAX_LENGTH?`${text2.slice(0,DUMP_BODY_MAX_LENGTH)}
3
+ ... (truncated, ${text2.length-DUMP_BODY_MAX_LENGTH} more characters)`:text2)}}}catch{console.log(`${yellow("Response Body:")} (unable to read)`)}console.log(`${cyan("=".repeat(80))}
4
+ `)}function styleStatus(status){let text2=String(status);return status>=500?magenta(text2):status>=400?red(text2):status>=300?yellow(text2):green(text2)}function isNoisyRequest(httpMethod,pathname){return httpMethod!=="GET"&&httpMethod!=="HEAD"?!1:pathname.endsWith("/favicon.ico")}function requestLogger(options={}){return options.enabled===!1?(_request,next)=>next():async(request,next)=>{let level=resolveLogLevel(options.level),startedAt=Date.now(),httpMethod=request.method,pathname=new URL(request.url).pathname;if(isNoisyRequest(httpMethod,pathname))return next();let requestHeaders={};level==="trace"&&request.headers.forEach((value,key)=>{requestHeaders[key]=value});let requestBody;if(httpMethod!=="GET"&&httpMethod!=="HEAD"){let parsedBody=getRequestBag(request).parsedBody;if(parsedBody!==void 0)requestBody=parsedBody;else try{requestBody=await request.clone().json()}catch{}}let response=await next(),durationMs=Date.now()-startedAt,timestamp=new Date().toISOString().substring(11,19),mcpRequest=isJSONRPCRequest(requestBody)?requestBody:void 0,isStreamingMethod=mcpRequest?.method==="subscriptions/listen",lines=[[dim(timestamp),bold(httpMethod),pathname,styleStatus(response.status),dim(`in ${durationMs}ms`)].join(" ")];if(mcpRequest!==void 0){let method=sanitize(mcpRequest.method),parts=[` ${methodStyle(method)(method)}`],detail=formatDetail(mcpRequest);detail.subject!==void 0&&parts.push(bold(sanitize(detail.subject)));let echoPayloads=level!=="info";echoPayloads&&detail.input!==void 0&&parts.push(inlineJson(detail.input));let outcome=isStreamingMethod?{errorMessage:null}:await extractResponseOutcome(response);if(echoPayloads&&mcpRequest.method==="tools/call"&&outcome.errorMessage===null&&outcome.result!==void 0&&parts.push(dim("->"),inlineJson(compactToolResult(outcome.result))),mcpRequest.method!=="initialize"){let client=formatClientIdentity(mcpRequest);client!==void 0&&parts.push(dim(sanitize(client)))}outcome.errorMessage!==null?parts.push(red(`ERROR ${sanitize(outcome.errorMessage)}`)):response.status>=400&&parts.push(red(`ERROR (HTTP ${response.status})`)),lines.push(parts.join(" "))}return console.log(lines.join(`
5
+ `)),level==="trace"&&await printTraceDump(response,requestHeaders,requestBody,!isStreamingMethod),response}}import{createMcpHandler}from"@modelcontextprotocol/server";function createMcpMount(factory,options={}){let{path="/mcp",handler:handlerOptions,authInfo:getAuthInfo}=options,legacyMode=handlerOptions?.legacy??"stateless",handler=createMcpHandler(factory,{legacy:"stateless",...handlerOptions});return{handler,fetch:async request=>{if(!matchesPath(request,path))return new Response("Not Found",{status:404});if(legacyMode==="stateless"){let method=request.method.toUpperCase();if(method==="GET"||method==="DELETE"||method==="HEAD")return new Response(null,{status:204})}let bag=getRequestBag(request),parsedBody=bag.parsedBody;if(parsedBody===void 0)try{parsedBody=await request.clone().json()}catch{}let capabilities=extractClientCapabilitiesFromBody(parsedBody);capabilities!==void 0&&stashClientCapabilities(request,capabilities);let authInfo=getAuthInfo?.(request)??bag.authInfo;return handler.fetch(request,{...parsedBody!==void 0&&{parsedBody},...authInfo!==void 0&&{authInfo}})}}}function resolveToolInputSchema(definition){return definition.inputSchema??definition.schema}var registerViews=Symbol("mcp-use/registerViews");function resolveAssetUrl(assetPath,origin){if(!assetPath.startsWith("/"))throw new Error(`View manifest asset path must be origin-absolute (start with "/"); got ${JSON.stringify(assetPath)}`);return`${origin}${assetPath}`}function viewAssetsBasePath(basePath,viewName){return`${pathUnderBase(basePath,`_mcp-use/views/${viewName}`)}/`}function resolveExternalAssetUrl(assetPath,assetsBase,basePath,viewName){return assetPath.startsWith("http://")||assetPath.startsWith("https://")||assetPath.startsWith("data:")?assetPath:assetPath.startsWith("/")?resolveAssetUrl(assetPath,assetsBase):`${assetsBase}${viewAssetsBasePath(basePath,viewName)}${assetPath.replace(/^\/+/,"")}`}function resolvePublicBase(assetsBase,basePath){return`${assetsBase}${pathUnderBase(basePath,"_mcp-use/public")}/`}function escapeInlineScript(code){return code.replaceAll(/<\/script/gi,"<\\/script").replaceAll("<!--","\\x3C!--")}function escapeInlineStyle(css2){return css2.replaceAll(/<\/style/gi,"<\\/style")}function escapeHtml(value){return value.replaceAll("&","&amp;").replaceAll('"',"&quot;").replaceAll("<","&lt;").replaceAll(">","&gt;")}var TRANSPARENT_IFRAME_STYLE="<style>html,body,#root{background:transparent}</style>";function synthesizeViewDocument(entry,assetsBase,basePath,viewName){let viewConfig={publicBase:resolvePublicBase(assetsBase,basePath)},configScript=`<script>globalThis.__mcpUseViewConfig=${JSON.stringify(viewConfig)};</script>`;if(entry.kind==="inline"){let styleTag=entry.css.length>0?`<style>${escapeInlineStyle(entry.css)}</style>`:"",moduleScript=`<script type="module">${escapeInlineScript(entry.js)}</script>`;return`<!doctype html>
1386
6
  <html>
1387
7
  <head>
1388
8
  <meta charset="utf-8">
@@ -1394,26 +14,9 @@ ${styleTag}
1394
14
  <div id="root"></div>
1395
15
  ${moduleScript}
1396
16
  </body>
1397
- </html>`;
1398
- }
1399
- if (viewName === void 0) {
1400
- throw new Error(
1401
- "viewName is required when synthesizing an external view document."
1402
- );
1403
- }
1404
- const cssLinks = entry.css.map(
1405
- (path) => `<link rel="stylesheet" href="${escapeHtml(resolveExternalAssetUrl(path, assetsBase, basePath, viewName))}">`
1406
- ).join("\n");
1407
- const scriptTags = (entry.scripts ?? []).map(
1408
- (path) => `<script type="module" src="${escapeHtml(resolveExternalAssetUrl(path, assetsBase, basePath, viewName))}"></script>`
1409
- ).join("\n");
1410
- const entryUrl = resolveExternalAssetUrl(
1411
- entry.entry,
1412
- assetsBase,
1413
- basePath,
1414
- viewName
1415
- );
1416
- return `<!doctype html>
17
+ </html>`}if(viewName===void 0)throw new Error("viewName is required when synthesizing an external view document.");let cssLinks=entry.css.map(path=>`<link rel="stylesheet" href="${escapeHtml(resolveExternalAssetUrl(path,assetsBase,basePath,viewName))}">`).join(`
18
+ `),scriptTags=(entry.scripts??[]).map(path=>`<script type="module" src="${escapeHtml(resolveExternalAssetUrl(path,assetsBase,basePath,viewName))}"></script>`).join(`
19
+ `),entryUrl=resolveExternalAssetUrl(entry.entry,assetsBase,basePath,viewName);return`<!doctype html>
1417
20
  <html>
1418
21
  <head>
1419
22
  <meta charset="utf-8">
@@ -1426,1698 +29,4 @@ ${cssLinks}
1426
29
  ${scriptTags}
1427
30
  <script type="module" src="${escapeHtml(entryUrl)}"></script>
1428
31
  </body>
1429
- </html>`;
1430
- }
1431
-
1432
- // src/views/csp-env.ts
1433
- var CATEGORY_ENV = {
1434
- connectDomains: "CSP_CONNECT_DOMAINS",
1435
- resourceDomains: "CSP_RESOURCE_DOMAINS",
1436
- frameDomains: "CSP_FRAME_DOMAINS",
1437
- baseUriDomains: "CSP_BASE_URI_DOMAINS"
1438
- };
1439
- function parseDomainList(raw) {
1440
- if (raw === void 0 || raw.trim() === "") {
1441
- return [];
1442
- }
1443
- return raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
1444
- }
1445
- function readEnvDomains(name) {
1446
- if (typeof process === "undefined") {
1447
- return void 0;
1448
- }
1449
- const raw = process.env[name];
1450
- if (raw === void 0 || raw.trim() === "") {
1451
- return void 0;
1452
- }
1453
- return parseDomainList(raw);
1454
- }
1455
- function readCspUrlsShortcut() {
1456
- return readEnvDomains("CSP_URLS") ?? [];
1457
- }
1458
- function readEnvDomainsForCategory(category) {
1459
- const perCategory = readEnvDomains(CATEGORY_ENV[category]);
1460
- if (perCategory !== void 0) {
1461
- return perCategory;
1462
- }
1463
- return readCspUrlsShortcut();
1464
- }
1465
- function mergeDomainLists(...segments) {
1466
- const seen = /* @__PURE__ */ new Set();
1467
- const out = [];
1468
- for (const segment of segments) {
1469
- for (const domain of segment) {
1470
- if (!seen.has(domain)) {
1471
- seen.add(domain);
1472
- out.push(domain);
1473
- }
1474
- }
1475
- }
1476
- return out;
1477
- }
1478
- function toWebSocketOrigin(serverOrigin) {
1479
- if (serverOrigin.startsWith("https://")) {
1480
- return `wss://${serverOrigin.slice("https://".length)}`;
1481
- }
1482
- if (serverOrigin.startsWith("http://")) {
1483
- return `ws://${serverOrigin.slice("http://".length)}`;
1484
- }
1485
- return serverOrigin;
1486
- }
1487
- function buildMergedResourceCsp(authorFacts, options) {
1488
- const author = authorFacts?.csp;
1489
- const mcpConnectAuto = [];
1490
- if (options.serverOrigin !== "") {
1491
- mcpConnectAuto.push(options.serverOrigin);
1492
- if (options.hmrWs === true) {
1493
- mcpConnectAuto.push(toWebSocketOrigin(options.serverOrigin));
1494
- }
1495
- }
1496
- const mcpResourceAuto = [];
1497
- const resourceOrigin = options.explicitAssetsBase ? options.assetsOrigin : options.serverOrigin;
1498
- if (resourceOrigin !== "") {
1499
- mcpResourceAuto.push(resourceOrigin);
1500
- }
1501
- const connectDomains = mergeDomainLists(
1502
- author?.connectDomains ?? [],
1503
- readEnvDomainsForCategory("connectDomains"),
1504
- mcpConnectAuto
1505
- );
1506
- const resourceDomains = mergeDomainLists(
1507
- author?.resourceDomains ?? [],
1508
- readEnvDomainsForCategory("resourceDomains"),
1509
- mcpResourceAuto
1510
- );
1511
- const frameDomains = mergeDomainLists(
1512
- author?.frameDomains ?? [],
1513
- readEnvDomainsForCategory("frameDomains")
1514
- );
1515
- const baseUriDomains = mergeDomainLists(
1516
- author?.baseUriDomains ?? [],
1517
- readEnvDomainsForCategory("baseUriDomains")
1518
- );
1519
- return {
1520
- ...author,
1521
- connectDomains,
1522
- resourceDomains,
1523
- frameDomains,
1524
- baseUriDomains
1525
- };
1526
- }
1527
-
1528
- // src/views/routes.ts
1529
- var PUBLIC_BUILD_DIR = ".mcp-use/build/views/public";
1530
- var PUBLIC_DEV_DIR = "public";
1531
- var VIEW_ASSETS_BUILD_ROOT = ".mcp-use/build/views";
1532
- function createViewAssetsHandler(basePath, views, options) {
1533
- if (views.size === 0) {
1534
- return void 0;
1535
- }
1536
- const assetsPrefix = pathUnderBase(basePath, "_mcp-use/views");
1537
- const projectRoot = options?.projectRoot ?? process.cwd();
1538
- return async (request) => {
1539
- if (request.method !== "GET" && request.method !== "HEAD") {
1540
- return new Response("Method Not Allowed", { status: 405 });
1541
- }
1542
- if (!matchesPathPrefix(request, assetsPrefix)) {
1543
- return new Response("Not Found", { status: 404 });
1544
- }
1545
- const pathname = pathnameOf(request);
1546
- const remainder = pathname.slice(assetsPrefix.length + 1);
1547
- const slash = remainder.indexOf("/");
1548
- if (slash <= 0 || slash === remainder.length - 1) {
1549
- return new Response("Not Found", { status: 404 });
1550
- }
1551
- const viewName = remainder.slice(0, slash);
1552
- const subpath = remainder.slice(slash + 1);
1553
- const entry = views.get(viewName);
1554
- if (entry === void 0 || entry.kind !== "external") {
1555
- return new Response("Not Found", { status: 404 });
1556
- }
1557
- const [{ join }, { resolvePublicFilePath: resolvePublicFilePath2, servePublicFile: servePublicFile2 }] = await Promise.all([import("path"), import("./public-route-BAMZRI4R.js")]);
1558
- const viewRoot = join(projectRoot, VIEW_ASSETS_BUILD_ROOT, viewName);
1559
- const diskPath = await resolvePublicFilePath2(viewRoot, subpath);
1560
- if (diskPath === null) {
1561
- return new Response("Not Found", { status: 404 });
1562
- }
1563
- return await servePublicFile2(diskPath, {
1564
- ...options?.deferCors === true && { deferCors: true },
1565
- ...request.method === "HEAD" && { head: true }
1566
- });
1567
- };
1568
- }
1569
- function createViewPublicHandler(basePath, views, options) {
1570
- if (views.size === 0 && options?.enabled !== true) {
1571
- return void 0;
1572
- }
1573
- const publicPrefix = pathUnderBase(basePath, "_mcp-use/public");
1574
- const subdir = options?.dev === true ? PUBLIC_DEV_DIR : PUBLIC_BUILD_DIR;
1575
- const projectRoot = options?.projectRoot ?? process.cwd();
1576
- return async (request) => {
1577
- if (request.method !== "GET" && request.method !== "HEAD") {
1578
- return new Response("Method Not Allowed", { status: 405 });
1579
- }
1580
- if (!matchesPathPrefix(request, publicPrefix)) {
1581
- return new Response("Not Found", { status: 404 });
1582
- }
1583
- const pathname = pathnameOf(request);
1584
- const encodedSubpath = pathname.slice(publicPrefix.length + 1);
1585
- let subpath;
1586
- try {
1587
- subpath = decodeURIComponent(encodedSubpath);
1588
- } catch {
1589
- return new Response("Not Found", { status: 404 });
1590
- }
1591
- if (subpath.length === 0) {
1592
- return new Response("Not Found", { status: 404 });
1593
- }
1594
- const [{ join }, { resolvePublicFilePath: resolvePublicFilePath2, servePublicFile: servePublicFile2 }] = await Promise.all([import("path"), import("./public-route-BAMZRI4R.js")]);
1595
- const publicRoot = join(projectRoot, subdir);
1596
- const diskPath = await resolvePublicFilePath2(publicRoot, subpath);
1597
- if (diskPath === null) {
1598
- return new Response("Not Found", { status: 404 });
1599
- }
1600
- return await servePublicFile2(diskPath, {
1601
- ...options?.deferCors === true && { deferCors: true },
1602
- ...request.method === "HEAD" && { head: true }
1603
- });
1604
- };
1605
- }
1606
-
1607
- // src/views/wire.ts
1608
- function buildToolUiMeta(viewName, visibility, existingMetadata) {
1609
- if (viewName === void 0 && visibility === void 0 && existingMetadata === void 0) {
1610
- return void 0;
1611
- }
1612
- const meta = { ...existingMetadata };
1613
- const existingUi = existingMetadata?.[UI_META_KEY];
1614
- const existingUiIsObject = typeof existingUi === "object" && existingUi !== null && !Array.isArray(existingUi);
1615
- const ui = existingUiIsObject ? { ...existingUi } : {};
1616
- if (viewName !== void 0) {
1617
- const resourceUri = viewResourceUri(viewName);
1618
- ui["resourceUri"] = resourceUri;
1619
- meta[UI_RESOURCE_URI_META_KEY] = resourceUri;
1620
- } else {
1621
- delete ui["resourceUri"];
1622
- delete meta[UI_RESOURCE_URI_META_KEY];
1623
- }
1624
- if (visibility !== void 0) {
1625
- ui["visibility"] = [visibility];
1626
- } else {
1627
- delete ui["visibility"];
1628
- }
1629
- if (viewName !== void 0 || visibility !== void 0 || existingUiIsObject) {
1630
- meta[UI_META_KEY] = ui;
1631
- }
1632
- return meta;
1633
- }
1634
- function buildToolResultUiMeta(viewName) {
1635
- const resourceUri = viewResourceUri(viewName);
1636
- return {
1637
- [UI_META_KEY]: { resourceUri },
1638
- [UI_RESOURCE_URI_META_KEY]: resourceUri
1639
- };
1640
- }
1641
- function resolveCspOptions(options) {
1642
- const request = options?.request;
1643
- const serverOrigin = options?.serverOrigin ?? (request !== void 0 ? resolveServerOrigin(request) : "");
1644
- const assetsBase = options?.assetsBase ?? (request !== void 0 ? resolveAssetsBase(request) : serverOrigin);
1645
- return {
1646
- serverOrigin,
1647
- assetsOrigin: originFromAssetsBase(assetsBase),
1648
- explicitAssetsBase: hasExplicitAssetsBase(),
1649
- ...options?.hmrWs === true ? { hmrWs: true } : {}
1650
- };
1651
- }
1652
- function buildResourceUiMeta(authorFacts, options) {
1653
- const csp = buildMergedResourceCsp(authorFacts, resolveCspOptions(options));
1654
- const ui = { csp };
1655
- if (authorFacts?.permissions !== void 0) {
1656
- ui["permissions"] = authorFacts.permissions;
1657
- }
1658
- if (authorFacts?.domain !== void 0) {
1659
- ui["domain"] = authorFacts.domain;
1660
- }
1661
- if (authorFacts?.prefersBorder !== void 0) {
1662
- ui["prefersBorder"] = authorFacts.prefersBorder;
1663
- }
1664
- return { [UI_META_KEY]: ui };
1665
- }
1666
- function viewResourceConfig(_viewName, _entry, authorFacts, options) {
1667
- return {
1668
- mimeType: UI_MIME_TYPE,
1669
- ...authorFacts?.description !== void 0 && {
1670
- description: authorFacts.description
1671
- },
1672
- _meta: buildResourceUiMeta(authorFacts, options)
1673
- };
1674
- }
1675
-
1676
- // src/server.ts
1677
- function omitRootSchemaDialect(schema) {
1678
- if (typeof schema !== "object" || schema === null || Array.isArray(schema) || !("$schema" in schema)) {
1679
- return schema;
1680
- }
1681
- const emittedSchema = { ...schema };
1682
- delete emittedSchema["$schema"];
1683
- return emittedSchema;
1684
- }
1685
- function omitToolSchemaDialects(tools) {
1686
- return tools.map((tool) => ({
1687
- ...tool,
1688
- inputSchema: omitRootSchemaDialect(tool.inputSchema),
1689
- ...tool.outputSchema === void 0 ? {} : { outputSchema: omitRootSchemaDialect(tool.outputSchema) }
1690
- }));
1691
- }
1692
- function registerFetchMiddleware(app, middleware) {
1693
- app.use("*", async (context, next) => {
1694
- const response = await middleware(context.req.raw, async () => {
1695
- await next();
1696
- return context.res;
1697
- });
1698
- context.res = response;
1699
- return response;
1700
- });
1701
- }
1702
- var MCPServer = class _MCPServer {
1703
- #config;
1704
- #branding;
1705
- #tools = /* @__PURE__ */ new Map();
1706
- #resources = /* @__PURE__ */ new Map();
1707
- #resourceTemplates = /* @__PURE__ */ new Map();
1708
- #prompts = /* @__PURE__ */ new Map();
1709
- #views = /* @__PURE__ */ new Map();
1710
- /**
1711
- * One-to-one tool→view bindings. Each view name maps to the single tool
1712
- * that bound it; that tool's `view:` config is the sole source of
1713
- * resource facts for the primed view resource.
1714
- */
1715
- #viewBindings = /* @__PURE__ */ new Map();
1716
- #viewsPrimed = false;
1717
- /** When true, resource CSP emission includes the HMR websocket origin. */
1718
- #viewsDevMode = false;
1719
- /** Project root for filesystem-backed view bundle and public routes. */
1720
- #viewsProjectRoot = process.cwd();
1721
- #fetchHandler;
1722
- #httpApp;
1723
- #handler;
1724
- #eventBus;
1725
- #httpServer;
1726
- #oauthResource;
1727
- #oauthResourceResolved = false;
1728
- #oauthResourceConfigurationAbsent = false;
1729
- /** Whether the mounted app validates Host headers (fixed at first mount). */
1730
- #hostValidated = false;
1731
- #mcpMiddlewares = [];
1732
- #mcpEventListeners = [];
1733
- /** Client instances created by {@link MCPServer.proxy} and owned by this server. */
1734
- #proxyOwners = [];
1735
- /** Proxy registrations that {@link close} must let finish before cleanup. */
1736
- #proxyOperations = /* @__PURE__ */ new Set();
1737
- /** Whether terminal shutdown has begun. */
1738
- #closed = false;
1739
- /** Hono application that owns HTTP middleware and routes. */
1740
- app;
1741
- /** Register a typed `GET` route on {@link MCPServer.app}. */
1742
- get;
1743
- /** Register a typed `POST` route on {@link MCPServer.app}. */
1744
- post;
1745
- /** Register a typed `PUT` route on {@link MCPServer.app}. */
1746
- put;
1747
- /** Register a typed `PATCH` route on {@link MCPServer.app}. */
1748
- patch;
1749
- /** Register a typed `DELETE` route on {@link MCPServer.app}. */
1750
- delete;
1751
- /** Register a typed route for every HTTP method on {@link MCPServer.app}. */
1752
- all;
1753
- /**
1754
- * Canonical Web-standard handler for edge runtimes and framework mounting.
1755
- *
1756
- * @example
1757
- * ```ts
1758
- * export default server;
1759
- * // or: export const POST = server.fetch;
1760
- * ```
1761
- */
1762
- fetch;
1763
- /**
1764
- * Create an MCP server from a parsed, bundled OpenAPI document.
1765
- *
1766
- * Each included OpenAPI operation becomes a tool that validates its input,
1767
- * calls the matching upstream HTTP endpoint, and returns the response using
1768
- * the SDK's raw tool-result shape. External `$ref` values are not fetched;
1769
- * bundle the document before passing it in.
1770
- *
1771
- * @param options - OpenAPI document, operation filters, upstream URL, and
1772
- * request authentication options.
1773
- * @returns An unauthenticated MCP server populated with generated tools.
1774
- *
1775
- * @example
1776
- * ```ts
1777
- * const spec = await fetch("https://api.example.com/openapi.json")
1778
- * .then((response) => response.json());
1779
- * const server = MCPServer.fromOpenAPI({ spec });
1780
- * await server.listen(3000);
1781
- * ```
1782
- */
1783
- static fromOpenAPI(options) {
1784
- const server = new _MCPServer({
1785
- name: options.name ?? options.spec.info.title,
1786
- version: options.version ?? options.spec.info.version ?? "1.0.0"
1787
- });
1788
- registerOpenAPITools(server, options);
1789
- return server;
1790
- }
1791
- /**
1792
- * Create a server. `config.name` and `config.version` identify the server
1793
- * to clients during initialization. `config.basePath` (default `"/mcp"`)
1794
- * is both the MCP route and the path of the OAuth protected-resource
1795
- * identity, so any explicit OAuth resource URL must use that exact path.
1796
- * Nothing binds or listens until {@link MCPServer.listen} or
1797
- * the first request reaches {@link MCPServer.fetch}.
1798
- */
1799
- constructor(config) {
1800
- assertServerConfig(config);
1801
- this.#config = config;
1802
- this.#branding = normalizeServerBranding(config);
1803
- this.app = new Hono();
1804
- this.app.use("*", async (context, next) => {
1805
- getRequestBag(context.req.raw).honoContext = context;
1806
- await next();
1807
- });
1808
- this.get = this.app.get.bind(this.app);
1809
- this.post = this.app.post.bind(this.app);
1810
- this.put = this.app.put.bind(this.app);
1811
- this.patch = this.app.patch.bind(this.app);
1812
- this.delete = this.app.delete.bind(this.app);
1813
- this.all = this.app.all.bind(this.app);
1814
- this.fetch = async (request, env, executionCtx) => {
1815
- this.#ensureMounted("handler");
1816
- return this.#httpApp.fetch(request, env, executionCtx);
1817
- };
1818
- if (config.oauth !== void 0) {
1819
- const mcpUrl = typeof process === "undefined" ? void 0 : process.env["MCP_URL"];
1820
- const resource2 = resolveConfiguredOAuthResource({
1821
- provider: config.oauth,
1822
- basePath: this.#basePath(),
1823
- ...mcpUrl !== void 0 && { mcpUrl }
1824
- });
1825
- this.#oauthResource = resource2;
1826
- this.#oauthResourceResolved = resource2 !== void 0;
1827
- this.#oauthResourceConfigurationAbsent = resource2 === void 0;
1828
- }
1829
- }
1830
- /**
1831
- * The URL path prefix the MCP endpoint is mounted at.
1832
- *
1833
- * Reflects `config.basePath` (default `"/mcp"`). Exposed so tooling that
1834
- * imports the entry module — `mcp-use dev`'s startup log, for example —
1835
- * can build endpoint and development-tool URLs without assuming the default.
1836
- */
1837
- get basePath() {
1838
- return this.#basePath();
1839
- }
1840
- /** Configured bind host, before CLI and environment overrides. */
1841
- get host() {
1842
- return this.#config.host;
1843
- }
1844
- /** Configured bind port, before CLI and environment overrides. */
1845
- get port() {
1846
- return this.#config.port;
1847
- }
1848
- /**
1849
- * Immutable normalized branding shared by MCP identity and browser pages.
1850
- *
1851
- * `favicon` is the final source after explicit-favicon and icon-selection
1852
- * precedence. Landing-page integrations can use this accessor and link to
1853
- * the server's root-level `/favicon.ico` route without reading private
1854
- * configuration or depending on the landing/view layers.
1855
- *
1856
- * @example
1857
- * ```ts
1858
- * if (server.branding.favicon) {
1859
- * console.log("Browser favicon: /favicon.ico");
1860
- * }
1861
- * ```
1862
- */
1863
- get branding() {
1864
- return this.#branding;
1865
- }
1866
- /** @deprecated Use {@link MCPServer.fetch} directly. */
1867
- getHandler() {
1868
- return this.fetch;
1869
- }
1870
- /**
1871
- * Register a tool. Input is validated against `inputSchema` before the callback
1872
- * runs; results carrying `structuredContent` are type-checked against
1873
- * `outputSchema` at the callback's return position.
1874
- *
1875
- * Assign static registrations to exported constants so `mcp-env.d.ts` can
1876
- * expose their {@link ToolRef} types to views:
1877
- * `export const search = server.tool(...)`.
1878
- *
1879
- * @returns A {@link ToolRef} carrying the tool name and phantom types for
1880
- * inference-based view typing.
1881
- */
1882
- tool(definition, callback) {
1883
- this.#assertNotStarted("tool", definition.name);
1884
- this.#validateToolViewBinding(definition);
1885
- this.#tools.set(definition.name, {
1886
- definition,
1887
- callback
1888
- });
1889
- return Object.freeze({
1890
- name: definition.name
1891
- });
1892
- }
1893
- /**
1894
- * Prime the views registry from build/dev registry data.
1895
- *
1896
- * @param views - Registry map keyed by view directory name.
1897
- * @param options - Priming options. When `dev` is true, resource CSP
1898
- * emission appends the serving origin's websocket variant to
1899
- * `connectDomains` so Vite HMR passes host-enforced CSP. Pass
1900
- * `projectRoot` in dev so the `public/` route resolves against the user's
1901
- * project directory rather than the CLI process cwd.
1902
- * @throws If views are already primed, or after the server has started.
1903
- *
1904
- * @internal
1905
- */
1906
- [registerViews](views, options) {
1907
- if (this.#viewsPrimed) {
1908
- throw new Error(
1909
- "Cannot prime views: the views registry is already primed on this server instance."
1910
- );
1911
- }
1912
- this.#assertNotStarted("views", "manifest");
1913
- this.#viewsDevMode = options?.dev === true;
1914
- if (options?.projectRoot !== void 0) {
1915
- this.#viewsProjectRoot = options.projectRoot;
1916
- }
1917
- for (const [name, entry] of Object.entries(views)) {
1918
- this.#views.set(name, entry);
1919
- }
1920
- this.#viewsPrimed = true;
1921
- }
1922
- /**
1923
- * Prime the views registry — string-keyed alias for {@link registerViews}
1924
- * used by the CLI when the symbol export cannot be shared across duplicate
1925
- * module copies (dev module runner with an externalized package).
1926
- *
1927
- * @param views - Manifest map keyed by view directory name.
1928
- * @param options - Priming options forwarded to {@link registerViews}.
1929
- * @throws If views are already primed, or after the server has started.
1930
- *
1931
- * @internal
1932
- */
1933
- __primeViews(views, options) {
1934
- this[registerViews](views, options);
1935
- }
1936
- /** Register a static resource readable at `definition.uri`. */
1937
- resource(definition, callback) {
1938
- this.#assertNotStarted("resource", definition.name);
1939
- this.#resources.set(definition.name, { definition, callback });
1940
- return this;
1941
- }
1942
- /**
1943
- * Register a parameterized resource. Reads matching `uriTemplate` invoke
1944
- * the callback with the extracted variables.
1945
- *
1946
- * The `const` type parameter keeps `uriTemplate` a string literal during
1947
- * inference (plain generic inference widens object-literal properties to
1948
- * `string`), which is what lets `InferTemplateParams` type the callback's
1949
- * `params` from the template's variables.
1950
- */
1951
- resourceTemplate(definition, callback) {
1952
- this.#assertNotStarted("resourceTemplate", definition.name);
1953
- const complete = definition.complete === void 0 ? void 0 : normalizeCompletions(definition.complete);
1954
- this.#resourceTemplates.set(definition.name, {
1955
- definition,
1956
- ...complete !== void 0 && { complete },
1957
- callback
1958
- });
1959
- return this;
1960
- }
1961
- /**
1962
- * Register a prompt template. Schema fields wrapped with `completable()`
1963
- * gain autocomplete via `completion/complete`.
1964
- */
1965
- prompt(definition, callback) {
1966
- this.#assertNotStarted("prompt", definition.name);
1967
- this.#prompts.set(definition.name, {
1968
- definition,
1969
- callback
1970
- });
1971
- return this;
1972
- }
1973
- async proxy(input) {
1974
- this.#assertOpen("proxy()");
1975
- const operation = (async () => {
1976
- const { isProxyConnection, mountProxyConnection, mountProxyServers } = await import("./mcp-proxy-JK7IC5CR.js");
1977
- if (isProxyConnection(input)) {
1978
- await mountProxyConnection(this.#proxyHost(), input);
1979
- return;
1980
- }
1981
- await mountProxyServers(this.#proxyHost(), input);
1982
- })();
1983
- this.#proxyOperations.add(operation);
1984
- try {
1985
- await operation;
1986
- } finally {
1987
- this.#proxyOperations.delete(operation);
1988
- }
1989
- }
1990
- use(patternOrHandler, ...handlers) {
1991
- if (typeof patternOrHandler === "string" && patternOrHandler.startsWith("mcp:")) {
1992
- this.#assertNotStarted("middleware", patternOrHandler);
1993
- const handler = handlers[0];
1994
- this.#mcpMiddlewares.push(
1995
- createMcpMiddlewareEntry(
1996
- patternOrHandler,
1997
- handler
1998
- )
1999
- );
2000
- return this;
2001
- }
2002
- const register = this.app.use;
2003
- register.call(this.app, patternOrHandler, ...handlers);
2004
- return this;
2005
- }
2006
- /**
2007
- * Register a read-only MCP observer. Unlike {@link MCPServer.use}, listeners
2008
- * cannot block, override, or mutate params. Throwing is logged and does not
2009
- * fail the request.
2010
- *
2011
- * Append `:complete` to run after the handler (for example
2012
- * `mcp:tools/call:complete`).
2013
- *
2014
- * @example
2015
- * ```ts
2016
- * server.on("mcp:tools/call", (ctx) => {
2017
- * metrics.increment("tools.call", { tool: ctx.params.name });
2018
- * });
2019
- * ```
2020
- */
2021
- on(pattern, handler) {
2022
- this.#assertNotStarted("event listener", pattern);
2023
- this.#mcpEventListeners.push(createMcpEventListenerEntry(pattern, handler));
2024
- return this;
2025
- }
2026
- /**
2027
- * Attach the shared development event bus before the first request.
2028
- *
2029
- * @param bus - Bus retained across hot-reloaded server instances.
2030
- * @internal
2031
- */
2032
- __setEventBus(bus) {
2033
- this.#assertNotStarted("event bus", "shared");
2034
- this.#eventBus = bus;
2035
- }
2036
- /** Mount and validate the Hono/MCP application without serving a request. @internal */
2037
- __mount() {
2038
- this.#ensureMounted("handler");
2039
- }
2040
- /**
2041
- * Publish a tools-list change to v2 clients with active subscriptions.
2042
- *
2043
- * @example
2044
- * ```ts
2045
- * await server.notifyToolsChanged();
2046
- * ```
2047
- */
2048
- async notifyToolsChanged() {
2049
- await this.#ensureMounted("handler").handler.notify.toolsChanged();
2050
- }
2051
- /**
2052
- * Publish a prompts-list change to v2 clients with active subscriptions.
2053
- *
2054
- * @example
2055
- * ```ts
2056
- * await server.notifyPromptsChanged();
2057
- * ```
2058
- */
2059
- async notifyPromptsChanged() {
2060
- await this.#ensureMounted("handler").handler.notify.promptsChanged();
2061
- }
2062
- /**
2063
- * Publish a resources-list change to v2 clients with active subscriptions.
2064
- *
2065
- * @example
2066
- * ```ts
2067
- * await server.notifyResourcesChanged();
2068
- * ```
2069
- */
2070
- async notifyResourcesChanged() {
2071
- await this.#ensureMounted("handler").handler.notify.resourcesChanged();
2072
- }
2073
- /**
2074
- * Publish a resource update to subscribed v2 clients.
2075
- *
2076
- * @param uri - Resource URI whose representation changed.
2077
- *
2078
- * @example
2079
- * ```ts
2080
- * await server.notifyResourceUpdated("config://settings");
2081
- * ```
2082
- */
2083
- async notifyResourceUpdated(uri) {
2084
- await this.#ensureMounted("handler").handler.notify.resourceUpdated(uri);
2085
- }
2086
- /**
2087
- * Serve over HTTP on Node. Pass port `0` for an ephemeral port. Port
2088
- * precedence is the argument, `PORT`, `config.port`, then `3000`; host
2089
- * precedence is `options.host`, `HOST`, `config.host`, then `127.0.0.1`.
2090
- *
2091
- * Localhost-class binds get
2092
- * DNS-rebinding Host protection automatically. Origin validation is off
2093
- * unless `allowedOrigins` is set. To serve publicly set `host: "0.0.0.0"`;
2094
- * behind a platform edge that is all that's needed, and `allowedHosts`
2095
- * restricts direct exposure (additive — localhost-class values stay allowed).
2096
- *
2097
- * With OAuth and no explicit resource or `MCP_URL`, a localhost listener
2098
- * derives its protected-resource URL from the actual bound port. Mounting
2099
- * therefore waits for the listener callback (especially for port `0`), and
2100
- * requests accepted before then are queued. Public/wildcard listeners must
2101
- * configure the resource before calling this method.
2102
- *
2103
- * @throws If called on a localhost-class bind after {@link MCPServer.fetch}
2104
- * already mounted the app without Host validation.
2105
- */
2106
- async listen(port = void 0, options = {}) {
2107
- this.#assertOpen("listen()");
2108
- const { createServer } = await import("http");
2109
- const { toNodeHandler } = await import("./node-bridge.js");
2110
- const host = resolveListenHost(options.host, this.#config.host);
2111
- const requestedPort = resolveListenPort(port, this.#config.port);
2112
- this.#assertListenOAuthConfiguration(host);
2113
- return new Promise((resolve, reject) => {
2114
- let resolveFetch;
2115
- let rejectFetch;
2116
- const fetchReady = new Promise(
2117
- (resolveFetchPromise, rejectFetchPromise) => {
2118
- resolveFetch = resolveFetchPromise;
2119
- rejectFetch = rejectFetchPromise;
2120
- }
2121
- );
2122
- void fetchReady.catch(() => void 0);
2123
- let settled = false;
2124
- const rejectAndClose = (error2) => {
2125
- if (!settled) {
2126
- settled = true;
2127
- reject(error2);
2128
- }
2129
- rejectFetch?.(error2);
2130
- void new Promise(
2131
- (closeResolve) => server.close(() => closeResolve())
2132
- ).catch(() => void 0).finally(() => {
2133
- if (this.#httpServer === server) {
2134
- this.#httpServer = void 0;
2135
- }
2136
- });
2137
- };
2138
- const nodeHandler = toNodeHandler({
2139
- fetch: async (request) => (await fetchReady)(request)
2140
- });
2141
- const server = createServer((req, res) => {
2142
- void nodeHandler(req, res);
2143
- });
2144
- server.once("error", rejectAndClose);
2145
- server.listen(requestedPort, host, () => {
2146
- try {
2147
- const address = server.address();
2148
- const boundPort = typeof address === "object" && address !== null ? address.port : requestedPort;
2149
- const { fetch } = this.#ensureMounted("listen", boundPort, host);
2150
- resolveFetch?.(fetch);
2151
- if (!settled) {
2152
- settled = true;
2153
- resolve({
2154
- port: boundPort,
2155
- url: `http://localhost:${boundPort}${this.#basePath()}`
2156
- });
2157
- }
2158
- } catch (error2) {
2159
- rejectAndClose(error2);
2160
- }
2161
- });
2162
- this.#httpServer = server;
2163
- });
2164
- }
2165
- /**
2166
- * Abort in-flight MCP exchanges and stop the HTTP listener.
2167
- *
2168
- * A closed server is done for good — the underlying MCP handler stays
2169
- * closed, so `listen()`/`fetch()` cannot revive it. Create a new
2170
- * instance to serve again.
2171
- */
2172
- async close() {
2173
- this.#closed = true;
2174
- await Promise.allSettled([...this.#proxyOperations]);
2175
- const errors = [];
2176
- const proxyOwners = this.#proxyOwners.splice(0);
2177
- const ownerResults = await Promise.allSettled(
2178
- proxyOwners.map((owner) => owner.close())
2179
- );
2180
- for (const result of ownerResults) {
2181
- if (result.status === "rejected") errors.push(result.reason);
2182
- }
2183
- try {
2184
- await this.#handler?.close();
2185
- } catch (error2) {
2186
- errors.push(error2);
2187
- }
2188
- const httpServer = this.#httpServer;
2189
- if (httpServer !== void 0) {
2190
- try {
2191
- await new Promise((resolve, reject) => {
2192
- httpServer.close((err) => err ? reject(err) : resolve());
2193
- });
2194
- this.#httpServer = void 0;
2195
- } catch (error2) {
2196
- errors.push(error2);
2197
- }
2198
- }
2199
- if (errors.length > 0) {
2200
- throw new AggregateError(errors, "Failed to close MCP server cleanly");
2201
- }
2202
- }
2203
- #assertOpen(operation) {
2204
- if (!this.#closed) return;
2205
- if (operation !== void 0) {
2206
- throw new Error(`Cannot call ${operation} after the server has closed.`);
2207
- }
2208
- throw new Error("Cannot use the server after it has closed.");
2209
- }
2210
- #basePath() {
2211
- return this.#config.basePath ?? "/mcp";
2212
- }
2213
- #resolveOAuthResource(mode, listenPort, listenHost) {
2214
- if (this.#config.oauth === void 0) {
2215
- return void 0;
2216
- }
2217
- if (this.#oauthResourceResolved) {
2218
- return this.#oauthResource;
2219
- }
2220
- const host = listenHost ?? this.#config.host ?? "127.0.0.1";
2221
- const localListen = mode === "listen" && listenPort !== void 0 && ["127.0.0.1", "localhost", "::1"].includes(host);
2222
- if (this.#oauthResourceConfigurationAbsent && localListen) {
2223
- this.#oauthResource = resolveLocalOAuthResource(
2224
- `http://localhost:${listenPort}`,
2225
- this.#basePath()
2226
- );
2227
- this.#oauthResourceResolved = true;
2228
- return this.#oauthResource;
2229
- }
2230
- throw new Error(
2231
- "OAuth requires an explicit resource or MCP_URL when using server.fetch or listening on a non-local host"
2232
- );
2233
- }
2234
- #assertListenOAuthConfiguration(host) {
2235
- if (this.#config.oauth === void 0) {
2236
- return;
2237
- }
2238
- if (["127.0.0.1", "localhost", "::1"].includes(host)) {
2239
- return;
2240
- }
2241
- if (!this.#oauthResourceResolved) {
2242
- throw new Error(
2243
- "OAuth listen() on a public or wildcard host requires an explicit provider resource or valid MCP_URL."
2244
- );
2245
- }
2246
- }
2247
- #assertNotStarted(kind, name) {
2248
- if (this.#handler !== void 0) {
2249
- throw new Error(
2250
- `Cannot register ${kind} "${name}" after the server has started: registrations are replayed per request from the registry, so register everything before listen()/server.fetch.`
2251
- );
2252
- }
2253
- }
2254
- #proxyHost() {
2255
- return {
2256
- isStarted: () => this.#handler !== void 0,
2257
- hasTool: (name) => this.#tools.has(name),
2258
- hasResource: (name) => this.#resources.has(name),
2259
- hasPrompt: (name) => this.#prompts.has(name),
2260
- registerTool: (definition, callback) => {
2261
- this.#assertNotStarted("tool", definition.name);
2262
- this.#tools.set(definition.name, {
2263
- definition,
2264
- callback
2265
- });
2266
- },
2267
- registerResource: (definition, callback) => {
2268
- this.#assertNotStarted("resource", definition.name);
2269
- this.#resources.set(definition.name, {
2270
- definition,
2271
- callback
2272
- });
2273
- },
2274
- registerPrompt: (definition, callback) => {
2275
- this.#assertNotStarted("prompt", definition.name);
2276
- this.#prompts.set(definition.name, {
2277
- definition,
2278
- callback
2279
- });
2280
- },
2281
- trackOwner: (owner) => {
2282
- this.#proxyOwners.push(owner);
2283
- }
2284
- };
2285
- }
2286
- /**
2287
- * Effective Host/Origin allowlists for a mount mode; `undefined` means the
2288
- * corresponding validation is off.
2289
- *
2290
- * Configured lists are additive to the localhost-class allowlists, so local
2291
- * runs keep working when a deployment hostname is added. With nothing
2292
- * configured, `listen()` on a localhost-class bind validates Host against the
2293
- * localhost lists (the DNS-rebinding threat model), while `server.fetch` —
2294
- * which never binds — applies no validation. Origin validation is off unless
2295
- * `allowedOrigins` is set explicitly (SDK-aligned: the handler is open by
2296
- * default). When enabled, Origin is checked only on non-GET/HEAD requests.
2297
- */
2298
- #validationPolicy(mode, listenHost) {
2299
- const { allowedHosts, allowedOrigins } = this.#config;
2300
- const host = listenHost ?? this.#config.host ?? "127.0.0.1";
2301
- const localhostBind = ["127.0.0.1", "localhost", "::1"].includes(host);
2302
- const hosts = allowedHosts !== void 0 ? [.../* @__PURE__ */ new Set([...localhostAllowedHostnames(), ...allowedHosts])] : mode === "listen" && localhostBind ? localhostAllowedHostnames() : void 0;
2303
- const origins = allowedOrigins !== void 0 ? [.../* @__PURE__ */ new Set([...localhostAllowedOrigins(), ...allowedOrigins])] : void 0;
2304
- return { hosts, origins };
2305
- }
2306
- #ensureMounted(mode, listenPort, listenHost) {
2307
- this.#assertOpen();
2308
- if (this.#fetchHandler === void 0 || this.#handler === void 0) {
2309
- const { hosts, origins } = this.#validationPolicy(mode, listenHost);
2310
- const basePath = this.#basePath();
2311
- const nestedBasePath = basePath === "/" ? "" : basePath;
2312
- const httpApp = new Hono();
2313
- const middlewares = [
2314
- jsonBodyMiddleware(),
2315
- requestLogger(this.#config.logging)
2316
- ];
2317
- const corsConfig = this.#config.cors;
2318
- if (corsConfig !== void 0) {
2319
- middlewares.unshift(corsFetchMiddleware(corsConfig));
2320
- }
2321
- const deferViewCors = isGlobalCorsEnabled(corsConfig);
2322
- if (hosts !== void 0) {
2323
- middlewares.unshift(hostValidationMiddleware(hosts));
2324
- }
2325
- if (origins !== void 0) {
2326
- middlewares.push(originValidationMiddleware(origins));
2327
- }
2328
- if (hosts === void 0) {
2329
- if (mode === "listen") {
2330
- console.warn(
2331
- `[mcp-use] listen() is serving on ${listenHost} without Host validation. Behind a platform edge that only routes your own domains this is expected; if this process is reachable directly, set allowedHosts to restrict it.`
2332
- );
2333
- }
2334
- }
2335
- this.#validateViewBindingsAtMount();
2336
- const resource2 = this.#resolveOAuthResource(mode, listenPort, listenHost);
2337
- if (resource2 !== void 0) {
2338
- const provider = this.#config.oauth;
2339
- middlewares.push(oauthMetadata(provider, resource2));
2340
- }
2341
- for (const middleware of middlewares) {
2342
- registerFetchMiddleware(httpApp, middleware);
2343
- }
2344
- const { handler, fetch: mcpFetch } = createMcpMount(
2345
- (ctx) => this.#buildSdkServer(ctx),
2346
- {
2347
- path: basePath,
2348
- ...(this.#config.legacy !== void 0 || this.#eventBus !== void 0) && {
2349
- handler: {
2350
- ...this.#config.legacy !== void 0 && {
2351
- legacy: this.#config.legacy
2352
- },
2353
- ...this.#eventBus !== void 0 && { bus: this.#eventBus }
2354
- }
2355
- },
2356
- ...resource2 !== void 0 && {
2357
- authInfo: (request) => authInfoFromRequest(request)
2358
- }
2359
- }
2360
- );
2361
- let protectWithBearer = async (_request, next) => next();
2362
- if (resource2 !== void 0) {
2363
- const provider = this.#config.oauth;
2364
- const providerOptions = getOAuthProviderOptions(provider);
2365
- const gate = requireBearerAuth({
2366
- verifier: wrapOAuthTokenVerifier(provider, resource2),
2367
- resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(resource2),
2368
- ...providerOptions.requiredScopes !== void 0 && {
2369
- requiredScopes: providerOptions.requiredScopes
2370
- }
2371
- });
2372
- protectWithBearer = async (request, next) => {
2373
- const result = await gate(request);
2374
- if (result instanceof Response) {
2375
- return result;
2376
- }
2377
- const bag = getRequestBag(request);
2378
- bag.authInfo = result;
2379
- return next();
2380
- };
2381
- }
2382
- const mcpRouteHandler = (request) => protectWithBearer(request, () => mcpFetch(request));
2383
- const endpointHandler = async (request) => {
2384
- if (!isHtmlNavigationRequest(request)) {
2385
- return mcpRouteHandler(request);
2386
- }
2387
- const respond = async () => {
2388
- const { createLandingPageResponse } = await import("./landing-handler-QEH2ATIR.js");
2389
- return createLandingPageResponse(
2390
- request,
2391
- basePath,
2392
- this.#config,
2393
- this.#branding,
2394
- this.#tools.values(),
2395
- this.#prompts.values(),
2396
- this.#resources.values()
2397
- );
2398
- };
2399
- if (resource2 !== void 0 && this.#config.publicLandingPage !== true) {
2400
- return protectWithBearer(request, respond);
2401
- }
2402
- return respond();
2403
- };
2404
- const brandingDevMode = this.#viewsPrimed ? this.#viewsDevMode : process.env["NODE_ENV"] !== "production";
2405
- const faviconHandler = createFaviconHandler(this.#branding, {
2406
- dev: brandingDevMode,
2407
- projectRoot: this.#viewsProjectRoot,
2408
- deferCors: deferViewCors
2409
- });
2410
- if (faviconHandler !== void 0) {
2411
- this.app.all(
2412
- "/favicon.ico",
2413
- (context) => faviconHandler(context.req.raw)
2414
- );
2415
- }
2416
- const viewHandler = createViewPublicHandler(basePath, this.#views, {
2417
- dev: this.#viewsPrimed ? this.#viewsDevMode : brandingDevMode,
2418
- projectRoot: this.#viewsProjectRoot,
2419
- enabled: hasLocalBrandingAsset(this.#branding),
2420
- deferCors: deferViewCors
2421
- });
2422
- if (viewHandler !== void 0) {
2423
- this.app.on(
2424
- ["GET", "HEAD"],
2425
- `${nestedBasePath}/_mcp-use/public/*`,
2426
- (context) => viewHandler(context.req.raw)
2427
- );
2428
- }
2429
- if (!this.#viewsDevMode) {
2430
- const viewAssetsHandler = createViewAssetsHandler(
2431
- basePath,
2432
- this.#views,
2433
- { projectRoot: this.#viewsProjectRoot, deferCors: deferViewCors }
2434
- );
2435
- if (viewAssetsHandler !== void 0) {
2436
- this.app.on(
2437
- ["GET", "HEAD"],
2438
- `${nestedBasePath}/_mcp-use/views/*`,
2439
- (context) => viewAssetsHandler(context.req.raw)
2440
- );
2441
- }
2442
- }
2443
- this.app.all(basePath, (context) => endpointHandler(context.req.raw));
2444
- httpApp.route("/", this.app);
2445
- this.#httpApp = httpApp;
2446
- this.#fetchHandler = async (request) => httpApp.fetch(request);
2447
- this.#handler = handler;
2448
- this.#hostValidated = hosts !== void 0;
2449
- } else if (mode === "listen" && !this.#hostValidated && this.#validationPolicy("listen", listenHost).hosts !== void 0) {
2450
- throw new Error(
2451
- "Cannot listen() on a localhost bind after server.fetch mounted the app without Host validation (server.fetch expects a platform edge in front). Call listen() first, or set allowedHosts."
2452
- );
2453
- }
2454
- return { fetch: this.#fetchHandler, handler: this.#handler };
2455
- }
2456
- #validateToolViewBinding(definition) {
2457
- const view = definition.view;
2458
- if (view === void 0) {
2459
- return;
2460
- }
2461
- if (definition.outputSchema === void 0) {
2462
- throw new Error(
2463
- `Tool "${definition.name}" declares view "${view.name}" but has no outputSchema. View-bound tools require an outputSchema \u2014 the view reads structuredContent typed from it. Use outputSchema: z.object({}) for a view that takes no structured output.`
2464
- );
2465
- }
2466
- const existing = this.#viewBindings.get(view.name);
2467
- if (existing !== void 0) {
2468
- throw new Error(
2469
- `View "${view.name}" is already bound to tool "${existing.toolName}"; tool "${definition.name}" cannot bind the same view. Each view may be bound to one tool.`
2470
- );
2471
- }
2472
- this.#viewBindings.set(view.name, {
2473
- toolName: definition.name,
2474
- config: view
2475
- });
2476
- }
2477
- #validateViewBindingsAtMount() {
2478
- if (this.#viewBindings.size > 0 && !this.#viewsPrimed) {
2479
- const first = [...this.#tools.values()].find(
2480
- (entry) => entry.definition.view !== void 0
2481
- );
2482
- const viewName = first?.definition.view?.name ?? "unknown";
2483
- throw new Error(
2484
- `Tool "${first?.definition.name ?? "unknown"}" is bound to view "${viewName}" but no views were primed. Run \`mcp-use build\` and deploy the built entry, or in dev let the CLI prime views automatically.`
2485
- );
2486
- }
2487
- for (const entry of this.#tools.values()) {
2488
- const viewName = entry.definition.view?.name;
2489
- if (viewName !== void 0 && !this.#views.has(viewName)) {
2490
- throw new Error(
2491
- `Tool "${entry.definition.name}" is bound to view "${viewName}" which is not in the primed views registry. Run \`mcp-use build\` and deploy the built entry, or in dev let the CLI prime views automatically.`
2492
- );
2493
- }
2494
- }
2495
- for (const viewName of this.#views.keys()) {
2496
- if (!this.#viewBindings.has(viewName)) {
2497
- console.warn(
2498
- `[mcp-use] View "${viewName}" is registered but no tool binds it.`
2499
- );
2500
- }
2501
- }
2502
- }
2503
- /** Build a fresh SDK server from the registry (runs once per request). */
2504
- #buildSdkServer(ctx) {
2505
- const { name, version, title, description, instructions } = this.#config;
2506
- const authInfo = ctx.authInfo;
2507
- const server = new SdkMcpServer(
2508
- {
2509
- name,
2510
- version,
2511
- ...title !== void 0 && { title },
2512
- ...description !== void 0 && { description },
2513
- ...this.#branding.websiteUrl !== void 0 && {
2514
- websiteUrl: this.#branding.websiteUrl
2515
- },
2516
- ...this.#branding.icons !== void 0 && {
2517
- icons: resolveImplementationIcons(
2518
- this.#branding.icons,
2519
- ctx.requestInfo,
2520
- this.#basePath()
2521
- )
2522
- }
2523
- },
2524
- {
2525
- capabilities: {
2526
- logging: {},
2527
- tools: { listChanged: true },
2528
- prompts: { listChanged: true },
2529
- resources: { listChanged: true, subscribe: true }
2530
- },
2531
- ...instructions !== void 0 && { instructions },
2532
- ...authInfo !== void 0 && { authInfo },
2533
- ...this.#config.requestState !== void 0 && {
2534
- requestState: this.#config.requestState
2535
- }
2536
- }
2537
- );
2538
- const request = ctx.requestInfo;
2539
- const viewMetaOptions = request !== void 0 ? { request, hmrWs: this.#viewsDevMode } : { hmrWs: this.#viewsDevMode };
2540
- const basePath = this.#basePath();
2541
- for (const entry of this.#tools.values()) {
2542
- this.#registerTool(server, entry);
2543
- }
2544
- for (const entry of this.#resources.values()) {
2545
- this.#registerResource(server, entry);
2546
- }
2547
- for (const entry of this.#resourceTemplates.values()) {
2548
- this.#registerResourceTemplate(server, entry);
2549
- }
2550
- for (const entry of this.#prompts.values()) {
2551
- this.#registerPrompt(server, entry);
2552
- }
2553
- for (const [viewName, viewEntry] of this.#views.entries()) {
2554
- this.#registerViewResource(
2555
- server,
2556
- viewName,
2557
- viewEntry,
2558
- viewMetaOptions,
2559
- basePath
2560
- );
2561
- }
2562
- this.#wrapListHandlers(server);
2563
- return server;
2564
- }
2565
- #createMiddlewareContext(method, params, ctx) {
2566
- const requestContext = toRequestContext(ctx);
2567
- return Object.assign(requestContext, {
2568
- method,
2569
- params,
2570
- ...ctx.sessionId !== void 0 && {
2571
- session: { sessionId: ctx.sessionId }
2572
- },
2573
- ...ctx.http?.authInfo !== void 0 && { auth: ctx.http.authInfo },
2574
- state: /* @__PURE__ */ new Map()
2575
- });
2576
- }
2577
- #runMcpHook(method, ctx, innerFn) {
2578
- return runMcpOperation(
2579
- this.#mcpMiddlewares,
2580
- this.#mcpEventListeners,
2581
- method,
2582
- ctx,
2583
- innerFn
2584
- );
2585
- }
2586
- /**
2587
- * Wrap native SDK list handlers with the MCP middleware chain.
2588
- *
2589
- * ponytail: uses SDK-private `_requestHandlers`; pin compile-time test.
2590
- *
2591
- * @internal
2592
- */
2593
- #wrapListHandlers(server) {
2594
- const handlers = server.server._requestHandlers;
2595
- if (handlers === void 0) {
2596
- return;
2597
- }
2598
- const wrapListMethod = (method, resultKey, transform) => {
2599
- const original = handlers.get(method);
2600
- if (original === void 0) {
2601
- return;
2602
- }
2603
- if (original.__mcpListWrapped) {
2604
- return;
2605
- }
2606
- const wrapped = async (request, extra) => {
2607
- const serverContext = extra;
2608
- const params = request.params ?? {};
2609
- const mwCtx = this.#createMiddlewareContext(
2610
- method,
2611
- params,
2612
- serverContext
2613
- );
2614
- let originalEnvelope;
2615
- const innerFn = async () => {
2616
- const downstreamRequest = withMcpMiddlewareParams(
2617
- request,
2618
- mwCtx.params
2619
- );
2620
- const result = await original(downstreamRequest, extra);
2621
- if (typeof result !== "object" || result === null) {
2622
- throw new TypeError(
2623
- `[mcp-use] ${method} handler returned a non-object result`
2624
- );
2625
- }
2626
- originalEnvelope = result;
2627
- const items = originalEnvelope[resultKey];
2628
- if (!Array.isArray(items)) {
2629
- throw new TypeError(
2630
- `[mcp-use] ${method} handler result is missing a ${resultKey} array`
2631
- );
2632
- }
2633
- return items;
2634
- };
2635
- const filtered = await this.#runMcpHook(method, mwCtx, innerFn);
2636
- if (!Array.isArray(filtered)) {
2637
- throw new TypeError(
2638
- `[mcp-use] ${method} middleware must return a ${resultKey} array`
2639
- );
2640
- }
2641
- const emitted = transform?.(filtered) ?? filtered;
2642
- return {
2643
- ...originalEnvelope,
2644
- [resultKey]: emitted
2645
- };
2646
- };
2647
- wrapped.__mcpListWrapped = true;
2648
- handlers.set(method, wrapped);
2649
- };
2650
- wrapListMethod("tools/list", "tools", omitToolSchemaDialects);
2651
- wrapListMethod("resources/list", "resources");
2652
- wrapListMethod("prompts/list", "prompts");
2653
- }
2654
- #registerTool(server, { definition, callback }) {
2655
- const view = definition.view;
2656
- const toolMeta = buildToolUiMeta(
2657
- view?.name,
2658
- definition.visibility,
2659
- definition._meta
2660
- );
2661
- const config = {
2662
- ...definition.title !== void 0 && { title: definition.title },
2663
- ...definition.description !== void 0 && {
2664
- description: definition.description
2665
- },
2666
- ...definition.annotations !== void 0 && {
2667
- annotations: definition.annotations
2668
- },
2669
- ...definition.outputSchema !== void 0 && {
2670
- outputSchema: definition.outputSchema
2671
- },
2672
- ...toolMeta !== void 0 && { _meta: toolMeta }
2673
- };
2674
- const wireResultMeta = view !== void 0 ? buildToolResultUiMeta(view.name) : void 0;
2675
- const inputSchema = resolveToolInputSchema(definition);
2676
- const invokeTool = async (args, ctx) => {
2677
- const mwCtx = this.#createMiddlewareContext(
2678
- "tools/call",
2679
- {
2680
- name: definition.name,
2681
- arguments: args,
2682
- ...ctx.mcpReq._meta !== void 0 && { _meta: ctx.mcpReq._meta }
2683
- },
2684
- ctx
2685
- );
2686
- const innerFn = async () => {
2687
- const effectiveArgs = mwCtx.params.arguments ?? {};
2688
- const result = await callback(
2689
- effectiveArgs,
2690
- this.#toRequestContext(ctx)
2691
- );
2692
- if (isInputRequiredResult2(result) || wireResultMeta === void 0 || result.isError === true) {
2693
- return result;
2694
- }
2695
- return {
2696
- ...result,
2697
- _meta: { ...result._meta, ...wireResultMeta }
2698
- };
2699
- };
2700
- return await this.#runMcpHook("tools/call", mwCtx, innerFn);
2701
- };
2702
- if (inputSchema !== void 0) {
2703
- server.registerTool(
2704
- definition.name,
2705
- { ...config, inputSchema },
2706
- async (args, ctx) => invokeTool(args, ctx)
2707
- );
2708
- } else {
2709
- server.registerTool(
2710
- definition.name,
2711
- config,
2712
- async (ctx) => invokeTool({}, ctx)
2713
- );
2714
- }
2715
- }
2716
- #registerViewResource(server, viewName, entry, metaOptions, basePath) {
2717
- const uri = viewResourceUri(viewName);
2718
- const authorFacts = this.#viewResourceFacts(
2719
- this.#viewBindings.get(viewName)?.config
2720
- );
2721
- const resourceConfig = viewResourceConfig(
2722
- viewName,
2723
- entry,
2724
- authorFacts,
2725
- metaOptions
2726
- );
2727
- server.registerResource(
2728
- viewName,
2729
- uri,
2730
- resourceConfig,
2731
- async (readUri, ctx) => {
2732
- const req = ctx.http?.req;
2733
- const readOptions = req !== void 0 ? {
2734
- request: req,
2735
- ...metaOptions.hmrWs === true ? { hmrWs: true } : {}
2736
- } : metaOptions.hmrWs === true ? { hmrWs: true } : {};
2737
- const assetsBase = req !== void 0 ? resolveAssetsBase(req) : metaOptions.request !== void 0 ? resolveAssetsBase(metaOptions.request) : "";
2738
- const html2 = synthesizeViewDocument(
2739
- entry,
2740
- assetsBase,
2741
- basePath,
2742
- viewName
2743
- );
2744
- return {
2745
- contents: [
2746
- {
2747
- uri: readUri.href,
2748
- mimeType: resourceConfig.mimeType,
2749
- text: html2,
2750
- _meta: buildResourceUiMeta(authorFacts, readOptions)
2751
- }
2752
- ]
2753
- };
2754
- }
2755
- );
2756
- }
2757
- #registerResource(server, { definition, callback }) {
2758
- server.registerResource(
2759
- definition.name,
2760
- definition.uri,
2761
- {
2762
- ...definition.title !== void 0 && { title: definition.title },
2763
- ...definition.description !== void 0 && {
2764
- description: definition.description
2765
- },
2766
- ...definition.mimeType !== void 0 && {
2767
- mimeType: definition.mimeType
2768
- },
2769
- ...definition.annotations !== void 0 && {
2770
- annotations: definition.annotations
2771
- },
2772
- ...definition._meta !== void 0 && {
2773
- _meta: { ...definition._meta }
2774
- }
2775
- },
2776
- async (uri, ctx) => {
2777
- const mwCtx = this.#createMiddlewareContext(
2778
- "resources/read",
2779
- {
2780
- uri: uri.href,
2781
- ...ctx.mcpReq._meta !== void 0 && { _meta: ctx.mcpReq._meta }
2782
- },
2783
- ctx
2784
- );
2785
- const innerFn = async () => toResourceResult(
2786
- await callback(uri, this.#toRequestContext(ctx)),
2787
- uri.href
2788
- );
2789
- return await this.#runMcpHook("resources/read", mwCtx, innerFn);
2790
- }
2791
- );
2792
- }
2793
- #registerResourceTemplate(server, { definition, callback, complete }) {
2794
- const template = new ResourceTemplate(definition.uriTemplate, {
2795
- list: void 0,
2796
- ...complete !== void 0 && { complete }
2797
- });
2798
- server.registerResource(
2799
- definition.name,
2800
- template,
2801
- {
2802
- ...definition.title !== void 0 && { title: definition.title },
2803
- ...definition.description !== void 0 && {
2804
- description: definition.description
2805
- },
2806
- ...definition.mimeType !== void 0 && {
2807
- mimeType: definition.mimeType
2808
- },
2809
- ...definition.annotations !== void 0 && {
2810
- annotations: definition.annotations
2811
- },
2812
- ...definition._meta !== void 0 && {
2813
- _meta: { ...definition._meta }
2814
- }
2815
- },
2816
- async (uri, variables, ctx) => {
2817
- const mwCtx = this.#createMiddlewareContext(
2818
- "resources/read",
2819
- {
2820
- uri: uri.href,
2821
- ...ctx.mcpReq._meta !== void 0 && { _meta: ctx.mcpReq._meta }
2822
- },
2823
- ctx
2824
- );
2825
- const innerFn = async () => toResourceResult(
2826
- await callback(
2827
- uri,
2828
- variables,
2829
- this.#toRequestContext(ctx)
2830
- ),
2831
- uri.href
2832
- );
2833
- return await this.#runMcpHook("resources/read", mwCtx, innerFn);
2834
- }
2835
- );
2836
- }
2837
- #viewResourceFacts(viewConfig) {
2838
- if (viewConfig === void 0) {
2839
- return void 0;
2840
- }
2841
- return {
2842
- ...viewConfig.description !== void 0 && {
2843
- description: viewConfig.description
2844
- },
2845
- ...viewConfig.csp !== void 0 && { csp: viewConfig.csp },
2846
- ...viewConfig.permissions !== void 0 && {
2847
- permissions: viewConfig.permissions
2848
- },
2849
- ...viewConfig.domain !== void 0 && { domain: viewConfig.domain },
2850
- ...viewConfig.prefersBorder !== void 0 && {
2851
- prefersBorder: viewConfig.prefersBorder
2852
- }
2853
- };
2854
- }
2855
- #registerPrompt(server, { definition, callback }) {
2856
- const config = {
2857
- ...definition.title !== void 0 && { title: definition.title },
2858
- ...definition.description !== void 0 && {
2859
- description: definition.description
2860
- }
2861
- };
2862
- const invokePrompt = async (args, ctx) => {
2863
- const mwCtx = this.#createMiddlewareContext(
2864
- "prompts/get",
2865
- {
2866
- name: definition.name,
2867
- arguments: args,
2868
- ...ctx.mcpReq._meta !== void 0 && { _meta: ctx.mcpReq._meta }
2869
- },
2870
- ctx
2871
- );
2872
- const innerFn = async () => {
2873
- const effectiveArgs = mwCtx.params.arguments ?? {};
2874
- return toPromptResult(
2875
- await callback(effectiveArgs, this.#toRequestContext(ctx))
2876
- );
2877
- };
2878
- return await this.#runMcpHook("prompts/get", mwCtx, innerFn);
2879
- };
2880
- if (definition.schema !== void 0) {
2881
- server.registerPrompt(
2882
- definition.name,
2883
- { ...config, argsSchema: definition.schema },
2884
- async (args, ctx) => invokePrompt(args, ctx)
2885
- );
2886
- } else {
2887
- const handler = async (ctx) => invokePrompt({}, ctx);
2888
- server.registerPrompt(
2889
- definition.name,
2890
- config,
2891
- handler
2892
- );
2893
- }
2894
- }
2895
- #toRequestContext(ctx) {
2896
- if (this.#config.oauth === void 0) {
2897
- return toRequestContext(ctx);
2898
- }
2899
- return toAuthenticatedRequestContext(ctx);
2900
- }
2901
- };
2902
-
2903
- // src/index.ts
2904
- import {
2905
- acceptedContent,
2906
- createRequestStateCodec,
2907
- inputRequired as inputRequired2,
2908
- inputResponse as inputResponse2,
2909
- isInputRequiredResult as isInputRequiredResult3
2910
- } from "@modelcontextprotocol/server";
2911
-
2912
- // src/response-helpers.ts
2913
- function text(content) {
2914
- return {
2915
- content: [{ type: "text", text: content }],
2916
- _meta: { mimeType: "text/plain" }
2917
- };
2918
- }
2919
- function markdown(content) {
2920
- return {
2921
- content: [{ type: "text", text: content }],
2922
- _meta: { mimeType: "text/markdown" }
2923
- };
2924
- }
2925
- function html(content) {
2926
- return {
2927
- content: [{ type: "text", text: content }],
2928
- _meta: { mimeType: "text/html" }
2929
- };
2930
- }
2931
- function xml(content) {
2932
- return {
2933
- content: [{ type: "text", text: content }],
2934
- _meta: { mimeType: "text/xml" }
2935
- };
2936
- }
2937
- function css(content) {
2938
- return {
2939
- content: [{ type: "text", text: content }],
2940
- _meta: { mimeType: "text/css" }
2941
- };
2942
- }
2943
- function javascript(content) {
2944
- return {
2945
- content: [{ type: "text", text: content }],
2946
- _meta: { mimeType: "text/javascript" }
2947
- };
2948
- }
2949
- function image(data, mimeType = "image/png") {
2950
- return {
2951
- content: [{ type: "image", data, mimeType }],
2952
- _meta: { mimeType, isImage: true }
2953
- };
2954
- }
2955
- function audio(data, mimeType = "audio/wav") {
2956
- return {
2957
- content: [{ type: "audio", data, mimeType }],
2958
- _meta: { mimeType, isAudio: true }
2959
- };
2960
- }
2961
- function binary(base64Data, mimeType) {
2962
- return {
2963
- content: [{ type: "text", text: base64Data }],
2964
- _meta: { mimeType, isBinary: true }
2965
- };
2966
- }
2967
- function resource(uri, mimeTypeOrContent, text2) {
2968
- if (typeof mimeTypeOrContent === "object" && mimeTypeOrContent !== null && "content" in mimeTypeOrContent) {
2969
- const contentResult = mimeTypeOrContent;
2970
- let extractedText;
2971
- let extractedMimeType;
2972
- if (contentResult._meta && typeof contentResult._meta === "object") {
2973
- const meta = contentResult._meta;
2974
- if (typeof meta.mimeType === "string") {
2975
- extractedMimeType = meta.mimeType;
2976
- }
2977
- }
2978
- const first = contentResult.content?.[0];
2979
- if (first?.type === "text" && "text" in first) {
2980
- extractedText = first.text;
2981
- }
2982
- return {
2983
- content: [
2984
- {
2985
- type: "resource",
2986
- resource: {
2987
- uri,
2988
- ...extractedMimeType !== void 0 && {
2989
- mimeType: extractedMimeType
2990
- },
2991
- text: extractedText ?? ""
2992
- }
2993
- }
2994
- ]
2995
- };
2996
- }
2997
- const mimeType = mimeTypeOrContent;
2998
- return {
2999
- content: [
3000
- {
3001
- type: "resource",
3002
- resource: {
3003
- uri,
3004
- ...mimeType !== void 0 && mimeType !== "" && { mimeType },
3005
- text: text2 ?? ""
3006
- }
3007
- }
3008
- ]
3009
- };
3010
- }
3011
- function error(message) {
3012
- return {
3013
- isError: true,
3014
- content: [{ type: "text", text: message }]
3015
- };
3016
- }
3017
- function object(data) {
3018
- if (Array.isArray(data)) {
3019
- return array(data);
3020
- }
3021
- return {
3022
- content: [
3023
- {
3024
- type: "text",
3025
- text: JSON.stringify(data, null, 2)
3026
- }
3027
- ],
3028
- structuredContent: data,
3029
- _meta: { mimeType: "application/json" }
3030
- };
3031
- }
3032
- function array(data) {
3033
- return {
3034
- content: [
3035
- {
3036
- type: "text",
3037
- text: JSON.stringify(data, null, 2)
3038
- }
3039
- ],
3040
- structuredContent: data
3041
- };
3042
- }
3043
- function widget(config) {
3044
- const props = config.props ?? config.data ?? {};
3045
- const { output, message, metadata } = config;
3046
- const finalContent = message ? [{ type: "text", text: message }] : Array.isArray(output?.content) && output.content.length > 0 ? output.content : [{ type: "text", text: "" }];
3047
- const result = {
3048
- content: finalContent
3049
- };
3050
- if (metadata !== void 0 && Object.keys(metadata).length > 0) {
3051
- result._meta = metadata;
3052
- }
3053
- if (output?.structuredContent !== void 0) {
3054
- result.structuredContent = output.structuredContent;
3055
- } else if (Object.keys(props).length > 0) {
3056
- result.structuredContent = props;
3057
- }
3058
- return result;
3059
- }
3060
- function mix(...results) {
3061
- const withStructured = results.filter(
3062
- (result) => result.structuredContent !== void 0
3063
- );
3064
- const structuredContent = withStructured.length > 0 ? withStructured.map((result) => result.structuredContent).reduce(
3065
- (acc, value) => ({
3066
- ...acc,
3067
- ...typeof value === "object" && value !== null ? value : {}
3068
- }),
3069
- {}
3070
- ) : void 0;
3071
- const withMeta = results.filter((result) => result._meta !== void 0);
3072
- const _meta = withMeta.length > 0 ? withMeta.map((result) => result._meta).reduce(
3073
- (acc, value) => ({
3074
- ...acc,
3075
- ...value !== void 0 ? value : {}
3076
- }),
3077
- {}
3078
- ) : void 0;
3079
- return {
3080
- content: results.flatMap((result) => result.content),
3081
- ...structuredContent !== void 0 && Object.keys(structuredContent).length > 0 && { structuredContent },
3082
- ..._meta !== void 0 && Object.keys(_meta).length > 0 && { _meta }
3083
- };
3084
- }
3085
- export {
3086
- MCPServer,
3087
- acceptedContent,
3088
- array,
3089
- audio,
3090
- binary,
3091
- completable,
3092
- composeFetch,
3093
- composeMiddleware,
3094
- createMcpEventListenerEntry,
3095
- createMcpMiddlewareEntry,
3096
- createMcpMount,
3097
- createRequestStateCodec,
3098
- css,
3099
- error,
3100
- getRequestBag,
3101
- hostValidationMiddleware,
3102
- html,
3103
- image,
3104
- inputRequired2 as inputRequired,
3105
- inputResponse2 as inputResponse,
3106
- isInputRequiredResult3 as isInputRequiredResult,
3107
- javascript,
3108
- jsonBodyMiddleware,
3109
- markdown,
3110
- matchesPath,
3111
- matchesPathPrefix,
3112
- matchesPattern,
3113
- mix,
3114
- object,
3115
- originValidationMiddleware,
3116
- pathnameOf,
3117
- registerViews,
3118
- requestLogger,
3119
- resource,
3120
- text,
3121
- widget,
3122
- xml
3123
- };
32
+ </html>`}var CATEGORY_ENV={connectDomains:"CSP_CONNECT_DOMAINS",resourceDomains:"CSP_RESOURCE_DOMAINS",frameDomains:"CSP_FRAME_DOMAINS",baseUriDomains:"CSP_BASE_URI_DOMAINS"};function parseDomainList(raw){return raw===void 0||raw.trim()===""?[]:raw.split(",").map(s=>s.trim()).filter(s=>s.length>0)}function readEnvDomains(name){if(typeof process>"u")return;let raw=process.env[name];if(!(raw===void 0||raw.trim()===""))return parseDomainList(raw)}function readCspUrlsShortcut(){return readEnvDomains("CSP_URLS")??[]}function readEnvDomainsForCategory(category){let perCategory=readEnvDomains(CATEGORY_ENV[category]);return perCategory!==void 0?perCategory:readCspUrlsShortcut()}function mergeDomainLists(...segments){let seen=new Set,out=[];for(let segment of segments)for(let domain of segment)seen.has(domain)||(seen.add(domain),out.push(domain));return out}function toWebSocketOrigin(serverOrigin){return serverOrigin.startsWith("https://")?`wss://${serverOrigin.slice(8)}`:serverOrigin.startsWith("http://")?`ws://${serverOrigin.slice(7)}`:serverOrigin}function buildMergedResourceCsp(authorFacts,options){let author=authorFacts?.csp,mcpConnectAuto=[];options.serverOrigin!==""&&(mcpConnectAuto.push(options.serverOrigin),options.hmrWs===!0&&mcpConnectAuto.push(toWebSocketOrigin(options.serverOrigin)));let mcpResourceAuto=[],resourceOrigin=options.explicitAssetsBase?options.assetsOrigin:options.serverOrigin;resourceOrigin!==""&&mcpResourceAuto.push(resourceOrigin);let connectDomains=mergeDomainLists(author?.connectDomains??[],readEnvDomainsForCategory("connectDomains"),mcpConnectAuto),resourceDomains=mergeDomainLists(author?.resourceDomains??[],readEnvDomainsForCategory("resourceDomains"),mcpResourceAuto),frameDomains=mergeDomainLists(author?.frameDomains??[],readEnvDomainsForCategory("frameDomains")),baseUriDomains=mergeDomainLists(author?.baseUriDomains??[],readEnvDomainsForCategory("baseUriDomains"));return{...author,connectDomains,resourceDomains,frameDomains,baseUriDomains}}var PUBLIC_BUILD_DIR=".mcp-use/build/views/public",PUBLIC_DEV_DIR="public",VIEW_ASSETS_BUILD_ROOT=".mcp-use/build/views";function createViewAssetsHandler(basePath,views,options){if(views.size===0)return;let assetsPrefix=pathUnderBase(basePath,"_mcp-use/views"),projectRoot=options?.projectRoot??process.cwd();return async request=>{if(request.method!=="GET"&&request.method!=="HEAD")return new Response("Method Not Allowed",{status:405});if(!matchesPathPrefix(request,assetsPrefix))return new Response("Not Found",{status:404});let remainder=pathnameOf(request).slice(assetsPrefix.length+1),slash=remainder.indexOf("/");if(slash<=0||slash===remainder.length-1)return new Response("Not Found",{status:404});let viewName=remainder.slice(0,slash),subpath=remainder.slice(slash+1),entry=views.get(viewName);if(entry===void 0||entry.kind!=="external")return new Response("Not Found",{status:404});let[{join},{resolvePublicFilePath:resolvePublicFilePath2,servePublicFile:servePublicFile2}]=await Promise.all([import("path"),import("./public-route-DAQJGS6K.js")]),viewRoot=join(projectRoot,VIEW_ASSETS_BUILD_ROOT,viewName),diskPath=await resolvePublicFilePath2(viewRoot,subpath);return diskPath===null?new Response("Not Found",{status:404}):await servePublicFile2(diskPath,{...options?.deferCors===!0&&{deferCors:!0},...request.method==="HEAD"&&{head:!0}})}}function createViewPublicHandler(basePath,views,options){if(views.size===0&&options?.enabled!==!0)return;let publicPrefix=pathUnderBase(basePath,"_mcp-use/public"),subdir=options?.dev===!0?PUBLIC_DEV_DIR:PUBLIC_BUILD_DIR,projectRoot=options?.projectRoot??process.cwd();return async request=>{if(request.method!=="GET"&&request.method!=="HEAD")return new Response("Method Not Allowed",{status:405});if(!matchesPathPrefix(request,publicPrefix))return new Response("Not Found",{status:404});let encodedSubpath=pathnameOf(request).slice(publicPrefix.length+1),subpath;try{subpath=decodeURIComponent(encodedSubpath)}catch{return new Response("Not Found",{status:404})}if(subpath.length===0)return new Response("Not Found",{status:404});let[{join},{resolvePublicFilePath:resolvePublicFilePath2,servePublicFile:servePublicFile2}]=await Promise.all([import("path"),import("./public-route-DAQJGS6K.js")]),publicRoot=join(projectRoot,subdir),diskPath=await resolvePublicFilePath2(publicRoot,subpath);return diskPath===null?new Response("Not Found",{status:404}):await servePublicFile2(diskPath,{...options?.deferCors===!0&&{deferCors:!0},...request.method==="HEAD"&&{head:!0}})}}function buildToolUiMeta(viewName,visibility,existingMetadata){if(viewName===void 0&&visibility===void 0&&existingMetadata===void 0)return;let meta={...existingMetadata},existingUi=existingMetadata?.["ui"],existingUiIsObject=typeof existingUi=="object"&&existingUi!==null&&!Array.isArray(existingUi),ui=existingUiIsObject?{...existingUi}:{};if(viewName!==void 0){let resourceUri=viewResourceUri(viewName);ui.resourceUri=resourceUri,meta[UI_RESOURCE_URI_META_KEY]=resourceUri}else delete ui.resourceUri,delete meta[UI_RESOURCE_URI_META_KEY];return visibility!==void 0?ui.visibility=[visibility]:delete ui.visibility,(viewName!==void 0||visibility!==void 0||existingUiIsObject)&&(meta["ui"]=ui),meta}function buildToolResultUiMeta(viewName){let resourceUri=viewResourceUri(viewName);return{ui:{resourceUri},[UI_RESOURCE_URI_META_KEY]:resourceUri}}function resolveCspOptions(options){let request=options?.request,serverOrigin=options?.serverOrigin??(request!==void 0?resolveServerOrigin(request):""),assetsBase=options?.assetsBase??(request!==void 0?resolveAssetsBase(request):serverOrigin);return{serverOrigin,assetsOrigin:originFromAssetsBase(assetsBase),explicitAssetsBase:hasExplicitAssetsBase(),...options?.hmrWs===!0?{hmrWs:!0}:{}}}function buildResourceUiMeta(authorFacts,options){let ui={csp:buildMergedResourceCsp(authorFacts,resolveCspOptions(options))};return authorFacts?.permissions!==void 0&&(ui.permissions=authorFacts.permissions),authorFacts?.domain!==void 0&&(ui.domain=authorFacts.domain),authorFacts?.prefersBorder!==void 0&&(ui.prefersBorder=authorFacts.prefersBorder),{ui}}function viewResourceConfig(_viewName,_entry,authorFacts,options){return{mimeType:UI_MIME_TYPE,...authorFacts?.description!==void 0&&{description:authorFacts.description},_meta:buildResourceUiMeta(authorFacts,options)}}function record(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)?value:void 0}function productId(value,fallback){if(typeof value!="string")return fallback;let normalized=value.trim();return normalized.length>0&&normalized.length<=64&&![...normalized].some(character=>{let code=character.charCodeAt(0);return code<32||code===127})?normalized:fallback}function clientUsageFromBody(body){if(!isJSONRPCRequest2(body))return;let params=record(body.params);if(body.method==="initialize"){let info2=record(params?.clientInfo),capabilities2=record(params?.capabilities)??{};return clientUsage(info2,capabilities2,params?.protocolVersion,"legacy")}let meta=record(params?._meta),info=record(meta?.[CLIENT_INFO_META_KEY3]),capabilities=record(meta?.[CLIENT_CAPABILITIES_META_KEY3]);if(!(info===void 0||capabilities===void 0))return clientUsage(info,capabilities,meta?.[PROTOCOL_VERSION_META_KEY],"modern")}function clientUsage(info,capabilities,protocolVersion,era){let typedCapabilities=capabilities;return{client_name:productId(info?.name,"other"),client_version:productId(info?.version,"unknown"),protocol_era:era,protocol_version:productId(protocolVersion,"unknown"),connection_mode:era==="modern"?"stateless_request":"legacy_session",sampling_capability:Object.hasOwn(capabilities,"sampling"),elicitation_capability:Object.hasOwn(capabilities,"elicitation"),roots_capability:Object.hasOwn(capabilities,"roots"),extensions_capability:Object.hasOwn(capabilities,"extensions"),views_capability:supportsViews(typedCapabilities),capability_count:Object.keys(capabilities).length}}function omitRootSchemaDialect(schema){if(typeof schema!="object"||schema===null||Array.isArray(schema)||!("$schema"in schema))return schema;let emittedSchema={...schema};return delete emittedSchema.$schema,emittedSchema}function omitToolSchemaDialects(tools){return tools.map(tool=>({...tool,inputSchema:omitRootSchemaDialect(tool.inputSchema),...tool.outputSchema===void 0?{}:{outputSchema:omitRootSchemaDialect(tool.outputSchema)}}))}function registerFetchMiddleware(app,middleware){app.use("*",async(context,next)=>{let response=await middleware(context.req.raw,async()=>(await next(),context.res));return context.res=response,response})}var MCPServer=class _MCPServer{#config;#branding;#tools=new Map;#resources=new Map;#resourceTemplates=new Map;#prompts=new Map;#views=new Map;#viewBindings=new Map;#viewsPrimed=!1;#viewsDevMode=!1;#viewsProjectRoot=process.cwd();#fetchHandler;#httpApp;#handler;#eventBus;#httpServer;#oauthResource;#oauthResourceResolved=!1;#oauthResourceConfigurationAbsent=!1;#hostValidated=!1;#mcpMiddlewares=[];#mcpEventListeners=[];#usageScope=crypto.randomUUID();#openApiTools=new Set;#proxiedTools=new Set;#proxiedResources=new Set;#proxiedPrompts=new Set;#httpMiddlewareCount=0;#proxyServersConfigured=0;#proxyServersConnected=0;#proxyToolsDiscovered=0;#proxyResourcesDiscovered=0;#proxyPromptsDiscovered=0;#proxyOwners=[];#proxyOperations=new Set;#closed=!1;app;get;post;put;patch;delete;all;fetch;static fromOpenAPI(options){let server=new _MCPServer({name:options.name??options.spec.info.title,version:options.version??options.spec.info.version??"1.0.0"});registerOpenAPITools(server,options);for(let name of server.#tools.keys())server.#openApiTools.add(name);return server}constructor(config){if(assertServerConfig(config),this.#config=config,this.#branding=normalizeServerBranding(config),this.app=new Hono,this.app.use("*",async(context,next)=>{getRequestBag(context.req.raw).honoContext=context,await next()}),this.get=this.app.get.bind(this.app),this.post=this.app.post.bind(this.app),this.put=this.app.put.bind(this.app),this.patch=this.app.patch.bind(this.app),this.delete=this.app.delete.bind(this.app),this.all=this.app.all.bind(this.app),this.fetch=async(request,env,executionCtx)=>(this.#ensureMounted("handler"),this.#httpApp.fetch(request,env,executionCtx)),config.oauth!==void 0){let mcpUrl=typeof process>"u"?void 0:process.env.MCP_URL,resource2=resolveConfiguredOAuthResource({provider:config.oauth,basePath:this.#basePath(),...mcpUrl!==void 0&&{mcpUrl}});this.#oauthResource=resource2,this.#oauthResourceResolved=resource2!==void 0,this.#oauthResourceConfigurationAbsent=resource2===void 0}}get basePath(){return this.#basePath()}get host(){return this.#config.host}get port(){return this.#config.port}get branding(){return this.#branding}getHandler(){return this.fetch}tool(definition,callback){return this.#assertNotStarted("tool",definition.name),this.#validateToolViewBinding(definition),this.#openApiTools.delete(definition.name),this.#proxiedTools.delete(definition.name),this.#tools.set(definition.name,{definition,callback}),Object.freeze({name:definition.name})}[registerViews](views,options){if(this.#viewsPrimed)throw new Error("Cannot prime views: the views registry is already primed on this server instance.");this.#assertNotStarted("views","manifest"),this.#viewsDevMode=options?.dev===!0,options?.projectRoot!==void 0&&(this.#viewsProjectRoot=options.projectRoot);for(let[name,entry]of Object.entries(views))this.#views.set(name,entry);this.#viewsPrimed=!0}__primeViews(views,options){this[registerViews](views,options)}resource(definition,callback){this.#assertNotStarted("resource",definition.name);let previous=this.#resources.get(definition.name);return previous!==void 0&&this.#proxiedResources.delete(previous.definition.uri),this.#resources.set(definition.name,{definition,callback}),this}resourceTemplate(definition,callback){this.#assertNotStarted("resourceTemplate",definition.name);let complete=definition.complete===void 0?void 0:normalizeCompletions(definition.complete);return this.#resourceTemplates.set(definition.name,{definition,...complete!==void 0&&{complete},callback}),this}prompt(definition,callback){return this.#assertNotStarted("prompt",definition.name),this.#proxiedPrompts.delete(definition.name),this.#prompts.set(definition.name,{definition,callback}),this}async proxy(input){this.#assertOpen("proxy()");let operation=(async()=>{let{isProxyConnection,mountProxyConnection,mountProxyServers}=await import("./mcp-proxy-NETCUGUD.js");if(isProxyConnection(input)){this.#proxyServersConfigured+=1,await mountProxyConnection(this.#proxyHost(),input);return}this.#proxyServersConfigured+=Object.keys(input).length,await mountProxyServers(this.#proxyHost(),input)})();this.#proxyOperations.add(operation);try{await operation}finally{this.#proxyOperations.delete(operation)}}use(patternOrHandler,...handlers){if(typeof patternOrHandler=="string"&&patternOrHandler.startsWith("mcp:")){this.#assertNotStarted("middleware",patternOrHandler);let handler=handlers[0];return this.#mcpMiddlewares.push(createMcpMiddlewareEntry(patternOrHandler,handler)),this}return this.app.use.call(this.app,patternOrHandler,...handlers),this.#httpMiddlewareCount+=typeof patternOrHandler=="function"?1:handlers.length,this}on(pattern,handler){return this.#assertNotStarted("event listener",pattern),this.#mcpEventListeners.push(createMcpEventListenerEntry(pattern,handler)),this}__setEventBus(bus){this.#assertNotStarted("event bus","shared"),this.#eventBus=bus}__mount(){this.#ensureMounted("handler")}async notifyToolsChanged(){await this.#ensureMounted("handler").handler.notify.toolsChanged()}async notifyPromptsChanged(){await this.#ensureMounted("handler").handler.notify.promptsChanged()}async notifyResourcesChanged(){await this.#ensureMounted("handler").handler.notify.resourcesChanged()}async notifyResourceUpdated(uri){await this.#ensureMounted("handler").handler.notify.resourceUpdated(uri)}async listen(port=void 0,options={}){this.#assertOpen("listen()");let{createServer}=await import("http"),{toNodeHandler}=await import("./node-bridge.js"),host=resolveListenHost(options.host,this.#config.host),requestedPort=resolveListenPort(port,this.#config.port);return this.#assertListenOAuthConfiguration(host),new Promise((resolve,reject)=>{let resolveFetch,rejectFetch,fetchReady=new Promise((resolveFetchPromise,rejectFetchPromise)=>{resolveFetch=resolveFetchPromise,rejectFetch=rejectFetchPromise});fetchReady.catch(()=>{});let settled=!1,rejectAndClose=error2=>{settled||(settled=!0,reject(error2)),rejectFetch?.(error2),new Promise(closeResolve=>server.close(()=>closeResolve())).catch(()=>{}).finally(()=>{this.#httpServer===server&&(this.#httpServer=void 0)})},nodeHandler=toNodeHandler({fetch:async request=>(await fetchReady)(request)}),server=createServer((req,res)=>{nodeHandler(req,res)});server.once("error",rejectAndClose),server.listen(requestedPort,host,()=>{try{let address=server.address(),boundPort=typeof address=="object"&&address!==null?address.port:requestedPort,{fetch}=this.#ensureMounted("listen",boundPort,host);resolveFetch?.(fetch),settled||(settled=!0,resolve({port:boundPort,url:`http://localhost:${boundPort}${this.#basePath()}`}))}catch(error2){rejectAndClose(error2)}}),this.#httpServer=server})}async close(){this.#closed=!0,await Promise.allSettled([...this.#proxyOperations]);let errors=[],proxyOwners=this.#proxyOwners.splice(0),ownerResults=await Promise.allSettled(proxyOwners.map(owner=>owner.close()));for(let result of ownerResults)result.status==="rejected"&&errors.push(result.reason);try{await this.#handler?.close()}catch(error2){errors.push(error2)}let httpServer=this.#httpServer;if(httpServer!==void 0)try{await new Promise((resolve,reject)=>{httpServer.close(err=>err?reject(err):resolve())}),this.#httpServer=void 0}catch(error2){errors.push(error2)}if(errors.length>0)throw new AggregateError(errors,"Failed to close MCP server cleanly")}#assertOpen(operation){if(this.#closed)throw operation!==void 0?new Error(`Cannot call ${operation} after the server has closed.`):new Error("Cannot use the server after it has closed.")}#basePath(){return this.#config.basePath??"/mcp"}#resolveOAuthResource(mode,listenPort,listenHost){if(this.#config.oauth===void 0)return;if(this.#oauthResourceResolved)return this.#oauthResource;let host=listenHost??this.#config.host??"127.0.0.1",localListen=mode==="listen"&&listenPort!==void 0&&["127.0.0.1","localhost","::1"].includes(host);if(this.#oauthResourceConfigurationAbsent&&localListen)return this.#oauthResource=resolveLocalOAuthResource(`http://localhost:${listenPort}`,this.#basePath()),this.#oauthResourceResolved=!0,this.#oauthResource;throw new Error("OAuth requires an explicit resource or MCP_URL when using server.fetch or listening on a non-local host")}#assertListenOAuthConfiguration(host){if(this.#config.oauth!==void 0&&!["127.0.0.1","localhost","::1"].includes(host)&&!this.#oauthResourceResolved)throw new Error("OAuth listen() on a public or wildcard host requires an explicit provider resource or valid MCP_URL.")}#assertNotStarted(kind,name){if(this.#handler!==void 0)throw new Error(`Cannot register ${kind} "${name}" after the server has started: registrations are replayed per request from the registry, so register everything before listen()/server.fetch.`)}#trackConfigured(){recordUsage("server","configured",{tools_total:this.#tools.size,tools_local:this.#tools.size-this.#openApiTools.size-this.#proxiedTools.size,tools_openapi:this.#openApiTools.size,tools_proxied:this.#proxiedTools.size,resources:this.#resources.size,resource_templates:this.#resourceTemplates.size,prompts:this.#prompts.size,views:this.#views.size,proxy_servers_configured:this.#proxyServersConfigured,proxy_servers_connected:this.#proxyServersConnected,proxy_tools_discovered:this.#proxyToolsDiscovered,proxy_resources_discovered:this.#proxyResourcesDiscovered,proxy_prompts_discovered:this.#proxyPromptsDiscovered,proxy_tools_mounted:this.#proxiedTools.size,proxy_resources_mounted:this.#proxiedResources.size,proxy_prompts_mounted:this.#proxiedPrompts.size,http_middleware:this.#httpMiddlewareCount,mcp_middleware:this.#mcpMiddlewares.length,observers_before:this.#mcpEventListeners.filter(({phase})=>phase==="before").length,observers_complete:this.#mcpEventListeners.filter(({phase})=>phase==="complete").length,oauth_configured:this.#config.oauth!==void 0,cors_configured:this.#config.cors!==void 0,request_state_configured:this.#config.requestState!==void 0,legacy_policy:this.#config.legacy??"stateless"},{onceKey:`${this.#usageScope}:server`,serverRoot:this.#viewsProjectRoot})}#trackClient(body){let client=clientUsageFromBody(body);client!==void 0&&recordUsage("client","observed",{...client},{onceKey:`${this.#usageScope}:client:${JSON.stringify(client)}`,serverRoot:this.#viewsProjectRoot})}#proxyHost(){return{isStarted:()=>this.#handler!==void 0,hasTool:name=>this.#tools.has(name),hasResource:name=>this.#resources.has(name),hasPrompt:name=>this.#prompts.has(name),registerTool:(definition,callback)=>{this.#assertNotStarted("tool",definition.name),this.#proxiedTools.add(definition.name),this.#tools.set(definition.name,{definition,callback})},registerResource:(definition,callback)=>{this.#assertNotStarted("resource",definition.name),this.#proxiedResources.add(definition.uri),this.#resources.set(definition.name,{definition,callback})},registerPrompt:(definition,callback)=>{this.#assertNotStarted("prompt",definition.name),this.#proxiedPrompts.add(definition.name),this.#prompts.set(definition.name,{definition,callback})},trackOwner:owner=>{this.#proxyOwners.push(owner)},trackNamespace:({tools,resources,prompts})=>{this.#proxyServersConnected+=1,this.#proxyToolsDiscovered+=tools,this.#proxyResourcesDiscovered+=resources,this.#proxyPromptsDiscovered+=prompts}}}#validationPolicy(mode,listenHost){let{allowedHosts,allowedOrigins}=this.#config,host=listenHost??this.#config.host??"127.0.0.1",localhostBind=["127.0.0.1","localhost","::1"].includes(host),hosts=allowedHosts!==void 0?[...new Set([...localhostAllowedHostnames(),...allowedHosts])]:mode==="listen"&&localhostBind?localhostAllowedHostnames():void 0,origins=allowedOrigins!==void 0?[...new Set([...localhostAllowedOrigins(),...allowedOrigins])]:void 0;return{hosts,origins}}#ensureMounted(mode,listenPort,listenHost){if(this.#assertOpen(),this.#fetchHandler===void 0||this.#handler===void 0){let{hosts,origins}=this.#validationPolicy(mode,listenHost),basePath=this.#basePath(),nestedBasePath=basePath==="/"?"":basePath,httpApp=new Hono,middlewares=[jsonBodyMiddleware(),requestLogger(this.#config.logging)],corsConfig=this.#config.cors;corsConfig!==void 0&&middlewares.unshift(corsFetchMiddleware(corsConfig));let deferViewCors=isGlobalCorsEnabled(corsConfig);hosts!==void 0&&middlewares.unshift(hostValidationMiddleware(hosts)),origins!==void 0&&middlewares.push(originValidationMiddleware(origins)),hosts===void 0&&mode==="listen"&&console.warn(`[mcp-use] listen() is serving on ${listenHost} without Host validation. Behind a platform edge that only routes your own domains this is expected; if this process is reachable directly, set allowedHosts to restrict it.`),this.#validateViewBindingsAtMount();let resource2=this.#resolveOAuthResource(mode,listenPort,listenHost);if(resource2!==void 0){let provider=this.#config.oauth;middlewares.push(oauthMetadata(provider,resource2))}for(let middleware of middlewares)registerFetchMiddleware(httpApp,middleware);let{handler,fetch:mcpFetch}=createMcpMount(ctx=>this.#buildSdkServer(ctx),{path:basePath,...(this.#config.legacy!==void 0||this.#eventBus!==void 0)&&{handler:{...this.#config.legacy!==void 0&&{legacy:this.#config.legacy},...this.#eventBus!==void 0&&{bus:this.#eventBus}}},...resource2!==void 0&&{authInfo:request=>authInfoFromRequest(request)}}),protectWithBearer=async(_request,next)=>next();if(resource2!==void 0){let provider=this.#config.oauth,providerOptions=getOAuthProviderOptions(provider),gate=requireBearerAuth({verifier:wrapOAuthTokenVerifier(provider,resource2),resourceMetadataUrl:getOAuthProtectedResourceMetadataUrl(resource2),...providerOptions.requiredScopes!==void 0&&{requiredScopes:providerOptions.requiredScopes}});protectWithBearer=async(request,next)=>{let result=await gate(request);if(result instanceof Response)return result;let bag=getRequestBag(request);return bag.authInfo=result,next()}}let mcpRouteHandler=request=>protectWithBearer(request,()=>{let body=getRequestBag(request).parsedBody;return isJSONRPCRequest2(body)&&(this.#trackConfigured(),this.#trackClient(body)),mcpFetch(request)}),endpointHandler=async request=>{if(!isHtmlNavigationRequest(request))return mcpRouteHandler(request);let respond=async()=>{let{createLandingPageResponse}=await import("./landing-handler-TG6LVQBI.js");return createLandingPageResponse(request,basePath,this.#config,this.#branding,this.#tools.values(),this.#prompts.values(),this.#resources.values())};return resource2!==void 0&&this.#config.publicLandingPage!==!0?protectWithBearer(request,respond):respond()},brandingDevMode=this.#viewsPrimed?this.#viewsDevMode:process.env.NODE_ENV!=="production",faviconHandler=createFaviconHandler(this.#branding,{dev:brandingDevMode,projectRoot:this.#viewsProjectRoot,deferCors:deferViewCors});faviconHandler!==void 0&&this.app.all("/favicon.ico",context=>faviconHandler(context.req.raw));let viewHandler=createViewPublicHandler(basePath,this.#views,{dev:this.#viewsPrimed?this.#viewsDevMode:brandingDevMode,projectRoot:this.#viewsProjectRoot,enabled:hasLocalBrandingAsset(this.#branding),deferCors:deferViewCors});if(viewHandler!==void 0&&this.app.on(["GET","HEAD"],`${nestedBasePath}/_mcp-use/public/*`,context=>viewHandler(context.req.raw)),!this.#viewsDevMode){let viewAssetsHandler=createViewAssetsHandler(basePath,this.#views,{projectRoot:this.#viewsProjectRoot,deferCors:deferViewCors});viewAssetsHandler!==void 0&&this.app.on(["GET","HEAD"],`${nestedBasePath}/_mcp-use/views/*`,context=>viewAssetsHandler(context.req.raw))}this.app.all(basePath,context=>endpointHandler(context.req.raw)),httpApp.route("/",this.app),this.#httpApp=httpApp,this.#fetchHandler=async request=>httpApp.fetch(request),this.#handler=handler,this.#hostValidated=hosts!==void 0}else if(mode==="listen"&&!this.#hostValidated&&this.#validationPolicy("listen",listenHost).hosts!==void 0)throw new Error("Cannot listen() on a localhost bind after server.fetch mounted the app without Host validation (server.fetch expects a platform edge in front). Call listen() first, or set allowedHosts.");return{fetch:this.#fetchHandler,handler:this.#handler}}#validateToolViewBinding(definition){let view=definition.view;if(view===void 0)return;if(definition.outputSchema===void 0)throw new Error(`Tool "${definition.name}" declares view "${view.name}" but has no outputSchema. View-bound tools require an outputSchema \u2014 the view reads structuredContent typed from it. Use outputSchema: z.object({}) for a view that takes no structured output.`);let existing=this.#viewBindings.get(view.name);if(existing!==void 0)throw new Error(`View "${view.name}" is already bound to tool "${existing.toolName}"; tool "${definition.name}" cannot bind the same view. Each view may be bound to one tool.`);this.#viewBindings.set(view.name,{toolName:definition.name,config:view})}#validateViewBindingsAtMount(){if(this.#viewBindings.size>0&&!this.#viewsPrimed){let first=[...this.#tools.values()].find(entry=>entry.definition.view!==void 0),viewName=first?.definition.view?.name??"unknown";throw new Error(`Tool "${first?.definition.name??"unknown"}" is bound to view "${viewName}" but no views were primed. Run \`mcp-use build\` and deploy the built entry, or in dev let the CLI prime views automatically.`)}for(let entry of this.#tools.values()){let viewName=entry.definition.view?.name;if(viewName!==void 0&&!this.#views.has(viewName))throw new Error(`Tool "${entry.definition.name}" is bound to view "${viewName}" which is not in the primed views registry. Run \`mcp-use build\` and deploy the built entry, or in dev let the CLI prime views automatically.`)}for(let viewName of this.#views.keys())this.#viewBindings.has(viewName)||console.warn(`[mcp-use] View "${viewName}" is registered but no tool binds it.`)}#buildSdkServer(ctx){let{name,version,title,description,instructions}=this.#config,authInfo=ctx.authInfo,server=new SdkMcpServer({name,version,...title!==void 0&&{title},...description!==void 0&&{description},...this.#branding.websiteUrl!==void 0&&{websiteUrl:this.#branding.websiteUrl},...this.#branding.icons!==void 0&&{icons:resolveImplementationIcons(this.#branding.icons,ctx.requestInfo,this.#basePath())}},{capabilities:{logging:{},tools:{listChanged:!0},prompts:{listChanged:!0},resources:{listChanged:!0,subscribe:!0}},...instructions!==void 0&&{instructions},...authInfo!==void 0&&{authInfo},...this.#config.requestState!==void 0&&{requestState:this.#config.requestState}}),request=ctx.requestInfo,viewMetaOptions=request!==void 0?{request,hmrWs:this.#viewsDevMode}:{hmrWs:this.#viewsDevMode},basePath=this.#basePath();for(let entry of this.#tools.values())this.#registerTool(server,entry);for(let entry of this.#resources.values())this.#registerResource(server,entry);for(let entry of this.#resourceTemplates.values())this.#registerResourceTemplate(server,entry);for(let entry of this.#prompts.values())this.#registerPrompt(server,entry);for(let[viewName,viewEntry]of this.#views.entries())this.#registerViewResource(server,viewName,viewEntry,viewMetaOptions,basePath);return this.#wrapListHandlers(server),server}#createMiddlewareContext(method,params,ctx){let requestContext=toRequestContext(ctx);return Object.assign(requestContext,{method,params,...ctx.sessionId!==void 0&&{session:{sessionId:ctx.sessionId}},...ctx.http?.authInfo!==void 0&&{auth:ctx.http.authInfo},state:new Map})}#runMcpHook(method,ctx,innerFn){let startedAt=performance.now(),matchedMiddleware=this.#mcpMiddlewares.filter(entry=>matchesPattern(entry.pattern,method)).length,matchedObservers=phase=>this.#mcpEventListeners.filter(entry=>entry.phase===phase&&matchesPattern(entry.pattern,method)).length,request=ctx.request?.raw,client=request===void 0?void 0:clientUsageFromBody(getRequestBag(request).parsedBody),capture=(outcome,completedPhase)=>{recordUsage("operation","completed",{method,outcome,duration_ms:Math.max(0,Math.round(performance.now()-startedAt)),primitive_origin:this.#primitiveOrigin(method,ctx.params),matched_middleware:matchedMiddleware,observers_before:matchedObservers("before"),observers_complete:completedPhase?matchedObservers("complete"):0,...client?.protocol_era==="modern"?client:{client_name:"unknown",protocol_era:"legacy"}},{sampleRate:outcome==="success"?.1:1,serverRoot:this.#viewsProjectRoot})};return runMcpOperation(this.#mcpMiddlewares,this.#mcpEventListeners,method,ctx,innerFn).then(result=>{let outcome=isInputRequiredResult2(result)?"input_required":method==="tools/call"&&typeof result=="object"&&result!==null&&"isError"in result&&result.isError===!0?"error":"success";return capture(outcome,!0),result},error2=>{throw capture("error",!1),error2})}#primitiveOrigin(method,params){if(method==="tools/call"){let name=String(params.name);return this.#proxiedTools.has(name)?"proxied":this.#openApiTools.has(name)?"openapi":"local"}return method==="resources/read"?this.#proxiedResources.has(String(params.uri))?"proxied":"local":method==="prompts/get"?this.#proxiedPrompts.has(String(params.name))?"proxied":"local":"mixed"}#wrapListHandlers(server){let handlers=server.server._requestHandlers;if(handlers===void 0)return;let wrapListMethod=(method,resultKey,transform)=>{let original=handlers.get(method);if(original===void 0||original.__mcpListWrapped)return;let wrapped=async(request,extra)=>{let serverContext=extra,params=request.params??{},mwCtx=this.#createMiddlewareContext(method,params,serverContext),originalEnvelope,innerFn=async()=>{let downstreamRequest=withMcpMiddlewareParams(request,mwCtx.params),result=await original(downstreamRequest,extra);if(typeof result!="object"||result===null)throw new TypeError(`[mcp-use] ${method} handler returned a non-object result`);originalEnvelope=result;let items=originalEnvelope[resultKey];if(!Array.isArray(items))throw new TypeError(`[mcp-use] ${method} handler result is missing a ${resultKey} array`);return items},filtered=await this.#runMcpHook(method,mwCtx,innerFn);if(!Array.isArray(filtered))throw new TypeError(`[mcp-use] ${method} middleware must return a ${resultKey} array`);let emitted=transform?.(filtered)??filtered;return{...originalEnvelope,[resultKey]:emitted}};wrapped.__mcpListWrapped=!0,handlers.set(method,wrapped)};wrapListMethod("tools/list","tools",omitToolSchemaDialects),wrapListMethod("resources/list","resources"),wrapListMethod("prompts/list","prompts")}#registerTool(server,{definition,callback}){let view=definition.view,toolMeta=buildToolUiMeta(view?.name,definition.visibility,definition._meta),config={...definition.title!==void 0&&{title:definition.title},...definition.description!==void 0&&{description:definition.description},...definition.annotations!==void 0&&{annotations:definition.annotations},...definition.outputSchema!==void 0&&{outputSchema:definition.outputSchema},...toolMeta!==void 0&&{_meta:toolMeta}},wireResultMeta=view!==void 0?buildToolResultUiMeta(view.name):void 0,inputSchema=resolveToolInputSchema(definition),invokeTool=async(args,ctx)=>{let mwCtx=this.#createMiddlewareContext("tools/call",{name:definition.name,arguments:args,...ctx.mcpReq._meta!==void 0&&{_meta:ctx.mcpReq._meta}},ctx),innerFn=async()=>{let effectiveArgs=mwCtx.params.arguments??{},result=await callback(effectiveArgs,this.#toRequestContext(ctx));return isInputRequiredResult2(result)||wireResultMeta===void 0||result.isError===!0?result:{...result,_meta:{...result._meta,...wireResultMeta}}};return await this.#runMcpHook("tools/call",mwCtx,innerFn)};inputSchema!==void 0?server.registerTool(definition.name,{...config,inputSchema},async(args,ctx)=>invokeTool(args,ctx)):server.registerTool(definition.name,config,async ctx=>invokeTool({},ctx))}#registerViewResource(server,viewName,entry,metaOptions,basePath){let uri=viewResourceUri(viewName),authorFacts=this.#viewResourceFacts(this.#viewBindings.get(viewName)?.config),resourceConfig=viewResourceConfig(viewName,entry,authorFacts,metaOptions);server.registerResource(viewName,uri,resourceConfig,async(readUri,ctx)=>{let req=ctx.http?.req,readOptions=req!==void 0?{request:req,...metaOptions.hmrWs===!0?{hmrWs:!0}:{}}:metaOptions.hmrWs===!0?{hmrWs:!0}:{},assetsBase=req!==void 0?resolveAssetsBase(req):metaOptions.request!==void 0?resolveAssetsBase(metaOptions.request):"",html2=synthesizeViewDocument(entry,assetsBase,basePath,viewName);return{contents:[{uri:readUri.href,mimeType:resourceConfig.mimeType,text:html2,_meta:buildResourceUiMeta(authorFacts,readOptions)}]}})}#registerResource(server,{definition,callback}){server.registerResource(definition.name,definition.uri,{...definition.title!==void 0&&{title:definition.title},...definition.description!==void 0&&{description:definition.description},...definition.mimeType!==void 0&&{mimeType:definition.mimeType},...definition.annotations!==void 0&&{annotations:definition.annotations},...definition._meta!==void 0&&{_meta:{...definition._meta}}},async(uri,ctx)=>{let mwCtx=this.#createMiddlewareContext("resources/read",{uri:uri.href,...ctx.mcpReq._meta!==void 0&&{_meta:ctx.mcpReq._meta}},ctx),innerFn=async()=>toResourceResult(await callback(uri,this.#toRequestContext(ctx)),uri.href);return await this.#runMcpHook("resources/read",mwCtx,innerFn)})}#registerResourceTemplate(server,{definition,callback,complete}){let template=new ResourceTemplate(definition.uriTemplate,{list:void 0,...complete!==void 0&&{complete}});server.registerResource(definition.name,template,{...definition.title!==void 0&&{title:definition.title},...definition.description!==void 0&&{description:definition.description},...definition.mimeType!==void 0&&{mimeType:definition.mimeType},...definition.annotations!==void 0&&{annotations:definition.annotations},...definition._meta!==void 0&&{_meta:{...definition._meta}}},async(uri,variables,ctx)=>{let mwCtx=this.#createMiddlewareContext("resources/read",{uri:uri.href,...ctx.mcpReq._meta!==void 0&&{_meta:ctx.mcpReq._meta}},ctx),innerFn=async()=>toResourceResult(await callback(uri,variables,this.#toRequestContext(ctx)),uri.href);return await this.#runMcpHook("resources/read",mwCtx,innerFn)})}#viewResourceFacts(viewConfig){if(viewConfig!==void 0)return{...viewConfig.description!==void 0&&{description:viewConfig.description},...viewConfig.csp!==void 0&&{csp:viewConfig.csp},...viewConfig.permissions!==void 0&&{permissions:viewConfig.permissions},...viewConfig.domain!==void 0&&{domain:viewConfig.domain},...viewConfig.prefersBorder!==void 0&&{prefersBorder:viewConfig.prefersBorder}}}#registerPrompt(server,{definition,callback}){let config={...definition.title!==void 0&&{title:definition.title},...definition.description!==void 0&&{description:definition.description}},invokePrompt=async(args,ctx)=>{let mwCtx=this.#createMiddlewareContext("prompts/get",{name:definition.name,arguments:args,...ctx.mcpReq._meta!==void 0&&{_meta:ctx.mcpReq._meta}},ctx),innerFn=async()=>{let effectiveArgs=mwCtx.params.arguments??{};return toPromptResult(await callback(effectiveArgs,this.#toRequestContext(ctx)))};return await this.#runMcpHook("prompts/get",mwCtx,innerFn)};if(definition.schema!==void 0)server.registerPrompt(definition.name,{...config,argsSchema:definition.schema},async(args,ctx)=>invokePrompt(args,ctx));else{let handler=async ctx=>invokePrompt({},ctx);server.registerPrompt(definition.name,config,handler)}}#toRequestContext(ctx){return this.#config.oauth===void 0?toRequestContext(ctx):toAuthenticatedRequestContext(ctx)}};import{acceptedContent,createRequestStateCodec,inputRequired as inputRequired2,inputResponse as inputResponse2,isInputRequiredResult as isInputRequiredResult3}from"@modelcontextprotocol/server";function text(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/plain"}}}function markdown(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/markdown"}}}function html(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/html"}}}function xml(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/xml"}}}function css(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/css"}}}function javascript(content){return{content:[{type:"text",text:content}],_meta:{mimeType:"text/javascript"}}}function image(data,mimeType="image/png"){return{content:[{type:"image",data,mimeType}],_meta:{mimeType,isImage:!0}}}function audio(data,mimeType="audio/wav"){return{content:[{type:"audio",data,mimeType}],_meta:{mimeType,isAudio:!0}}}function binary(base64Data,mimeType){return{content:[{type:"text",text:base64Data}],_meta:{mimeType,isBinary:!0}}}function resource(uri,mimeTypeOrContent,text2){if(typeof mimeTypeOrContent=="object"&&mimeTypeOrContent!==null&&"content"in mimeTypeOrContent){let contentResult=mimeTypeOrContent,extractedText,extractedMimeType;if(contentResult._meta&&typeof contentResult._meta=="object"){let meta=contentResult._meta;typeof meta.mimeType=="string"&&(extractedMimeType=meta.mimeType)}let first=contentResult.content?.[0];return first?.type==="text"&&"text"in first&&(extractedText=first.text),{content:[{type:"resource",resource:{uri,...extractedMimeType!==void 0&&{mimeType:extractedMimeType},text:extractedText??""}}]}}let mimeType=mimeTypeOrContent;return{content:[{type:"resource",resource:{uri,...mimeType!==void 0&&mimeType!==""&&{mimeType},text:text2??""}}]}}function error(message){return{isError:!0,content:[{type:"text",text:message}]}}function object(data){return Array.isArray(data)?array(data):{content:[{type:"text",text:JSON.stringify(data,null,2)}],structuredContent:data,_meta:{mimeType:"application/json"}}}function array(data){return{content:[{type:"text",text:JSON.stringify(data,null,2)}],structuredContent:data}}function widget(config){let props=config.props??config.data??{},{output,message,metadata}=config,result={content:message?[{type:"text",text:message}]:Array.isArray(output?.content)&&output.content.length>0?output.content:[{type:"text",text:""}]};return metadata!==void 0&&Object.keys(metadata).length>0&&(result._meta=metadata),output?.structuredContent!==void 0?result.structuredContent=output.structuredContent:Object.keys(props).length>0&&(result.structuredContent=props),result}function mix(...results){let withStructured=results.filter(result=>result.structuredContent!==void 0),structuredContent=withStructured.length>0?withStructured.map(result=>result.structuredContent).reduce((acc,value)=>({...acc,...typeof value=="object"&&value!==null?value:{}}),{}):void 0,withMeta=results.filter(result=>result._meta!==void 0),_meta=withMeta.length>0?withMeta.map(result=>result._meta).reduce((acc,value)=>({...acc,...value!==void 0?value:{}}),{}):void 0;return{content:results.flatMap(result=>result.content),...structuredContent!==void 0&&Object.keys(structuredContent).length>0&&{structuredContent},..._meta!==void 0&&Object.keys(_meta).length>0&&{_meta}}}export{MCPServer,acceptedContent,array,audio,binary,completable,composeFetch,composeMiddleware,createMcpEventListenerEntry,createMcpMiddlewareEntry,createMcpMount,createRequestStateCodec,css,error,getRequestBag,hostValidationMiddleware,html,image,inputRequired2 as inputRequired,inputResponse2 as inputResponse,isInputRequiredResult3 as isInputRequiredResult,javascript,jsonBodyMiddleware,markdown,matchesPath,matchesPathPrefix,matchesPattern,mix,object,originValidationMiddleware,pathnameOf,registerViews,requestLogger,resource,text,widget,xml};