@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/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
- listToolsHandlerIsRegistered = false;
1340
- callToolHandlerIsRegistered = false;
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.registerListToolsHandler();
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
- await this.server.connect(transport);
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) {