mcp-use 2.0.0-beta.28 → 2.0.0-beta.30
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.
- package/dist/{chunk-26JBVQUY.js → chunk-QKJJ6DWK.js} +0 -18
- package/dist/config.d.ts +5 -5
- package/dist/context.d.ts +14 -7
- package/dist/fetch-app.d.ts +3 -27
- package/dist/index.d.ts +21 -8
- package/dist/index.js +478 -190
- package/dist/{mcp-proxy-QYZQ6LNV.js → mcp-proxy-JK7IC5CR.js} +2 -2
- package/dist/middleware/mcp-middleware.d.ts +32 -27
- package/dist/next/index.js +1 -1
- package/dist/oauth/index.js +1 -1
- package/dist/prompts.d.ts +7 -3
- package/dist/react/hooks/use-call-tool.d.ts +29 -11
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +7 -0
- package/dist/react/types/register.d.ts +10 -2
- package/dist/resources.d.ts +14 -5
- package/dist/response-conversion.d.ts +25 -0
- package/dist/response-helpers.d.ts +223 -0
- package/dist/server.d.ts +62 -68
- package/dist/tools.d.ts +5 -4
- package/dist/views/routes.d.ts +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -29,10 +29,8 @@ import {
|
|
|
29
29
|
originValidationMiddleware,
|
|
30
30
|
pathUnderBase,
|
|
31
31
|
pathnameOf,
|
|
32
|
-
requireBearerAuth
|
|
33
|
-
|
|
34
|
-
toFrameworkHandler
|
|
35
|
-
} from "./chunk-26JBVQUY.js";
|
|
32
|
+
requireBearerAuth
|
|
33
|
+
} from "./chunk-QKJJ6DWK.js";
|
|
36
34
|
import {
|
|
37
35
|
getOAuthProviderOptions,
|
|
38
36
|
resolveConfiguredOAuthResource,
|
|
@@ -48,6 +46,7 @@ import {
|
|
|
48
46
|
ResourceTemplate,
|
|
49
47
|
isInputRequiredResult as isInputRequiredResult2
|
|
50
48
|
} from "@modelcontextprotocol/server";
|
|
49
|
+
import { Hono } from "hono";
|
|
51
50
|
|
|
52
51
|
// src/branding.ts
|
|
53
52
|
var FAVICON_CACHE_CONTROL = "public, max-age=31536000, immutable";
|
|
@@ -87,10 +86,10 @@ function parseDataImage(source, field) {
|
|
|
87
86
|
}
|
|
88
87
|
try {
|
|
89
88
|
if (parts.includes("base64")) {
|
|
90
|
-
const
|
|
89
|
+
const binary2 = atob(payload);
|
|
91
90
|
return {
|
|
92
91
|
mimeType,
|
|
93
|
-
bytes: Uint8Array.from(
|
|
92
|
+
bytes: Uint8Array.from(binary2, (character) => character.charCodeAt(0))
|
|
94
93
|
};
|
|
95
94
|
}
|
|
96
95
|
return {
|
|
@@ -323,6 +322,7 @@ import {
|
|
|
323
322
|
inputRequired,
|
|
324
323
|
inputResponse
|
|
325
324
|
} from "@modelcontextprotocol/server";
|
|
325
|
+
import { HonoRequest } from "hono/request";
|
|
326
326
|
|
|
327
327
|
// src/views/capabilities.ts
|
|
328
328
|
import {
|
|
@@ -436,8 +436,10 @@ function createElicit(inputResponses) {
|
|
|
436
436
|
};
|
|
437
437
|
}
|
|
438
438
|
function toRequestContext(ctx) {
|
|
439
|
-
const
|
|
440
|
-
|
|
439
|
+
const rawRequest = ctx.http?.req;
|
|
440
|
+
const http = rawRequest === void 0 ? void 0 : getRequestBag(rawRequest).honoContext;
|
|
441
|
+
const request = http?.req ?? (rawRequest === void 0 ? void 0 : new HonoRequest(rawRequest));
|
|
442
|
+
const additions = {
|
|
441
443
|
signal: ctx.mcpReq.signal,
|
|
442
444
|
...request !== void 0 && { request },
|
|
443
445
|
...ctx.mcpReq.inputResponses !== void 0 && {
|
|
@@ -471,12 +473,18 @@ function toRequestContext(ctx) {
|
|
|
471
473
|
});
|
|
472
474
|
}
|
|
473
475
|
};
|
|
476
|
+
if (http !== void 0) {
|
|
477
|
+
return Object.assign(http, additions);
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
...additions,
|
|
481
|
+
...request !== void 0 && { req: request }
|
|
482
|
+
};
|
|
474
483
|
}
|
|
475
484
|
function toAuthenticatedRequestContext(ctx) {
|
|
476
485
|
const authInfo = ctx.http?.authInfo;
|
|
477
486
|
requireOAuthAuthInfo(authInfo);
|
|
478
|
-
return {
|
|
479
|
-
...toRequestContext(ctx),
|
|
487
|
+
return Object.assign(toRequestContext(ctx), {
|
|
480
488
|
auth: {
|
|
481
489
|
user: authInfo.extra.user,
|
|
482
490
|
payload: authInfo.extra.payload,
|
|
@@ -487,7 +495,84 @@ function toAuthenticatedRequestContext(ctx) {
|
|
|
487
495
|
expiresAt: authInfo.expiresAt,
|
|
488
496
|
...authInfo.resource !== void 0 && { resource: authInfo.resource }
|
|
489
497
|
}
|
|
490
|
-
};
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/response-conversion.ts
|
|
502
|
+
function isReadResourceResult(result) {
|
|
503
|
+
return "contents" in result && Array.isArray(result.contents);
|
|
504
|
+
}
|
|
505
|
+
function isGetPromptResult(result) {
|
|
506
|
+
return "messages" in result && Array.isArray(result.messages);
|
|
507
|
+
}
|
|
508
|
+
function toResourceResult(result, uri) {
|
|
509
|
+
if (isReadResourceResult(result)) {
|
|
510
|
+
return result;
|
|
511
|
+
}
|
|
512
|
+
const mime = result._meta && typeof result._meta === "object" && typeof result._meta.mimeType === "string" ? result._meta.mimeType : void 0;
|
|
513
|
+
const contents = [];
|
|
514
|
+
for (const block of result.content ?? []) {
|
|
515
|
+
const mapped = contentBlockToResourceContents(block, uri, mime);
|
|
516
|
+
if (mapped !== void 0) {
|
|
517
|
+
contents.push(mapped);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
if (contents.length === 0 && result.structuredContent !== void 0) {
|
|
521
|
+
contents.push({
|
|
522
|
+
uri,
|
|
523
|
+
mimeType: "application/json",
|
|
524
|
+
text: JSON.stringify(result.structuredContent)
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
if (contents.length === 0) {
|
|
528
|
+
contents.push({ uri, mimeType: "text/plain", text: "" });
|
|
529
|
+
}
|
|
530
|
+
return { contents };
|
|
531
|
+
}
|
|
532
|
+
function contentBlockToResourceContents(block, uri, mimeHint) {
|
|
533
|
+
if (block.type === "text") {
|
|
534
|
+
return {
|
|
535
|
+
uri,
|
|
536
|
+
mimeType: mimeHint ?? "text/plain",
|
|
537
|
+
text: block.text
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
if (block.type === "image" || block.type === "audio") {
|
|
541
|
+
return {
|
|
542
|
+
uri,
|
|
543
|
+
mimeType: block.mimeType,
|
|
544
|
+
blob: block.data
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
if (block.type === "resource") {
|
|
548
|
+
return { ...block.resource };
|
|
549
|
+
}
|
|
550
|
+
return void 0;
|
|
551
|
+
}
|
|
552
|
+
function toPromptResult(result) {
|
|
553
|
+
if (isGetPromptResult(result)) {
|
|
554
|
+
return result;
|
|
555
|
+
}
|
|
556
|
+
const messages = (result.content ?? []).map((content) => ({
|
|
557
|
+
role: "user",
|
|
558
|
+
content
|
|
559
|
+
}));
|
|
560
|
+
if (messages.length === 0 && result.structuredContent !== void 0) {
|
|
561
|
+
messages.push({
|
|
562
|
+
role: "user",
|
|
563
|
+
content: {
|
|
564
|
+
type: "text",
|
|
565
|
+
text: JSON.stringify(result.structuredContent)
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
if (messages.length === 0) {
|
|
570
|
+
messages.push({
|
|
571
|
+
role: "user",
|
|
572
|
+
content: { type: "text", text: "" }
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
return { messages };
|
|
491
576
|
}
|
|
492
577
|
|
|
493
578
|
// src/middleware/cors.ts
|
|
@@ -677,7 +762,10 @@ function composeMiddleware(entries, method, innerFn) {
|
|
|
677
762
|
return innerFn();
|
|
678
763
|
}
|
|
679
764
|
const entry = matching[i];
|
|
680
|
-
return entry.handler(
|
|
765
|
+
return entry.handler(
|
|
766
|
+
ctx,
|
|
767
|
+
() => dispatch(i + 1)
|
|
768
|
+
);
|
|
681
769
|
};
|
|
682
770
|
return dispatch(0);
|
|
683
771
|
};
|
|
@@ -687,6 +775,7 @@ function freezeMiddlewareContext(ctx) {
|
|
|
687
775
|
method: ctx.method,
|
|
688
776
|
params: Object.freeze({ ...ctx.params }),
|
|
689
777
|
...ctx.request !== void 0 && { request: ctx.request },
|
|
778
|
+
...ctx.req !== void 0 && { req: ctx.req },
|
|
690
779
|
...ctx.session !== void 0 && {
|
|
691
780
|
session: Object.freeze({ ...ctx.session })
|
|
692
781
|
},
|
|
@@ -758,10 +847,10 @@ function dispatchMcpEvents(events, method, phase, ctx, result) {
|
|
|
758
847
|
}
|
|
759
848
|
try {
|
|
760
849
|
entry.handler(frozen, result);
|
|
761
|
-
} catch (
|
|
850
|
+
} catch (error2) {
|
|
762
851
|
console.error(
|
|
763
852
|
`[mcp-use] MCP event listener for "${entry.pattern}" (${phase}) threw:`,
|
|
764
|
-
|
|
853
|
+
error2
|
|
765
854
|
);
|
|
766
855
|
}
|
|
767
856
|
}
|
|
@@ -791,7 +880,7 @@ function colorsEnabled() {
|
|
|
791
880
|
return process.stdout?.isTTY === true;
|
|
792
881
|
}
|
|
793
882
|
function ansi(open, close) {
|
|
794
|
-
return (
|
|
883
|
+
return (text2) => colorsEnabled() ? `\x1B[${open}m${text2}\x1B[${close}m` : text2;
|
|
795
884
|
}
|
|
796
885
|
var bold = ansi(1, 22);
|
|
797
886
|
var dim = ansi(2, 22);
|
|
@@ -849,13 +938,13 @@ function formatDetail(message) {
|
|
|
849
938
|
}
|
|
850
939
|
var INLINE_JSON_MAX_LENGTH = 80;
|
|
851
940
|
function inlineJson(value) {
|
|
852
|
-
let
|
|
941
|
+
let text2;
|
|
853
942
|
try {
|
|
854
|
-
|
|
943
|
+
text2 = JSON.stringify(value) ?? String(value);
|
|
855
944
|
} catch {
|
|
856
|
-
|
|
945
|
+
text2 = String(value);
|
|
857
946
|
}
|
|
858
|
-
return
|
|
947
|
+
return text2.length > INLINE_JSON_MAX_LENGTH ? `${text2.slice(0, INLINE_JSON_MAX_LENGTH)}...` : text2;
|
|
859
948
|
}
|
|
860
949
|
function formatClientIdentity(message) {
|
|
861
950
|
const meta = message.params?._meta;
|
|
@@ -866,8 +955,8 @@ function formatClientIdentity(message) {
|
|
|
866
955
|
}
|
|
867
956
|
return formatClientInfo(info);
|
|
868
957
|
}
|
|
869
|
-
function sanitize(
|
|
870
|
-
return
|
|
958
|
+
function sanitize(text2) {
|
|
959
|
+
return text2.replace(/[\u0000-\u001F\u007F-\u009F]+/g, " ");
|
|
871
960
|
}
|
|
872
961
|
function methodStyle(method) {
|
|
873
962
|
if (method.startsWith("tools/")) return cyan;
|
|
@@ -893,13 +982,13 @@ function redactHeaders(headers) {
|
|
|
893
982
|
}
|
|
894
983
|
async function extractResponseOutcome(res) {
|
|
895
984
|
if (!res.body) return { errorMessage: null };
|
|
896
|
-
let
|
|
985
|
+
let text2;
|
|
897
986
|
try {
|
|
898
|
-
|
|
987
|
+
text2 = await res.clone().text();
|
|
899
988
|
} catch {
|
|
900
989
|
return { errorMessage: null };
|
|
901
990
|
}
|
|
902
|
-
if (!
|
|
991
|
+
if (!text2) return { errorMessage: null };
|
|
903
992
|
const isSse = (res.headers.get("content-type") ?? "").includes(
|
|
904
993
|
"text/event-stream"
|
|
905
994
|
);
|
|
@@ -911,14 +1000,14 @@ async function extractResponseOutcome(res) {
|
|
|
911
1000
|
}
|
|
912
1001
|
};
|
|
913
1002
|
if (isSse) {
|
|
914
|
-
for (const line of
|
|
1003
|
+
for (const line of text2.split(/\r?\n/)) {
|
|
915
1004
|
if (line.startsWith("data:")) {
|
|
916
1005
|
const data = line.slice(5).trim();
|
|
917
1006
|
if (data) tryParse(data);
|
|
918
1007
|
}
|
|
919
1008
|
}
|
|
920
1009
|
} else {
|
|
921
|
-
tryParse(
|
|
1010
|
+
tryParse(text2);
|
|
922
1011
|
}
|
|
923
1012
|
let result;
|
|
924
1013
|
for (const payload of payloads) {
|
|
@@ -1002,17 +1091,17 @@ ${cyan("=".repeat(80))}`);
|
|
|
1002
1091
|
console.log(`${yellow("Response Body:")} (no body)`);
|
|
1003
1092
|
} else {
|
|
1004
1093
|
try {
|
|
1005
|
-
const
|
|
1006
|
-
if (
|
|
1094
|
+
const text2 = await response.clone().text();
|
|
1095
|
+
if (text2.length === 0) {
|
|
1007
1096
|
console.log(`${yellow("Response Body:")} (empty)`);
|
|
1008
1097
|
} else {
|
|
1009
1098
|
console.log(yellow("Response Body:"));
|
|
1010
1099
|
try {
|
|
1011
|
-
console.log(formatForDump(JSON.parse(
|
|
1100
|
+
console.log(formatForDump(JSON.parse(text2)));
|
|
1012
1101
|
} catch {
|
|
1013
1102
|
console.log(
|
|
1014
|
-
|
|
1015
|
-
... (truncated, ${
|
|
1103
|
+
text2.length > DUMP_BODY_MAX_LENGTH ? `${text2.slice(0, DUMP_BODY_MAX_LENGTH)}
|
|
1104
|
+
... (truncated, ${text2.length - DUMP_BODY_MAX_LENGTH} more characters)` : text2
|
|
1016
1105
|
);
|
|
1017
1106
|
}
|
|
1018
1107
|
}
|
|
@@ -1024,11 +1113,11 @@ ${cyan("=".repeat(80))}`);
|
|
|
1024
1113
|
`);
|
|
1025
1114
|
}
|
|
1026
1115
|
function styleStatus(status) {
|
|
1027
|
-
const
|
|
1028
|
-
if (status >= 500) return magenta(
|
|
1029
|
-
if (status >= 400) return red(
|
|
1030
|
-
if (status >= 300) return yellow(
|
|
1031
|
-
return green(
|
|
1116
|
+
const text2 = String(status);
|
|
1117
|
+
if (status >= 500) return magenta(text2);
|
|
1118
|
+
if (status >= 400) return red(text2);
|
|
1119
|
+
if (status >= 300) return yellow(text2);
|
|
1120
|
+
return green(text2);
|
|
1032
1121
|
}
|
|
1033
1122
|
function isNoisyRequest(httpMethod, pathname) {
|
|
1034
1123
|
if (httpMethod !== "GET" && httpMethod !== "HEAD") return false;
|
|
@@ -1198,8 +1287,8 @@ function resolvePublicBase(assetsBase, basePath) {
|
|
|
1198
1287
|
function escapeInlineScript(code) {
|
|
1199
1288
|
return code.replaceAll(/<\/script/gi, "<\\/script").replaceAll("<!--", "\\x3C!--");
|
|
1200
1289
|
}
|
|
1201
|
-
function escapeInlineStyle(
|
|
1202
|
-
return
|
|
1290
|
+
function escapeInlineStyle(css2) {
|
|
1291
|
+
return css2.replaceAll(/<\/style/gi, "<\\/style");
|
|
1203
1292
|
}
|
|
1204
1293
|
function escapeHtml(value) {
|
|
1205
1294
|
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -1520,6 +1609,16 @@ function omitToolSchemaDialects(tools) {
|
|
|
1520
1609
|
...tool.outputSchema === void 0 ? {} : { outputSchema: omitRootSchemaDialect(tool.outputSchema) }
|
|
1521
1610
|
}));
|
|
1522
1611
|
}
|
|
1612
|
+
function registerFetchMiddleware(app, middleware) {
|
|
1613
|
+
app.use("*", async (context, next) => {
|
|
1614
|
+
const response = await middleware(context.req.raw, async () => {
|
|
1615
|
+
await next();
|
|
1616
|
+
return context.res;
|
|
1617
|
+
});
|
|
1618
|
+
context.res = response;
|
|
1619
|
+
return response;
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1523
1622
|
var MCPServer = class _MCPServer {
|
|
1524
1623
|
#config;
|
|
1525
1624
|
#branding;
|
|
@@ -1540,7 +1639,9 @@ var MCPServer = class _MCPServer {
|
|
|
1540
1639
|
/** Project root for filesystem-backed view bundle and public routes. */
|
|
1541
1640
|
#viewsProjectRoot = process.cwd();
|
|
1542
1641
|
#fetchHandler;
|
|
1642
|
+
#httpApp;
|
|
1543
1643
|
#handler;
|
|
1644
|
+
#eventBus;
|
|
1544
1645
|
#httpServer;
|
|
1545
1646
|
#oauthResource;
|
|
1546
1647
|
#oauthResourceResolved = false;
|
|
@@ -1555,6 +1656,30 @@ var MCPServer = class _MCPServer {
|
|
|
1555
1656
|
#proxyOperations = /* @__PURE__ */ new Set();
|
|
1556
1657
|
/** Whether terminal shutdown has begun. */
|
|
1557
1658
|
#closed = false;
|
|
1659
|
+
/** Hono application that owns HTTP middleware and routes. */
|
|
1660
|
+
app;
|
|
1661
|
+
/** Register a typed `GET` route on {@link MCPServer.app}. */
|
|
1662
|
+
get;
|
|
1663
|
+
/** Register a typed `POST` route on {@link MCPServer.app}. */
|
|
1664
|
+
post;
|
|
1665
|
+
/** Register a typed `PUT` route on {@link MCPServer.app}. */
|
|
1666
|
+
put;
|
|
1667
|
+
/** Register a typed `PATCH` route on {@link MCPServer.app}. */
|
|
1668
|
+
patch;
|
|
1669
|
+
/** Register a typed `DELETE` route on {@link MCPServer.app}. */
|
|
1670
|
+
delete;
|
|
1671
|
+
/** Register a typed route for every HTTP method on {@link MCPServer.app}. */
|
|
1672
|
+
all;
|
|
1673
|
+
/**
|
|
1674
|
+
* Canonical Web-standard handler for edge runtimes and framework mounting.
|
|
1675
|
+
*
|
|
1676
|
+
* @example
|
|
1677
|
+
* ```ts
|
|
1678
|
+
* export default server;
|
|
1679
|
+
* // or: export const POST = server.fetch;
|
|
1680
|
+
* ```
|
|
1681
|
+
*/
|
|
1682
|
+
fetch;
|
|
1558
1683
|
/**
|
|
1559
1684
|
* Create an MCP server from a parsed, bundled OpenAPI document.
|
|
1560
1685
|
*
|
|
@@ -1589,22 +1714,37 @@ var MCPServer = class _MCPServer {
|
|
|
1589
1714
|
* is both the MCP route and the path of the OAuth protected-resource
|
|
1590
1715
|
* identity, so any explicit OAuth resource URL must use that exact path.
|
|
1591
1716
|
* Nothing binds or listens until {@link MCPServer.listen} or
|
|
1592
|
-
* {@link MCPServer.
|
|
1717
|
+
* the first request reaches {@link MCPServer.fetch}.
|
|
1593
1718
|
*/
|
|
1594
1719
|
constructor(config) {
|
|
1595
1720
|
assertServerConfig(config);
|
|
1596
1721
|
this.#config = config;
|
|
1597
1722
|
this.#branding = normalizeServerBranding(config);
|
|
1723
|
+
this.app = new Hono();
|
|
1724
|
+
this.app.use("*", async (context, next) => {
|
|
1725
|
+
getRequestBag(context.req.raw).honoContext = context;
|
|
1726
|
+
await next();
|
|
1727
|
+
});
|
|
1728
|
+
this.get = this.app.get.bind(this.app);
|
|
1729
|
+
this.post = this.app.post.bind(this.app);
|
|
1730
|
+
this.put = this.app.put.bind(this.app);
|
|
1731
|
+
this.patch = this.app.patch.bind(this.app);
|
|
1732
|
+
this.delete = this.app.delete.bind(this.app);
|
|
1733
|
+
this.all = this.app.all.bind(this.app);
|
|
1734
|
+
this.fetch = async (request, env, executionCtx) => {
|
|
1735
|
+
this.#ensureMounted("handler");
|
|
1736
|
+
return this.#httpApp.fetch(request, env, executionCtx);
|
|
1737
|
+
};
|
|
1598
1738
|
if (config.oauth !== void 0) {
|
|
1599
1739
|
const mcpUrl = typeof process === "undefined" ? void 0 : process.env["MCP_URL"];
|
|
1600
|
-
const
|
|
1740
|
+
const resource2 = resolveConfiguredOAuthResource({
|
|
1601
1741
|
provider: config.oauth,
|
|
1602
1742
|
basePath: this.#basePath(),
|
|
1603
1743
|
...mcpUrl !== void 0 && { mcpUrl }
|
|
1604
1744
|
});
|
|
1605
|
-
this.#oauthResource =
|
|
1606
|
-
this.#oauthResourceResolved =
|
|
1607
|
-
this.#oauthResourceConfigurationAbsent =
|
|
1745
|
+
this.#oauthResource = resource2;
|
|
1746
|
+
this.#oauthResourceResolved = resource2 !== void 0;
|
|
1747
|
+
this.#oauthResourceConfigurationAbsent = resource2 === void 0;
|
|
1608
1748
|
}
|
|
1609
1749
|
}
|
|
1610
1750
|
/**
|
|
@@ -1643,11 +1783,19 @@ var MCPServer = class _MCPServer {
|
|
|
1643
1783
|
get branding() {
|
|
1644
1784
|
return this.#branding;
|
|
1645
1785
|
}
|
|
1786
|
+
/** @deprecated Use {@link MCPServer.fetch} directly. */
|
|
1787
|
+
getHandler() {
|
|
1788
|
+
return this.fetch;
|
|
1789
|
+
}
|
|
1646
1790
|
/**
|
|
1647
1791
|
* Register a tool. Input is validated against `inputSchema` before the callback
|
|
1648
1792
|
* runs; results carrying `structuredContent` are type-checked against
|
|
1649
1793
|
* `outputSchema` at the callback's return position.
|
|
1650
1794
|
*
|
|
1795
|
+
* Assign static registrations to exported constants so `mcp-env.d.ts` can
|
|
1796
|
+
* expose their {@link ToolRef} types to views:
|
|
1797
|
+
* `export const search = server.tool(...)`.
|
|
1798
|
+
*
|
|
1651
1799
|
* @returns A {@link ToolRef} carrying the tool name and phantom types for
|
|
1652
1800
|
* inference-based view typing.
|
|
1653
1801
|
*/
|
|
@@ -1745,7 +1893,7 @@ var MCPServer = class _MCPServer {
|
|
|
1745
1893
|
async proxy(input) {
|
|
1746
1894
|
this.#assertOpen("proxy()");
|
|
1747
1895
|
const operation = (async () => {
|
|
1748
|
-
const { isProxyConnection, mountProxyConnection, mountProxyServers } = await import("./mcp-proxy-
|
|
1896
|
+
const { isProxyConnection, mountProxyConnection, mountProxyServers } = await import("./mcp-proxy-JK7IC5CR.js");
|
|
1749
1897
|
if (isProxyConnection(input)) {
|
|
1750
1898
|
await mountProxyConnection(this.#proxyHost(), input);
|
|
1751
1899
|
return;
|
|
@@ -1759,70 +1907,20 @@ var MCPServer = class _MCPServer {
|
|
|
1759
1907
|
this.#proxyOperations.delete(operation);
|
|
1760
1908
|
}
|
|
1761
1909
|
}
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
* @param options - Optional handler wiring.
|
|
1777
|
-
*
|
|
1778
|
-
* @example
|
|
1779
|
-
* ```ts
|
|
1780
|
-
* const handler = server.getHandler();
|
|
1781
|
-
* export default { fetch: handler };
|
|
1782
|
-
* ```
|
|
1783
|
-
*/
|
|
1784
|
-
getHandler(options = {}) {
|
|
1785
|
-
this.#assertOpen("getHandler()");
|
|
1786
|
-
const { fetch } = this.#ensureMounted("handler", void 0, options.bus);
|
|
1787
|
-
return toFrameworkHandler(fetch);
|
|
1788
|
-
}
|
|
1789
|
-
/**
|
|
1790
|
-
* Node `(req, res) => void` handler for composing with an existing
|
|
1791
|
-
* `http.Server`. Uses the same internal `toNodeHandler` bridge as
|
|
1792
|
-
* {@link MCPServer.listen}; MCPServer users do not need to import
|
|
1793
|
-
* `mcp-use/node`.
|
|
1794
|
-
*
|
|
1795
|
-
* @example
|
|
1796
|
-
* ```ts
|
|
1797
|
-
* import { createServer } from "node:http";
|
|
1798
|
-
* const httpServer = createServer(await server.getNodeHandler());
|
|
1799
|
-
* httpServer.listen(3000);
|
|
1800
|
-
* ```
|
|
1801
|
-
*/
|
|
1802
|
-
async getNodeHandler() {
|
|
1803
|
-
const { fetch } = this.#ensureMounted("handler");
|
|
1804
|
-
const { toNodeHandler } = await import("./node-bridge.js");
|
|
1805
|
-
return toNodeHandler({ fetch });
|
|
1806
|
-
}
|
|
1807
|
-
/**
|
|
1808
|
-
* Register MCP operation middleware that intercepts JSON-RPC dispatch.
|
|
1809
|
-
*
|
|
1810
|
-
* Patterns use an `mcp:` prefix (for example `mcp:tools/call`, `mcp:*`).
|
|
1811
|
-
* Exact methods may transform their typed result. The global `mcp:*` pattern
|
|
1812
|
-
* is pass-through middleware. Middleware runs in registration order; call
|
|
1813
|
-
* `next()` to continue the chain.
|
|
1814
|
-
*
|
|
1815
|
-
* @example
|
|
1816
|
-
* ```ts
|
|
1817
|
-
* server.use("mcp:tools/call", async (ctx, next) => {
|
|
1818
|
-
* console.log(`Calling tool: ${ctx.params.name}`);
|
|
1819
|
-
* return next();
|
|
1820
|
-
* });
|
|
1821
|
-
* ```
|
|
1822
|
-
*/
|
|
1823
|
-
use(pattern, handler) {
|
|
1824
|
-
this.#assertNotStarted("middleware", pattern);
|
|
1825
|
-
this.#mcpMiddlewares.push(createMcpMiddlewareEntry(pattern, handler));
|
|
1910
|
+
use(patternOrHandler, ...handlers) {
|
|
1911
|
+
if (typeof patternOrHandler === "string" && patternOrHandler.startsWith("mcp:")) {
|
|
1912
|
+
this.#assertNotStarted("middleware", patternOrHandler);
|
|
1913
|
+
const handler = handlers[0];
|
|
1914
|
+
this.#mcpMiddlewares.push(
|
|
1915
|
+
createMcpMiddlewareEntry(
|
|
1916
|
+
patternOrHandler,
|
|
1917
|
+
handler
|
|
1918
|
+
)
|
|
1919
|
+
);
|
|
1920
|
+
return this;
|
|
1921
|
+
}
|
|
1922
|
+
const register = this.app.use;
|
|
1923
|
+
register.call(this.app, patternOrHandler, ...handlers);
|
|
1826
1924
|
return this;
|
|
1827
1925
|
}
|
|
1828
1926
|
/**
|
|
@@ -1845,6 +1943,20 @@ var MCPServer = class _MCPServer {
|
|
|
1845
1943
|
this.#mcpEventListeners.push(createMcpEventListenerEntry(pattern, handler));
|
|
1846
1944
|
return this;
|
|
1847
1945
|
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Attach the shared development event bus before the first request.
|
|
1948
|
+
*
|
|
1949
|
+
* @param bus - Bus retained across hot-reloaded server instances.
|
|
1950
|
+
* @internal
|
|
1951
|
+
*/
|
|
1952
|
+
__setEventBus(bus) {
|
|
1953
|
+
this.#assertNotStarted("event bus", "shared");
|
|
1954
|
+
this.#eventBus = bus;
|
|
1955
|
+
}
|
|
1956
|
+
/** Mount and validate the Hono/MCP application without serving a request. @internal */
|
|
1957
|
+
__mount() {
|
|
1958
|
+
this.#ensureMounted("handler");
|
|
1959
|
+
}
|
|
1848
1960
|
/**
|
|
1849
1961
|
* Publish a tools-list change to v2 clients with active subscriptions.
|
|
1850
1962
|
*
|
|
@@ -1908,7 +2020,7 @@ var MCPServer = class _MCPServer {
|
|
|
1908
2020
|
* requests accepted before then are queued. Public/wildcard listeners must
|
|
1909
2021
|
* configure the resource before calling this method.
|
|
1910
2022
|
*
|
|
1911
|
-
* @throws If called on a localhost-class bind after {@link MCPServer.
|
|
2023
|
+
* @throws If called on a localhost-class bind after {@link MCPServer.fetch}
|
|
1912
2024
|
* already mounted the app without Host validation.
|
|
1913
2025
|
*/
|
|
1914
2026
|
async listen(port = void 0, options = {}) {
|
|
@@ -1929,12 +2041,12 @@ var MCPServer = class _MCPServer {
|
|
|
1929
2041
|
);
|
|
1930
2042
|
void fetchReady.catch(() => void 0);
|
|
1931
2043
|
let settled = false;
|
|
1932
|
-
const rejectAndClose = (
|
|
2044
|
+
const rejectAndClose = (error2) => {
|
|
1933
2045
|
if (!settled) {
|
|
1934
2046
|
settled = true;
|
|
1935
|
-
reject(
|
|
2047
|
+
reject(error2);
|
|
1936
2048
|
}
|
|
1937
|
-
rejectFetch?.(
|
|
2049
|
+
rejectFetch?.(error2);
|
|
1938
2050
|
void new Promise(
|
|
1939
2051
|
(closeResolve) => server.close(() => closeResolve())
|
|
1940
2052
|
).catch(() => void 0).finally(() => {
|
|
@@ -1954,13 +2066,7 @@ var MCPServer = class _MCPServer {
|
|
|
1954
2066
|
try {
|
|
1955
2067
|
const address = server.address();
|
|
1956
2068
|
const boundPort = typeof address === "object" && address !== null ? address.port : requestedPort;
|
|
1957
|
-
const { fetch } = this.#ensureMounted(
|
|
1958
|
-
"listen",
|
|
1959
|
-
boundPort,
|
|
1960
|
-
void 0,
|
|
1961
|
-
options.routes,
|
|
1962
|
-
host
|
|
1963
|
-
);
|
|
2069
|
+
const { fetch } = this.#ensureMounted("listen", boundPort, host);
|
|
1964
2070
|
resolveFetch?.(fetch);
|
|
1965
2071
|
if (!settled) {
|
|
1966
2072
|
settled = true;
|
|
@@ -1969,8 +2075,8 @@ var MCPServer = class _MCPServer {
|
|
|
1969
2075
|
url: `http://localhost:${boundPort}${this.#basePath()}`
|
|
1970
2076
|
});
|
|
1971
2077
|
}
|
|
1972
|
-
} catch (
|
|
1973
|
-
rejectAndClose(
|
|
2078
|
+
} catch (error2) {
|
|
2079
|
+
rejectAndClose(error2);
|
|
1974
2080
|
}
|
|
1975
2081
|
});
|
|
1976
2082
|
this.#httpServer = server;
|
|
@@ -1980,7 +2086,7 @@ var MCPServer = class _MCPServer {
|
|
|
1980
2086
|
* Abort in-flight MCP exchanges and stop the HTTP listener.
|
|
1981
2087
|
*
|
|
1982
2088
|
* A closed server is done for good — the underlying MCP handler stays
|
|
1983
|
-
* closed, so `listen()`/`
|
|
2089
|
+
* closed, so `listen()`/`fetch()` cannot revive it. Create a new
|
|
1984
2090
|
* instance to serve again.
|
|
1985
2091
|
*/
|
|
1986
2092
|
async close() {
|
|
@@ -1996,8 +2102,8 @@ var MCPServer = class _MCPServer {
|
|
|
1996
2102
|
}
|
|
1997
2103
|
try {
|
|
1998
2104
|
await this.#handler?.close();
|
|
1999
|
-
} catch (
|
|
2000
|
-
errors.push(
|
|
2105
|
+
} catch (error2) {
|
|
2106
|
+
errors.push(error2);
|
|
2001
2107
|
}
|
|
2002
2108
|
const httpServer = this.#httpServer;
|
|
2003
2109
|
if (httpServer !== void 0) {
|
|
@@ -2006,8 +2112,8 @@ var MCPServer = class _MCPServer {
|
|
|
2006
2112
|
httpServer.close((err) => err ? reject(err) : resolve());
|
|
2007
2113
|
});
|
|
2008
2114
|
this.#httpServer = void 0;
|
|
2009
|
-
} catch (
|
|
2010
|
-
errors.push(
|
|
2115
|
+
} catch (error2) {
|
|
2116
|
+
errors.push(error2);
|
|
2011
2117
|
}
|
|
2012
2118
|
}
|
|
2013
2119
|
if (errors.length > 0) {
|
|
@@ -2042,7 +2148,7 @@ var MCPServer = class _MCPServer {
|
|
|
2042
2148
|
return this.#oauthResource;
|
|
2043
2149
|
}
|
|
2044
2150
|
throw new Error(
|
|
2045
|
-
"OAuth requires an explicit resource or MCP_URL when using
|
|
2151
|
+
"OAuth requires an explicit resource or MCP_URL when using server.fetch or listening on a non-local host"
|
|
2046
2152
|
);
|
|
2047
2153
|
}
|
|
2048
2154
|
#assertListenOAuthConfiguration(host) {
|
|
@@ -2061,7 +2167,7 @@ var MCPServer = class _MCPServer {
|
|
|
2061
2167
|
#assertNotStarted(kind, name) {
|
|
2062
2168
|
if (this.#handler !== void 0) {
|
|
2063
2169
|
throw new Error(
|
|
2064
|
-
`Cannot register ${kind} "${name}" after the server has started: registrations are replayed per request from the registry, so register everything before listen()/
|
|
2170
|
+
`Cannot register ${kind} "${name}" after the server has started: registrations are replayed per request from the registry, so register everything before listen()/server.fetch.`
|
|
2065
2171
|
);
|
|
2066
2172
|
}
|
|
2067
2173
|
}
|
|
@@ -2104,7 +2210,7 @@ var MCPServer = class _MCPServer {
|
|
|
2104
2210
|
* Configured lists are additive to the localhost-class allowlists, so local
|
|
2105
2211
|
* runs keep working when a deployment hostname is added. With nothing
|
|
2106
2212
|
* configured, `listen()` on a localhost-class bind validates Host against the
|
|
2107
|
-
* localhost lists (the DNS-rebinding threat model), while `
|
|
2213
|
+
* localhost lists (the DNS-rebinding threat model), while `server.fetch` —
|
|
2108
2214
|
* which never binds — applies no validation. Origin validation is off unless
|
|
2109
2215
|
* `allowedOrigins` is set explicitly (SDK-aligned: the handler is open by
|
|
2110
2216
|
* default). When enabled, Origin is checked only on non-GET/HEAD requests.
|
|
@@ -2117,12 +2223,13 @@ var MCPServer = class _MCPServer {
|
|
|
2117
2223
|
const origins = allowedOrigins !== void 0 ? [.../* @__PURE__ */ new Set([...localhostAllowedOrigins(), ...allowedOrigins])] : void 0;
|
|
2118
2224
|
return { hosts, origins };
|
|
2119
2225
|
}
|
|
2120
|
-
#ensureMounted(mode, listenPort,
|
|
2226
|
+
#ensureMounted(mode, listenPort, listenHost) {
|
|
2121
2227
|
this.#assertOpen();
|
|
2122
2228
|
if (this.#fetchHandler === void 0 || this.#handler === void 0) {
|
|
2123
2229
|
const { hosts, origins } = this.#validationPolicy(mode, listenHost);
|
|
2124
2230
|
const basePath = this.#basePath();
|
|
2125
2231
|
const nestedBasePath = basePath === "/" ? "" : basePath;
|
|
2232
|
+
const httpApp = new Hono();
|
|
2126
2233
|
const middlewares = [
|
|
2127
2234
|
jsonBodyMiddleware(),
|
|
2128
2235
|
requestLogger(this.#config.logging)
|
|
@@ -2146,35 +2253,38 @@ var MCPServer = class _MCPServer {
|
|
|
2146
2253
|
}
|
|
2147
2254
|
}
|
|
2148
2255
|
this.#validateViewBindingsAtMount();
|
|
2149
|
-
const
|
|
2150
|
-
if (
|
|
2256
|
+
const resource2 = this.#resolveOAuthResource(mode, listenPort, listenHost);
|
|
2257
|
+
if (resource2 !== void 0) {
|
|
2151
2258
|
const provider = this.#config.oauth;
|
|
2152
|
-
middlewares.push(oauthMetadata(provider,
|
|
2259
|
+
middlewares.push(oauthMetadata(provider, resource2));
|
|
2260
|
+
}
|
|
2261
|
+
for (const middleware of middlewares) {
|
|
2262
|
+
registerFetchMiddleware(httpApp, middleware);
|
|
2153
2263
|
}
|
|
2154
2264
|
const { handler, fetch: mcpFetch } = createMcpMount(
|
|
2155
2265
|
(ctx) => this.#buildSdkServer(ctx),
|
|
2156
2266
|
{
|
|
2157
2267
|
path: basePath,
|
|
2158
|
-
...(this.#config.legacy !== void 0 ||
|
|
2268
|
+
...(this.#config.legacy !== void 0 || this.#eventBus !== void 0) && {
|
|
2159
2269
|
handler: {
|
|
2160
2270
|
...this.#config.legacy !== void 0 && {
|
|
2161
2271
|
legacy: this.#config.legacy
|
|
2162
2272
|
},
|
|
2163
|
-
...
|
|
2273
|
+
...this.#eventBus !== void 0 && { bus: this.#eventBus }
|
|
2164
2274
|
}
|
|
2165
2275
|
},
|
|
2166
|
-
...
|
|
2276
|
+
...resource2 !== void 0 && {
|
|
2167
2277
|
authInfo: (request) => authInfoFromRequest(request)
|
|
2168
2278
|
}
|
|
2169
2279
|
}
|
|
2170
2280
|
);
|
|
2171
2281
|
let protectWithBearer = async (_request, next) => next();
|
|
2172
|
-
if (
|
|
2282
|
+
if (resource2 !== void 0) {
|
|
2173
2283
|
const provider = this.#config.oauth;
|
|
2174
2284
|
const providerOptions = getOAuthProviderOptions(provider);
|
|
2175
2285
|
const gate = requireBearerAuth({
|
|
2176
|
-
verifier: wrapOAuthTokenVerifier(provider,
|
|
2177
|
-
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(
|
|
2286
|
+
verifier: wrapOAuthTokenVerifier(provider, resource2),
|
|
2287
|
+
resourceMetadataUrl: getOAuthProtectedResourceMetadataUrl(resource2),
|
|
2178
2288
|
...providerOptions.requiredScopes !== void 0 && {
|
|
2179
2289
|
requiredScopes: providerOptions.requiredScopes
|
|
2180
2290
|
}
|
|
@@ -2206,12 +2316,11 @@ var MCPServer = class _MCPServer {
|
|
|
2206
2316
|
this.#resources.values()
|
|
2207
2317
|
);
|
|
2208
2318
|
};
|
|
2209
|
-
if (
|
|
2319
|
+
if (resource2 !== void 0 && this.#config.publicLandingPage !== true) {
|
|
2210
2320
|
return protectWithBearer(request, respond);
|
|
2211
2321
|
}
|
|
2212
2322
|
return respond();
|
|
2213
2323
|
};
|
|
2214
|
-
const routes = [...additionalRoutes];
|
|
2215
2324
|
const brandingDevMode = this.#viewsPrimed ? this.#viewsDevMode : process.env["NODE_ENV"] !== "production";
|
|
2216
2325
|
const faviconHandler = createFaviconHandler(this.#branding, {
|
|
2217
2326
|
dev: brandingDevMode,
|
|
@@ -2219,10 +2328,10 @@ var MCPServer = class _MCPServer {
|
|
|
2219
2328
|
deferCors: deferViewCors
|
|
2220
2329
|
});
|
|
2221
2330
|
if (faviconHandler !== void 0) {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2331
|
+
this.app.all(
|
|
2332
|
+
"/favicon.ico",
|
|
2333
|
+
(context) => faviconHandler(context.req.raw)
|
|
2334
|
+
);
|
|
2226
2335
|
}
|
|
2227
2336
|
const viewHandler = createViewPublicHandler(basePath, this.#views, {
|
|
2228
2337
|
dev: this.#viewsPrimed ? this.#viewsDevMode : brandingDevMode,
|
|
@@ -2231,12 +2340,11 @@ var MCPServer = class _MCPServer {
|
|
|
2231
2340
|
deferCors: deferViewCors
|
|
2232
2341
|
});
|
|
2233
2342
|
if (viewHandler !== void 0) {
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
)
|
|
2238
|
-
|
|
2239
|
-
});
|
|
2343
|
+
this.app.on(
|
|
2344
|
+
["GET", "HEAD"],
|
|
2345
|
+
`${nestedBasePath}/_mcp-use/public/*`,
|
|
2346
|
+
(context) => viewHandler(context.req.raw)
|
|
2347
|
+
);
|
|
2240
2348
|
}
|
|
2241
2349
|
if (!this.#viewsDevMode) {
|
|
2242
2350
|
const viewAssetsHandler = createViewAssetsHandler(
|
|
@@ -2245,29 +2353,22 @@ var MCPServer = class _MCPServer {
|
|
|
2245
2353
|
{ projectRoot: this.#viewsProjectRoot, deferCors: deferViewCors }
|
|
2246
2354
|
);
|
|
2247
2355
|
if (viewAssetsHandler !== void 0) {
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
)
|
|
2252
|
-
|
|
2253
|
-
});
|
|
2356
|
+
this.app.on(
|
|
2357
|
+
["GET", "HEAD"],
|
|
2358
|
+
`${nestedBasePath}/_mcp-use/views/*`,
|
|
2359
|
+
(context) => viewAssetsHandler(context.req.raw)
|
|
2360
|
+
);
|
|
2254
2361
|
}
|
|
2255
2362
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
const terminal = routeFetch(routes);
|
|
2261
|
-
this.#fetchHandler = composeFetch(terminal, ...middlewares);
|
|
2363
|
+
this.app.all(basePath, (context) => endpointHandler(context.req.raw));
|
|
2364
|
+
httpApp.route("/", this.app);
|
|
2365
|
+
this.#httpApp = httpApp;
|
|
2366
|
+
this.#fetchHandler = async (request) => httpApp.fetch(request);
|
|
2262
2367
|
this.#handler = handler;
|
|
2263
2368
|
this.#hostValidated = hosts !== void 0;
|
|
2264
|
-
} else if (bus !== void 0 && this.#handler.bus !== bus) {
|
|
2265
|
-
throw new Error(
|
|
2266
|
-
"Cannot change the MCP event bus after the server has started."
|
|
2267
|
-
);
|
|
2268
2369
|
} else if (mode === "listen" && !this.#hostValidated && this.#validationPolicy("listen", listenHost).hosts !== void 0) {
|
|
2269
2370
|
throw new Error(
|
|
2270
|
-
"Cannot listen() on a localhost bind after
|
|
2371
|
+
"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."
|
|
2271
2372
|
);
|
|
2272
2373
|
}
|
|
2273
2374
|
return { fetch: this.#fetchHandler, handler: this.#handler };
|
|
@@ -2382,16 +2483,16 @@ var MCPServer = class _MCPServer {
|
|
|
2382
2483
|
return server;
|
|
2383
2484
|
}
|
|
2384
2485
|
#createMiddlewareContext(method, params, ctx) {
|
|
2385
|
-
|
|
2486
|
+
const requestContext = toRequestContext(ctx);
|
|
2487
|
+
return Object.assign(requestContext, {
|
|
2386
2488
|
method,
|
|
2387
2489
|
params,
|
|
2388
|
-
...ctx.http?.req !== void 0 && { request: ctx.http.req },
|
|
2389
2490
|
...ctx.sessionId !== void 0 && {
|
|
2390
2491
|
session: { sessionId: ctx.sessionId }
|
|
2391
2492
|
},
|
|
2392
2493
|
...ctx.http?.authInfo !== void 0 && { auth: ctx.http.authInfo },
|
|
2393
2494
|
state: /* @__PURE__ */ new Map()
|
|
2394
|
-
};
|
|
2495
|
+
});
|
|
2395
2496
|
}
|
|
2396
2497
|
#runMcpHook(method, ctx, innerFn) {
|
|
2397
2498
|
return runMcpOperation(
|
|
@@ -2554,7 +2655,7 @@ var MCPServer = class _MCPServer {
|
|
|
2554
2655
|
...metaOptions.hmrWs === true ? { hmrWs: true } : {}
|
|
2555
2656
|
} : metaOptions.hmrWs === true ? { hmrWs: true } : {};
|
|
2556
2657
|
const assetsBase = req !== void 0 ? resolveAssetsBase(req) : metaOptions.request !== void 0 ? resolveAssetsBase(metaOptions.request) : "";
|
|
2557
|
-
const
|
|
2658
|
+
const html2 = synthesizeViewDocument(
|
|
2558
2659
|
entry,
|
|
2559
2660
|
assetsBase,
|
|
2560
2661
|
basePath,
|
|
@@ -2565,7 +2666,7 @@ var MCPServer = class _MCPServer {
|
|
|
2565
2666
|
{
|
|
2566
2667
|
uri: readUri.href,
|
|
2567
2668
|
mimeType: resourceConfig.mimeType,
|
|
2568
|
-
text:
|
|
2669
|
+
text: html2,
|
|
2569
2670
|
_meta: buildResourceUiMeta(authorFacts, readOptions)
|
|
2570
2671
|
}
|
|
2571
2672
|
]
|
|
@@ -2601,12 +2702,11 @@ var MCPServer = class _MCPServer {
|
|
|
2601
2702
|
},
|
|
2602
2703
|
ctx
|
|
2603
2704
|
);
|
|
2604
|
-
const innerFn = async () =>
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
mwCtx,
|
|
2608
|
-
innerFn
|
|
2705
|
+
const innerFn = async () => toResourceResult(
|
|
2706
|
+
await callback(uri, this.#toRequestContext(ctx)),
|
|
2707
|
+
uri.href
|
|
2609
2708
|
);
|
|
2709
|
+
return await this.#runMcpHook("resources/read", mwCtx, innerFn);
|
|
2610
2710
|
}
|
|
2611
2711
|
);
|
|
2612
2712
|
}
|
|
@@ -2642,16 +2742,15 @@ var MCPServer = class _MCPServer {
|
|
|
2642
2742
|
},
|
|
2643
2743
|
ctx
|
|
2644
2744
|
);
|
|
2645
|
-
const innerFn = async () =>
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
mwCtx,
|
|
2653
|
-
innerFn
|
|
2745
|
+
const innerFn = async () => toResourceResult(
|
|
2746
|
+
await callback(
|
|
2747
|
+
uri,
|
|
2748
|
+
variables,
|
|
2749
|
+
this.#toRequestContext(ctx)
|
|
2750
|
+
),
|
|
2751
|
+
uri.href
|
|
2654
2752
|
);
|
|
2753
|
+
return await this.#runMcpHook("resources/read", mwCtx, innerFn);
|
|
2655
2754
|
}
|
|
2656
2755
|
);
|
|
2657
2756
|
}
|
|
@@ -2692,7 +2791,9 @@ var MCPServer = class _MCPServer {
|
|
|
2692
2791
|
);
|
|
2693
2792
|
const innerFn = async () => {
|
|
2694
2793
|
const effectiveArgs = mwCtx.params.arguments ?? {};
|
|
2695
|
-
return
|
|
2794
|
+
return toPromptResult(
|
|
2795
|
+
await callback(effectiveArgs, this.#toRequestContext(ctx))
|
|
2796
|
+
);
|
|
2696
2797
|
};
|
|
2697
2798
|
return await this.#runMcpHook("prompts/get", mwCtx, innerFn);
|
|
2698
2799
|
};
|
|
@@ -2727,9 +2828,186 @@ import {
|
|
|
2727
2828
|
inputResponse as inputResponse2,
|
|
2728
2829
|
isInputRequiredResult as isInputRequiredResult3
|
|
2729
2830
|
} from "@modelcontextprotocol/server";
|
|
2831
|
+
|
|
2832
|
+
// src/response-helpers.ts
|
|
2833
|
+
function text(content) {
|
|
2834
|
+
return {
|
|
2835
|
+
content: [{ type: "text", text: content }],
|
|
2836
|
+
_meta: { mimeType: "text/plain" }
|
|
2837
|
+
};
|
|
2838
|
+
}
|
|
2839
|
+
function markdown(content) {
|
|
2840
|
+
return {
|
|
2841
|
+
content: [{ type: "text", text: content }],
|
|
2842
|
+
_meta: { mimeType: "text/markdown" }
|
|
2843
|
+
};
|
|
2844
|
+
}
|
|
2845
|
+
function html(content) {
|
|
2846
|
+
return {
|
|
2847
|
+
content: [{ type: "text", text: content }],
|
|
2848
|
+
_meta: { mimeType: "text/html" }
|
|
2849
|
+
};
|
|
2850
|
+
}
|
|
2851
|
+
function xml(content) {
|
|
2852
|
+
return {
|
|
2853
|
+
content: [{ type: "text", text: content }],
|
|
2854
|
+
_meta: { mimeType: "text/xml" }
|
|
2855
|
+
};
|
|
2856
|
+
}
|
|
2857
|
+
function css(content) {
|
|
2858
|
+
return {
|
|
2859
|
+
content: [{ type: "text", text: content }],
|
|
2860
|
+
_meta: { mimeType: "text/css" }
|
|
2861
|
+
};
|
|
2862
|
+
}
|
|
2863
|
+
function javascript(content) {
|
|
2864
|
+
return {
|
|
2865
|
+
content: [{ type: "text", text: content }],
|
|
2866
|
+
_meta: { mimeType: "text/javascript" }
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
function image(data, mimeType = "image/png") {
|
|
2870
|
+
return {
|
|
2871
|
+
content: [{ type: "image", data, mimeType }],
|
|
2872
|
+
_meta: { mimeType, isImage: true }
|
|
2873
|
+
};
|
|
2874
|
+
}
|
|
2875
|
+
function audio(data, mimeType = "audio/wav") {
|
|
2876
|
+
return {
|
|
2877
|
+
content: [{ type: "audio", data, mimeType }],
|
|
2878
|
+
_meta: { mimeType, isAudio: true }
|
|
2879
|
+
};
|
|
2880
|
+
}
|
|
2881
|
+
function binary(base64Data, mimeType) {
|
|
2882
|
+
return {
|
|
2883
|
+
content: [{ type: "text", text: base64Data }],
|
|
2884
|
+
_meta: { mimeType, isBinary: true }
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
function resource(uri, mimeTypeOrContent, text2) {
|
|
2888
|
+
if (typeof mimeTypeOrContent === "object" && mimeTypeOrContent !== null && "content" in mimeTypeOrContent) {
|
|
2889
|
+
const contentResult = mimeTypeOrContent;
|
|
2890
|
+
let extractedText;
|
|
2891
|
+
let extractedMimeType;
|
|
2892
|
+
if (contentResult._meta && typeof contentResult._meta === "object") {
|
|
2893
|
+
const meta = contentResult._meta;
|
|
2894
|
+
if (typeof meta.mimeType === "string") {
|
|
2895
|
+
extractedMimeType = meta.mimeType;
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
const first = contentResult.content?.[0];
|
|
2899
|
+
if (first?.type === "text" && "text" in first) {
|
|
2900
|
+
extractedText = first.text;
|
|
2901
|
+
}
|
|
2902
|
+
return {
|
|
2903
|
+
content: [
|
|
2904
|
+
{
|
|
2905
|
+
type: "resource",
|
|
2906
|
+
resource: {
|
|
2907
|
+
uri,
|
|
2908
|
+
...extractedMimeType !== void 0 && {
|
|
2909
|
+
mimeType: extractedMimeType
|
|
2910
|
+
},
|
|
2911
|
+
text: extractedText ?? ""
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
]
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2917
|
+
const mimeType = mimeTypeOrContent;
|
|
2918
|
+
return {
|
|
2919
|
+
content: [
|
|
2920
|
+
{
|
|
2921
|
+
type: "resource",
|
|
2922
|
+
resource: {
|
|
2923
|
+
uri,
|
|
2924
|
+
...mimeType !== void 0 && mimeType !== "" && { mimeType },
|
|
2925
|
+
text: text2 ?? ""
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
]
|
|
2929
|
+
};
|
|
2930
|
+
}
|
|
2931
|
+
function error(message) {
|
|
2932
|
+
return {
|
|
2933
|
+
isError: true,
|
|
2934
|
+
content: [{ type: "text", text: message }]
|
|
2935
|
+
};
|
|
2936
|
+
}
|
|
2937
|
+
function object(data) {
|
|
2938
|
+
if (Array.isArray(data)) {
|
|
2939
|
+
return array(data);
|
|
2940
|
+
}
|
|
2941
|
+
return {
|
|
2942
|
+
content: [
|
|
2943
|
+
{
|
|
2944
|
+
type: "text",
|
|
2945
|
+
text: JSON.stringify(data, null, 2)
|
|
2946
|
+
}
|
|
2947
|
+
],
|
|
2948
|
+
structuredContent: data,
|
|
2949
|
+
_meta: { mimeType: "application/json" }
|
|
2950
|
+
};
|
|
2951
|
+
}
|
|
2952
|
+
function array(data) {
|
|
2953
|
+
return {
|
|
2954
|
+
content: [
|
|
2955
|
+
{
|
|
2956
|
+
type: "text",
|
|
2957
|
+
text: JSON.stringify(data, null, 2)
|
|
2958
|
+
}
|
|
2959
|
+
],
|
|
2960
|
+
structuredContent: data
|
|
2961
|
+
};
|
|
2962
|
+
}
|
|
2963
|
+
function widget(config) {
|
|
2964
|
+
const props = config.props ?? config.data ?? {};
|
|
2965
|
+
const { output, message, metadata } = config;
|
|
2966
|
+
const finalContent = message ? [{ type: "text", text: message }] : Array.isArray(output?.content) && output.content.length > 0 ? output.content : [{ type: "text", text: "" }];
|
|
2967
|
+
const result = {
|
|
2968
|
+
content: finalContent
|
|
2969
|
+
};
|
|
2970
|
+
if (metadata !== void 0 && Object.keys(metadata).length > 0) {
|
|
2971
|
+
result._meta = metadata;
|
|
2972
|
+
}
|
|
2973
|
+
if (output?.structuredContent !== void 0) {
|
|
2974
|
+
result.structuredContent = output.structuredContent;
|
|
2975
|
+
} else if (Object.keys(props).length > 0) {
|
|
2976
|
+
result.structuredContent = props;
|
|
2977
|
+
}
|
|
2978
|
+
return result;
|
|
2979
|
+
}
|
|
2980
|
+
function mix(...results) {
|
|
2981
|
+
const withStructured = results.filter(
|
|
2982
|
+
(result) => result.structuredContent !== void 0
|
|
2983
|
+
);
|
|
2984
|
+
const structuredContent = withStructured.length > 0 ? withStructured.map((result) => result.structuredContent).reduce(
|
|
2985
|
+
(acc, value) => ({
|
|
2986
|
+
...acc,
|
|
2987
|
+
...typeof value === "object" && value !== null ? value : {}
|
|
2988
|
+
}),
|
|
2989
|
+
{}
|
|
2990
|
+
) : void 0;
|
|
2991
|
+
const withMeta = results.filter((result) => result._meta !== void 0);
|
|
2992
|
+
const _meta = withMeta.length > 0 ? withMeta.map((result) => result._meta).reduce(
|
|
2993
|
+
(acc, value) => ({
|
|
2994
|
+
...acc,
|
|
2995
|
+
...value !== void 0 ? value : {}
|
|
2996
|
+
}),
|
|
2997
|
+
{}
|
|
2998
|
+
) : void 0;
|
|
2999
|
+
return {
|
|
3000
|
+
content: results.flatMap((result) => result.content),
|
|
3001
|
+
...structuredContent !== void 0 && Object.keys(structuredContent).length > 0 && { structuredContent },
|
|
3002
|
+
..._meta !== void 0 && Object.keys(_meta).length > 0 && { _meta }
|
|
3003
|
+
};
|
|
3004
|
+
}
|
|
2730
3005
|
export {
|
|
2731
3006
|
MCPServer,
|
|
2732
3007
|
acceptedContent,
|
|
3008
|
+
array,
|
|
3009
|
+
audio,
|
|
3010
|
+
binary,
|
|
2733
3011
|
completable,
|
|
2734
3012
|
composeFetch,
|
|
2735
3013
|
composeMiddleware,
|
|
@@ -2737,19 +3015,29 @@ export {
|
|
|
2737
3015
|
createMcpMiddlewareEntry,
|
|
2738
3016
|
createMcpMount,
|
|
2739
3017
|
createRequestStateCodec,
|
|
3018
|
+
css,
|
|
3019
|
+
error,
|
|
2740
3020
|
getRequestBag,
|
|
2741
3021
|
hostValidationMiddleware,
|
|
3022
|
+
html,
|
|
3023
|
+
image,
|
|
2742
3024
|
inputRequired2 as inputRequired,
|
|
2743
3025
|
inputResponse2 as inputResponse,
|
|
2744
3026
|
isInputRequiredResult3 as isInputRequiredResult,
|
|
3027
|
+
javascript,
|
|
2745
3028
|
jsonBodyMiddleware,
|
|
3029
|
+
markdown,
|
|
2746
3030
|
matchesPath,
|
|
2747
3031
|
matchesPathPrefix,
|
|
2748
3032
|
matchesPattern,
|
|
3033
|
+
mix,
|
|
3034
|
+
object,
|
|
2749
3035
|
originValidationMiddleware,
|
|
2750
3036
|
pathnameOf,
|
|
2751
3037
|
registerViews,
|
|
2752
3038
|
requestLogger,
|
|
2753
|
-
|
|
2754
|
-
|
|
3039
|
+
resource,
|
|
3040
|
+
text,
|
|
3041
|
+
widget,
|
|
3042
|
+
xml
|
|
2755
3043
|
};
|