mcp-use 1.9.1-canary.0 → 1.10.0-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -6
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-MUZ5WYE3.js → chunk-BFFS67JY.js} +1 -1
- package/dist/{chunk-D22NUQTL.js → chunk-HRWL2M2I.js} +184 -0
- package/dist/{chunk-5URNFWCQ.js → chunk-LWVK6RXA.js} +8 -3
- package/dist/{chunk-KHTTBIRP.js → chunk-Q3PFK7Y4.js} +138 -1
- package/dist/{context-storage-TXQ4DVSS.js → context-storage-NA4MHWOZ.js} +3 -1
- package/dist/index.cjs +184 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/src/browser.cjs +184 -0
- package/dist/src/browser.js +1 -1
- package/dist/src/react/index.cjs +184 -0
- package/dist/src/react/index.js +2 -2
- package/dist/src/server/context-storage.d.ts +8 -1
- package/dist/src/server/context-storage.d.ts.map +1 -1
- package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
- package/dist/src/server/index.cjs +595 -63
- package/dist/src/server/index.d.ts +3 -3
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +459 -67
- package/dist/src/server/mcp-server.d.ts +49 -9
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/oauth/providers.d.ts +27 -9
- package/dist/src/server/oauth/providers.d.ts.map +1 -1
- package/dist/src/server/prompts/index.d.ts.map +1 -1
- package/dist/src/server/resources/index.d.ts +43 -23
- package/dist/src/server/resources/index.d.ts.map +1 -1
- package/dist/src/server/resources/subscriptions.d.ts +54 -0
- package/dist/src/server/resources/subscriptions.d.ts.map +1 -0
- package/dist/src/server/sessions/session-manager.d.ts +9 -1
- package/dist/src/server/sessions/session-manager.d.ts.map +1 -1
- package/dist/src/server/tools/tool-execution-helpers.d.ts +30 -17
- package/dist/src/server/tools/tool-execution-helpers.d.ts.map +1 -1
- package/dist/src/server/tools/tool-registration.d.ts.map +1 -1
- package/dist/src/server/types/common.d.ts +24 -8
- package/dist/src/server/types/common.d.ts.map +1 -1
- package/dist/src/server/types/index.d.ts +3 -3
- package/dist/src/server/types/index.d.ts.map +1 -1
- package/dist/src/server/types/prompt.d.ts +2 -1
- package/dist/src/server/types/prompt.d.ts.map +1 -1
- package/dist/src/server/types/resource.d.ts +53 -8
- package/dist/src/server/types/resource.d.ts.map +1 -1
- package/dist/src/server/types/tool-context.d.ts +131 -0
- package/dist/src/server/types/tool-context.d.ts.map +1 -1
- package/dist/src/server/types/tool.d.ts +1 -1
- package/dist/src/server/types/tool.d.ts.map +1 -1
- package/dist/src/server/utils/response-helpers.d.ts +48 -4
- package/dist/src/server/utils/response-helpers.d.ts.map +1 -1
- package/dist/src/server/widgets/index.d.ts +2 -2
- package/dist/src/server/widgets/ui-resource-registration.d.ts +2 -2
- package/dist/src/session.d.ts +337 -2
- package/dist/src/session.d.ts.map +1 -1
- package/dist/{tool-execution-helpers-IVUDHXMK.js → tool-execution-helpers-RRMGLAHR.js} +7 -1
- package/package.json +3 -3
|
@@ -126,14 +126,18 @@ var init_runtime = __esm({
|
|
|
126
126
|
var context_storage_exports = {};
|
|
127
127
|
__export(context_storage_exports, {
|
|
128
128
|
getRequestContext: () => getRequestContext,
|
|
129
|
+
getSessionId: () => getSessionId,
|
|
129
130
|
hasRequestContext: () => hasRequestContext,
|
|
130
131
|
runWithContext: () => runWithContext
|
|
131
132
|
});
|
|
132
|
-
async function runWithContext(context, fn) {
|
|
133
|
-
return requestContextStorage.run(context, fn);
|
|
133
|
+
async function runWithContext(context, fn, sessionId) {
|
|
134
|
+
return requestContextStorage.run({ honoContext: context, sessionId }, fn);
|
|
134
135
|
}
|
|
135
136
|
function getRequestContext() {
|
|
136
|
-
return requestContextStorage.getStore();
|
|
137
|
+
return requestContextStorage.getStore()?.honoContext;
|
|
138
|
+
}
|
|
139
|
+
function getSessionId() {
|
|
140
|
+
return requestContextStorage.getStore()?.sessionId;
|
|
137
141
|
}
|
|
138
142
|
function hasRequestContext() {
|
|
139
143
|
return requestContextStorage.getStore() !== void 0;
|
|
@@ -146,6 +150,7 @@ var init_context_storage = __esm({
|
|
|
146
150
|
requestContextStorage = new import_node_async_hooks.AsyncLocalStorage();
|
|
147
151
|
__name(runWithContext, "runWithContext");
|
|
148
152
|
__name(getRequestContext, "getRequestContext");
|
|
153
|
+
__name(getSessionId, "getSessionId");
|
|
149
154
|
__name(hasRequestContext, "hasRequestContext");
|
|
150
155
|
}
|
|
151
156
|
});
|
|
@@ -174,13 +179,16 @@ var init_errors = __esm({
|
|
|
174
179
|
// src/server/tools/tool-execution-helpers.ts
|
|
175
180
|
var tool_execution_helpers_exports = {};
|
|
176
181
|
__export(tool_execution_helpers_exports, {
|
|
182
|
+
VALID_LOG_LEVELS: () => VALID_LOG_LEVELS,
|
|
177
183
|
createElicitMethod: () => createElicitMethod,
|
|
178
184
|
createEnhancedContext: () => createEnhancedContext,
|
|
179
185
|
createReportProgressMethod: () => createReportProgressMethod,
|
|
180
186
|
createSampleMethod: () => createSampleMethod,
|
|
181
187
|
findSessionContext: () => findSessionContext,
|
|
188
|
+
isValidLogLevel: () => isValidLogLevel,
|
|
182
189
|
parseElicitParams: () => parseElicitParams,
|
|
183
190
|
sendProgressNotification: () => sendProgressNotification,
|
|
191
|
+
shouldLogMessage: () => shouldLogMessage,
|
|
184
192
|
withTimeout: () => withTimeout
|
|
185
193
|
});
|
|
186
194
|
function findSessionContext(sessions, initialRequestContext, extraProgressToken, extraSendNotification) {
|
|
@@ -418,7 +426,97 @@ function createReportProgressMethod(progressToken, sendNotification2) {
|
|
|
418
426
|
}
|
|
419
427
|
return void 0;
|
|
420
428
|
}
|
|
421
|
-
function
|
|
429
|
+
function isValidLogLevel(level) {
|
|
430
|
+
return VALID_LOG_LEVELS.includes(level);
|
|
431
|
+
}
|
|
432
|
+
function shouldLogMessage(messageLevel, minLevel) {
|
|
433
|
+
if (!minLevel) {
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
if (!isValidLogLevel(messageLevel) || !isValidLogLevel(minLevel)) {
|
|
437
|
+
return true;
|
|
438
|
+
}
|
|
439
|
+
return LOG_LEVELS[messageLevel] >= LOG_LEVELS[minLevel];
|
|
440
|
+
}
|
|
441
|
+
function createLogMethod(sendNotification2, minLogLevel) {
|
|
442
|
+
if (!sendNotification2) {
|
|
443
|
+
return void 0;
|
|
444
|
+
}
|
|
445
|
+
return async (level, message, logger) => {
|
|
446
|
+
if (!shouldLogMessage(level, minLogLevel)) {
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
await sendNotification2({
|
|
450
|
+
method: "notifications/message",
|
|
451
|
+
params: {
|
|
452
|
+
level,
|
|
453
|
+
data: message,
|
|
454
|
+
logger: logger || "tool"
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
function createClientCapabilityChecker(clientCapabilities) {
|
|
460
|
+
const caps = clientCapabilities || {};
|
|
461
|
+
return {
|
|
462
|
+
can(capability) {
|
|
463
|
+
return capability in caps;
|
|
464
|
+
},
|
|
465
|
+
capabilities() {
|
|
466
|
+
return { ...caps };
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
function createSendNotificationMethod(sessionId, sessions) {
|
|
471
|
+
if (!sessionId || !sessions) {
|
|
472
|
+
return void 0;
|
|
473
|
+
}
|
|
474
|
+
return async (method, params) => {
|
|
475
|
+
const session = sessions.get(sessionId);
|
|
476
|
+
if (!session?.sendNotification) {
|
|
477
|
+
console.warn(
|
|
478
|
+
`[MCP] Cannot send notification to session ${sessionId} - no sendNotification function`
|
|
479
|
+
);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
await session.sendNotification({
|
|
484
|
+
method,
|
|
485
|
+
params: params || {}
|
|
486
|
+
});
|
|
487
|
+
} catch (error2) {
|
|
488
|
+
console.error(
|
|
489
|
+
`[MCP] Error sending notification to session ${sessionId}:`,
|
|
490
|
+
error2
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function createSendNotificationToSessionMethod(sessions) {
|
|
496
|
+
if (!sessions) {
|
|
497
|
+
return void 0;
|
|
498
|
+
}
|
|
499
|
+
return async (sessionId, method, params) => {
|
|
500
|
+
const session = sessions.get(sessionId);
|
|
501
|
+
if (!session?.sendNotification) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
try {
|
|
505
|
+
await session.sendNotification({
|
|
506
|
+
method,
|
|
507
|
+
params: params || {}
|
|
508
|
+
});
|
|
509
|
+
return true;
|
|
510
|
+
} catch (error2) {
|
|
511
|
+
console.error(
|
|
512
|
+
`[MCP] Error sending notification to session ${sessionId}:`,
|
|
513
|
+
error2
|
|
514
|
+
);
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
function createEnhancedContext(baseContext, createMessage, elicitInput, progressToken, sendNotification2, minLogLevel, clientCapabilities, sessionId, sessions) {
|
|
422
520
|
const enhancedContext = baseContext ? Object.create(baseContext) : {};
|
|
423
521
|
enhancedContext.sample = createSampleMethod(
|
|
424
522
|
createMessage,
|
|
@@ -430,9 +528,27 @@ function createEnhancedContext(baseContext, createMessage, elicitInput, progress
|
|
|
430
528
|
progressToken,
|
|
431
529
|
sendNotification2
|
|
432
530
|
);
|
|
531
|
+
enhancedContext.log = createLogMethod(sendNotification2, minLogLevel);
|
|
532
|
+
enhancedContext.client = createClientCapabilityChecker(clientCapabilities);
|
|
533
|
+
if (sessionId) {
|
|
534
|
+
enhancedContext.session = {
|
|
535
|
+
sessionId
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
const sendNotificationMethod = createSendNotificationMethod(
|
|
539
|
+
sessionId,
|
|
540
|
+
sessions
|
|
541
|
+
);
|
|
542
|
+
if (sendNotificationMethod) {
|
|
543
|
+
enhancedContext.sendNotification = sendNotificationMethod;
|
|
544
|
+
}
|
|
545
|
+
const sendNotificationToSessionMethod = createSendNotificationToSessionMethod(sessions);
|
|
546
|
+
if (sendNotificationToSessionMethod) {
|
|
547
|
+
enhancedContext.sendNotificationToSession = sendNotificationToSessionMethod;
|
|
548
|
+
}
|
|
433
549
|
return enhancedContext;
|
|
434
550
|
}
|
|
435
|
-
var import_zod_json_schema_compat;
|
|
551
|
+
var import_zod_json_schema_compat, LOG_LEVELS, VALID_LOG_LEVELS;
|
|
436
552
|
var init_tool_execution_helpers = __esm({
|
|
437
553
|
"src/server/tools/tool-execution-helpers.ts"() {
|
|
438
554
|
"use strict";
|
|
@@ -446,6 +562,32 @@ var init_tool_execution_helpers = __esm({
|
|
|
446
562
|
__name(createSampleMethod, "createSampleMethod");
|
|
447
563
|
__name(createElicitMethod, "createElicitMethod");
|
|
448
564
|
__name(createReportProgressMethod, "createReportProgressMethod");
|
|
565
|
+
LOG_LEVELS = {
|
|
566
|
+
debug: 0,
|
|
567
|
+
info: 1,
|
|
568
|
+
notice: 2,
|
|
569
|
+
warning: 3,
|
|
570
|
+
error: 4,
|
|
571
|
+
critical: 5,
|
|
572
|
+
alert: 6,
|
|
573
|
+
emergency: 7
|
|
574
|
+
};
|
|
575
|
+
VALID_LOG_LEVELS = [
|
|
576
|
+
"debug",
|
|
577
|
+
"info",
|
|
578
|
+
"notice",
|
|
579
|
+
"warning",
|
|
580
|
+
"error",
|
|
581
|
+
"critical",
|
|
582
|
+
"alert",
|
|
583
|
+
"emergency"
|
|
584
|
+
];
|
|
585
|
+
__name(isValidLogLevel, "isValidLogLevel");
|
|
586
|
+
__name(shouldLogMessage, "shouldLogMessage");
|
|
587
|
+
__name(createLogMethod, "createLogMethod");
|
|
588
|
+
__name(createClientCapabilityChecker, "createClientCapabilityChecker");
|
|
589
|
+
__name(createSendNotificationMethod, "createSendNotificationMethod");
|
|
590
|
+
__name(createSendNotificationToSessionMethod, "createSendNotificationToSessionMethod");
|
|
449
591
|
__name(createEnhancedContext, "createEnhancedContext");
|
|
450
592
|
}
|
|
451
593
|
});
|
|
@@ -643,9 +785,11 @@ var init_conversion2 = __esm({
|
|
|
643
785
|
// src/server/index.ts
|
|
644
786
|
var server_exports = {};
|
|
645
787
|
__export(server_exports, {
|
|
788
|
+
MCPServer: () => MCPServer,
|
|
646
789
|
adaptConnectMiddleware: () => adaptConnectMiddleware,
|
|
647
790
|
adaptMiddleware: () => adaptMiddleware,
|
|
648
791
|
array: () => array,
|
|
792
|
+
audio: () => audio,
|
|
649
793
|
binary: () => binary,
|
|
650
794
|
buildWidgetUrl: () => buildWidgetUrl,
|
|
651
795
|
createExternalUrlResource: () => createExternalUrlResource,
|
|
@@ -684,11 +828,14 @@ module.exports = __toCommonJS(server_exports);
|
|
|
684
828
|
|
|
685
829
|
// src/server/mcp-server.ts
|
|
686
830
|
var import_mcp2 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
831
|
+
var import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
832
|
+
var import_zod2 = require("zod");
|
|
687
833
|
|
|
688
834
|
// src/server/widgets/index.ts
|
|
689
835
|
init_runtime();
|
|
690
836
|
|
|
691
837
|
// src/server/utils/response-helpers.ts
|
|
838
|
+
init_runtime();
|
|
692
839
|
function text(content) {
|
|
693
840
|
return {
|
|
694
841
|
content: [
|
|
@@ -719,7 +866,109 @@ function image(data, mimeType = "image/png") {
|
|
|
719
866
|
};
|
|
720
867
|
}
|
|
721
868
|
__name(image, "image");
|
|
722
|
-
function
|
|
869
|
+
function getAudioMimeType(filename) {
|
|
870
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
871
|
+
switch (ext) {
|
|
872
|
+
case "wav":
|
|
873
|
+
return "audio/wav";
|
|
874
|
+
case "mp3":
|
|
875
|
+
return "audio/mpeg";
|
|
876
|
+
case "ogg":
|
|
877
|
+
return "audio/ogg";
|
|
878
|
+
case "m4a":
|
|
879
|
+
return "audio/mp4";
|
|
880
|
+
case "webm":
|
|
881
|
+
return "audio/webm";
|
|
882
|
+
case "flac":
|
|
883
|
+
return "audio/flac";
|
|
884
|
+
case "aac":
|
|
885
|
+
return "audio/aac";
|
|
886
|
+
default:
|
|
887
|
+
return "audio/wav";
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
__name(getAudioMimeType, "getAudioMimeType");
|
|
891
|
+
function arrayBufferToBase64(buffer) {
|
|
892
|
+
if (isDeno) {
|
|
893
|
+
const bytes = new Uint8Array(buffer);
|
|
894
|
+
let binary2 = "";
|
|
895
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
896
|
+
binary2 += String.fromCharCode(bytes[i]);
|
|
897
|
+
}
|
|
898
|
+
return btoa(binary2);
|
|
899
|
+
} else {
|
|
900
|
+
return Buffer.from(buffer).toString("base64");
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
__name(arrayBufferToBase64, "arrayBufferToBase64");
|
|
904
|
+
function audio(dataOrPath, mimeType) {
|
|
905
|
+
const isFilePath = dataOrPath.includes("/") || dataOrPath.includes("\\") || dataOrPath.includes(".");
|
|
906
|
+
if (isFilePath && dataOrPath.length < 1e3) {
|
|
907
|
+
return (async () => {
|
|
908
|
+
const buffer = await fsHelpers.readFile(dataOrPath);
|
|
909
|
+
const base64Data = arrayBufferToBase64(buffer);
|
|
910
|
+
const inferredMimeType = mimeType || getAudioMimeType(dataOrPath);
|
|
911
|
+
return {
|
|
912
|
+
content: [
|
|
913
|
+
{
|
|
914
|
+
type: "audio",
|
|
915
|
+
data: base64Data,
|
|
916
|
+
mimeType: inferredMimeType
|
|
917
|
+
}
|
|
918
|
+
],
|
|
919
|
+
_meta: {
|
|
920
|
+
mimeType: inferredMimeType,
|
|
921
|
+
isAudio: true
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
})();
|
|
925
|
+
}
|
|
926
|
+
const finalMimeType = mimeType || "audio/wav";
|
|
927
|
+
return {
|
|
928
|
+
content: [
|
|
929
|
+
{
|
|
930
|
+
type: "audio",
|
|
931
|
+
data: dataOrPath,
|
|
932
|
+
mimeType: finalMimeType
|
|
933
|
+
}
|
|
934
|
+
],
|
|
935
|
+
_meta: {
|
|
936
|
+
mimeType: finalMimeType,
|
|
937
|
+
isAudio: true
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
__name(audio, "audio");
|
|
942
|
+
function resource(uri, mimeTypeOrContent, text2) {
|
|
943
|
+
if (typeof mimeTypeOrContent === "object" && mimeTypeOrContent !== null && "content" in mimeTypeOrContent) {
|
|
944
|
+
const contentResult = mimeTypeOrContent;
|
|
945
|
+
let extractedText;
|
|
946
|
+
let extractedMimeType;
|
|
947
|
+
if (contentResult._meta && typeof contentResult._meta === "object") {
|
|
948
|
+
const meta = contentResult._meta;
|
|
949
|
+
if (meta.mimeType && typeof meta.mimeType === "string") {
|
|
950
|
+
extractedMimeType = meta.mimeType;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (contentResult.content && contentResult.content.length > 0) {
|
|
954
|
+
const firstContent = contentResult.content[0];
|
|
955
|
+
if (firstContent.type === "text" && "text" in firstContent) {
|
|
956
|
+
extractedText = firstContent.text;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
const resourceContent2 = {
|
|
960
|
+
type: "resource",
|
|
961
|
+
resource: {
|
|
962
|
+
uri,
|
|
963
|
+
...extractedMimeType && { mimeType: extractedMimeType },
|
|
964
|
+
...extractedText && { text: extractedText }
|
|
965
|
+
}
|
|
966
|
+
};
|
|
967
|
+
return {
|
|
968
|
+
content: [resourceContent2]
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
const mimeType = mimeTypeOrContent;
|
|
723
972
|
const resourceContent = {
|
|
724
973
|
type: "resource",
|
|
725
974
|
resource: {
|
|
@@ -998,7 +1247,7 @@ function parseTemplateUri(template, uri) {
|
|
|
998
1247
|
const params = {};
|
|
999
1248
|
let regexPattern = template.replace(/[.*+?^$()[\]\\|]/g, "\\$&");
|
|
1000
1249
|
const paramNames = [];
|
|
1001
|
-
regexPattern = regexPattern.replace(
|
|
1250
|
+
regexPattern = regexPattern.replace(/\{([^}]+)\}/g, (_, paramName) => {
|
|
1002
1251
|
paramNames.push(paramName);
|
|
1003
1252
|
return "([^/]+)";
|
|
1004
1253
|
});
|
|
@@ -2431,7 +2680,7 @@ function toolRegistration(toolDefinition, callback) {
|
|
|
2431
2680
|
const initialRequestContext = getRequestContext();
|
|
2432
2681
|
const extraProgressToken = extra?._meta?.progressToken;
|
|
2433
2682
|
const extraSendNotification = extra?.sendNotification;
|
|
2434
|
-
const { requestContext, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
2683
|
+
const { requestContext, session, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
2435
2684
|
this.sessions,
|
|
2436
2685
|
initialRequestContext,
|
|
2437
2686
|
extraProgressToken,
|
|
@@ -2442,7 +2691,9 @@ function toolRegistration(toolDefinition, callback) {
|
|
|
2442
2691
|
this.createMessage.bind(this),
|
|
2443
2692
|
this.server.server.elicitInput.bind(this.server.server),
|
|
2444
2693
|
progressToken,
|
|
2445
|
-
sendNotification2
|
|
2694
|
+
sendNotification2,
|
|
2695
|
+
session?.logLevel,
|
|
2696
|
+
session?.clientCapabilities
|
|
2446
2697
|
);
|
|
2447
2698
|
const executeCallback = /* @__PURE__ */ __name(async () => {
|
|
2448
2699
|
if (actualCallback.length >= 2) {
|
|
@@ -2467,6 +2718,152 @@ init_tool_execution_helpers();
|
|
|
2467
2718
|
// src/server/resources/index.ts
|
|
2468
2719
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2469
2720
|
init_conversion();
|
|
2721
|
+
|
|
2722
|
+
// src/server/resources/subscriptions.ts
|
|
2723
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
2724
|
+
init_context_storage();
|
|
2725
|
+
var ResourceSubscriptionManager = class {
|
|
2726
|
+
static {
|
|
2727
|
+
__name(this, "ResourceSubscriptionManager");
|
|
2728
|
+
}
|
|
2729
|
+
/**
|
|
2730
|
+
* Tracks resource subscriptions per session
|
|
2731
|
+
* Map structure: uri -> Set<sessionId>
|
|
2732
|
+
*/
|
|
2733
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
2734
|
+
/**
|
|
2735
|
+
* Register subscription handlers with an MCP server instance
|
|
2736
|
+
*
|
|
2737
|
+
* @param server - The native MCP server instance
|
|
2738
|
+
* @param sessions - Map of active sessions
|
|
2739
|
+
*/
|
|
2740
|
+
registerHandlers(server, sessions) {
|
|
2741
|
+
server.server.setRequestHandler(
|
|
2742
|
+
import_types.SubscribeRequestSchema,
|
|
2743
|
+
async (request) => {
|
|
2744
|
+
const { uri } = request.params;
|
|
2745
|
+
const sessionId = this.getSessionIdFromContext(sessions, server);
|
|
2746
|
+
if (!sessionId) {
|
|
2747
|
+
console.warn(
|
|
2748
|
+
`[MCP] Could not determine session ID for resource subscription to ${uri}`
|
|
2749
|
+
);
|
|
2750
|
+
return {};
|
|
2751
|
+
}
|
|
2752
|
+
if (!this.subscriptions.has(uri)) {
|
|
2753
|
+
this.subscriptions.set(uri, /* @__PURE__ */ new Set());
|
|
2754
|
+
}
|
|
2755
|
+
this.subscriptions.get(uri).add(sessionId);
|
|
2756
|
+
console.log(
|
|
2757
|
+
`[MCP] Session ${sessionId} subscribed to resource: ${uri}`
|
|
2758
|
+
);
|
|
2759
|
+
return {};
|
|
2760
|
+
}
|
|
2761
|
+
);
|
|
2762
|
+
server.server.setRequestHandler(
|
|
2763
|
+
import_types.UnsubscribeRequestSchema,
|
|
2764
|
+
async (request) => {
|
|
2765
|
+
const { uri } = request.params;
|
|
2766
|
+
const sessionId = this.getSessionIdFromContext(sessions, server);
|
|
2767
|
+
if (!sessionId) {
|
|
2768
|
+
console.warn(
|
|
2769
|
+
`[MCP] Could not determine session ID for resource unsubscribe from ${uri}`
|
|
2770
|
+
);
|
|
2771
|
+
return {};
|
|
2772
|
+
}
|
|
2773
|
+
const subscribers = this.subscriptions.get(uri);
|
|
2774
|
+
if (subscribers) {
|
|
2775
|
+
subscribers.delete(sessionId);
|
|
2776
|
+
if (subscribers.size === 0) {
|
|
2777
|
+
this.subscriptions.delete(uri);
|
|
2778
|
+
}
|
|
2779
|
+
console.log(
|
|
2780
|
+
`[MCP] Session ${sessionId} unsubscribed from resource: ${uri}`
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
return {};
|
|
2784
|
+
}
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
/**
|
|
2788
|
+
* Get session ID from request context or sessions map
|
|
2789
|
+
*
|
|
2790
|
+
* @param sessions - Map of active sessions
|
|
2791
|
+
* @param server - The server instance to match against
|
|
2792
|
+
* @returns The session ID, or undefined if not found
|
|
2793
|
+
*/
|
|
2794
|
+
getSessionIdFromContext(sessions, server) {
|
|
2795
|
+
const requestContext = getRequestContext();
|
|
2796
|
+
let sessionId;
|
|
2797
|
+
if (requestContext) {
|
|
2798
|
+
sessionId = requestContext.req.header("mcp-session-id");
|
|
2799
|
+
}
|
|
2800
|
+
if (!sessionId) {
|
|
2801
|
+
for (const [sid, session] of sessions.entries()) {
|
|
2802
|
+
if (session.server === server) {
|
|
2803
|
+
sessionId = sid;
|
|
2804
|
+
break;
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
return sessionId;
|
|
2809
|
+
}
|
|
2810
|
+
/**
|
|
2811
|
+
* Notify subscribed clients that a resource has been updated
|
|
2812
|
+
*
|
|
2813
|
+
* This method sends a `notifications/resources/updated` notification to all
|
|
2814
|
+
* sessions that have subscribed to the specified resource URI.
|
|
2815
|
+
*
|
|
2816
|
+
* @param uri - The URI of the resource that changed
|
|
2817
|
+
* @param sessions - Map of active sessions
|
|
2818
|
+
* @returns Promise that resolves when all notifications have been sent
|
|
2819
|
+
*/
|
|
2820
|
+
async notifyResourceUpdated(uri, sessions) {
|
|
2821
|
+
const subscribers = this.subscriptions.get(uri);
|
|
2822
|
+
if (!subscribers || subscribers.size === 0) {
|
|
2823
|
+
return;
|
|
2824
|
+
}
|
|
2825
|
+
console.log(
|
|
2826
|
+
`[MCP] Notifying ${subscribers.size} subscriber(s) of resource update: ${uri}`
|
|
2827
|
+
);
|
|
2828
|
+
for (const sessionId of subscribers) {
|
|
2829
|
+
const session = sessions.get(sessionId);
|
|
2830
|
+
if (session?.server) {
|
|
2831
|
+
try {
|
|
2832
|
+
await session.server.server.sendResourceUpdated({ uri });
|
|
2833
|
+
console.log(
|
|
2834
|
+
`[MCP] Sent resource update notification to session ${sessionId}`
|
|
2835
|
+
);
|
|
2836
|
+
} catch (error2) {
|
|
2837
|
+
console.error(
|
|
2838
|
+
`[MCP] Failed to send resource update notification to session ${sessionId}:`,
|
|
2839
|
+
error2
|
|
2840
|
+
);
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
}
|
|
2844
|
+
}
|
|
2845
|
+
/**
|
|
2846
|
+
* Clean up resource subscriptions for a closed session
|
|
2847
|
+
*
|
|
2848
|
+
* This method is called automatically when a session is closed to remove
|
|
2849
|
+
* all resource subscriptions associated with that session.
|
|
2850
|
+
*
|
|
2851
|
+
* @param sessionId - The session ID to clean up
|
|
2852
|
+
*/
|
|
2853
|
+
cleanupSession(sessionId) {
|
|
2854
|
+
for (const [uri, subscribers] of this.subscriptions) {
|
|
2855
|
+
subscribers.delete(sessionId);
|
|
2856
|
+
if (subscribers.size === 0) {
|
|
2857
|
+
this.subscriptions.delete(uri);
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
console.log(
|
|
2861
|
+
`[MCP] Cleaned up resource subscriptions for session ${sessionId}`
|
|
2862
|
+
);
|
|
2863
|
+
}
|
|
2864
|
+
};
|
|
2865
|
+
|
|
2866
|
+
// src/server/resources/index.ts
|
|
2470
2867
|
function registerResource(resourceDefinition, callback) {
|
|
2471
2868
|
const actualCallback = callback || resourceDefinition.readCallback;
|
|
2472
2869
|
if (!actualCallback) {
|
|
@@ -2525,24 +2922,25 @@ function registerResourceTemplate(resourceTemplateDefinition, callback) {
|
|
|
2525
2922
|
`Resource template '${resourceTemplateDefinition.name}' must have either a readCallback property or a callback parameter`
|
|
2526
2923
|
);
|
|
2527
2924
|
}
|
|
2528
|
-
const
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2925
|
+
const isFlatStructure = "uriTemplate" in resourceTemplateDefinition;
|
|
2926
|
+
const uriTemplate = isFlatStructure ? resourceTemplateDefinition.uriTemplate : resourceTemplateDefinition.resourceTemplate.uriTemplate;
|
|
2927
|
+
const mimeType = isFlatStructure ? resourceTemplateDefinition.mimeType : resourceTemplateDefinition.resourceTemplate.mimeType;
|
|
2928
|
+
const templateDescription = isFlatStructure ? void 0 : resourceTemplateDefinition.resourceTemplate.description;
|
|
2929
|
+
const template = new import_mcp.ResourceTemplate(uriTemplate, {
|
|
2930
|
+
list: void 0,
|
|
2931
|
+
// Optional: callback to list all matching resources
|
|
2932
|
+
complete: void 0
|
|
2933
|
+
// Optional: callback for auto-completion
|
|
2934
|
+
});
|
|
2537
2935
|
const metadata = {};
|
|
2538
2936
|
if (resourceTemplateDefinition.title) {
|
|
2539
2937
|
metadata.title = resourceTemplateDefinition.title;
|
|
2540
2938
|
}
|
|
2541
|
-
if (resourceTemplateDefinition.description ||
|
|
2542
|
-
metadata.description = resourceTemplateDefinition.description ||
|
|
2939
|
+
if (resourceTemplateDefinition.description || templateDescription) {
|
|
2940
|
+
metadata.description = resourceTemplateDefinition.description || templateDescription;
|
|
2543
2941
|
}
|
|
2544
|
-
if (
|
|
2545
|
-
metadata.mimeType =
|
|
2942
|
+
if (mimeType) {
|
|
2943
|
+
metadata.mimeType = mimeType;
|
|
2546
2944
|
}
|
|
2547
2945
|
if (resourceTemplateDefinition.annotations) {
|
|
2548
2946
|
metadata.annotations = resourceTemplateDefinition.annotations;
|
|
@@ -2552,10 +2950,7 @@ function registerResourceTemplate(resourceTemplateDefinition, callback) {
|
|
|
2552
2950
|
template,
|
|
2553
2951
|
metadata,
|
|
2554
2952
|
async (uri) => {
|
|
2555
|
-
const params = this.parseTemplateUri(
|
|
2556
|
-
resourceTemplateDefinition.resourceTemplate.uriTemplate,
|
|
2557
|
-
uri.toString()
|
|
2558
|
-
);
|
|
2953
|
+
const params = this.parseTemplateUri(uriTemplate, uri.toString());
|
|
2559
2954
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await Promise.resolve().then(() => (init_context_storage(), context_storage_exports));
|
|
2560
2955
|
const { findSessionContext: findSessionContext2 } = await Promise.resolve().then(() => (init_tool_execution_helpers(), tool_execution_helpers_exports));
|
|
2561
2956
|
const initialRequestContext = getRequestContext2();
|
|
@@ -2570,8 +2965,12 @@ function registerResourceTemplate(resourceTemplateDefinition, callback) {
|
|
|
2570
2965
|
const executeCallback = /* @__PURE__ */ __name(async () => {
|
|
2571
2966
|
if (actualCallback.length >= 3) {
|
|
2572
2967
|
return await actualCallback(uri, params, enhancedContext);
|
|
2968
|
+
} else if (actualCallback.length === 2) {
|
|
2969
|
+
return await actualCallback(uri, params);
|
|
2970
|
+
} else if (actualCallback.length === 1) {
|
|
2971
|
+
return await actualCallback(uri);
|
|
2573
2972
|
}
|
|
2574
|
-
return await actualCallback(
|
|
2973
|
+
return await actualCallback();
|
|
2575
2974
|
}, "executeCallback");
|
|
2576
2975
|
const result = requestContext ? await runWithContext2(requestContext, executeCallback) : await executeCallback();
|
|
2577
2976
|
if ("contents" in result && Array.isArray(result.contents)) {
|
|
@@ -2602,8 +3001,10 @@ function registerPrompt(promptDefinition, callback) {
|
|
|
2602
3001
|
argsSchema = this.convertZodSchemaToParams(
|
|
2603
3002
|
promptDefinition.schema
|
|
2604
3003
|
);
|
|
3004
|
+
} else if (promptDefinition.args && promptDefinition.args.length > 0) {
|
|
3005
|
+
argsSchema = this.createParamsSchema(promptDefinition.args);
|
|
2605
3006
|
} else {
|
|
2606
|
-
argsSchema =
|
|
3007
|
+
argsSchema = void 0;
|
|
2607
3008
|
}
|
|
2608
3009
|
const wrappedCallback = /* @__PURE__ */ __name(async (params, extra) => {
|
|
2609
3010
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await Promise.resolve().then(() => (init_context_storage(), context_storage_exports));
|
|
@@ -2886,7 +3287,7 @@ init_tool_execution_helpers();
|
|
|
2886
3287
|
init_context_storage();
|
|
2887
3288
|
|
|
2888
3289
|
// src/server/sessions/session-manager.ts
|
|
2889
|
-
function startIdleCleanup(sessions, idleTimeoutMs) {
|
|
3290
|
+
function startIdleCleanup(sessions, idleTimeoutMs, mcpServerInstance) {
|
|
2890
3291
|
if (idleTimeoutMs <= 0) {
|
|
2891
3292
|
return void 0;
|
|
2892
3293
|
}
|
|
@@ -2904,6 +3305,7 @@ function startIdleCleanup(sessions, idleTimeoutMs) {
|
|
|
2904
3305
|
);
|
|
2905
3306
|
for (const sessionId of expiredSessions) {
|
|
2906
3307
|
sessions.delete(sessionId);
|
|
3308
|
+
mcpServerInstance?.cleanupSessionSubscriptions?.(sessionId);
|
|
2907
3309
|
}
|
|
2908
3310
|
}
|
|
2909
3311
|
}, 6e4);
|
|
@@ -2918,7 +3320,11 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
2918
3320
|
const transports = /* @__PURE__ */ new Map();
|
|
2919
3321
|
let idleCleanupInterval;
|
|
2920
3322
|
if (idleTimeoutMs > 0) {
|
|
2921
|
-
idleCleanupInterval = startIdleCleanup(
|
|
3323
|
+
idleCleanupInterval = startIdleCleanup(
|
|
3324
|
+
sessions,
|
|
3325
|
+
idleTimeoutMs,
|
|
3326
|
+
mcpServerInstance
|
|
3327
|
+
);
|
|
2922
3328
|
}
|
|
2923
3329
|
const handleRequest = /* @__PURE__ */ __name(async (c) => {
|
|
2924
3330
|
const sessionId = c.req.header("mcp-session-id");
|
|
@@ -2945,11 +3351,23 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
2945
3351
|
context: c,
|
|
2946
3352
|
honoContext: c
|
|
2947
3353
|
});
|
|
3354
|
+
server.server.oninitialized = () => {
|
|
3355
|
+
const clientCapabilities = server.server.getClientCapabilities();
|
|
3356
|
+
if (clientCapabilities && sessions.has(sid)) {
|
|
3357
|
+
const session = sessions.get(sid);
|
|
3358
|
+
session.clientCapabilities = clientCapabilities;
|
|
3359
|
+
console.log(
|
|
3360
|
+
`[MCP] Captured client capabilities for session ${sid}:`,
|
|
3361
|
+
Object.keys(clientCapabilities)
|
|
3362
|
+
);
|
|
3363
|
+
}
|
|
3364
|
+
};
|
|
2948
3365
|
}, "onsessioninitialized"),
|
|
2949
3366
|
onsessionclosed: /* @__PURE__ */ __name((sid) => {
|
|
2950
3367
|
console.log(`[MCP] Session closed: ${sid}`);
|
|
2951
3368
|
transports.delete(sid);
|
|
2952
3369
|
sessions.delete(sid);
|
|
3370
|
+
mcpServerInstance.cleanupSessionSubscriptions?.(sid);
|
|
2953
3371
|
}, "onsessionclosed")
|
|
2954
3372
|
});
|
|
2955
3373
|
await server.connect(transport);
|
|
@@ -3240,9 +3658,9 @@ async function setupOAuthForServer(app, oauthProvider, baseUrl, state) {
|
|
|
3240
3658
|
__name(setupOAuthForServer, "setupOAuthForServer");
|
|
3241
3659
|
|
|
3242
3660
|
// src/server/mcp-server.ts
|
|
3243
|
-
var
|
|
3661
|
+
var MCPServer = class {
|
|
3244
3662
|
static {
|
|
3245
|
-
__name(this, "
|
|
3663
|
+
__name(this, "MCPServer");
|
|
3246
3664
|
}
|
|
3247
3665
|
/**
|
|
3248
3666
|
* Native MCP server instance from @modelcontextprotocol/sdk
|
|
@@ -3285,6 +3703,22 @@ var McpServer = class {
|
|
|
3285
3703
|
resources: /* @__PURE__ */ new Map(),
|
|
3286
3704
|
resourceTemplates: /* @__PURE__ */ new Map()
|
|
3287
3705
|
};
|
|
3706
|
+
/**
|
|
3707
|
+
* Resource subscription manager for tracking and notifying resource updates
|
|
3708
|
+
*/
|
|
3709
|
+
subscriptionManager = new ResourceSubscriptionManager();
|
|
3710
|
+
/**
|
|
3711
|
+
* Clean up resource subscriptions for a closed session
|
|
3712
|
+
*
|
|
3713
|
+
* This method is called automatically when a session is closed to remove
|
|
3714
|
+
* all resource subscriptions associated with that session.
|
|
3715
|
+
*
|
|
3716
|
+
* @param sessionId - The session ID to clean up
|
|
3717
|
+
* @internal
|
|
3718
|
+
*/
|
|
3719
|
+
cleanupSessionSubscriptions(sessionId) {
|
|
3720
|
+
this.subscriptionManager.cleanupSession(sessionId);
|
|
3721
|
+
}
|
|
3288
3722
|
/**
|
|
3289
3723
|
* Creates a new MCP server instance with Hono integration
|
|
3290
3724
|
*
|
|
@@ -3293,16 +3727,27 @@ var McpServer = class {
|
|
|
3293
3727
|
* access to Hono methods while preserving MCP server functionality.
|
|
3294
3728
|
*
|
|
3295
3729
|
* @param config - Server configuration including name, version, and description
|
|
3296
|
-
* @returns A proxied
|
|
3730
|
+
* @returns A proxied MCPServer instance that supports both MCP and Hono methods
|
|
3297
3731
|
*/
|
|
3298
3732
|
constructor(config) {
|
|
3299
3733
|
this.config = config;
|
|
3300
3734
|
this.serverHost = config.host || "localhost";
|
|
3301
3735
|
this.serverBaseUrl = config.baseUrl;
|
|
3302
|
-
this.nativeServer = new import_mcp2.McpServer(
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3736
|
+
this.nativeServer = new import_mcp2.McpServer(
|
|
3737
|
+
{
|
|
3738
|
+
name: config.name,
|
|
3739
|
+
version: config.version
|
|
3740
|
+
},
|
|
3741
|
+
{
|
|
3742
|
+
capabilities: {
|
|
3743
|
+
logging: {},
|
|
3744
|
+
resources: {
|
|
3745
|
+
subscribe: true,
|
|
3746
|
+
listChanged: true
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
);
|
|
3306
3751
|
this.app = createHonoApp(requestLogger);
|
|
3307
3752
|
this.oauthConfig = config.oauth;
|
|
3308
3753
|
this.wrapRegistrationMethods();
|
|
@@ -3357,10 +3802,17 @@ var McpServer = class {
|
|
|
3357
3802
|
* This is called for each initialize request to create an isolated server.
|
|
3358
3803
|
*/
|
|
3359
3804
|
getServerForSession() {
|
|
3360
|
-
const newServer = new import_mcp2.McpServer(
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3805
|
+
const newServer = new import_mcp2.McpServer(
|
|
3806
|
+
{
|
|
3807
|
+
name: this.config.name,
|
|
3808
|
+
version: this.config.version
|
|
3809
|
+
},
|
|
3810
|
+
{
|
|
3811
|
+
capabilities: {
|
|
3812
|
+
logging: {}
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
);
|
|
3364
3816
|
for (const [name, recipe] of this.registrationRecipes.tools) {
|
|
3365
3817
|
const { config, handler: actualCallback } = recipe;
|
|
3366
3818
|
let inputSchema;
|
|
@@ -3375,12 +3827,21 @@ var McpServer = class {
|
|
|
3375
3827
|
const initialRequestContext = getRequestContext();
|
|
3376
3828
|
const extraProgressToken = extra?._meta?.progressToken;
|
|
3377
3829
|
const extraSendNotification = extra?.sendNotification;
|
|
3378
|
-
const { requestContext, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
3830
|
+
const { requestContext, session, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
3379
3831
|
this.sessions,
|
|
3380
3832
|
initialRequestContext,
|
|
3381
3833
|
extraProgressToken,
|
|
3382
3834
|
extraSendNotification
|
|
3383
3835
|
);
|
|
3836
|
+
let sessionId;
|
|
3837
|
+
if (session) {
|
|
3838
|
+
for (const [id, s] of this.sessions.entries()) {
|
|
3839
|
+
if (s === session) {
|
|
3840
|
+
sessionId = id;
|
|
3841
|
+
break;
|
|
3842
|
+
}
|
|
3843
|
+
}
|
|
3844
|
+
}
|
|
3384
3845
|
const createMessageWithLogging = /* @__PURE__ */ __name(async (params2, options) => {
|
|
3385
3846
|
console.log("[createMessage] About to call server.createMessage");
|
|
3386
3847
|
console.log("[createMessage] Has server:", !!newServer);
|
|
@@ -3406,7 +3867,11 @@ var McpServer = class {
|
|
|
3406
3867
|
createMessageWithLogging,
|
|
3407
3868
|
newServer.server.elicitInput.bind(newServer.server),
|
|
3408
3869
|
progressToken,
|
|
3409
|
-
sendNotification2
|
|
3870
|
+
sendNotification2,
|
|
3871
|
+
session?.logLevel,
|
|
3872
|
+
session?.clientCapabilities,
|
|
3873
|
+
sessionId,
|
|
3874
|
+
this.sessions
|
|
3410
3875
|
);
|
|
3411
3876
|
const executeCallback = /* @__PURE__ */ __name(async () => {
|
|
3412
3877
|
if (actualCallback.length >= 2) {
|
|
@@ -3436,8 +3901,10 @@ var McpServer = class {
|
|
|
3436
3901
|
let argsSchema;
|
|
3437
3902
|
if (config.schema) {
|
|
3438
3903
|
argsSchema = this.convertZodSchemaToParams(config.schema);
|
|
3904
|
+
} else if (config.args && config.args.length > 0) {
|
|
3905
|
+
argsSchema = this.createParamsSchema(config.args);
|
|
3439
3906
|
} else {
|
|
3440
|
-
argsSchema =
|
|
3907
|
+
argsSchema = void 0;
|
|
3441
3908
|
}
|
|
3442
3909
|
const wrappedHandler = /* @__PURE__ */ __name(async (params) => {
|
|
3443
3910
|
const result = await handler(params);
|
|
@@ -3480,22 +3947,23 @@ var McpServer = class {
|
|
|
3480
3947
|
}
|
|
3481
3948
|
for (const [_name, recipe] of this.registrationRecipes.resourceTemplates) {
|
|
3482
3949
|
const { config, handler } = recipe;
|
|
3483
|
-
const
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3950
|
+
const isFlatStructure = "uriTemplate" in config;
|
|
3951
|
+
const uriTemplate = isFlatStructure ? config.uriTemplate : config.resourceTemplate.uriTemplate;
|
|
3952
|
+
const mimeType = isFlatStructure ? config.mimeType : config.resourceTemplate.mimeType;
|
|
3953
|
+
const templateDescription = isFlatStructure ? void 0 : config.resourceTemplate.description;
|
|
3954
|
+
const template = new import_mcp2.ResourceTemplate(uriTemplate, {
|
|
3955
|
+
list: void 0,
|
|
3956
|
+
complete: void 0
|
|
3957
|
+
});
|
|
3490
3958
|
const metadata = {};
|
|
3491
3959
|
if (config.title) {
|
|
3492
3960
|
metadata.title = config.title;
|
|
3493
3961
|
}
|
|
3494
|
-
if (config.description ||
|
|
3495
|
-
metadata.description = config.description ||
|
|
3962
|
+
if (config.description || templateDescription) {
|
|
3963
|
+
metadata.description = config.description || templateDescription;
|
|
3496
3964
|
}
|
|
3497
|
-
if (
|
|
3498
|
-
metadata.mimeType =
|
|
3965
|
+
if (mimeType) {
|
|
3966
|
+
metadata.mimeType = mimeType;
|
|
3499
3967
|
}
|
|
3500
3968
|
if (config.annotations) {
|
|
3501
3969
|
metadata.annotations = config.annotations;
|
|
@@ -3505,10 +3973,7 @@ var McpServer = class {
|
|
|
3505
3973
|
template,
|
|
3506
3974
|
metadata,
|
|
3507
3975
|
async (uri) => {
|
|
3508
|
-
const params = this.parseTemplateUri(
|
|
3509
|
-
config.resourceTemplate.uriTemplate,
|
|
3510
|
-
uri.toString()
|
|
3511
|
-
);
|
|
3976
|
+
const params = this.parseTemplateUri(uriTemplate, uri.toString());
|
|
3512
3977
|
const result = await handler(uri, params);
|
|
3513
3978
|
if ("contents" in result && Array.isArray(result.contents)) {
|
|
3514
3979
|
return result;
|
|
@@ -3518,6 +3983,50 @@ var McpServer = class {
|
|
|
3518
3983
|
}
|
|
3519
3984
|
);
|
|
3520
3985
|
}
|
|
3986
|
+
newServer.server.setRequestHandler(
|
|
3987
|
+
import_zod2.z.object({ method: import_zod2.z.literal("logging/setLevel") }).passthrough(),
|
|
3988
|
+
async (request) => {
|
|
3989
|
+
const level = request.params?.level;
|
|
3990
|
+
if (!level) {
|
|
3991
|
+
throw new import_types2.McpError(
|
|
3992
|
+
import_types2.ErrorCode.InvalidParams,
|
|
3993
|
+
"Missing 'level' parameter"
|
|
3994
|
+
);
|
|
3995
|
+
}
|
|
3996
|
+
if (!isValidLogLevel(level)) {
|
|
3997
|
+
throw new import_types2.McpError(
|
|
3998
|
+
import_types2.ErrorCode.InvalidParams,
|
|
3999
|
+
`Invalid log level '${level}'. Must be one of: debug, info, notice, warning, error, critical, alert, emergency`
|
|
4000
|
+
);
|
|
4001
|
+
}
|
|
4002
|
+
const requestContext = getRequestContext();
|
|
4003
|
+
if (requestContext) {
|
|
4004
|
+
const sessionId = requestContext.req.header("mcp-session-id");
|
|
4005
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
4006
|
+
const session = this.sessions.get(sessionId);
|
|
4007
|
+
session.logLevel = level;
|
|
4008
|
+
console.log(
|
|
4009
|
+
`[MCP] Set log level to '${level}' for session ${sessionId}`
|
|
4010
|
+
);
|
|
4011
|
+
return {};
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
4015
|
+
if (session.server === newServer) {
|
|
4016
|
+
session.logLevel = level;
|
|
4017
|
+
console.log(
|
|
4018
|
+
`[MCP] Set log level to '${level}' for session ${sessionId}`
|
|
4019
|
+
);
|
|
4020
|
+
return {};
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
console.warn(
|
|
4024
|
+
"[MCP] Could not find session for logging/setLevel request"
|
|
4025
|
+
);
|
|
4026
|
+
throw new import_types2.McpError(import_types2.ErrorCode.InternalError, "Could not find session");
|
|
4027
|
+
}
|
|
4028
|
+
);
|
|
4029
|
+
this.subscriptionManager.registerHandlers(newServer, this.sessions);
|
|
3521
4030
|
return newServer;
|
|
3522
4031
|
}
|
|
3523
4032
|
/**
|
|
@@ -3547,6 +4056,24 @@ var McpServer = class {
|
|
|
3547
4056
|
getActiveSessions = getActiveSessions;
|
|
3548
4057
|
sendNotification = sendNotification;
|
|
3549
4058
|
sendNotificationToSession = sendNotificationToSession2;
|
|
4059
|
+
/**
|
|
4060
|
+
* Notify subscribed clients that a resource has been updated
|
|
4061
|
+
*
|
|
4062
|
+
* This method sends a `notifications/resources/updated` notification to all
|
|
4063
|
+
* sessions that have subscribed to the specified resource URI.
|
|
4064
|
+
*
|
|
4065
|
+
* @param uri - The URI of the resource that changed
|
|
4066
|
+
* @returns Promise that resolves when all notifications have been sent
|
|
4067
|
+
*
|
|
4068
|
+
* @example
|
|
4069
|
+
* ```typescript
|
|
4070
|
+
* // After updating a resource, notify subscribers
|
|
4071
|
+
* await server.notifyResourceUpdated("file:///path/to/resource.txt");
|
|
4072
|
+
* ```
|
|
4073
|
+
*/
|
|
4074
|
+
async notifyResourceUpdated(uri) {
|
|
4075
|
+
return this.subscriptionManager.notifyResourceUpdated(uri, this.sessions);
|
|
4076
|
+
}
|
|
3550
4077
|
uiResource = uiResourceRegistration;
|
|
3551
4078
|
/**
|
|
3552
4079
|
* Mount MCP server endpoints at /mcp and /sse
|
|
@@ -3572,7 +4099,7 @@ var McpServer = class {
|
|
|
3572
4099
|
const result = await mountMcp(
|
|
3573
4100
|
this.app,
|
|
3574
4101
|
this,
|
|
3575
|
-
// Pass the
|
|
4102
|
+
// Pass the MCPServer instance so mountMcp can call getServerForSession()
|
|
3576
4103
|
this.sessions,
|
|
3577
4104
|
this.config,
|
|
3578
4105
|
isProductionMode()
|
|
@@ -3630,6 +4157,11 @@ var McpServer = class {
|
|
|
3630
4157
|
if (hostEnv) {
|
|
3631
4158
|
this.serverHost = hostEnv;
|
|
3632
4159
|
}
|
|
4160
|
+
this.serverBaseUrl = getServerBaseUrl(
|
|
4161
|
+
this.serverBaseUrl,
|
|
4162
|
+
this.serverHost,
|
|
4163
|
+
this.serverPort
|
|
4164
|
+
);
|
|
3633
4165
|
if (this.oauthConfig && !this.oauthSetupState.complete) {
|
|
3634
4166
|
await setupOAuthForServer(
|
|
3635
4167
|
this.app,
|
|
@@ -3667,7 +4199,7 @@ var McpServer = class {
|
|
|
3667
4199
|
* @example
|
|
3668
4200
|
* ```typescript
|
|
3669
4201
|
* // For Supabase Edge Functions (handles path rewriting automatically)
|
|
3670
|
-
* const server =
|
|
4202
|
+
* const server = new MCPServer({ name: 'my-server', version: '1.0.0' });
|
|
3671
4203
|
* server.tool({ ... });
|
|
3672
4204
|
* const handler = await server.getHandler({ provider: 'supabase' });
|
|
3673
4205
|
* Deno.serve(handler);
|
|
@@ -3676,7 +4208,7 @@ var McpServer = class {
|
|
|
3676
4208
|
* @example
|
|
3677
4209
|
* ```typescript
|
|
3678
4210
|
* // For Cloudflare Workers
|
|
3679
|
-
* const server =
|
|
4211
|
+
* const server = new MCPServer({ name: 'my-server', version: '1.0.0' });
|
|
3680
4212
|
* server.tool({ ... });
|
|
3681
4213
|
* const handler = await server.getHandler();
|
|
3682
4214
|
* export default { fetch: handler };
|
|
@@ -3754,7 +4286,7 @@ var McpServer = class {
|
|
|
3754
4286
|
}
|
|
3755
4287
|
};
|
|
3756
4288
|
function createMCPServer(name, config = {}) {
|
|
3757
|
-
const instance = new
|
|
4289
|
+
const instance = new MCPServer({
|
|
3758
4290
|
name,
|
|
3759
4291
|
version: config.version || "1.0.0",
|
|
3760
4292
|
description: config.description,
|