@mastra/mcp 0.14.2 → 1.0.0-beta.0
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/CHANGELOG.md +64 -14
- package/README.md +8 -8
- package/dist/__fixtures__/tools.d.ts +1 -7
- package/dist/__fixtures__/tools.d.ts.map +1 -1
- package/dist/client/client.d.ts +4 -9
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/configuration.d.ts +10 -64
- package/dist/client/configuration.d.ts.map +1 -1
- package/dist/client/index.d.ts +0 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/index.cjs +168 -96
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +168 -94
- package/dist/index.js.map +1 -1
- package/dist/server/server.d.ts +44 -6
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/types.d.ts +0 -54
- package/dist/server/types.d.ts.map +1 -1
- package/package.json +8 -12
package/dist/index.cjs
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var $RefParser = require('@apidevtools/json-schema-ref-parser');
|
|
4
3
|
var base = require('@mastra/core/base');
|
|
5
4
|
var error = require('@mastra/core/error');
|
|
5
|
+
var protocol_js = require('@modelcontextprotocol/sdk/shared/protocol.js');
|
|
6
|
+
var equal = require('fast-deep-equal');
|
|
7
|
+
var uuid = require('uuid');
|
|
8
|
+
var $RefParser = require('@apidevtools/json-schema-ref-parser');
|
|
6
9
|
var tools = require('@mastra/core/tools');
|
|
7
10
|
var utils = require('@mastra/core/utils');
|
|
8
11
|
var index_js$1 = require('@modelcontextprotocol/sdk/client/index.js');
|
|
9
12
|
var sse_js$1 = require('@modelcontextprotocol/sdk/client/sse.js');
|
|
10
13
|
var stdio_js$1 = require('@modelcontextprotocol/sdk/client/stdio.js');
|
|
11
14
|
var streamableHttp_js$1 = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
12
|
-
var protocol_js = require('@modelcontextprotocol/sdk/shared/protocol.js');
|
|
13
15
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
14
16
|
var exitHook = require('exit-hook');
|
|
15
17
|
var zod = require('zod');
|
|
16
18
|
var zodFromJsonSchema = require('zod-from-json-schema');
|
|
17
19
|
var zodFromJsonSchemaV3 = require('zod-from-json-schema-v3');
|
|
18
|
-
var equal = require('fast-deep-equal');
|
|
19
|
-
var uuid = require('uuid');
|
|
20
20
|
var crypto$1 = require('crypto');
|
|
21
21
|
var mcp = require('@mastra/core/mcp');
|
|
22
|
-
var
|
|
22
|
+
var requestContext = require('@mastra/core/request-context');
|
|
23
23
|
var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
24
24
|
var sse_js = require('@modelcontextprotocol/sdk/server/sse.js');
|
|
25
25
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
@@ -27,10 +27,10 @@ var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp
|
|
|
27
27
|
|
|
28
28
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
29
29
|
|
|
30
|
-
var $RefParser__default = /*#__PURE__*/_interopDefault($RefParser);
|
|
31
30
|
var equal__default = /*#__PURE__*/_interopDefault(equal);
|
|
31
|
+
var $RefParser__default = /*#__PURE__*/_interopDefault($RefParser);
|
|
32
32
|
|
|
33
|
-
// src/client/
|
|
33
|
+
// src/client/configuration.ts
|
|
34
34
|
|
|
35
35
|
// src/client/elicitationActions.ts
|
|
36
36
|
var ElicitationClientActions = class {
|
|
@@ -454,7 +454,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
454
454
|
timestamp: /* @__PURE__ */ new Date(),
|
|
455
455
|
serverName: this.name,
|
|
456
456
|
details,
|
|
457
|
-
|
|
457
|
+
requestContext: this.currentOperationContext
|
|
458
458
|
});
|
|
459
459
|
}
|
|
460
460
|
}
|
|
@@ -784,15 +784,15 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
784
784
|
description: tool.description || "",
|
|
785
785
|
inputSchema: await this.convertInputSchema(tool.inputSchema),
|
|
786
786
|
outputSchema: await this.convertOutputSchema(tool.outputSchema),
|
|
787
|
-
execute: async (
|
|
787
|
+
execute: async (input, context) => {
|
|
788
788
|
const previousContext = this.currentOperationContext;
|
|
789
|
-
this.currentOperationContext =
|
|
789
|
+
this.currentOperationContext = context?.requestContext || null;
|
|
790
790
|
try {
|
|
791
|
-
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs:
|
|
791
|
+
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input });
|
|
792
792
|
const res = await this.client.callTool(
|
|
793
793
|
{
|
|
794
794
|
name: tool.name,
|
|
795
|
-
arguments:
|
|
795
|
+
arguments: input
|
|
796
796
|
},
|
|
797
797
|
types_js.CallToolResultSchema,
|
|
798
798
|
{
|
|
@@ -804,7 +804,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
804
804
|
} catch (e) {
|
|
805
805
|
this.log("error", `Error calling tool: ${tool.name}`, {
|
|
806
806
|
error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
|
|
807
|
-
toolArgs:
|
|
807
|
+
toolArgs: input
|
|
808
808
|
});
|
|
809
809
|
throw e;
|
|
810
810
|
} finally {
|
|
@@ -825,19 +825,8 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
825
825
|
return toolsRes;
|
|
826
826
|
}
|
|
827
827
|
};
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
super(args);
|
|
831
|
-
throw new error.MastraError(
|
|
832
|
-
{
|
|
833
|
-
id: "MASTRA_MCP_CLIENT_DEPRECATED",
|
|
834
|
-
domain: error.ErrorDomain.MCP,
|
|
835
|
-
category: error.ErrorCategory.USER,
|
|
836
|
-
text: "[DEPRECATION] MastraMCPClient is deprecated and will be removed in a future release. Please use MCPClient instead."
|
|
837
|
-
}
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
};
|
|
828
|
+
|
|
829
|
+
// src/client/configuration.ts
|
|
841
830
|
var mcpClientInstances = /* @__PURE__ */ new Map();
|
|
842
831
|
var MCPClient = class extends base.MastraBase {
|
|
843
832
|
serverConfigs = {};
|
|
@@ -1438,14 +1427,15 @@ To fix this you have three different options:
|
|
|
1438
1427
|
* @example
|
|
1439
1428
|
* ```typescript
|
|
1440
1429
|
* const agent = new Agent({
|
|
1430
|
+
* id: 'multi-tool-agent',
|
|
1441
1431
|
* name: 'Multi-tool Agent',
|
|
1442
1432
|
* instructions: 'You have access to weather and stock tools.',
|
|
1443
1433
|
* model: 'openai/gpt-4',
|
|
1444
|
-
* tools: await mcp.
|
|
1434
|
+
* tools: await mcp.listTools(), // weather_getWeather, stockPrice_getPrice
|
|
1445
1435
|
* });
|
|
1446
1436
|
* ```
|
|
1447
1437
|
*/
|
|
1448
|
-
async
|
|
1438
|
+
async listTools() {
|
|
1449
1439
|
this.addToInstanceCache();
|
|
1450
1440
|
const connectedTools = {};
|
|
1451
1441
|
try {
|
|
@@ -1469,7 +1459,7 @@ To fix this you have three different options:
|
|
|
1469
1459
|
/**
|
|
1470
1460
|
* Returns toolsets organized by server name for dynamic tool injection.
|
|
1471
1461
|
*
|
|
1472
|
-
* Unlike
|
|
1462
|
+
* Unlike listTools(), this returns tools grouped by server without namespacing.
|
|
1473
1463
|
* This is intended to be passed dynamically to the generate() or stream() method.
|
|
1474
1464
|
*
|
|
1475
1465
|
* @returns Object mapping server names to their tool collections
|
|
@@ -1478,17 +1468,18 @@ To fix this you have three different options:
|
|
|
1478
1468
|
* @example
|
|
1479
1469
|
* ```typescript
|
|
1480
1470
|
* const agent = new Agent({
|
|
1471
|
+
* id: 'dynamic-agent',
|
|
1481
1472
|
* name: 'Dynamic Agent',
|
|
1482
1473
|
* instructions: 'You can use tools dynamically.',
|
|
1483
1474
|
* model: 'openai/gpt-4',
|
|
1484
1475
|
* });
|
|
1485
1476
|
*
|
|
1486
1477
|
* const response = await agent.stream(prompt, {
|
|
1487
|
-
* toolsets: await mcp.
|
|
1478
|
+
* toolsets: await mcp.listToolsets(), // { weather: {...}, stockPrice: {...} }
|
|
1488
1479
|
* });
|
|
1489
1480
|
* ```
|
|
1490
1481
|
*/
|
|
1491
|
-
async
|
|
1482
|
+
async listToolsets() {
|
|
1492
1483
|
this.addToInstanceCache();
|
|
1493
1484
|
const connectedToolsets = {};
|
|
1494
1485
|
try {
|
|
@@ -1509,12 +1500,6 @@ To fix this you have three different options:
|
|
|
1509
1500
|
}
|
|
1510
1501
|
return connectedToolsets;
|
|
1511
1502
|
}
|
|
1512
|
-
/**
|
|
1513
|
-
* @deprecated all resource actions have been moved to the this.resources object. Use this.resources.list() instead.
|
|
1514
|
-
*/
|
|
1515
|
-
async getResources() {
|
|
1516
|
-
return this.resources.list();
|
|
1517
|
-
}
|
|
1518
1503
|
/**
|
|
1519
1504
|
* Gets current session IDs for all connected MCP clients using Streamable HTTP transport.
|
|
1520
1505
|
*
|
|
@@ -1601,24 +1586,8 @@ To fix this you have three different options:
|
|
|
1601
1586
|
);
|
|
1602
1587
|
}
|
|
1603
1588
|
};
|
|
1604
|
-
var MCPConfiguration = class extends MCPClient {
|
|
1605
|
-
/**
|
|
1606
|
-
* @deprecated Use MCPClient constructor instead
|
|
1607
|
-
*/
|
|
1608
|
-
constructor(args) {
|
|
1609
|
-
super(args);
|
|
1610
|
-
throw new error.MastraError(
|
|
1611
|
-
{
|
|
1612
|
-
id: "MCP_CLIENT_CONFIGURATION_DEPRECATED",
|
|
1613
|
-
domain: error.ErrorDomain.MCP,
|
|
1614
|
-
category: error.ErrorCategory.USER,
|
|
1615
|
-
text: "[DEPRECATION] MCPConfiguration has been renamed to MCPClient and MCPConfiguration is deprecated. The API is identical but the MCPConfiguration export will be removed in the future. Update your imports now to prevent future errors."
|
|
1616
|
-
}
|
|
1617
|
-
);
|
|
1618
|
-
}
|
|
1619
|
-
};
|
|
1620
1589
|
|
|
1621
|
-
// ../../node_modules/.pnpm/hono@4.10.
|
|
1590
|
+
// ../../node_modules/.pnpm/hono@4.10.3/node_modules/hono/dist/utils/stream.js
|
|
1622
1591
|
var StreamingApi = class {
|
|
1623
1592
|
writer;
|
|
1624
1593
|
encoder;
|
|
@@ -1685,7 +1654,7 @@ var StreamingApi = class {
|
|
|
1685
1654
|
}
|
|
1686
1655
|
};
|
|
1687
1656
|
|
|
1688
|
-
// ../../node_modules/.pnpm/hono@4.10.
|
|
1657
|
+
// ../../node_modules/.pnpm/hono@4.10.3/node_modules/hono/dist/helper/streaming/utils.js
|
|
1689
1658
|
var isOldBunVersion = () => {
|
|
1690
1659
|
const version = typeof Bun !== "undefined" ? Bun.version : void 0;
|
|
1691
1660
|
if (version === void 0) {
|
|
@@ -1696,7 +1665,7 @@ var isOldBunVersion = () => {
|
|
|
1696
1665
|
return result;
|
|
1697
1666
|
};
|
|
1698
1667
|
|
|
1699
|
-
// ../../node_modules/.pnpm/hono@4.10.
|
|
1668
|
+
// ../../node_modules/.pnpm/hono@4.10.3/node_modules/hono/dist/utils/html.js
|
|
1700
1669
|
var HtmlEscapedCallbackPhase = {
|
|
1701
1670
|
Stringify: 1};
|
|
1702
1671
|
var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) => {
|
|
@@ -1727,7 +1696,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer) =>
|
|
|
1727
1696
|
}
|
|
1728
1697
|
};
|
|
1729
1698
|
|
|
1730
|
-
// ../../node_modules/.pnpm/hono@4.10.
|
|
1699
|
+
// ../../node_modules/.pnpm/hono@4.10.3/node_modules/hono/dist/helper/streaming/sse.js
|
|
1731
1700
|
var SSEStreamingApi = class extends StreamingApi {
|
|
1732
1701
|
constructor(writable, readable) {
|
|
1733
1702
|
super(writable, readable);
|
|
@@ -2138,7 +2107,8 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2138
2107
|
* import { z } from 'zod';
|
|
2139
2108
|
*
|
|
2140
2109
|
* const myAgent = new Agent({
|
|
2141
|
-
*
|
|
2110
|
+
* id: 'helper',
|
|
2111
|
+
* name: 'Helper Agent',
|
|
2142
2112
|
* description: 'A helpful assistant',
|
|
2143
2113
|
* instructions: 'You are helpful.',
|
|
2144
2114
|
* model: 'openai/gpt-4o-mini',
|
|
@@ -2152,7 +2122,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2152
2122
|
* id: 'getWeather',
|
|
2153
2123
|
* description: 'Gets weather',
|
|
2154
2124
|
* inputSchema: z.object({ location: z.string() }),
|
|
2155
|
-
* execute: async (
|
|
2125
|
+
* execute: async (inputData) => `Sunny in ${inputData.location}`,
|
|
2156
2126
|
* })
|
|
2157
2127
|
* },
|
|
2158
2128
|
* agents: { myAgent },
|
|
@@ -2249,7 +2219,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2249
2219
|
return {
|
|
2250
2220
|
tools: Object.values(this.convertedTools).map((tool) => {
|
|
2251
2221
|
const toolSpec = {
|
|
2252
|
-
name: tool.
|
|
2222
|
+
name: tool.id || "unknown",
|
|
2253
2223
|
description: tool.description,
|
|
2254
2224
|
inputSchema: tool.parameters.jsonSchema
|
|
2255
2225
|
};
|
|
@@ -2308,12 +2278,23 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2308
2278
|
return this.handleElicitationRequest(request2, serverInstance);
|
|
2309
2279
|
}
|
|
2310
2280
|
};
|
|
2311
|
-
const
|
|
2281
|
+
const mcpOptions = {
|
|
2312
2282
|
messages: [],
|
|
2313
2283
|
toolCallId: "",
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2284
|
+
// Pass MCP-specific context through the mcp property
|
|
2285
|
+
mcp: {
|
|
2286
|
+
elicitation: sessionElicitation,
|
|
2287
|
+
extra
|
|
2288
|
+
},
|
|
2289
|
+
// @ts-ignore this is to let people know that the elicitation and extra keys are now nested under mcp.elicitation and mcp.extra in tool arguments
|
|
2290
|
+
get elicitation() {
|
|
2291
|
+
throw new Error(`The "elicitation" key is now nested under "mcp.elicitation" in tool arguments`);
|
|
2292
|
+
},
|
|
2293
|
+
get extra() {
|
|
2294
|
+
throw new Error(`The "extra" key is now nested under "mcp.extra" in tool arguments`);
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
const result = await tool.execute(validation?.value ?? request.params.arguments ?? {}, mcpOptions);
|
|
2317
2298
|
this.logger.debug(`CallTool: Tool '${request.params.name}' executed successfully with result:`, result);
|
|
2318
2299
|
const duration = Date.now() - startTime;
|
|
2319
2300
|
this.logger.info(`Tool '${request.params.name}' executed successfully in ${duration}ms.`);
|
|
@@ -2589,12 +2570,12 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2589
2570
|
inputSchema: zod.z.object({
|
|
2590
2571
|
message: zod.z.string().describe("The question or input for the agent.")
|
|
2591
2572
|
}),
|
|
2592
|
-
execute: async (
|
|
2573
|
+
execute: async (inputData, context) => {
|
|
2593
2574
|
this.logger.debug(
|
|
2594
|
-
`Executing agent tool '${agentToolName}' for agent '${agent.name}' with message: "${
|
|
2575
|
+
`Executing agent tool '${agentToolName}' for agent '${agent.name}' with message: "${inputData.message}"`
|
|
2595
2576
|
);
|
|
2596
2577
|
try {
|
|
2597
|
-
const response = await agent.generate(
|
|
2578
|
+
const response = await agent.generate(inputData.message, context);
|
|
2598
2579
|
return response;
|
|
2599
2580
|
} catch (error) {
|
|
2600
2581
|
this.logger.error(`Error executing agent tool '${agentToolName}' for agent '${agent.name}':`, error);
|
|
@@ -2606,17 +2587,17 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2606
2587
|
name: agentToolName,
|
|
2607
2588
|
logger: this.logger,
|
|
2608
2589
|
mastra: this.mastra,
|
|
2609
|
-
|
|
2590
|
+
requestContext: new requestContext.RequestContext(),
|
|
2610
2591
|
tracingContext: {},
|
|
2611
2592
|
description: agentToolDefinition.description
|
|
2612
2593
|
};
|
|
2613
2594
|
const coreTool = utils.makeCoreTool(agentToolDefinition, options);
|
|
2614
2595
|
agentTools[agentToolName] = {
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2596
|
+
...coreTool,
|
|
2597
|
+
id: agentToolName,
|
|
2598
|
+
mcp: {
|
|
2599
|
+
toolType: "agent"
|
|
2600
|
+
}
|
|
2620
2601
|
};
|
|
2621
2602
|
this.logger.info(`Registered agent '${agent.name}' (key: '${agentKey}') as tool: '${agentToolName}'`);
|
|
2622
2603
|
}
|
|
@@ -2652,14 +2633,18 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2652
2633
|
id: workflowToolName,
|
|
2653
2634
|
description: `Run workflow '${workflowKey}'. Workflow description: ${workflowDescription}`,
|
|
2654
2635
|
inputSchema: workflow.inputSchema,
|
|
2655
|
-
execute: async (
|
|
2636
|
+
execute: async (inputData, context) => {
|
|
2656
2637
|
this.logger.debug(
|
|
2657
2638
|
`Executing workflow tool '${workflowToolName}' for workflow '${workflow.id}' with input:`,
|
|
2658
|
-
|
|
2639
|
+
inputData
|
|
2659
2640
|
);
|
|
2660
2641
|
try {
|
|
2661
|
-
const run2 = await workflow.
|
|
2662
|
-
const response = await run2.start({
|
|
2642
|
+
const run2 = await workflow.createRun({ runId: context?.requestContext?.get("runId") });
|
|
2643
|
+
const response = await run2.start({
|
|
2644
|
+
inputData,
|
|
2645
|
+
requestContext: context?.requestContext,
|
|
2646
|
+
tracingContext: context?.tracingContext
|
|
2647
|
+
});
|
|
2663
2648
|
return response;
|
|
2664
2649
|
} catch (error) {
|
|
2665
2650
|
this.logger.error(
|
|
@@ -2674,18 +2659,17 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2674
2659
|
name: workflowToolName,
|
|
2675
2660
|
logger: this.logger,
|
|
2676
2661
|
mastra: this.mastra,
|
|
2677
|
-
|
|
2662
|
+
requestContext: new requestContext.RequestContext(),
|
|
2678
2663
|
tracingContext: {},
|
|
2679
2664
|
description: workflowToolDefinition.description
|
|
2680
2665
|
};
|
|
2681
2666
|
const coreTool = utils.makeCoreTool(workflowToolDefinition, options);
|
|
2682
2667
|
workflowTools[workflowToolName] = {
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
toolType: "workflow"
|
|
2668
|
+
...coreTool,
|
|
2669
|
+
id: workflowToolName,
|
|
2670
|
+
mcp: {
|
|
2671
|
+
toolType: "workflow"
|
|
2672
|
+
}
|
|
2689
2673
|
};
|
|
2690
2674
|
this.logger.info(`Registered workflow '${workflow.id}' (key: '${workflowKey}') as tool: '${workflowToolName}'`);
|
|
2691
2675
|
}
|
|
@@ -2713,7 +2697,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2713
2697
|
}
|
|
2714
2698
|
const options = {
|
|
2715
2699
|
name: toolName,
|
|
2716
|
-
|
|
2700
|
+
requestContext: new requestContext.RequestContext(),
|
|
2717
2701
|
tracingContext: {},
|
|
2718
2702
|
mastra: this.mastra,
|
|
2719
2703
|
logger: this.logger,
|
|
@@ -2721,11 +2705,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2721
2705
|
};
|
|
2722
2706
|
const coreTool = utils.makeCoreTool(toolInstance, options);
|
|
2723
2707
|
definedConvertedTools[toolName] = {
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
parameters: coreTool.parameters,
|
|
2727
|
-
outputSchema: coreTool.outputSchema,
|
|
2728
|
-
execute: coreTool.execute
|
|
2708
|
+
...coreTool,
|
|
2709
|
+
id: toolName
|
|
2729
2710
|
};
|
|
2730
2711
|
this.logger.info(`Registered explicit tool: '${toolName}'`);
|
|
2731
2712
|
}
|
|
@@ -2969,6 +2950,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2969
2950
|
* @param options.options.onsessioninitialized - Callback when a new session is initialized
|
|
2970
2951
|
* @param options.options.enableJsonResponse - If true, return JSON instead of SSE streaming
|
|
2971
2952
|
* @param options.options.eventStore - Event store for message resumability
|
|
2953
|
+
* @param options.options.serverless - If true, run in stateless mode without session management (ideal for serverless environments)
|
|
2972
2954
|
*
|
|
2973
2955
|
* @throws {MastraError} If HTTP connection setup fails
|
|
2974
2956
|
*
|
|
@@ -2994,6 +2976,25 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2994
2976
|
*
|
|
2995
2977
|
* httpServer.listen(1234);
|
|
2996
2978
|
* ```
|
|
2979
|
+
*
|
|
2980
|
+
* @example Serverless mode (Cloudflare Workers, Vercel Edge, etc.)
|
|
2981
|
+
* ```typescript
|
|
2982
|
+
* export default {
|
|
2983
|
+
* async fetch(request: Request) {
|
|
2984
|
+
* const url = new URL(request.url);
|
|
2985
|
+
* if (url.pathname === '/mcp') {
|
|
2986
|
+
* await server.startHTTP({
|
|
2987
|
+
* url,
|
|
2988
|
+
* httpPath: '/mcp',
|
|
2989
|
+
* req: request,
|
|
2990
|
+
* res: response,
|
|
2991
|
+
* options: { serverless: true },
|
|
2992
|
+
* });
|
|
2993
|
+
* }
|
|
2994
|
+
* return new Response('Not found', { status: 404 });
|
|
2995
|
+
* },
|
|
2996
|
+
* };
|
|
2997
|
+
* ```
|
|
2997
2998
|
*/
|
|
2998
2999
|
async startHTTP({
|
|
2999
3000
|
url,
|
|
@@ -3009,6 +3010,11 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3009
3010
|
res.end();
|
|
3010
3011
|
return;
|
|
3011
3012
|
}
|
|
3013
|
+
if (options?.serverless) {
|
|
3014
|
+
this.logger.debug("startHTTP: Running in serverless (stateless) mode");
|
|
3015
|
+
await this.handleServerlessRequest(req, res);
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3012
3018
|
const sessionId = req.headers["mcp-session-id"];
|
|
3013
3019
|
let transport;
|
|
3014
3020
|
this.logger.debug(
|
|
@@ -3144,6 +3150,74 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3144
3150
|
}
|
|
3145
3151
|
}
|
|
3146
3152
|
}
|
|
3153
|
+
/**
|
|
3154
|
+
* Handles a stateless, serverless HTTP request without session management.
|
|
3155
|
+
*
|
|
3156
|
+
* This method bypasses all session/transport state and handles each request independently.
|
|
3157
|
+
* For serverless environments (Cloudflare Workers, Vercel Edge, etc.) where
|
|
3158
|
+
* persistent connections and session state cannot be maintained across requests.
|
|
3159
|
+
*
|
|
3160
|
+
* Each request gets a fresh transport and server instance that are discarded after the response.
|
|
3161
|
+
*
|
|
3162
|
+
* @param req - Incoming HTTP request
|
|
3163
|
+
* @param res - HTTP response object
|
|
3164
|
+
* @private
|
|
3165
|
+
*/
|
|
3166
|
+
async handleServerlessRequest(req, res) {
|
|
3167
|
+
try {
|
|
3168
|
+
this.logger.debug(`handleServerlessRequest: Received ${req.method} request`);
|
|
3169
|
+
const body = req.method === "POST" ? await new Promise((resolve, reject) => {
|
|
3170
|
+
let data = "";
|
|
3171
|
+
req.on("data", (chunk) => data += chunk);
|
|
3172
|
+
req.on("end", () => {
|
|
3173
|
+
try {
|
|
3174
|
+
resolve(JSON.parse(data));
|
|
3175
|
+
} catch (e) {
|
|
3176
|
+
reject(new Error(`Invalid JSON in request body: ${e instanceof Error ? e.message : String(e)}`));
|
|
3177
|
+
}
|
|
3178
|
+
});
|
|
3179
|
+
req.on("error", reject);
|
|
3180
|
+
}) : void 0;
|
|
3181
|
+
this.logger.debug(`handleServerlessRequest: Processing ${req.method} request`, {
|
|
3182
|
+
method: body?.method,
|
|
3183
|
+
id: body?.id
|
|
3184
|
+
});
|
|
3185
|
+
const transientServer = this.createServerInstance();
|
|
3186
|
+
const tempTransport = new streamableHttp_js.StreamableHTTPServerTransport({
|
|
3187
|
+
sessionIdGenerator: void 0,
|
|
3188
|
+
enableJsonResponse: true
|
|
3189
|
+
});
|
|
3190
|
+
await transientServer.connect(tempTransport);
|
|
3191
|
+
await tempTransport.handleRequest(req, res, body);
|
|
3192
|
+
this.logger.debug(`handleServerlessRequest: Completed ${body?.method} request`, { id: body?.id });
|
|
3193
|
+
} catch (error$1) {
|
|
3194
|
+
const mastraError = new error.MastraError(
|
|
3195
|
+
{
|
|
3196
|
+
id: "MCP_SERVER_SERVERLESS_REQUEST_FAILED",
|
|
3197
|
+
domain: error.ErrorDomain.MCP,
|
|
3198
|
+
category: error.ErrorCategory.USER,
|
|
3199
|
+
text: "Failed to handle serverless MCP request"
|
|
3200
|
+
},
|
|
3201
|
+
error$1
|
|
3202
|
+
);
|
|
3203
|
+
this.logger.trackException(mastraError);
|
|
3204
|
+
this.logger.error("handleServerlessRequest: Error handling request:", { error: mastraError });
|
|
3205
|
+
if (!res.headersSent) {
|
|
3206
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
3207
|
+
res.end(
|
|
3208
|
+
JSON.stringify({
|
|
3209
|
+
jsonrpc: "2.0",
|
|
3210
|
+
error: {
|
|
3211
|
+
code: -32603,
|
|
3212
|
+
message: "Internal server error",
|
|
3213
|
+
data: error$1 instanceof Error ? error$1.message : String(error$1)
|
|
3214
|
+
},
|
|
3215
|
+
id: null
|
|
3216
|
+
})
|
|
3217
|
+
);
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3147
3221
|
/**
|
|
3148
3222
|
* Establishes the SSE connection for the MCP server.
|
|
3149
3223
|
*
|
|
@@ -3392,11 +3466,11 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3392
3466
|
return {
|
|
3393
3467
|
tools: Object.entries(this.convertedTools).map(([toolId, tool]) => ({
|
|
3394
3468
|
id: toolId,
|
|
3395
|
-
name: tool.
|
|
3469
|
+
name: tool.id || toolId,
|
|
3396
3470
|
description: tool.description,
|
|
3397
3471
|
inputSchema: tool.parameters?.jsonSchema || tool.parameters,
|
|
3398
3472
|
outputSchema: tool.outputSchema?.jsonSchema || tool.outputSchema,
|
|
3399
|
-
toolType: tool.toolType
|
|
3473
|
+
toolType: tool.mcp?.toolType
|
|
3400
3474
|
}))
|
|
3401
3475
|
};
|
|
3402
3476
|
}
|
|
@@ -3426,11 +3500,11 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3426
3500
|
}
|
|
3427
3501
|
this.logger.debug(`Getting info for tool '${toolId}' on MCPServer '${this.name}'`);
|
|
3428
3502
|
return {
|
|
3429
|
-
name: tool.
|
|
3503
|
+
name: tool.id || toolId,
|
|
3430
3504
|
description: tool.description,
|
|
3431
3505
|
inputSchema: tool.parameters?.jsonSchema || tool.parameters,
|
|
3432
3506
|
outputSchema: tool.outputSchema?.jsonSchema || tool.outputSchema,
|
|
3433
|
-
toolType: tool.toolType
|
|
3507
|
+
toolType: tool.mcp?.toolType
|
|
3434
3508
|
};
|
|
3435
3509
|
}
|
|
3436
3510
|
/**
|
|
@@ -3535,8 +3609,6 @@ Provided arguments: ${JSON.stringify(args, null, 2)}`,
|
|
|
3535
3609
|
};
|
|
3536
3610
|
|
|
3537
3611
|
exports.MCPClient = MCPClient;
|
|
3538
|
-
exports.MCPConfiguration = MCPConfiguration;
|
|
3539
3612
|
exports.MCPServer = MCPServer;
|
|
3540
|
-
exports.MastraMCPClient = MastraMCPClient;
|
|
3541
3613
|
//# sourceMappingURL=index.cjs.map
|
|
3542
3614
|
//# sourceMappingURL=index.cjs.map
|