@mastra/mcp 0.10.5-alpha.1 → 0.10.5
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +38 -0
- package/dist/_tsup-dts-rollup.d.cts +84 -51
- package/dist/_tsup-dts-rollup.d.ts +84 -51
- package/dist/index.cjs +403 -398
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +404 -399
- package/integration-tests/node_modules/.bin/mastra +21 -0
- package/package.json +3 -3
- package/src/client/client.test.ts +310 -1
- package/src/client/client.ts +21 -2
- package/src/client/configuration.ts +22 -2
- package/src/client/elicitationActions.ts +26 -0
- package/src/client/index.ts +1 -1
- package/src/server/server.test.ts +349 -0
- package/src/server/server.ts +424 -457
- package/src/server/types.ts +25 -1
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,23 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
29
29
|
var equal__default = /*#__PURE__*/_interopDefault(equal);
|
|
30
30
|
|
|
31
31
|
// src/client/client.ts
|
|
32
|
+
|
|
33
|
+
// src/client/elicitationActions.ts
|
|
34
|
+
var ElicitationClientActions = class {
|
|
35
|
+
client;
|
|
36
|
+
logger;
|
|
37
|
+
constructor({ client, logger }) {
|
|
38
|
+
this.client = client;
|
|
39
|
+
this.logger = logger;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Set a handler for elicitation requests.
|
|
43
|
+
* @param handler The callback function to handle the elicitation request.
|
|
44
|
+
*/
|
|
45
|
+
onRequest(handler) {
|
|
46
|
+
this.client.setElicitationRequestHandler(handler);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
32
49
|
var PromptClientActions = class {
|
|
33
50
|
client;
|
|
34
51
|
logger;
|
|
@@ -211,6 +228,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
211
228
|
currentOperationContext = null;
|
|
212
229
|
resources;
|
|
213
230
|
prompts;
|
|
231
|
+
elicitation;
|
|
214
232
|
constructor({
|
|
215
233
|
name,
|
|
216
234
|
version = "1.0.0",
|
|
@@ -224,18 +242,20 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
224
242
|
this.logHandler = server.logger;
|
|
225
243
|
this.enableServerLogs = server.enableServerLogs ?? true;
|
|
226
244
|
this.serverConfig = server;
|
|
245
|
+
const clientCapabilities = { ...capabilities, elicitation: {} };
|
|
227
246
|
this.client = new index_js$1.Client(
|
|
228
247
|
{
|
|
229
248
|
name,
|
|
230
249
|
version
|
|
231
250
|
},
|
|
232
251
|
{
|
|
233
|
-
capabilities
|
|
252
|
+
capabilities: clientCapabilities
|
|
234
253
|
}
|
|
235
254
|
);
|
|
236
255
|
this.setupLogging();
|
|
237
256
|
this.resources = new ResourceClientActions({ client: this, logger: this.logger });
|
|
238
257
|
this.prompts = new PromptClientActions({ client: this, logger: this.logger });
|
|
258
|
+
this.elicitation = new ElicitationClientActions({ client: this, logger: this.logger });
|
|
239
259
|
}
|
|
240
260
|
/**
|
|
241
261
|
* Log a message at the specified level
|
|
@@ -477,6 +497,13 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
477
497
|
handler();
|
|
478
498
|
});
|
|
479
499
|
}
|
|
500
|
+
setElicitationRequestHandler(handler) {
|
|
501
|
+
this.log("debug", "Setting elicitation request handler");
|
|
502
|
+
this.client.setRequestHandler(types_js.ElicitRequestSchema, async (request) => {
|
|
503
|
+
this.log("debug", `Received elicitation request: ${request.params.message}`);
|
|
504
|
+
return handler(request.params);
|
|
505
|
+
});
|
|
506
|
+
}
|
|
480
507
|
convertInputSchema(inputSchema) {
|
|
481
508
|
if (utils.isZodType(inputSchema)) {
|
|
482
509
|
return inputSchema;
|
|
@@ -641,6 +668,26 @@ To fix this you have three different options:
|
|
|
641
668
|
this.addToInstanceCache();
|
|
642
669
|
return this;
|
|
643
670
|
}
|
|
671
|
+
get elicitation() {
|
|
672
|
+
this.addToInstanceCache();
|
|
673
|
+
return {
|
|
674
|
+
onRequest: async (serverName, handler) => {
|
|
675
|
+
try {
|
|
676
|
+
const internalClient = await this.getConnectedClientForServer(serverName);
|
|
677
|
+
return internalClient.elicitation.onRequest(handler);
|
|
678
|
+
} catch (err) {
|
|
679
|
+
throw new error.MastraError({
|
|
680
|
+
id: "MCP_CLIENT_ON_REQUEST_ELICITATION_FAILED",
|
|
681
|
+
domain: error.ErrorDomain.MCP,
|
|
682
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
683
|
+
details: {
|
|
684
|
+
serverName
|
|
685
|
+
}
|
|
686
|
+
}, err);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
644
691
|
get resources() {
|
|
645
692
|
this.addToInstanceCache();
|
|
646
693
|
return {
|
|
@@ -1336,15 +1383,8 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1336
1383
|
sseTransport;
|
|
1337
1384
|
sseHonoTransports;
|
|
1338
1385
|
streamableHTTPTransports = /* @__PURE__ */ new Map();
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
listResourcesHandlerIsRegistered = false;
|
|
1342
|
-
readResourceHandlerIsRegistered = false;
|
|
1343
|
-
listResourceTemplatesHandlerIsRegistered = false;
|
|
1344
|
-
subscribeResourceHandlerIsRegistered = false;
|
|
1345
|
-
unsubscribeResourceHandlerIsRegistered = false;
|
|
1346
|
-
listPromptsHandlerIsRegistered = false;
|
|
1347
|
-
getPromptHandlerIsRegistered = false;
|
|
1386
|
+
// Track server instances for each HTTP session
|
|
1387
|
+
httpServerInstances = /* @__PURE__ */ new Map();
|
|
1348
1388
|
definedResources;
|
|
1349
1389
|
definedResourceTemplates;
|
|
1350
1390
|
resourceOptions;
|
|
@@ -1353,6 +1393,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1353
1393
|
subscriptions = /* @__PURE__ */ new Set();
|
|
1354
1394
|
resources;
|
|
1355
1395
|
prompts;
|
|
1396
|
+
elicitation;
|
|
1356
1397
|
/**
|
|
1357
1398
|
* Get the current stdio transport.
|
|
1358
1399
|
*/
|
|
@@ -1387,7 +1428,8 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1387
1428
|
this.promptOptions = opts.prompts;
|
|
1388
1429
|
const capabilities = {
|
|
1389
1430
|
tools: {},
|
|
1390
|
-
logging: { enabled: true }
|
|
1431
|
+
logging: { enabled: true },
|
|
1432
|
+
elicitation: {}
|
|
1391
1433
|
};
|
|
1392
1434
|
if (opts.resources) {
|
|
1393
1435
|
capabilities.resources = { subscribe: true, listChanged: true };
|
|
@@ -1400,23 +1442,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1400
1442
|
`Initialized MCPServer '${this.name}' v${this.version} (ID: ${this.id}) with tools: ${Object.keys(this.convertedTools).join(", ")} and resources. Capabilities: ${JSON.stringify(capabilities)}`
|
|
1401
1443
|
);
|
|
1402
1444
|
this.sseHonoTransports = /* @__PURE__ */ new Map();
|
|
1403
|
-
this.
|
|
1404
|
-
this.registerCallToolHandler();
|
|
1405
|
-
if (opts.resources) {
|
|
1406
|
-
this.registerListResourcesHandler();
|
|
1407
|
-
this.registerReadResourceHandler({ getResourcesCallback: opts.resources.getResourceContent });
|
|
1408
|
-
this.registerSubscribeResourceHandler();
|
|
1409
|
-
this.registerUnsubscribeResourceHandler();
|
|
1410
|
-
if (opts.resources.resourceTemplates) {
|
|
1411
|
-
this.registerListResourceTemplatesHandler();
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
if (opts.prompts) {
|
|
1415
|
-
this.registerListPromptsHandler();
|
|
1416
|
-
this.registerGetPromptHandler({
|
|
1417
|
-
getPromptMessagesCallback: opts.prompts.getPromptMessages
|
|
1418
|
-
});
|
|
1419
|
-
}
|
|
1445
|
+
this.registerHandlersOnServer(this.server);
|
|
1420
1446
|
this.resources = new ServerResourceActions({
|
|
1421
1447
|
getSubscriptions: () => this.subscriptions,
|
|
1422
1448
|
getLogger: () => this.logger,
|
|
@@ -1435,6 +1461,342 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1435
1461
|
this.definedPrompts = void 0;
|
|
1436
1462
|
}
|
|
1437
1463
|
});
|
|
1464
|
+
this.elicitation = {
|
|
1465
|
+
sendRequest: async (request) => {
|
|
1466
|
+
return this.handleElicitationRequest(request);
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
/**
|
|
1471
|
+
* Handle an elicitation request by sending it to the connected client.
|
|
1472
|
+
* This method sends an elicitation/create request to the client and waits for the response.
|
|
1473
|
+
*
|
|
1474
|
+
* @param request - The elicitation request containing message and schema
|
|
1475
|
+
* @param serverInstance - Optional server instance to use; defaults to main server for backward compatibility
|
|
1476
|
+
* @returns Promise that resolves to the client's response
|
|
1477
|
+
*/
|
|
1478
|
+
async handleElicitationRequest(request, serverInstance) {
|
|
1479
|
+
this.logger.debug(`Sending elicitation request: ${request.message}`);
|
|
1480
|
+
const server = serverInstance || this.server;
|
|
1481
|
+
const response = await server.elicitInput(request);
|
|
1482
|
+
this.logger.debug(`Received elicitation response: ${JSON.stringify(response)}`);
|
|
1483
|
+
return response;
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* Creates a new Server instance configured with all handlers for HTTP sessions.
|
|
1487
|
+
* Each HTTP client connection gets its own Server instance to avoid routing conflicts.
|
|
1488
|
+
*/
|
|
1489
|
+
createServerInstance() {
|
|
1490
|
+
const capabilities = {
|
|
1491
|
+
tools: {},
|
|
1492
|
+
logging: { enabled: true },
|
|
1493
|
+
elicitation: {}
|
|
1494
|
+
};
|
|
1495
|
+
if (this.resourceOptions) {
|
|
1496
|
+
capabilities.resources = { subscribe: true, listChanged: true };
|
|
1497
|
+
}
|
|
1498
|
+
if (this.promptOptions) {
|
|
1499
|
+
capabilities.prompts = { listChanged: true };
|
|
1500
|
+
}
|
|
1501
|
+
const serverInstance = new index_js.Server({ name: this.name, version: this.version }, { capabilities });
|
|
1502
|
+
this.registerHandlersOnServer(serverInstance);
|
|
1503
|
+
return serverInstance;
|
|
1504
|
+
}
|
|
1505
|
+
/**
|
|
1506
|
+
* Registers all MCP handlers on a given server instance.
|
|
1507
|
+
* This allows us to create multiple server instances with identical functionality.
|
|
1508
|
+
*/
|
|
1509
|
+
registerHandlersOnServer(serverInstance) {
|
|
1510
|
+
serverInstance.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
|
|
1511
|
+
this.logger.debug("Handling ListTools request");
|
|
1512
|
+
return {
|
|
1513
|
+
tools: Object.values(this.convertedTools).map((tool) => {
|
|
1514
|
+
const toolSpec = {
|
|
1515
|
+
name: tool.name,
|
|
1516
|
+
description: tool.description,
|
|
1517
|
+
inputSchema: tool.parameters.jsonSchema
|
|
1518
|
+
};
|
|
1519
|
+
if (tool.outputSchema) {
|
|
1520
|
+
toolSpec.outputSchema = tool.outputSchema.jsonSchema;
|
|
1521
|
+
}
|
|
1522
|
+
return toolSpec;
|
|
1523
|
+
})
|
|
1524
|
+
};
|
|
1525
|
+
});
|
|
1526
|
+
serverInstance.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
|
|
1527
|
+
const startTime = Date.now();
|
|
1528
|
+
try {
|
|
1529
|
+
const tool = this.convertedTools[request.params.name];
|
|
1530
|
+
if (!tool) {
|
|
1531
|
+
this.logger.warn(`CallTool: Unknown tool '${request.params.name}' requested.`);
|
|
1532
|
+
return {
|
|
1533
|
+
content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
|
|
1534
|
+
isError: true
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
const validation = tool.parameters.validate?.(request.params.arguments ?? {});
|
|
1538
|
+
if (validation && !validation.success) {
|
|
1539
|
+
this.logger.warn(`CallTool: Invalid tool arguments for '${request.params.name}'`, {
|
|
1540
|
+
errors: validation.error
|
|
1541
|
+
});
|
|
1542
|
+
return {
|
|
1543
|
+
content: [{ type: "text", text: `Invalid tool arguments: ${JSON.stringify(validation.error)}` }],
|
|
1544
|
+
isError: true
|
|
1545
|
+
};
|
|
1546
|
+
}
|
|
1547
|
+
if (!tool.execute) {
|
|
1548
|
+
this.logger.warn(`CallTool: Tool '${request.params.name}' does not have an execute function.`);
|
|
1549
|
+
return {
|
|
1550
|
+
content: [{ type: "text", text: `Tool '${request.params.name}' does not have an execute function.` }],
|
|
1551
|
+
isError: true
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
const sessionElicitation = {
|
|
1555
|
+
sendRequest: async (request2) => {
|
|
1556
|
+
return this.handleElicitationRequest(request2, serverInstance);
|
|
1557
|
+
}
|
|
1558
|
+
};
|
|
1559
|
+
const result = await tool.execute(validation?.value, {
|
|
1560
|
+
messages: [],
|
|
1561
|
+
toolCallId: "",
|
|
1562
|
+
elicitation: sessionElicitation
|
|
1563
|
+
});
|
|
1564
|
+
this.logger.debug(`CallTool: Tool '${request.params.name}' executed successfully with result:`, result);
|
|
1565
|
+
const duration = Date.now() - startTime;
|
|
1566
|
+
this.logger.info(`Tool '${request.params.name}' executed successfully in ${duration}ms.`);
|
|
1567
|
+
const response = { isError: false, content: [] };
|
|
1568
|
+
if (tool.outputSchema) {
|
|
1569
|
+
if (!result.structuredContent) {
|
|
1570
|
+
throw new Error(`Tool ${request.params.name} has an output schema but no structured content was provided.`);
|
|
1571
|
+
}
|
|
1572
|
+
const outputValidation = tool.outputSchema.validate?.(result.structuredContent ?? {});
|
|
1573
|
+
if (outputValidation && !outputValidation.success) {
|
|
1574
|
+
this.logger.warn(`CallTool: Invalid structured content for '${request.params.name}'`, {
|
|
1575
|
+
errors: outputValidation.error
|
|
1576
|
+
});
|
|
1577
|
+
throw new Error(
|
|
1578
|
+
`Invalid structured content for tool ${request.params.name}: ${JSON.stringify(outputValidation.error)}`
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
response.structuredContent = result.structuredContent;
|
|
1582
|
+
}
|
|
1583
|
+
if (response.structuredContent) {
|
|
1584
|
+
response.content = [{ type: "text", text: JSON.stringify(response.structuredContent) }];
|
|
1585
|
+
} else {
|
|
1586
|
+
response.content = [
|
|
1587
|
+
{
|
|
1588
|
+
type: "text",
|
|
1589
|
+
text: typeof result === "string" ? result : JSON.stringify(result)
|
|
1590
|
+
}
|
|
1591
|
+
];
|
|
1592
|
+
}
|
|
1593
|
+
return response;
|
|
1594
|
+
} catch (error) {
|
|
1595
|
+
const duration = Date.now() - startTime;
|
|
1596
|
+
if (error instanceof zod.z.ZodError) {
|
|
1597
|
+
this.logger.warn("Invalid tool arguments", {
|
|
1598
|
+
tool: request.params.name,
|
|
1599
|
+
errors: error.errors,
|
|
1600
|
+
duration: `${duration}ms`
|
|
1601
|
+
});
|
|
1602
|
+
return {
|
|
1603
|
+
content: [
|
|
1604
|
+
{
|
|
1605
|
+
type: "text",
|
|
1606
|
+
text: `Invalid arguments: ${error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ")}`
|
|
1607
|
+
}
|
|
1608
|
+
],
|
|
1609
|
+
isError: true
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
this.logger.error(`Tool execution failed: ${request.params.name}`, { error });
|
|
1613
|
+
return {
|
|
1614
|
+
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
1615
|
+
isError: true
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
if (this.resourceOptions) {
|
|
1620
|
+
this.registerResourceHandlersOnServer(serverInstance);
|
|
1621
|
+
}
|
|
1622
|
+
if (this.promptOptions) {
|
|
1623
|
+
this.registerPromptHandlersOnServer(serverInstance);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Registers resource-related handlers on a server instance.
|
|
1628
|
+
*/
|
|
1629
|
+
registerResourceHandlersOnServer(serverInstance) {
|
|
1630
|
+
const capturedResourceOptions = this.resourceOptions;
|
|
1631
|
+
if (!capturedResourceOptions) return;
|
|
1632
|
+
if (capturedResourceOptions.listResources) {
|
|
1633
|
+
serverInstance.setRequestHandler(types_js.ListResourcesRequestSchema, async () => {
|
|
1634
|
+
this.logger.debug("Handling ListResources request");
|
|
1635
|
+
if (this.definedResources) {
|
|
1636
|
+
return { resources: this.definedResources };
|
|
1637
|
+
} else {
|
|
1638
|
+
try {
|
|
1639
|
+
const resources = await capturedResourceOptions.listResources();
|
|
1640
|
+
this.definedResources = resources;
|
|
1641
|
+
this.logger.debug(`Fetched and cached ${this.definedResources.length} resources.`);
|
|
1642
|
+
return { resources: this.definedResources };
|
|
1643
|
+
} catch (error) {
|
|
1644
|
+
this.logger.error("Error fetching resources via listResources():", { error });
|
|
1645
|
+
throw error;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1650
|
+
if (capturedResourceOptions.getResourceContent) {
|
|
1651
|
+
serverInstance.setRequestHandler(types_js.ReadResourceRequestSchema, async (request) => {
|
|
1652
|
+
const startTime = Date.now();
|
|
1653
|
+
const uri = request.params.uri;
|
|
1654
|
+
this.logger.debug(`Handling ReadResource request for URI: ${uri}`);
|
|
1655
|
+
if (!this.definedResources) {
|
|
1656
|
+
const resources = await this.resourceOptions?.listResources?.();
|
|
1657
|
+
if (!resources) throw new Error("Failed to load resources");
|
|
1658
|
+
this.definedResources = resources;
|
|
1659
|
+
}
|
|
1660
|
+
const resource = this.definedResources?.find((r) => r.uri === uri);
|
|
1661
|
+
if (!resource) {
|
|
1662
|
+
this.logger.warn(`ReadResource: Unknown resource URI '${uri}' requested.`);
|
|
1663
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
1664
|
+
}
|
|
1665
|
+
try {
|
|
1666
|
+
const resourcesOrResourceContent = await capturedResourceOptions.getResourceContent({ uri });
|
|
1667
|
+
const resourcesContent = Array.isArray(resourcesOrResourceContent) ? resourcesOrResourceContent : [resourcesOrResourceContent];
|
|
1668
|
+
const contents = resourcesContent.map((resourceContent) => {
|
|
1669
|
+
const contentItem = {
|
|
1670
|
+
uri: resource.uri,
|
|
1671
|
+
mimeType: resource.mimeType
|
|
1672
|
+
};
|
|
1673
|
+
if ("text" in resourceContent) {
|
|
1674
|
+
contentItem.text = resourceContent.text;
|
|
1675
|
+
}
|
|
1676
|
+
if ("blob" in resourceContent) {
|
|
1677
|
+
contentItem.blob = resourceContent.blob;
|
|
1678
|
+
}
|
|
1679
|
+
return contentItem;
|
|
1680
|
+
});
|
|
1681
|
+
const duration = Date.now() - startTime;
|
|
1682
|
+
this.logger.info(`Resource '${uri}' read successfully in ${duration}ms.`);
|
|
1683
|
+
return {
|
|
1684
|
+
contents
|
|
1685
|
+
};
|
|
1686
|
+
} catch (error) {
|
|
1687
|
+
const duration = Date.now() - startTime;
|
|
1688
|
+
this.logger.error(`Failed to get content for resource URI '${uri}' in ${duration}ms`, { error });
|
|
1689
|
+
throw error;
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1693
|
+
if (capturedResourceOptions.resourceTemplates) {
|
|
1694
|
+
serverInstance.setRequestHandler(types_js.ListResourceTemplatesRequestSchema, async () => {
|
|
1695
|
+
this.logger.debug("Handling ListResourceTemplates request");
|
|
1696
|
+
if (this.definedResourceTemplates) {
|
|
1697
|
+
return { resourceTemplates: this.definedResourceTemplates };
|
|
1698
|
+
} else {
|
|
1699
|
+
try {
|
|
1700
|
+
const templates = await capturedResourceOptions.resourceTemplates();
|
|
1701
|
+
this.definedResourceTemplates = templates;
|
|
1702
|
+
this.logger.debug(`Fetched and cached ${this.definedResourceTemplates.length} resource templates.`);
|
|
1703
|
+
return { resourceTemplates: this.definedResourceTemplates };
|
|
1704
|
+
} catch (error) {
|
|
1705
|
+
this.logger.error("Error fetching resource templates via resourceTemplates():", { error });
|
|
1706
|
+
throw error;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
serverInstance.setRequestHandler(types_js.SubscribeRequestSchema, async (request) => {
|
|
1712
|
+
const uri = request.params.uri;
|
|
1713
|
+
this.logger.info(`Received resources/subscribe request for URI: ${uri}`);
|
|
1714
|
+
this.subscriptions.add(uri);
|
|
1715
|
+
return {};
|
|
1716
|
+
});
|
|
1717
|
+
serverInstance.setRequestHandler(types_js.UnsubscribeRequestSchema, async (request) => {
|
|
1718
|
+
const uri = request.params.uri;
|
|
1719
|
+
this.logger.info(`Received resources/unsubscribe request for URI: ${uri}`);
|
|
1720
|
+
this.subscriptions.delete(uri);
|
|
1721
|
+
return {};
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
/**
|
|
1725
|
+
* Registers prompt-related handlers on a server instance.
|
|
1726
|
+
*/
|
|
1727
|
+
registerPromptHandlersOnServer(serverInstance) {
|
|
1728
|
+
const capturedPromptOptions = this.promptOptions;
|
|
1729
|
+
if (!capturedPromptOptions) return;
|
|
1730
|
+
if (capturedPromptOptions.listPrompts) {
|
|
1731
|
+
serverInstance.setRequestHandler(types_js.ListPromptsRequestSchema, async () => {
|
|
1732
|
+
this.logger.debug("Handling ListPrompts request");
|
|
1733
|
+
if (this.definedPrompts) {
|
|
1734
|
+
return {
|
|
1735
|
+
prompts: this.definedPrompts?.map((p) => ({ ...p, version: p.version ?? void 0 }))
|
|
1736
|
+
};
|
|
1737
|
+
} else {
|
|
1738
|
+
try {
|
|
1739
|
+
const prompts = await capturedPromptOptions.listPrompts();
|
|
1740
|
+
for (const prompt of prompts) {
|
|
1741
|
+
types_js.PromptSchema.parse(prompt);
|
|
1742
|
+
}
|
|
1743
|
+
this.definedPrompts = prompts;
|
|
1744
|
+
this.logger.debug(`Fetched and cached ${this.definedPrompts.length} prompts.`);
|
|
1745
|
+
return {
|
|
1746
|
+
prompts: this.definedPrompts?.map((p) => ({ ...p, version: p.version ?? void 0 }))
|
|
1747
|
+
};
|
|
1748
|
+
} catch (error) {
|
|
1749
|
+
this.logger.error("Error fetching prompts via listPrompts():", {
|
|
1750
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1751
|
+
});
|
|
1752
|
+
throw error;
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
}
|
|
1757
|
+
if (capturedPromptOptions.getPromptMessages) {
|
|
1758
|
+
serverInstance.setRequestHandler(
|
|
1759
|
+
types_js.GetPromptRequestSchema,
|
|
1760
|
+
async (request) => {
|
|
1761
|
+
const startTime = Date.now();
|
|
1762
|
+
const { name, version, arguments: args } = request.params;
|
|
1763
|
+
if (!this.definedPrompts) {
|
|
1764
|
+
const prompts = await this.promptOptions?.listPrompts?.();
|
|
1765
|
+
if (!prompts) throw new Error("Failed to load prompts");
|
|
1766
|
+
this.definedPrompts = prompts;
|
|
1767
|
+
}
|
|
1768
|
+
let prompt;
|
|
1769
|
+
if (version) {
|
|
1770
|
+
prompt = this.definedPrompts?.find((p) => p.name === name && p.version === version);
|
|
1771
|
+
} else {
|
|
1772
|
+
prompt = this.definedPrompts?.find((p) => p.name === name);
|
|
1773
|
+
}
|
|
1774
|
+
if (!prompt) throw new Error(`Prompt "${name}"${version ? ` (version ${version})` : ""} not found`);
|
|
1775
|
+
if (prompt.arguments) {
|
|
1776
|
+
for (const arg of prompt.arguments) {
|
|
1777
|
+
if (arg.required && (args?.[arg.name] === void 0 || args?.[arg.name] === null)) {
|
|
1778
|
+
throw new Error(`Missing required argument: ${arg.name}`);
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
try {
|
|
1783
|
+
let messages = [];
|
|
1784
|
+
if (capturedPromptOptions.getPromptMessages) {
|
|
1785
|
+
messages = await capturedPromptOptions.getPromptMessages({ name, version, args });
|
|
1786
|
+
}
|
|
1787
|
+
const duration = Date.now() - startTime;
|
|
1788
|
+
this.logger.info(
|
|
1789
|
+
`Prompt '${name}'${version ? ` (version ${version})` : ""} retrieved successfully in ${duration}ms.`
|
|
1790
|
+
);
|
|
1791
|
+
return { prompt, messages };
|
|
1792
|
+
} catch (error) {
|
|
1793
|
+
const duration = Date.now() - startTime;
|
|
1794
|
+
this.logger.error(`Failed to get content for prompt '${name}' in ${duration}ms`, { error });
|
|
1795
|
+
throw error;
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1438
1800
|
}
|
|
1439
1801
|
convertAgentsToTools(agentsConfig, definedConvertedTools) {
|
|
1440
1802
|
const agentTools = {};
|
|
@@ -1634,368 +1996,6 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1634
1996
|
);
|
|
1635
1997
|
return allConvertedTools;
|
|
1636
1998
|
}
|
|
1637
|
-
/**
|
|
1638
|
-
* Register the ListTools handler for listing all available tools.
|
|
1639
|
-
*/
|
|
1640
|
-
registerListToolsHandler() {
|
|
1641
|
-
if (this.listToolsHandlerIsRegistered) {
|
|
1642
|
-
return;
|
|
1643
|
-
}
|
|
1644
|
-
this.listToolsHandlerIsRegistered = true;
|
|
1645
|
-
this.server.setRequestHandler(types_js.ListToolsRequestSchema, async () => {
|
|
1646
|
-
this.logger.debug("Handling ListTools request");
|
|
1647
|
-
return {
|
|
1648
|
-
tools: Object.values(this.convertedTools).map((tool) => {
|
|
1649
|
-
const toolSpec = {
|
|
1650
|
-
name: tool.name,
|
|
1651
|
-
description: tool.description,
|
|
1652
|
-
inputSchema: tool.parameters.jsonSchema
|
|
1653
|
-
};
|
|
1654
|
-
if (tool.outputSchema) {
|
|
1655
|
-
toolSpec.outputSchema = tool.outputSchema.jsonSchema;
|
|
1656
|
-
}
|
|
1657
|
-
return toolSpec;
|
|
1658
|
-
})
|
|
1659
|
-
};
|
|
1660
|
-
});
|
|
1661
|
-
}
|
|
1662
|
-
/**
|
|
1663
|
-
* Register the CallTool handler for executing a tool by name.
|
|
1664
|
-
*/
|
|
1665
|
-
registerCallToolHandler() {
|
|
1666
|
-
if (this.callToolHandlerIsRegistered) {
|
|
1667
|
-
return;
|
|
1668
|
-
}
|
|
1669
|
-
this.callToolHandlerIsRegistered = true;
|
|
1670
|
-
this.server.setRequestHandler(types_js.CallToolRequestSchema, async (request) => {
|
|
1671
|
-
const startTime = Date.now();
|
|
1672
|
-
try {
|
|
1673
|
-
const tool = this.convertedTools[request.params.name];
|
|
1674
|
-
if (!tool) {
|
|
1675
|
-
this.logger.warn(`CallTool: Unknown tool '${request.params.name}' requested.`);
|
|
1676
|
-
return {
|
|
1677
|
-
content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }],
|
|
1678
|
-
isError: true
|
|
1679
|
-
};
|
|
1680
|
-
}
|
|
1681
|
-
const validation = tool.parameters.validate?.(request.params.arguments ?? {});
|
|
1682
|
-
if (validation && !validation.success) {
|
|
1683
|
-
this.logger.warn(`CallTool: Invalid tool arguments for '${request.params.name}'`, {
|
|
1684
|
-
errors: validation.error
|
|
1685
|
-
});
|
|
1686
|
-
return {
|
|
1687
|
-
content: [{ type: "text", text: `Invalid tool arguments: ${JSON.stringify(validation.error)}` }],
|
|
1688
|
-
isError: true
|
|
1689
|
-
};
|
|
1690
|
-
}
|
|
1691
|
-
if (!tool.execute) {
|
|
1692
|
-
this.logger.warn(`CallTool: Tool '${request.params.name}' does not have an execute function.`);
|
|
1693
|
-
return {
|
|
1694
|
-
content: [{ type: "text", text: `Tool '${request.params.name}' does not have an execute function.` }],
|
|
1695
|
-
isError: true
|
|
1696
|
-
};
|
|
1697
|
-
}
|
|
1698
|
-
const result = await tool.execute(validation?.value, { messages: [], toolCallId: "" });
|
|
1699
|
-
this.logger.debug(`CallTool: Tool '${request.params.name}' executed successfully with result:`, result);
|
|
1700
|
-
const duration = Date.now() - startTime;
|
|
1701
|
-
this.logger.info(`Tool '${request.params.name}' executed successfully in ${duration}ms.`);
|
|
1702
|
-
const response = { isError: false, content: [] };
|
|
1703
|
-
if (tool.outputSchema) {
|
|
1704
|
-
if (!result.structuredContent) {
|
|
1705
|
-
throw new Error(`Tool ${request.params.name} has an output schema but no structured content was provided.`);
|
|
1706
|
-
}
|
|
1707
|
-
const outputValidation = tool.outputSchema.validate?.(result.structuredContent ?? {});
|
|
1708
|
-
if (outputValidation && !outputValidation.success) {
|
|
1709
|
-
this.logger.warn(`CallTool: Invalid structured content for '${request.params.name}'`, {
|
|
1710
|
-
errors: outputValidation.error
|
|
1711
|
-
});
|
|
1712
|
-
throw new Error(
|
|
1713
|
-
`Invalid structured content for tool ${request.params.name}: ${JSON.stringify(outputValidation.error)}`
|
|
1714
|
-
);
|
|
1715
|
-
}
|
|
1716
|
-
response.structuredContent = result.structuredContent;
|
|
1717
|
-
}
|
|
1718
|
-
if (result.content) {
|
|
1719
|
-
response.content = result.content;
|
|
1720
|
-
} else if (response.structuredContent) {
|
|
1721
|
-
response.content = [{ type: "text", text: JSON.stringify(response.structuredContent) }];
|
|
1722
|
-
} else {
|
|
1723
|
-
response.content = [
|
|
1724
|
-
{
|
|
1725
|
-
type: "text",
|
|
1726
|
-
text: typeof result === "string" ? result : JSON.stringify(result)
|
|
1727
|
-
}
|
|
1728
|
-
];
|
|
1729
|
-
}
|
|
1730
|
-
return response;
|
|
1731
|
-
} catch (error) {
|
|
1732
|
-
const duration = Date.now() - startTime;
|
|
1733
|
-
if (error instanceof zod.z.ZodError) {
|
|
1734
|
-
this.logger.warn("Invalid tool arguments", {
|
|
1735
|
-
tool: request.params.name,
|
|
1736
|
-
errors: error.errors,
|
|
1737
|
-
duration: `${duration}ms`
|
|
1738
|
-
});
|
|
1739
|
-
return {
|
|
1740
|
-
content: [
|
|
1741
|
-
{
|
|
1742
|
-
type: "text",
|
|
1743
|
-
text: `Invalid arguments: ${error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ")}`
|
|
1744
|
-
}
|
|
1745
|
-
],
|
|
1746
|
-
isError: true
|
|
1747
|
-
};
|
|
1748
|
-
}
|
|
1749
|
-
this.logger.error(`Tool execution failed: ${request.params.name}`, { error });
|
|
1750
|
-
return {
|
|
1751
|
-
content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
|
|
1752
|
-
isError: true
|
|
1753
|
-
};
|
|
1754
|
-
}
|
|
1755
|
-
});
|
|
1756
|
-
}
|
|
1757
|
-
/**
|
|
1758
|
-
* Register the ListResources handler for listing all available resources.
|
|
1759
|
-
*/
|
|
1760
|
-
registerListResourcesHandler() {
|
|
1761
|
-
if (this.listResourcesHandlerIsRegistered) {
|
|
1762
|
-
return;
|
|
1763
|
-
}
|
|
1764
|
-
this.listResourcesHandlerIsRegistered = true;
|
|
1765
|
-
const capturedResourceOptions = this.resourceOptions;
|
|
1766
|
-
if (!capturedResourceOptions?.listResources) {
|
|
1767
|
-
this.logger.warn("ListResources capability not supported by server configuration.");
|
|
1768
|
-
return;
|
|
1769
|
-
}
|
|
1770
|
-
this.server.setRequestHandler(types_js.ListResourcesRequestSchema, async () => {
|
|
1771
|
-
this.logger.debug("Handling ListResources request");
|
|
1772
|
-
if (this.definedResources) {
|
|
1773
|
-
return { resources: this.definedResources };
|
|
1774
|
-
} else {
|
|
1775
|
-
try {
|
|
1776
|
-
const resources = await capturedResourceOptions.listResources();
|
|
1777
|
-
this.definedResources = resources;
|
|
1778
|
-
this.logger.debug(`Fetched and cached ${this.definedResources.length} resources.`);
|
|
1779
|
-
return { resources: this.definedResources };
|
|
1780
|
-
} catch (error) {
|
|
1781
|
-
this.logger.error("Error fetching resources via listResources():", { error });
|
|
1782
|
-
throw error;
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
});
|
|
1786
|
-
}
|
|
1787
|
-
/**
|
|
1788
|
-
* Register the ReadResource handler for reading a resource by URI.
|
|
1789
|
-
*/
|
|
1790
|
-
registerReadResourceHandler({
|
|
1791
|
-
getResourcesCallback
|
|
1792
|
-
}) {
|
|
1793
|
-
if (this.readResourceHandlerIsRegistered) {
|
|
1794
|
-
return;
|
|
1795
|
-
}
|
|
1796
|
-
this.readResourceHandlerIsRegistered = true;
|
|
1797
|
-
this.server.setRequestHandler(types_js.ReadResourceRequestSchema, async (request) => {
|
|
1798
|
-
const startTime = Date.now();
|
|
1799
|
-
const uri = request.params.uri;
|
|
1800
|
-
this.logger.debug(`Handling ReadResource request for URI: ${uri}`);
|
|
1801
|
-
if (!this.definedResources) {
|
|
1802
|
-
const resources = await this.resourceOptions?.listResources?.();
|
|
1803
|
-
if (!resources) throw new Error("Failed to load resources");
|
|
1804
|
-
this.definedResources = resources;
|
|
1805
|
-
}
|
|
1806
|
-
const resource = this.definedResources?.find((r) => r.uri === uri);
|
|
1807
|
-
if (!resource) {
|
|
1808
|
-
this.logger.warn(`ReadResource: Unknown resource URI '${uri}' requested.`);
|
|
1809
|
-
throw new Error(`Resource not found: ${uri}`);
|
|
1810
|
-
}
|
|
1811
|
-
try {
|
|
1812
|
-
const resourcesOrResourceContent = await getResourcesCallback({ uri });
|
|
1813
|
-
const resourcesContent = Array.isArray(resourcesOrResourceContent) ? resourcesOrResourceContent : [resourcesOrResourceContent];
|
|
1814
|
-
const contents = resourcesContent.map((resourceContent) => {
|
|
1815
|
-
const contentItem = {
|
|
1816
|
-
uri: resource.uri,
|
|
1817
|
-
mimeType: resource.mimeType
|
|
1818
|
-
};
|
|
1819
|
-
if ("text" in resourceContent) {
|
|
1820
|
-
contentItem.text = resourceContent.text;
|
|
1821
|
-
}
|
|
1822
|
-
if ("blob" in resourceContent) {
|
|
1823
|
-
contentItem.blob = resourceContent.blob;
|
|
1824
|
-
}
|
|
1825
|
-
return contentItem;
|
|
1826
|
-
});
|
|
1827
|
-
const duration = Date.now() - startTime;
|
|
1828
|
-
this.logger.info(`Resource '${uri}' read successfully in ${duration}ms.`);
|
|
1829
|
-
return {
|
|
1830
|
-
contents
|
|
1831
|
-
};
|
|
1832
|
-
} catch (error) {
|
|
1833
|
-
const duration = Date.now() - startTime;
|
|
1834
|
-
this.logger.error(`Failed to get content for resource URI '${uri}' in ${duration}ms`, { error });
|
|
1835
|
-
throw error;
|
|
1836
|
-
}
|
|
1837
|
-
});
|
|
1838
|
-
}
|
|
1839
|
-
/**
|
|
1840
|
-
* Register the ListResourceTemplates handler.
|
|
1841
|
-
*/
|
|
1842
|
-
registerListResourceTemplatesHandler() {
|
|
1843
|
-
if (this.listResourceTemplatesHandlerIsRegistered) {
|
|
1844
|
-
return;
|
|
1845
|
-
}
|
|
1846
|
-
if (!this.resourceOptions || typeof this.resourceOptions.resourceTemplates !== "function") {
|
|
1847
|
-
this.logger.warn(
|
|
1848
|
-
"ListResourceTemplates handler called, but resourceTemplates function is not available on resourceOptions or not a function."
|
|
1849
|
-
);
|
|
1850
|
-
this.server.setRequestHandler(types_js.ListResourceTemplatesRequestSchema, async () => {
|
|
1851
|
-
this.logger.debug("Handling ListResourceTemplates request (no templates configured or resourceOptions issue)");
|
|
1852
|
-
return { resourceTemplates: [] };
|
|
1853
|
-
});
|
|
1854
|
-
this.listResourceTemplatesHandlerIsRegistered = true;
|
|
1855
|
-
return;
|
|
1856
|
-
}
|
|
1857
|
-
const resourceTemplatesFn = this.resourceOptions.resourceTemplates;
|
|
1858
|
-
this.listResourceTemplatesHandlerIsRegistered = true;
|
|
1859
|
-
this.server.setRequestHandler(types_js.ListResourceTemplatesRequestSchema, async () => {
|
|
1860
|
-
this.logger.debug("Handling ListResourceTemplates request");
|
|
1861
|
-
if (this.definedResourceTemplates) {
|
|
1862
|
-
return { resourceTemplates: this.definedResourceTemplates };
|
|
1863
|
-
} else {
|
|
1864
|
-
try {
|
|
1865
|
-
const templates = await resourceTemplatesFn();
|
|
1866
|
-
this.definedResourceTemplates = templates;
|
|
1867
|
-
this.logger.debug(`Fetched and cached ${this.definedResourceTemplates.length} resource templates.`);
|
|
1868
|
-
return { resourceTemplates: this.definedResourceTemplates };
|
|
1869
|
-
} catch (error) {
|
|
1870
|
-
this.logger.error("Error fetching resource templates via resourceTemplates():", { error });
|
|
1871
|
-
throw error;
|
|
1872
|
-
}
|
|
1873
|
-
}
|
|
1874
|
-
});
|
|
1875
|
-
}
|
|
1876
|
-
/**
|
|
1877
|
-
* Register the SubscribeResource handler.
|
|
1878
|
-
*/
|
|
1879
|
-
registerSubscribeResourceHandler() {
|
|
1880
|
-
if (this.subscribeResourceHandlerIsRegistered) {
|
|
1881
|
-
return;
|
|
1882
|
-
}
|
|
1883
|
-
if (!types_js.SubscribeRequestSchema) {
|
|
1884
|
-
this.logger.warn("SubscribeRequestSchema not available, cannot register SubscribeResource handler.");
|
|
1885
|
-
return;
|
|
1886
|
-
}
|
|
1887
|
-
this.subscribeResourceHandlerIsRegistered = true;
|
|
1888
|
-
this.server.setRequestHandler(types_js.SubscribeRequestSchema, async (request) => {
|
|
1889
|
-
const uri = request.params.uri;
|
|
1890
|
-
this.logger.info(`Received resources/subscribe request for URI: ${uri}`);
|
|
1891
|
-
this.subscriptions.add(uri);
|
|
1892
|
-
return {};
|
|
1893
|
-
});
|
|
1894
|
-
}
|
|
1895
|
-
/**
|
|
1896
|
-
* Register the UnsubscribeResource handler.
|
|
1897
|
-
*/
|
|
1898
|
-
registerUnsubscribeResourceHandler() {
|
|
1899
|
-
if (this.unsubscribeResourceHandlerIsRegistered) {
|
|
1900
|
-
return;
|
|
1901
|
-
}
|
|
1902
|
-
this.unsubscribeResourceHandlerIsRegistered = true;
|
|
1903
|
-
this.server.setRequestHandler(types_js.UnsubscribeRequestSchema, async (request) => {
|
|
1904
|
-
const uri = request.params.uri;
|
|
1905
|
-
this.logger.info(`Received resources/unsubscribe request for URI: ${uri}`);
|
|
1906
|
-
this.subscriptions.delete(uri);
|
|
1907
|
-
return {};
|
|
1908
|
-
});
|
|
1909
|
-
}
|
|
1910
|
-
/**
|
|
1911
|
-
* Register the ListPrompts handler.
|
|
1912
|
-
*/
|
|
1913
|
-
registerListPromptsHandler() {
|
|
1914
|
-
if (this.listPromptsHandlerIsRegistered) {
|
|
1915
|
-
return;
|
|
1916
|
-
}
|
|
1917
|
-
this.listPromptsHandlerIsRegistered = true;
|
|
1918
|
-
const capturedPromptOptions = this.promptOptions;
|
|
1919
|
-
if (!capturedPromptOptions?.listPrompts) {
|
|
1920
|
-
this.logger.warn("ListPrompts capability not supported by server configuration.");
|
|
1921
|
-
return;
|
|
1922
|
-
}
|
|
1923
|
-
this.server.setRequestHandler(types_js.ListPromptsRequestSchema, async () => {
|
|
1924
|
-
this.logger.debug("Handling ListPrompts request");
|
|
1925
|
-
if (this.definedPrompts) {
|
|
1926
|
-
return {
|
|
1927
|
-
prompts: this.definedPrompts?.map((p) => ({ ...p, version: p.version ?? void 0 }))
|
|
1928
|
-
};
|
|
1929
|
-
} else {
|
|
1930
|
-
try {
|
|
1931
|
-
const prompts = await capturedPromptOptions.listPrompts();
|
|
1932
|
-
for (const prompt of prompts) {
|
|
1933
|
-
types_js.PromptSchema.parse(prompt);
|
|
1934
|
-
}
|
|
1935
|
-
this.definedPrompts = prompts;
|
|
1936
|
-
this.logger.debug(`Fetched and cached ${this.definedPrompts.length} prompts.`);
|
|
1937
|
-
return {
|
|
1938
|
-
prompts: this.definedPrompts?.map((p) => ({ ...p, version: p.version ?? void 0 }))
|
|
1939
|
-
};
|
|
1940
|
-
} catch (error) {
|
|
1941
|
-
this.logger.error("Error fetching prompts via listPrompts():", {
|
|
1942
|
-
error: error instanceof Error ? error.message : String(error)
|
|
1943
|
-
});
|
|
1944
|
-
throw error;
|
|
1945
|
-
}
|
|
1946
|
-
}
|
|
1947
|
-
});
|
|
1948
|
-
}
|
|
1949
|
-
/**
|
|
1950
|
-
* Register the GetPrompt handler.
|
|
1951
|
-
*/
|
|
1952
|
-
registerGetPromptHandler({
|
|
1953
|
-
getPromptMessagesCallback
|
|
1954
|
-
}) {
|
|
1955
|
-
if (this.getPromptHandlerIsRegistered) return;
|
|
1956
|
-
this.getPromptHandlerIsRegistered = true;
|
|
1957
|
-
this.server.setRequestHandler(
|
|
1958
|
-
types_js.GetPromptRequestSchema,
|
|
1959
|
-
async (request) => {
|
|
1960
|
-
const startTime = Date.now();
|
|
1961
|
-
const { name, version, arguments: args } = request.params;
|
|
1962
|
-
if (!this.definedPrompts) {
|
|
1963
|
-
const prompts = await this.promptOptions?.listPrompts?.();
|
|
1964
|
-
if (!prompts) throw new Error("Failed to load prompts");
|
|
1965
|
-
this.definedPrompts = prompts;
|
|
1966
|
-
}
|
|
1967
|
-
let prompt;
|
|
1968
|
-
if (version) {
|
|
1969
|
-
prompt = this.definedPrompts?.find((p) => p.name === name && p.version === version);
|
|
1970
|
-
} else {
|
|
1971
|
-
prompt = this.definedPrompts?.find((p) => p.name === name);
|
|
1972
|
-
}
|
|
1973
|
-
if (!prompt) throw new Error(`Prompt "${name}"${version ? ` (version ${version})` : ""} not found`);
|
|
1974
|
-
if (prompt.arguments) {
|
|
1975
|
-
for (const arg of prompt.arguments) {
|
|
1976
|
-
if (arg.required && (args?.[arg.name] === void 0 || args?.[arg.name] === null)) {
|
|
1977
|
-
throw new Error(`Missing required argument: ${arg.name}`);
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1980
|
-
}
|
|
1981
|
-
try {
|
|
1982
|
-
let messages = [];
|
|
1983
|
-
if (getPromptMessagesCallback) {
|
|
1984
|
-
messages = await getPromptMessagesCallback({ name, version, args });
|
|
1985
|
-
}
|
|
1986
|
-
const duration = Date.now() - startTime;
|
|
1987
|
-
this.logger.info(
|
|
1988
|
-
`Prompt '${name}'${version ? ` (version ${version})` : ""} retrieved successfully in ${duration}ms.`
|
|
1989
|
-
);
|
|
1990
|
-
return { prompt, messages };
|
|
1991
|
-
} catch (error) {
|
|
1992
|
-
const duration = Date.now() - startTime;
|
|
1993
|
-
this.logger.error(`Failed to get content for prompt '${name}' in ${duration}ms`, { error });
|
|
1994
|
-
throw error;
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
);
|
|
1998
|
-
}
|
|
1999
1999
|
/**
|
|
2000
2000
|
* Start the MCP server using stdio transport (for Windsurf integration).
|
|
2001
2001
|
*/
|
|
@@ -2208,11 +2208,17 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2208
2208
|
`startHTTP: Streamable HTTP transport closed for session ${closedSessionId}, removing from map.`
|
|
2209
2209
|
);
|
|
2210
2210
|
this.streamableHTTPTransports.delete(closedSessionId);
|
|
2211
|
+
if (this.httpServerInstances.has(closedSessionId)) {
|
|
2212
|
+
this.httpServerInstances.delete(closedSessionId);
|
|
2213
|
+
this.logger.debug(`startHTTP: Cleaned up server instance for closed session ${closedSessionId}`);
|
|
2214
|
+
}
|
|
2211
2215
|
}
|
|
2212
2216
|
};
|
|
2213
|
-
|
|
2217
|
+
const sessionServerInstance = this.createServerInstance();
|
|
2218
|
+
await sessionServerInstance.connect(transport);
|
|
2214
2219
|
if (transport.sessionId) {
|
|
2215
2220
|
this.streamableHTTPTransports.set(transport.sessionId, transport);
|
|
2221
|
+
this.httpServerInstances.set(transport.sessionId, sessionServerInstance);
|
|
2216
2222
|
this.logger.debug(
|
|
2217
2223
|
`startHTTP: Streamable HTTP session initialized and stored with ID: ${transport.sessionId}`
|
|
2218
2224
|
);
|
|
@@ -2354,13 +2360,6 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2354
2360
|
* Close the MCP server and all its connections
|
|
2355
2361
|
*/
|
|
2356
2362
|
async close() {
|
|
2357
|
-
this.callToolHandlerIsRegistered = false;
|
|
2358
|
-
this.listToolsHandlerIsRegistered = false;
|
|
2359
|
-
this.listResourcesHandlerIsRegistered = false;
|
|
2360
|
-
this.readResourceHandlerIsRegistered = false;
|
|
2361
|
-
this.listResourceTemplatesHandlerIsRegistered = false;
|
|
2362
|
-
this.subscribeResourceHandlerIsRegistered = false;
|
|
2363
|
-
this.unsubscribeResourceHandlerIsRegistered = false;
|
|
2364
2363
|
try {
|
|
2365
2364
|
if (this.stdioTransport) {
|
|
2366
2365
|
await this.stdioTransport.close?.();
|
|
@@ -2382,6 +2381,12 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2382
2381
|
}
|
|
2383
2382
|
this.streamableHTTPTransports.clear();
|
|
2384
2383
|
}
|
|
2384
|
+
if (this.httpServerInstances) {
|
|
2385
|
+
for (const serverInstance of this.httpServerInstances.values()) {
|
|
2386
|
+
await serverInstance.close?.();
|
|
2387
|
+
}
|
|
2388
|
+
this.httpServerInstances.clear();
|
|
2389
|
+
}
|
|
2385
2390
|
await this.server.close();
|
|
2386
2391
|
this.logger.info("MCP server closed.");
|
|
2387
2392
|
} catch (error$1) {
|