mcp-use 1.9.1-canary.0 → 1.9.1-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-KHTTBIRP.js → chunk-33U4IA4N.js} +58 -1
- package/dist/{chunk-5URNFWCQ.js → chunk-LWVK6RXA.js} +8 -3
- package/dist/{context-storage-TXQ4DVSS.js → context-storage-NA4MHWOZ.js} +3 -1
- 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 +447 -21
- package/dist/src/server/index.d.ts +1 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +391 -25
- package/dist/src/server/mcp-server.d.ts +30 -0
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/prompts/index.d.ts.map +1 -1
- package/dist/src/server/resources/index.d.ts +1 -0
- 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 +7 -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/types/tool-context.d.ts +16 -0
- package/dist/src/server/types/tool-context.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/{tool-execution-helpers-IVUDHXMK.js → tool-execution-helpers-BQJTPWPN.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,37 @@ 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 createEnhancedContext(baseContext, createMessage, elicitInput, progressToken, sendNotification2, minLogLevel) {
|
|
422
460
|
const enhancedContext = baseContext ? Object.create(baseContext) : {};
|
|
423
461
|
enhancedContext.sample = createSampleMethod(
|
|
424
462
|
createMessage,
|
|
@@ -430,9 +468,10 @@ function createEnhancedContext(baseContext, createMessage, elicitInput, progress
|
|
|
430
468
|
progressToken,
|
|
431
469
|
sendNotification2
|
|
432
470
|
);
|
|
471
|
+
enhancedContext.log = createLogMethod(sendNotification2, minLogLevel);
|
|
433
472
|
return enhancedContext;
|
|
434
473
|
}
|
|
435
|
-
var import_zod_json_schema_compat;
|
|
474
|
+
var import_zod_json_schema_compat, LOG_LEVELS, VALID_LOG_LEVELS;
|
|
436
475
|
var init_tool_execution_helpers = __esm({
|
|
437
476
|
"src/server/tools/tool-execution-helpers.ts"() {
|
|
438
477
|
"use strict";
|
|
@@ -446,6 +485,29 @@ var init_tool_execution_helpers = __esm({
|
|
|
446
485
|
__name(createSampleMethod, "createSampleMethod");
|
|
447
486
|
__name(createElicitMethod, "createElicitMethod");
|
|
448
487
|
__name(createReportProgressMethod, "createReportProgressMethod");
|
|
488
|
+
LOG_LEVELS = {
|
|
489
|
+
debug: 0,
|
|
490
|
+
info: 1,
|
|
491
|
+
notice: 2,
|
|
492
|
+
warning: 3,
|
|
493
|
+
error: 4,
|
|
494
|
+
critical: 5,
|
|
495
|
+
alert: 6,
|
|
496
|
+
emergency: 7
|
|
497
|
+
};
|
|
498
|
+
VALID_LOG_LEVELS = [
|
|
499
|
+
"debug",
|
|
500
|
+
"info",
|
|
501
|
+
"notice",
|
|
502
|
+
"warning",
|
|
503
|
+
"error",
|
|
504
|
+
"critical",
|
|
505
|
+
"alert",
|
|
506
|
+
"emergency"
|
|
507
|
+
];
|
|
508
|
+
__name(isValidLogLevel, "isValidLogLevel");
|
|
509
|
+
__name(shouldLogMessage, "shouldLogMessage");
|
|
510
|
+
__name(createLogMethod, "createLogMethod");
|
|
449
511
|
__name(createEnhancedContext, "createEnhancedContext");
|
|
450
512
|
}
|
|
451
513
|
});
|
|
@@ -646,6 +708,7 @@ __export(server_exports, {
|
|
|
646
708
|
adaptConnectMiddleware: () => adaptConnectMiddleware,
|
|
647
709
|
adaptMiddleware: () => adaptMiddleware,
|
|
648
710
|
array: () => array,
|
|
711
|
+
audio: () => audio,
|
|
649
712
|
binary: () => binary,
|
|
650
713
|
buildWidgetUrl: () => buildWidgetUrl,
|
|
651
714
|
createExternalUrlResource: () => createExternalUrlResource,
|
|
@@ -684,11 +747,14 @@ module.exports = __toCommonJS(server_exports);
|
|
|
684
747
|
|
|
685
748
|
// src/server/mcp-server.ts
|
|
686
749
|
var import_mcp2 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
750
|
+
var import_types2 = require("@modelcontextprotocol/sdk/types.js");
|
|
751
|
+
var import_zod2 = require("zod");
|
|
687
752
|
|
|
688
753
|
// src/server/widgets/index.ts
|
|
689
754
|
init_runtime();
|
|
690
755
|
|
|
691
756
|
// src/server/utils/response-helpers.ts
|
|
757
|
+
init_runtime();
|
|
692
758
|
function text(content) {
|
|
693
759
|
return {
|
|
694
760
|
content: [
|
|
@@ -719,7 +785,109 @@ function image(data, mimeType = "image/png") {
|
|
|
719
785
|
};
|
|
720
786
|
}
|
|
721
787
|
__name(image, "image");
|
|
722
|
-
function
|
|
788
|
+
function getAudioMimeType(filename) {
|
|
789
|
+
const ext = filename.split(".").pop()?.toLowerCase();
|
|
790
|
+
switch (ext) {
|
|
791
|
+
case "wav":
|
|
792
|
+
return "audio/wav";
|
|
793
|
+
case "mp3":
|
|
794
|
+
return "audio/mpeg";
|
|
795
|
+
case "ogg":
|
|
796
|
+
return "audio/ogg";
|
|
797
|
+
case "m4a":
|
|
798
|
+
return "audio/mp4";
|
|
799
|
+
case "webm":
|
|
800
|
+
return "audio/webm";
|
|
801
|
+
case "flac":
|
|
802
|
+
return "audio/flac";
|
|
803
|
+
case "aac":
|
|
804
|
+
return "audio/aac";
|
|
805
|
+
default:
|
|
806
|
+
return "audio/wav";
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
__name(getAudioMimeType, "getAudioMimeType");
|
|
810
|
+
function arrayBufferToBase64(buffer) {
|
|
811
|
+
if (isDeno) {
|
|
812
|
+
const bytes = new Uint8Array(buffer);
|
|
813
|
+
let binary2 = "";
|
|
814
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
815
|
+
binary2 += String.fromCharCode(bytes[i]);
|
|
816
|
+
}
|
|
817
|
+
return btoa(binary2);
|
|
818
|
+
} else {
|
|
819
|
+
return Buffer.from(buffer).toString("base64");
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
__name(arrayBufferToBase64, "arrayBufferToBase64");
|
|
823
|
+
function audio(dataOrPath, mimeType) {
|
|
824
|
+
const isFilePath = dataOrPath.includes("/") || dataOrPath.includes("\\") || dataOrPath.includes(".");
|
|
825
|
+
if (isFilePath && dataOrPath.length < 1e3) {
|
|
826
|
+
return (async () => {
|
|
827
|
+
const buffer = await fsHelpers.readFile(dataOrPath);
|
|
828
|
+
const base64Data = arrayBufferToBase64(buffer);
|
|
829
|
+
const inferredMimeType = mimeType || getAudioMimeType(dataOrPath);
|
|
830
|
+
return {
|
|
831
|
+
content: [
|
|
832
|
+
{
|
|
833
|
+
type: "audio",
|
|
834
|
+
data: base64Data,
|
|
835
|
+
mimeType: inferredMimeType
|
|
836
|
+
}
|
|
837
|
+
],
|
|
838
|
+
_meta: {
|
|
839
|
+
mimeType: inferredMimeType,
|
|
840
|
+
isAudio: true
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
})();
|
|
844
|
+
}
|
|
845
|
+
const finalMimeType = mimeType || "audio/wav";
|
|
846
|
+
return {
|
|
847
|
+
content: [
|
|
848
|
+
{
|
|
849
|
+
type: "audio",
|
|
850
|
+
data: dataOrPath,
|
|
851
|
+
mimeType: finalMimeType
|
|
852
|
+
}
|
|
853
|
+
],
|
|
854
|
+
_meta: {
|
|
855
|
+
mimeType: finalMimeType,
|
|
856
|
+
isAudio: true
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
__name(audio, "audio");
|
|
861
|
+
function resource(uri, mimeTypeOrContent, text2) {
|
|
862
|
+
if (typeof mimeTypeOrContent === "object" && mimeTypeOrContent !== null && "content" in mimeTypeOrContent) {
|
|
863
|
+
const contentResult = mimeTypeOrContent;
|
|
864
|
+
let extractedText;
|
|
865
|
+
let extractedMimeType;
|
|
866
|
+
if (contentResult._meta && typeof contentResult._meta === "object") {
|
|
867
|
+
const meta = contentResult._meta;
|
|
868
|
+
if (meta.mimeType && typeof meta.mimeType === "string") {
|
|
869
|
+
extractedMimeType = meta.mimeType;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (contentResult.content && contentResult.content.length > 0) {
|
|
873
|
+
const firstContent = contentResult.content[0];
|
|
874
|
+
if (firstContent.type === "text" && "text" in firstContent) {
|
|
875
|
+
extractedText = firstContent.text;
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
const resourceContent2 = {
|
|
879
|
+
type: "resource",
|
|
880
|
+
resource: {
|
|
881
|
+
uri,
|
|
882
|
+
...extractedMimeType && { mimeType: extractedMimeType },
|
|
883
|
+
...extractedText && { text: extractedText }
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
return {
|
|
887
|
+
content: [resourceContent2]
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
const mimeType = mimeTypeOrContent;
|
|
723
891
|
const resourceContent = {
|
|
724
892
|
type: "resource",
|
|
725
893
|
resource: {
|
|
@@ -998,7 +1166,7 @@ function parseTemplateUri(template, uri) {
|
|
|
998
1166
|
const params = {};
|
|
999
1167
|
let regexPattern = template.replace(/[.*+?^$()[\]\\|]/g, "\\$&");
|
|
1000
1168
|
const paramNames = [];
|
|
1001
|
-
regexPattern = regexPattern.replace(
|
|
1169
|
+
regexPattern = regexPattern.replace(/\{([^}]+)\}/g, (_, paramName) => {
|
|
1002
1170
|
paramNames.push(paramName);
|
|
1003
1171
|
return "([^/]+)";
|
|
1004
1172
|
});
|
|
@@ -2467,6 +2635,152 @@ init_tool_execution_helpers();
|
|
|
2467
2635
|
// src/server/resources/index.ts
|
|
2468
2636
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
2469
2637
|
init_conversion();
|
|
2638
|
+
|
|
2639
|
+
// src/server/resources/subscriptions.ts
|
|
2640
|
+
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
2641
|
+
init_context_storage();
|
|
2642
|
+
var ResourceSubscriptionManager = class {
|
|
2643
|
+
static {
|
|
2644
|
+
__name(this, "ResourceSubscriptionManager");
|
|
2645
|
+
}
|
|
2646
|
+
/**
|
|
2647
|
+
* Tracks resource subscriptions per session
|
|
2648
|
+
* Map structure: uri -> Set<sessionId>
|
|
2649
|
+
*/
|
|
2650
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
2651
|
+
/**
|
|
2652
|
+
* Register subscription handlers with an MCP server instance
|
|
2653
|
+
*
|
|
2654
|
+
* @param server - The native MCP server instance
|
|
2655
|
+
* @param sessions - Map of active sessions
|
|
2656
|
+
*/
|
|
2657
|
+
registerHandlers(server, sessions) {
|
|
2658
|
+
server.server.setRequestHandler(
|
|
2659
|
+
import_types.SubscribeRequestSchema,
|
|
2660
|
+
async (request) => {
|
|
2661
|
+
const { uri } = request.params;
|
|
2662
|
+
const sessionId = this.getSessionIdFromContext(sessions, server);
|
|
2663
|
+
if (!sessionId) {
|
|
2664
|
+
console.warn(
|
|
2665
|
+
`[MCP] Could not determine session ID for resource subscription to ${uri}`
|
|
2666
|
+
);
|
|
2667
|
+
return {};
|
|
2668
|
+
}
|
|
2669
|
+
if (!this.subscriptions.has(uri)) {
|
|
2670
|
+
this.subscriptions.set(uri, /* @__PURE__ */ new Set());
|
|
2671
|
+
}
|
|
2672
|
+
this.subscriptions.get(uri).add(sessionId);
|
|
2673
|
+
console.log(
|
|
2674
|
+
`[MCP] Session ${sessionId} subscribed to resource: ${uri}`
|
|
2675
|
+
);
|
|
2676
|
+
return {};
|
|
2677
|
+
}
|
|
2678
|
+
);
|
|
2679
|
+
server.server.setRequestHandler(
|
|
2680
|
+
import_types.UnsubscribeRequestSchema,
|
|
2681
|
+
async (request) => {
|
|
2682
|
+
const { uri } = request.params;
|
|
2683
|
+
const sessionId = this.getSessionIdFromContext(sessions, server);
|
|
2684
|
+
if (!sessionId) {
|
|
2685
|
+
console.warn(
|
|
2686
|
+
`[MCP] Could not determine session ID for resource unsubscribe from ${uri}`
|
|
2687
|
+
);
|
|
2688
|
+
return {};
|
|
2689
|
+
}
|
|
2690
|
+
const subscribers = this.subscriptions.get(uri);
|
|
2691
|
+
if (subscribers) {
|
|
2692
|
+
subscribers.delete(sessionId);
|
|
2693
|
+
if (subscribers.size === 0) {
|
|
2694
|
+
this.subscriptions.delete(uri);
|
|
2695
|
+
}
|
|
2696
|
+
console.log(
|
|
2697
|
+
`[MCP] Session ${sessionId} unsubscribed from resource: ${uri}`
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
return {};
|
|
2701
|
+
}
|
|
2702
|
+
);
|
|
2703
|
+
}
|
|
2704
|
+
/**
|
|
2705
|
+
* Get session ID from request context or sessions map
|
|
2706
|
+
*
|
|
2707
|
+
* @param sessions - Map of active sessions
|
|
2708
|
+
* @param server - The server instance to match against
|
|
2709
|
+
* @returns The session ID, or undefined if not found
|
|
2710
|
+
*/
|
|
2711
|
+
getSessionIdFromContext(sessions, server) {
|
|
2712
|
+
const requestContext = getRequestContext();
|
|
2713
|
+
let sessionId;
|
|
2714
|
+
if (requestContext) {
|
|
2715
|
+
sessionId = requestContext.req.header("mcp-session-id");
|
|
2716
|
+
}
|
|
2717
|
+
if (!sessionId) {
|
|
2718
|
+
for (const [sid, session] of sessions.entries()) {
|
|
2719
|
+
if (session.server === server) {
|
|
2720
|
+
sessionId = sid;
|
|
2721
|
+
break;
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
return sessionId;
|
|
2726
|
+
}
|
|
2727
|
+
/**
|
|
2728
|
+
* Notify subscribed clients that a resource has been updated
|
|
2729
|
+
*
|
|
2730
|
+
* This method sends a `notifications/resources/updated` notification to all
|
|
2731
|
+
* sessions that have subscribed to the specified resource URI.
|
|
2732
|
+
*
|
|
2733
|
+
* @param uri - The URI of the resource that changed
|
|
2734
|
+
* @param sessions - Map of active sessions
|
|
2735
|
+
* @returns Promise that resolves when all notifications have been sent
|
|
2736
|
+
*/
|
|
2737
|
+
async notifyResourceUpdated(uri, sessions) {
|
|
2738
|
+
const subscribers = this.subscriptions.get(uri);
|
|
2739
|
+
if (!subscribers || subscribers.size === 0) {
|
|
2740
|
+
return;
|
|
2741
|
+
}
|
|
2742
|
+
console.log(
|
|
2743
|
+
`[MCP] Notifying ${subscribers.size} subscriber(s) of resource update: ${uri}`
|
|
2744
|
+
);
|
|
2745
|
+
for (const sessionId of subscribers) {
|
|
2746
|
+
const session = sessions.get(sessionId);
|
|
2747
|
+
if (session?.server) {
|
|
2748
|
+
try {
|
|
2749
|
+
await session.server.server.sendResourceUpdated({ uri });
|
|
2750
|
+
console.log(
|
|
2751
|
+
`[MCP] Sent resource update notification to session ${sessionId}`
|
|
2752
|
+
);
|
|
2753
|
+
} catch (error2) {
|
|
2754
|
+
console.error(
|
|
2755
|
+
`[MCP] Failed to send resource update notification to session ${sessionId}:`,
|
|
2756
|
+
error2
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
/**
|
|
2763
|
+
* Clean up resource subscriptions for a closed session
|
|
2764
|
+
*
|
|
2765
|
+
* This method is called automatically when a session is closed to remove
|
|
2766
|
+
* all resource subscriptions associated with that session.
|
|
2767
|
+
*
|
|
2768
|
+
* @param sessionId - The session ID to clean up
|
|
2769
|
+
*/
|
|
2770
|
+
cleanupSession(sessionId) {
|
|
2771
|
+
for (const [uri, subscribers] of this.subscriptions) {
|
|
2772
|
+
subscribers.delete(sessionId);
|
|
2773
|
+
if (subscribers.size === 0) {
|
|
2774
|
+
this.subscriptions.delete(uri);
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
console.log(
|
|
2778
|
+
`[MCP] Cleaned up resource subscriptions for session ${sessionId}`
|
|
2779
|
+
);
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
|
|
2783
|
+
// src/server/resources/index.ts
|
|
2470
2784
|
function registerResource(resourceDefinition, callback) {
|
|
2471
2785
|
const actualCallback = callback || resourceDefinition.readCallback;
|
|
2472
2786
|
if (!actualCallback) {
|
|
@@ -2602,8 +2916,10 @@ function registerPrompt(promptDefinition, callback) {
|
|
|
2602
2916
|
argsSchema = this.convertZodSchemaToParams(
|
|
2603
2917
|
promptDefinition.schema
|
|
2604
2918
|
);
|
|
2919
|
+
} else if (promptDefinition.args && promptDefinition.args.length > 0) {
|
|
2920
|
+
argsSchema = this.createParamsSchema(promptDefinition.args);
|
|
2605
2921
|
} else {
|
|
2606
|
-
argsSchema =
|
|
2922
|
+
argsSchema = void 0;
|
|
2607
2923
|
}
|
|
2608
2924
|
const wrappedCallback = /* @__PURE__ */ __name(async (params, extra) => {
|
|
2609
2925
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await Promise.resolve().then(() => (init_context_storage(), context_storage_exports));
|
|
@@ -2886,7 +3202,7 @@ init_tool_execution_helpers();
|
|
|
2886
3202
|
init_context_storage();
|
|
2887
3203
|
|
|
2888
3204
|
// src/server/sessions/session-manager.ts
|
|
2889
|
-
function startIdleCleanup(sessions, idleTimeoutMs) {
|
|
3205
|
+
function startIdleCleanup(sessions, idleTimeoutMs, mcpServerInstance) {
|
|
2890
3206
|
if (idleTimeoutMs <= 0) {
|
|
2891
3207
|
return void 0;
|
|
2892
3208
|
}
|
|
@@ -2904,6 +3220,7 @@ function startIdleCleanup(sessions, idleTimeoutMs) {
|
|
|
2904
3220
|
);
|
|
2905
3221
|
for (const sessionId of expiredSessions) {
|
|
2906
3222
|
sessions.delete(sessionId);
|
|
3223
|
+
mcpServerInstance?.cleanupSessionSubscriptions?.(sessionId);
|
|
2907
3224
|
}
|
|
2908
3225
|
}
|
|
2909
3226
|
}, 6e4);
|
|
@@ -2918,7 +3235,11 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
2918
3235
|
const transports = /* @__PURE__ */ new Map();
|
|
2919
3236
|
let idleCleanupInterval;
|
|
2920
3237
|
if (idleTimeoutMs > 0) {
|
|
2921
|
-
idleCleanupInterval = startIdleCleanup(
|
|
3238
|
+
idleCleanupInterval = startIdleCleanup(
|
|
3239
|
+
sessions,
|
|
3240
|
+
idleTimeoutMs,
|
|
3241
|
+
mcpServerInstance
|
|
3242
|
+
);
|
|
2922
3243
|
}
|
|
2923
3244
|
const handleRequest = /* @__PURE__ */ __name(async (c) => {
|
|
2924
3245
|
const sessionId = c.req.header("mcp-session-id");
|
|
@@ -2950,6 +3271,7 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
2950
3271
|
console.log(`[MCP] Session closed: ${sid}`);
|
|
2951
3272
|
transports.delete(sid);
|
|
2952
3273
|
sessions.delete(sid);
|
|
3274
|
+
mcpServerInstance.cleanupSessionSubscriptions?.(sid);
|
|
2953
3275
|
}, "onsessionclosed")
|
|
2954
3276
|
});
|
|
2955
3277
|
await server.connect(transport);
|
|
@@ -3285,6 +3607,22 @@ var McpServer = class {
|
|
|
3285
3607
|
resources: /* @__PURE__ */ new Map(),
|
|
3286
3608
|
resourceTemplates: /* @__PURE__ */ new Map()
|
|
3287
3609
|
};
|
|
3610
|
+
/**
|
|
3611
|
+
* Resource subscription manager for tracking and notifying resource updates
|
|
3612
|
+
*/
|
|
3613
|
+
subscriptionManager = new ResourceSubscriptionManager();
|
|
3614
|
+
/**
|
|
3615
|
+
* Clean up resource subscriptions for a closed session
|
|
3616
|
+
*
|
|
3617
|
+
* This method is called automatically when a session is closed to remove
|
|
3618
|
+
* all resource subscriptions associated with that session.
|
|
3619
|
+
*
|
|
3620
|
+
* @param sessionId - The session ID to clean up
|
|
3621
|
+
* @internal
|
|
3622
|
+
*/
|
|
3623
|
+
cleanupSessionSubscriptions(sessionId) {
|
|
3624
|
+
this.subscriptionManager.cleanupSession(sessionId);
|
|
3625
|
+
}
|
|
3288
3626
|
/**
|
|
3289
3627
|
* Creates a new MCP server instance with Hono integration
|
|
3290
3628
|
*
|
|
@@ -3299,10 +3637,21 @@ var McpServer = class {
|
|
|
3299
3637
|
this.config = config;
|
|
3300
3638
|
this.serverHost = config.host || "localhost";
|
|
3301
3639
|
this.serverBaseUrl = config.baseUrl;
|
|
3302
|
-
this.nativeServer = new import_mcp2.McpServer(
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3640
|
+
this.nativeServer = new import_mcp2.McpServer(
|
|
3641
|
+
{
|
|
3642
|
+
name: config.name,
|
|
3643
|
+
version: config.version
|
|
3644
|
+
},
|
|
3645
|
+
{
|
|
3646
|
+
capabilities: {
|
|
3647
|
+
logging: {},
|
|
3648
|
+
resources: {
|
|
3649
|
+
subscribe: true,
|
|
3650
|
+
listChanged: true
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
}
|
|
3654
|
+
);
|
|
3306
3655
|
this.app = createHonoApp(requestLogger);
|
|
3307
3656
|
this.oauthConfig = config.oauth;
|
|
3308
3657
|
this.wrapRegistrationMethods();
|
|
@@ -3357,10 +3706,17 @@ var McpServer = class {
|
|
|
3357
3706
|
* This is called for each initialize request to create an isolated server.
|
|
3358
3707
|
*/
|
|
3359
3708
|
getServerForSession() {
|
|
3360
|
-
const newServer = new import_mcp2.McpServer(
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3709
|
+
const newServer = new import_mcp2.McpServer(
|
|
3710
|
+
{
|
|
3711
|
+
name: this.config.name,
|
|
3712
|
+
version: this.config.version
|
|
3713
|
+
},
|
|
3714
|
+
{
|
|
3715
|
+
capabilities: {
|
|
3716
|
+
logging: {}
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
);
|
|
3364
3720
|
for (const [name, recipe] of this.registrationRecipes.tools) {
|
|
3365
3721
|
const { config, handler: actualCallback } = recipe;
|
|
3366
3722
|
let inputSchema;
|
|
@@ -3375,7 +3731,7 @@ var McpServer = class {
|
|
|
3375
3731
|
const initialRequestContext = getRequestContext();
|
|
3376
3732
|
const extraProgressToken = extra?._meta?.progressToken;
|
|
3377
3733
|
const extraSendNotification = extra?.sendNotification;
|
|
3378
|
-
const { requestContext, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
3734
|
+
const { requestContext, session, progressToken, sendNotification: sendNotification2 } = findSessionContext(
|
|
3379
3735
|
this.sessions,
|
|
3380
3736
|
initialRequestContext,
|
|
3381
3737
|
extraProgressToken,
|
|
@@ -3406,7 +3762,8 @@ var McpServer = class {
|
|
|
3406
3762
|
createMessageWithLogging,
|
|
3407
3763
|
newServer.server.elicitInput.bind(newServer.server),
|
|
3408
3764
|
progressToken,
|
|
3409
|
-
sendNotification2
|
|
3765
|
+
sendNotification2,
|
|
3766
|
+
session?.logLevel
|
|
3410
3767
|
);
|
|
3411
3768
|
const executeCallback = /* @__PURE__ */ __name(async () => {
|
|
3412
3769
|
if (actualCallback.length >= 2) {
|
|
@@ -3436,8 +3793,10 @@ var McpServer = class {
|
|
|
3436
3793
|
let argsSchema;
|
|
3437
3794
|
if (config.schema) {
|
|
3438
3795
|
argsSchema = this.convertZodSchemaToParams(config.schema);
|
|
3796
|
+
} else if (config.args && config.args.length > 0) {
|
|
3797
|
+
argsSchema = this.createParamsSchema(config.args);
|
|
3439
3798
|
} else {
|
|
3440
|
-
argsSchema =
|
|
3799
|
+
argsSchema = void 0;
|
|
3441
3800
|
}
|
|
3442
3801
|
const wrappedHandler = /* @__PURE__ */ __name(async (params) => {
|
|
3443
3802
|
const result = await handler(params);
|
|
@@ -3518,6 +3877,50 @@ var McpServer = class {
|
|
|
3518
3877
|
}
|
|
3519
3878
|
);
|
|
3520
3879
|
}
|
|
3880
|
+
newServer.server.setRequestHandler(
|
|
3881
|
+
import_zod2.z.object({ method: import_zod2.z.literal("logging/setLevel") }).passthrough(),
|
|
3882
|
+
async (request) => {
|
|
3883
|
+
const level = request.params?.level;
|
|
3884
|
+
if (!level) {
|
|
3885
|
+
throw new import_types2.McpError(
|
|
3886
|
+
import_types2.ErrorCode.InvalidParams,
|
|
3887
|
+
"Missing 'level' parameter"
|
|
3888
|
+
);
|
|
3889
|
+
}
|
|
3890
|
+
if (!isValidLogLevel(level)) {
|
|
3891
|
+
throw new import_types2.McpError(
|
|
3892
|
+
import_types2.ErrorCode.InvalidParams,
|
|
3893
|
+
`Invalid log level '${level}'. Must be one of: debug, info, notice, warning, error, critical, alert, emergency`
|
|
3894
|
+
);
|
|
3895
|
+
}
|
|
3896
|
+
const requestContext = getRequestContext();
|
|
3897
|
+
if (requestContext) {
|
|
3898
|
+
const sessionId = requestContext.req.header("mcp-session-id");
|
|
3899
|
+
if (sessionId && this.sessions.has(sessionId)) {
|
|
3900
|
+
const session = this.sessions.get(sessionId);
|
|
3901
|
+
session.logLevel = level;
|
|
3902
|
+
console.log(
|
|
3903
|
+
`[MCP] Set log level to '${level}' for session ${sessionId}`
|
|
3904
|
+
);
|
|
3905
|
+
return {};
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
3909
|
+
if (session.server === newServer) {
|
|
3910
|
+
session.logLevel = level;
|
|
3911
|
+
console.log(
|
|
3912
|
+
`[MCP] Set log level to '${level}' for session ${sessionId}`
|
|
3913
|
+
);
|
|
3914
|
+
return {};
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
console.warn(
|
|
3918
|
+
"[MCP] Could not find session for logging/setLevel request"
|
|
3919
|
+
);
|
|
3920
|
+
throw new import_types2.McpError(import_types2.ErrorCode.InternalError, "Could not find session");
|
|
3921
|
+
}
|
|
3922
|
+
);
|
|
3923
|
+
this.subscriptionManager.registerHandlers(newServer, this.sessions);
|
|
3521
3924
|
return newServer;
|
|
3522
3925
|
}
|
|
3523
3926
|
/**
|
|
@@ -3547,6 +3950,24 @@ var McpServer = class {
|
|
|
3547
3950
|
getActiveSessions = getActiveSessions;
|
|
3548
3951
|
sendNotification = sendNotification;
|
|
3549
3952
|
sendNotificationToSession = sendNotificationToSession2;
|
|
3953
|
+
/**
|
|
3954
|
+
* Notify subscribed clients that a resource has been updated
|
|
3955
|
+
*
|
|
3956
|
+
* This method sends a `notifications/resources/updated` notification to all
|
|
3957
|
+
* sessions that have subscribed to the specified resource URI.
|
|
3958
|
+
*
|
|
3959
|
+
* @param uri - The URI of the resource that changed
|
|
3960
|
+
* @returns Promise that resolves when all notifications have been sent
|
|
3961
|
+
*
|
|
3962
|
+
* @example
|
|
3963
|
+
* ```typescript
|
|
3964
|
+
* // After updating a resource, notify subscribers
|
|
3965
|
+
* await server.notifyResourceUpdated("file:///path/to/resource.txt");
|
|
3966
|
+
* ```
|
|
3967
|
+
*/
|
|
3968
|
+
async notifyResourceUpdated(uri) {
|
|
3969
|
+
return this.subscriptionManager.notifyResourceUpdated(uri, this.sessions);
|
|
3970
|
+
}
|
|
3550
3971
|
uiResource = uiResourceRegistration;
|
|
3551
3972
|
/**
|
|
3552
3973
|
* Mount MCP server endpoints at /mcp and /sse
|
|
@@ -3630,6 +4051,11 @@ var McpServer = class {
|
|
|
3630
4051
|
if (hostEnv) {
|
|
3631
4052
|
this.serverHost = hostEnv;
|
|
3632
4053
|
}
|
|
4054
|
+
this.serverBaseUrl = getServerBaseUrl(
|
|
4055
|
+
this.serverBaseUrl,
|
|
4056
|
+
this.serverHost,
|
|
4057
|
+
this.serverPort
|
|
4058
|
+
);
|
|
3633
4059
|
if (this.oauthConfig && !this.oauthSetupState.complete) {
|
|
3634
4060
|
await setupOAuthForServer(
|
|
3635
4061
|
this.app,
|
|
@@ -2,7 +2,7 @@ export { createMCPServer, type McpServerInstance } from "./mcp-server.js";
|
|
|
2
2
|
export type { ToolContext, SampleOptions, ElicitOptions, ElicitFormParams, ElicitUrlParams, } from "./types/tool-context.js";
|
|
3
3
|
export * from "./types/index.js";
|
|
4
4
|
export { getRequestContext, runWithContext, hasRequestContext, } from "./context-storage.js";
|
|
5
|
-
export { text, image, resource, error, object, array, widget, mix, html, markdown, xml, css, javascript, binary, type WidgetResponseConfig, type TypedCallToolResult, } from "./utils/response-helpers.js";
|
|
5
|
+
export { text, image, resource, error, object, array, widget, mix, audio, html, markdown, xml, css, javascript, binary, type WidgetResponseConfig, type TypedCallToolResult, } from "./utils/response-helpers.js";
|
|
6
6
|
export { getAuth, hasScope, hasAnyScope, requireScope, requireAnyScope, oauthSupabaseProvider, oauthAuth0Provider, oauthKeycloakProvider, oauthWorkOSProvider, oauthCustomProvider, type AuthInfo, type OAuthProvider, type UserInfo, type SupabaseProviderConfig, type Auth0ProviderConfig, type KeycloakProviderConfig, type WorkOSProviderConfig, type CustomProviderConfig, } from "./oauth/index.js";
|
|
7
7
|
export { buildWidgetUrl, createExternalUrlResource, createRawHtmlResource, createRemoteDomResource, createUIResourceFromDefinition, type UrlConfig, } from "./widgets/mcp-ui-adapter.js";
|
|
8
8
|
export { adaptConnectMiddleware, adaptMiddleware, isExpressMiddleware, } from "./connect-adapter.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG1E,YAAY,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,GAAG,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAG1E,YAAY,EACV,WAAW,EACX,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,MAAM,EACN,KAAK,EACL,MAAM,EACN,GAAG,EACH,KAAK,EAEL,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,GAAG,EACH,UAAU,EACV,MAAM,EACN,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,OAAO,EACP,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,eAAe,EACf,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,KAAK,SAAS,GACf,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EAEd,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
|