@mastra/mcp 0.5.0-alpha.3 → 0.5.0-alpha.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 +18 -0
- package/dist/_tsup-dts-rollup.d.cts +29 -1
- package/dist/_tsup-dts-rollup.d.ts +29 -1
- package/dist/index.cjs +227 -42
- package/dist/index.js +227 -41
- package/package.json +8 -3
- package/src/__fixtures__/fire-crawl-complex-schema.ts +1013 -0
- package/src/client.test.ts +4 -4
- package/src/client.ts +77 -38
- package/src/configuration.test.ts +272 -0
- package/src/server.test.ts +183 -23
- package/src/server.ts +86 -10
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/mcp@0.5.0-alpha.
|
|
2
|
+
> @mastra/mcp@0.5.0-alpha.5 build /home/runner/work/mastra/mastra/packages/mcp
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.4.0
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 18682ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 14171ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[
|
|
21
|
-
[
|
|
22
|
-
[
|
|
23
|
-
[
|
|
20
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m32.75 KB[39m
|
|
21
|
+
[32mCJS[39m ⚡️ Build success in 1159ms
|
|
22
|
+
[32mESM[39m [1mdist/index.js [22m[32m32.45 KB[39m
|
|
23
|
+
[32mESM[39m ⚡️ Build success in 1159ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @mastra/mcp
|
|
2
2
|
|
|
3
|
+
## 0.5.0-alpha.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8baa6c8: passes runtimeContext to the logger function inside MCPClient tool calls
|
|
8
|
+
|
|
9
|
+
## 0.5.0-alpha.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 396be50: updated mcp server routes for MCP SSE for use with hono server
|
|
14
|
+
- da082f8: Switch from serializing json schema string as a function to a library that creates a zod object in memory from the json schema. This reduces the errors we were seeing from zod schema code that could not be serialized.
|
|
15
|
+
- Updated dependencies [396be50]
|
|
16
|
+
- Updated dependencies [c3bd795]
|
|
17
|
+
- Updated dependencies [da082f8]
|
|
18
|
+
- Updated dependencies [a5810ce]
|
|
19
|
+
- @mastra/core@0.9.4-alpha.3
|
|
20
|
+
|
|
3
21
|
## 0.5.0-alpha.3
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -4,11 +4,15 @@ import type * as http from 'node:http';
|
|
|
4
4
|
import { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { MastraBase } from '@mastra/core/base';
|
|
6
6
|
import { MCPServerBase } from '@mastra/core/mcp';
|
|
7
|
+
import type { MCPServerHonoSSEOptions } from '@mastra/core/mcp';
|
|
7
8
|
import type { MCPServerSSEOptions } from '@mastra/core/mcp';
|
|
8
9
|
import type { Protocol } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
10
|
+
import type { RuntimeContext } from '@mastra/core/di';
|
|
9
11
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
12
|
import type { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
11
13
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
14
|
+
import type { SSEStreamingApi } from 'hono/streaming';
|
|
15
|
+
import { SSETransport } from 'hono-mcp-server-sse-transport';
|
|
12
16
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
13
17
|
import type { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
14
18
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
@@ -18,6 +22,8 @@ import { ToolExecutionContext } from '@mastra/core';
|
|
|
18
22
|
import type { ToolsInput } from '@mastra/core/agent';
|
|
19
23
|
import { z } from 'zod';
|
|
20
24
|
|
|
25
|
+
export declare const allTools: ToolsInput;
|
|
26
|
+
|
|
21
27
|
declare type BaseServerOptions = {
|
|
22
28
|
logger?: LogHandler;
|
|
23
29
|
timeout?: number;
|
|
@@ -46,6 +52,7 @@ export declare class InternalMastraMCPClient extends MastraBase {
|
|
|
46
52
|
private enableServerLogs?;
|
|
47
53
|
private serverConfig;
|
|
48
54
|
private transport?;
|
|
55
|
+
private currentOperationContext;
|
|
49
56
|
constructor({ name, version, server, capabilities, timeout, }: InternalMastraMCPClientOptions);
|
|
50
57
|
/**
|
|
51
58
|
* Log a message at the specified level
|
|
@@ -100,6 +107,7 @@ declare interface LogMessage {
|
|
|
100
107
|
timestamp: Date;
|
|
101
108
|
serverName: string;
|
|
102
109
|
details?: Record<string, any>;
|
|
110
|
+
runtimeContext?: RuntimeContext | null;
|
|
103
111
|
}
|
|
104
112
|
export { LogMessage }
|
|
105
113
|
export { LogMessage as LogMessage_alias_1 }
|
|
@@ -188,6 +196,7 @@ declare class MCPServer extends MCPServerBase {
|
|
|
188
196
|
private server;
|
|
189
197
|
private stdioTransport?;
|
|
190
198
|
private sseTransport?;
|
|
199
|
+
private sseHonoTransports;
|
|
191
200
|
private streamableHTTPTransport?;
|
|
192
201
|
private listToolsHandlerIsRegistered;
|
|
193
202
|
private callToolHandlerIsRegistered;
|
|
@@ -199,6 +208,10 @@ declare class MCPServer extends MCPServerBase {
|
|
|
199
208
|
* Get the current SSE transport.
|
|
200
209
|
*/
|
|
201
210
|
getSseTransport(): SSEServerTransport | undefined;
|
|
211
|
+
/**
|
|
212
|
+
* Get the current SSE Hono transport.
|
|
213
|
+
*/
|
|
214
|
+
getSseHonoTransport(sessionId: string): SSETransport | undefined;
|
|
202
215
|
/**
|
|
203
216
|
* Get the current streamable HTTP transport.
|
|
204
217
|
*/
|
|
@@ -243,6 +256,16 @@ declare class MCPServer extends MCPServerBase {
|
|
|
243
256
|
* @param res HTTP response (must support .write/.end)
|
|
244
257
|
*/
|
|
245
258
|
startSSE({ url, ssePath, messagePath, req, res }: MCPServerSSEOptions): Promise<void>;
|
|
259
|
+
/**
|
|
260
|
+
* Handles MCP-over-SSE protocol for user-provided HTTP servers.
|
|
261
|
+
* Call this from your HTTP server for both the SSE and message endpoints.
|
|
262
|
+
*
|
|
263
|
+
* @param url Parsed URL of the incoming request
|
|
264
|
+
* @param ssePath Path for establishing the SSE connection (e.g. '/sse')
|
|
265
|
+
* @param messagePath Path for POSTing client messages (e.g. '/message')
|
|
266
|
+
* @param context Incoming Hono context
|
|
267
|
+
*/
|
|
268
|
+
startHonoSSE({ url, ssePath, messagePath, context }: MCPServerHonoSSEOptions): Promise<Response>;
|
|
246
269
|
/**
|
|
247
270
|
* Handles MCP-over-StreamableHTTP protocol for user-provided HTTP servers.
|
|
248
271
|
* Call this from your HTTP server for the streamable HTTP endpoint.
|
|
@@ -260,11 +283,14 @@ declare class MCPServer extends MCPServerBase {
|
|
|
260
283
|
res: http.ServerResponse<http.IncomingMessage>;
|
|
261
284
|
options?: StreamableHTTPServerTransportOptions;
|
|
262
285
|
}): Promise<void>;
|
|
263
|
-
handlePostMessage(req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): Promise<void>;
|
|
264
286
|
connectSSE({ messagePath, res, }: {
|
|
265
287
|
messagePath: string;
|
|
266
288
|
res: http.ServerResponse<http.IncomingMessage>;
|
|
267
289
|
}): Promise<void>;
|
|
290
|
+
connectHonoSSE({ messagePath, stream }: {
|
|
291
|
+
messagePath: string;
|
|
292
|
+
stream: SSEStreamingApi;
|
|
293
|
+
}): Promise<void>;
|
|
268
294
|
/**
|
|
269
295
|
* Close the MCP server and all its connections
|
|
270
296
|
*/
|
|
@@ -273,6 +299,8 @@ declare class MCPServer extends MCPServerBase {
|
|
|
273
299
|
export { MCPServer }
|
|
274
300
|
export { MCPServer as MCPServer_alias_1 }
|
|
275
301
|
|
|
302
|
+
export declare const mcpServerName = "firecrawl-mcp-fixture";
|
|
303
|
+
|
|
276
304
|
export declare const server: Server<{
|
|
277
305
|
method: string;
|
|
278
306
|
params?: {
|
|
@@ -4,11 +4,15 @@ import type * as http from 'node:http';
|
|
|
4
4
|
import { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { MastraBase } from '@mastra/core/base';
|
|
6
6
|
import { MCPServerBase } from '@mastra/core/mcp';
|
|
7
|
+
import type { MCPServerHonoSSEOptions } from '@mastra/core/mcp';
|
|
7
8
|
import type { MCPServerSSEOptions } from '@mastra/core/mcp';
|
|
8
9
|
import type { Protocol } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
10
|
+
import type { RuntimeContext } from '@mastra/core/di';
|
|
9
11
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
10
12
|
import type { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
11
13
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
14
|
+
import type { SSEStreamingApi } from 'hono/streaming';
|
|
15
|
+
import { SSETransport } from 'hono-mcp-server-sse-transport';
|
|
12
16
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
13
17
|
import type { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
14
18
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
@@ -18,6 +22,8 @@ import { ToolExecutionContext } from '@mastra/core';
|
|
|
18
22
|
import type { ToolsInput } from '@mastra/core/agent';
|
|
19
23
|
import { z } from 'zod';
|
|
20
24
|
|
|
25
|
+
export declare const allTools: ToolsInput;
|
|
26
|
+
|
|
21
27
|
declare type BaseServerOptions = {
|
|
22
28
|
logger?: LogHandler;
|
|
23
29
|
timeout?: number;
|
|
@@ -46,6 +52,7 @@ export declare class InternalMastraMCPClient extends MastraBase {
|
|
|
46
52
|
private enableServerLogs?;
|
|
47
53
|
private serverConfig;
|
|
48
54
|
private transport?;
|
|
55
|
+
private currentOperationContext;
|
|
49
56
|
constructor({ name, version, server, capabilities, timeout, }: InternalMastraMCPClientOptions);
|
|
50
57
|
/**
|
|
51
58
|
* Log a message at the specified level
|
|
@@ -100,6 +107,7 @@ declare interface LogMessage {
|
|
|
100
107
|
timestamp: Date;
|
|
101
108
|
serverName: string;
|
|
102
109
|
details?: Record<string, any>;
|
|
110
|
+
runtimeContext?: RuntimeContext | null;
|
|
103
111
|
}
|
|
104
112
|
export { LogMessage }
|
|
105
113
|
export { LogMessage as LogMessage_alias_1 }
|
|
@@ -188,6 +196,7 @@ declare class MCPServer extends MCPServerBase {
|
|
|
188
196
|
private server;
|
|
189
197
|
private stdioTransport?;
|
|
190
198
|
private sseTransport?;
|
|
199
|
+
private sseHonoTransports;
|
|
191
200
|
private streamableHTTPTransport?;
|
|
192
201
|
private listToolsHandlerIsRegistered;
|
|
193
202
|
private callToolHandlerIsRegistered;
|
|
@@ -199,6 +208,10 @@ declare class MCPServer extends MCPServerBase {
|
|
|
199
208
|
* Get the current SSE transport.
|
|
200
209
|
*/
|
|
201
210
|
getSseTransport(): SSEServerTransport | undefined;
|
|
211
|
+
/**
|
|
212
|
+
* Get the current SSE Hono transport.
|
|
213
|
+
*/
|
|
214
|
+
getSseHonoTransport(sessionId: string): SSETransport | undefined;
|
|
202
215
|
/**
|
|
203
216
|
* Get the current streamable HTTP transport.
|
|
204
217
|
*/
|
|
@@ -243,6 +256,16 @@ declare class MCPServer extends MCPServerBase {
|
|
|
243
256
|
* @param res HTTP response (must support .write/.end)
|
|
244
257
|
*/
|
|
245
258
|
startSSE({ url, ssePath, messagePath, req, res }: MCPServerSSEOptions): Promise<void>;
|
|
259
|
+
/**
|
|
260
|
+
* Handles MCP-over-SSE protocol for user-provided HTTP servers.
|
|
261
|
+
* Call this from your HTTP server for both the SSE and message endpoints.
|
|
262
|
+
*
|
|
263
|
+
* @param url Parsed URL of the incoming request
|
|
264
|
+
* @param ssePath Path for establishing the SSE connection (e.g. '/sse')
|
|
265
|
+
* @param messagePath Path for POSTing client messages (e.g. '/message')
|
|
266
|
+
* @param context Incoming Hono context
|
|
267
|
+
*/
|
|
268
|
+
startHonoSSE({ url, ssePath, messagePath, context }: MCPServerHonoSSEOptions): Promise<Response>;
|
|
246
269
|
/**
|
|
247
270
|
* Handles MCP-over-StreamableHTTP protocol for user-provided HTTP servers.
|
|
248
271
|
* Call this from your HTTP server for the streamable HTTP endpoint.
|
|
@@ -260,11 +283,14 @@ declare class MCPServer extends MCPServerBase {
|
|
|
260
283
|
res: http.ServerResponse<http.IncomingMessage>;
|
|
261
284
|
options?: StreamableHTTPServerTransportOptions;
|
|
262
285
|
}): Promise<void>;
|
|
263
|
-
handlePostMessage(req: http.IncomingMessage, res: http.ServerResponse<http.IncomingMessage>): Promise<void>;
|
|
264
286
|
connectSSE({ messagePath, res, }: {
|
|
265
287
|
messagePath: string;
|
|
266
288
|
res: http.ServerResponse<http.IncomingMessage>;
|
|
267
289
|
}): Promise<void>;
|
|
290
|
+
connectHonoSSE({ messagePath, stream }: {
|
|
291
|
+
messagePath: string;
|
|
292
|
+
stream: SSEStreamingApi;
|
|
293
|
+
}): Promise<void>;
|
|
268
294
|
/**
|
|
269
295
|
* Close the MCP server and all its connections
|
|
270
296
|
*/
|
|
@@ -273,6 +299,8 @@ declare class MCPServer extends MCPServerBase {
|
|
|
273
299
|
export { MCPServer }
|
|
274
300
|
export { MCPServer as MCPServer_alias_1 }
|
|
275
301
|
|
|
302
|
+
export declare const mcpServerName = "firecrawl-mcp-fixture";
|
|
303
|
+
|
|
276
304
|
export declare const server: Server<{
|
|
277
305
|
method: string;
|
|
278
306
|
params?: {
|
package/dist/index.cjs
CHANGED
|
@@ -10,11 +10,11 @@ var streamableHttp_js$1 = require('@modelcontextprotocol/sdk/client/streamableHt
|
|
|
10
10
|
var protocol_js = require('@modelcontextprotocol/sdk/shared/protocol.js');
|
|
11
11
|
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
12
12
|
var exitHook = require('exit-hook');
|
|
13
|
-
var jsonSchemaToZod = require('json-schema-to-zod');
|
|
14
13
|
var zod = require('zod');
|
|
14
|
+
var zodFromJsonSchema = require('zod-from-json-schema');
|
|
15
15
|
var equal = require('fast-deep-equal');
|
|
16
16
|
var uuid = require('uuid');
|
|
17
|
-
var crypto = require('crypto');
|
|
17
|
+
var crypto$1 = require('crypto');
|
|
18
18
|
var core = require('@mastra/core');
|
|
19
19
|
var mcp = require('@mastra/core/mcp');
|
|
20
20
|
var runtimeContext = require('@mastra/core/runtime-context');
|
|
@@ -22,10 +22,10 @@ var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
|
22
22
|
var sse_js = require('@modelcontextprotocol/sdk/server/sse.js');
|
|
23
23
|
var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
|
|
24
24
|
var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
25
|
+
var streaming = require('hono/streaming');
|
|
25
26
|
|
|
26
27
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
28
|
|
|
28
|
-
var jsonSchemaToZod__default = /*#__PURE__*/_interopDefault(jsonSchemaToZod);
|
|
29
29
|
var equal__default = /*#__PURE__*/_interopDefault(equal);
|
|
30
30
|
|
|
31
31
|
// src/client.ts
|
|
@@ -55,6 +55,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
55
55
|
enableServerLogs;
|
|
56
56
|
serverConfig;
|
|
57
57
|
transport;
|
|
58
|
+
currentOperationContext = null;
|
|
58
59
|
constructor({
|
|
59
60
|
name,
|
|
60
61
|
version = "1.0.0",
|
|
@@ -95,7 +96,8 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
95
96
|
message: msg,
|
|
96
97
|
timestamp: /* @__PURE__ */ new Date(),
|
|
97
98
|
serverName: this.name,
|
|
98
|
-
details
|
|
99
|
+
details,
|
|
100
|
+
runtimeContext: this.currentOperationContext
|
|
99
101
|
});
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -238,7 +240,29 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
238
240
|
});
|
|
239
241
|
}
|
|
240
242
|
convertInputSchema(inputSchema) {
|
|
241
|
-
|
|
243
|
+
if (utils.isZodType(inputSchema)) {
|
|
244
|
+
return inputSchema;
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
const rawShape = zodFromJsonSchema.jsonSchemaObjectToZodRawShape(inputSchema);
|
|
248
|
+
return zod.z.object(rawShape);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
let errorDetails;
|
|
251
|
+
if (error instanceof Error) {
|
|
252
|
+
errorDetails = error.stack;
|
|
253
|
+
} else {
|
|
254
|
+
try {
|
|
255
|
+
errorDetails = JSON.stringify(error);
|
|
256
|
+
} catch {
|
|
257
|
+
errorDetails = String(error);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
this.log("error", "Failed to convert JSON schema to Zod schema using zodFromJsonSchema", {
|
|
261
|
+
error: errorDetails,
|
|
262
|
+
originalJsonSchema: inputSchema
|
|
263
|
+
});
|
|
264
|
+
throw new Error(errorDetails);
|
|
265
|
+
}
|
|
242
266
|
}
|
|
243
267
|
async tools() {
|
|
244
268
|
this.log("debug", `Requesting tools from MCP server`);
|
|
@@ -246,36 +270,47 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
246
270
|
const toolsRes = {};
|
|
247
271
|
tools$1.forEach((tool) => {
|
|
248
272
|
this.log("debug", `Processing tool: ${tool.name}`);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
273
|
+
try {
|
|
274
|
+
const mastraTool = tools.createTool({
|
|
275
|
+
id: `${this.name}_${tool.name}`,
|
|
276
|
+
description: tool.description || "",
|
|
277
|
+
inputSchema: this.convertInputSchema(tool.inputSchema),
|
|
278
|
+
execute: async ({ context, runtimeContext }) => {
|
|
279
|
+
const previousContext = this.currentOperationContext;
|
|
280
|
+
this.currentOperationContext = runtimeContext || null;
|
|
281
|
+
try {
|
|
282
|
+
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: context });
|
|
283
|
+
const res = await this.client.callTool(
|
|
284
|
+
{
|
|
285
|
+
name: tool.name,
|
|
286
|
+
arguments: context
|
|
287
|
+
},
|
|
288
|
+
types_js.CallToolResultSchema,
|
|
289
|
+
{
|
|
290
|
+
timeout: this.timeout
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
this.log("debug", `Tool executed successfully: ${tool.name}`);
|
|
294
|
+
return res;
|
|
295
|
+
} catch (e) {
|
|
296
|
+
this.log("error", `Error calling tool: ${tool.name}`, {
|
|
297
|
+
error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
|
|
298
|
+
toolArgs: context
|
|
299
|
+
});
|
|
300
|
+
throw e;
|
|
301
|
+
} finally {
|
|
302
|
+
this.currentOperationContext = previousContext;
|
|
303
|
+
}
|
|
274
304
|
}
|
|
305
|
+
});
|
|
306
|
+
if (tool.name) {
|
|
307
|
+
toolsRes[tool.name] = mastraTool;
|
|
275
308
|
}
|
|
276
|
-
})
|
|
277
|
-
|
|
278
|
-
|
|
309
|
+
} catch (toolCreationError) {
|
|
310
|
+
this.log("error", `Failed to create Mastra tool wrapper for MCP tool: ${tool.name}`, {
|
|
311
|
+
error: toolCreationError instanceof Error ? toolCreationError.stack : String(toolCreationError),
|
|
312
|
+
mcpToolDefinition: tool
|
|
313
|
+
});
|
|
279
314
|
}
|
|
280
315
|
});
|
|
281
316
|
return toolsRes;
|
|
@@ -477,10 +512,95 @@ var MCPConfiguration = class extends MCPClient {
|
|
|
477
512
|
);
|
|
478
513
|
}
|
|
479
514
|
};
|
|
515
|
+
var MAXIMUM_MESSAGE_SIZE = 4 * 1024 * 1024;
|
|
516
|
+
var SSETransport = class {
|
|
517
|
+
messageUrl;
|
|
518
|
+
stream;
|
|
519
|
+
_sessionId;
|
|
520
|
+
onclose;
|
|
521
|
+
onerror;
|
|
522
|
+
onmessage;
|
|
523
|
+
/**
|
|
524
|
+
* Creates a new SSETransport, which will direct the MPC client to POST messages to messageUrl
|
|
525
|
+
*/
|
|
526
|
+
constructor(messageUrl, stream) {
|
|
527
|
+
this.messageUrl = messageUrl;
|
|
528
|
+
this.stream = stream;
|
|
529
|
+
this._sessionId = crypto.randomUUID();
|
|
530
|
+
this.stream.onAbort(() => {
|
|
531
|
+
void this.close();
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
get sessionId() {
|
|
535
|
+
return this._sessionId;
|
|
536
|
+
}
|
|
537
|
+
// start() is automatically called after MCP Server connects to the transport
|
|
538
|
+
async start() {
|
|
539
|
+
if (this.stream == null) {
|
|
540
|
+
throw new Error("Stream not initialized");
|
|
541
|
+
}
|
|
542
|
+
if (this.stream.closed) {
|
|
543
|
+
throw new Error("SSE transport already closed!");
|
|
544
|
+
}
|
|
545
|
+
await this.stream.writeSSE({
|
|
546
|
+
event: "endpoint",
|
|
547
|
+
data: `${this.messageUrl}?sessionId=${this.sessionId}`
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
async handlePostMessage(context) {
|
|
551
|
+
if (this.stream?.closed == null) {
|
|
552
|
+
return context.text("SSE connection not established", 500);
|
|
553
|
+
}
|
|
554
|
+
try {
|
|
555
|
+
const contentType = context.req.header("content-type") || "";
|
|
556
|
+
if (!contentType.includes("application/json")) {
|
|
557
|
+
throw new Error(`Unsupported content-type: ${contentType}`);
|
|
558
|
+
}
|
|
559
|
+
const contentLength = Number.parseInt(context.req.header("content-length") || "0", 10);
|
|
560
|
+
if (contentLength > MAXIMUM_MESSAGE_SIZE) {
|
|
561
|
+
throw new Error(`Request body too large: ${contentLength} bytes`);
|
|
562
|
+
}
|
|
563
|
+
const body = await context.req.json();
|
|
564
|
+
await this.handleMessage(body);
|
|
565
|
+
return context.text("Accepted", 202);
|
|
566
|
+
} catch (error) {
|
|
567
|
+
this.onerror?.(error);
|
|
568
|
+
return context.text("Error", 400);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Handle a client message, regardless of how it arrived. This can be used to inform the server of messages that arrive via a means different than HTTP POST.
|
|
573
|
+
*/
|
|
574
|
+
async handleMessage(message) {
|
|
575
|
+
let parsedMessage;
|
|
576
|
+
try {
|
|
577
|
+
parsedMessage = types_js.JSONRPCMessageSchema.parse(message);
|
|
578
|
+
} catch (error) {
|
|
579
|
+
this.onerror?.(error);
|
|
580
|
+
throw error;
|
|
581
|
+
}
|
|
582
|
+
this.onmessage?.(parsedMessage);
|
|
583
|
+
}
|
|
584
|
+
async close() {
|
|
585
|
+
if (this.stream?.closed) {
|
|
586
|
+
this.stream.abort();
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
async send(message) {
|
|
590
|
+
if (this.stream?.closed) {
|
|
591
|
+
throw new Error("Not connected");
|
|
592
|
+
}
|
|
593
|
+
await this.stream.writeSSE({
|
|
594
|
+
event: "message",
|
|
595
|
+
data: JSON.stringify(message)
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
};
|
|
480
599
|
var MCPServer = class extends mcp.MCPServerBase {
|
|
481
600
|
server;
|
|
482
601
|
stdioTransport;
|
|
483
602
|
sseTransport;
|
|
603
|
+
sseHonoTransports;
|
|
484
604
|
streamableHTTPTransport;
|
|
485
605
|
listToolsHandlerIsRegistered = false;
|
|
486
606
|
callToolHandlerIsRegistered = false;
|
|
@@ -496,6 +616,12 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
496
616
|
getSseTransport() {
|
|
497
617
|
return this.sseTransport;
|
|
498
618
|
}
|
|
619
|
+
/**
|
|
620
|
+
* Get the current SSE Hono transport.
|
|
621
|
+
*/
|
|
622
|
+
getSseHonoTransport(sessionId) {
|
|
623
|
+
return this.sseHonoTransports.get(sessionId);
|
|
624
|
+
}
|
|
499
625
|
/**
|
|
500
626
|
* Get the current streamable HTTP transport.
|
|
501
627
|
*/
|
|
@@ -514,6 +640,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
514
640
|
this.logger.info(
|
|
515
641
|
`Initialized MCPServer '${name}' v${version} with tools: ${Object.keys(this.convertedTools).join(", ")}`
|
|
516
642
|
);
|
|
643
|
+
this.sseHonoTransports = /* @__PURE__ */ new Map();
|
|
517
644
|
this.registerListToolsHandler();
|
|
518
645
|
this.registerCallToolHandler();
|
|
519
646
|
}
|
|
@@ -685,6 +812,43 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
685
812
|
res.end();
|
|
686
813
|
}
|
|
687
814
|
}
|
|
815
|
+
/**
|
|
816
|
+
* Handles MCP-over-SSE protocol for user-provided HTTP servers.
|
|
817
|
+
* Call this from your HTTP server for both the SSE and message endpoints.
|
|
818
|
+
*
|
|
819
|
+
* @param url Parsed URL of the incoming request
|
|
820
|
+
* @param ssePath Path for establishing the SSE connection (e.g. '/sse')
|
|
821
|
+
* @param messagePath Path for POSTing client messages (e.g. '/message')
|
|
822
|
+
* @param context Incoming Hono context
|
|
823
|
+
*/
|
|
824
|
+
async startHonoSSE({ url, ssePath, messagePath, context }) {
|
|
825
|
+
if (url.pathname === ssePath) {
|
|
826
|
+
return streaming.streamSSE(context, async (stream) => {
|
|
827
|
+
await this.connectHonoSSE({
|
|
828
|
+
messagePath,
|
|
829
|
+
stream
|
|
830
|
+
});
|
|
831
|
+
});
|
|
832
|
+
} else if (url.pathname === messagePath) {
|
|
833
|
+
this.logger.debug("Received message");
|
|
834
|
+
const sessionId = context.req.query("sessionId");
|
|
835
|
+
this.logger.debug("Received message for sessionId", { sessionId });
|
|
836
|
+
if (!sessionId) {
|
|
837
|
+
return context.text("No sessionId provided", 400);
|
|
838
|
+
}
|
|
839
|
+
if (!this.sseHonoTransports.has(sessionId)) {
|
|
840
|
+
return context.text(`No transport found for sessionId ${sessionId}`, 400);
|
|
841
|
+
}
|
|
842
|
+
const message = await this.sseHonoTransports.get(sessionId)?.handlePostMessage(context);
|
|
843
|
+
if (!message) {
|
|
844
|
+
return context.text("Transport not found", 400);
|
|
845
|
+
}
|
|
846
|
+
return message;
|
|
847
|
+
} else {
|
|
848
|
+
this.logger.debug("Unknown path:", { path: url.pathname });
|
|
849
|
+
return context.text("Unknown path", 404);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
688
852
|
/**
|
|
689
853
|
* Handles MCP-over-StreamableHTTP protocol for user-provided HTTP servers.
|
|
690
854
|
* Call this from your HTTP server for the streamable HTTP endpoint.
|
|
@@ -700,7 +864,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
700
864
|
httpPath,
|
|
701
865
|
req,
|
|
702
866
|
res,
|
|
703
|
-
options = { sessionIdGenerator: () => crypto.randomUUID() }
|
|
867
|
+
options = { sessionIdGenerator: () => crypto$1.randomUUID() }
|
|
704
868
|
}) {
|
|
705
869
|
if (url.pathname === httpPath) {
|
|
706
870
|
this.streamableHTTPTransport = new streamableHttp_js.StreamableHTTPServerTransport(options);
|
|
@@ -732,14 +896,6 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
732
896
|
res.end();
|
|
733
897
|
}
|
|
734
898
|
}
|
|
735
|
-
async handlePostMessage(req, res) {
|
|
736
|
-
if (!this.sseTransport) {
|
|
737
|
-
res.writeHead(503);
|
|
738
|
-
res.end("SSE connection not established");
|
|
739
|
-
return;
|
|
740
|
-
}
|
|
741
|
-
await this.sseTransport.handlePostMessage(req, res);
|
|
742
|
-
}
|
|
743
899
|
async connectSSE({
|
|
744
900
|
messagePath,
|
|
745
901
|
res
|
|
@@ -755,6 +911,29 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
755
911
|
this.sseTransport = void 0;
|
|
756
912
|
});
|
|
757
913
|
}
|
|
914
|
+
async connectHonoSSE({ messagePath, stream }) {
|
|
915
|
+
this.logger.debug("Received SSE connection");
|
|
916
|
+
const sseTransport = new SSETransport(messagePath, stream);
|
|
917
|
+
const sessionId = sseTransport.sessionId;
|
|
918
|
+
this.logger.debug("SSE Transport created with sessionId:", { sessionId });
|
|
919
|
+
this.sseHonoTransports.set(sessionId, sseTransport);
|
|
920
|
+
stream.onAbort(() => {
|
|
921
|
+
this.logger.debug("SSE Transport aborted with sessionId:", { sessionId });
|
|
922
|
+
this.sseHonoTransports.delete(sessionId);
|
|
923
|
+
});
|
|
924
|
+
await this.server.connect(sseTransport);
|
|
925
|
+
this.server.onclose = async () => {
|
|
926
|
+
this.logger.debug("SSE Transport closed with sessionId:", { sessionId });
|
|
927
|
+
this.sseHonoTransports.delete(sessionId);
|
|
928
|
+
await this.server.close();
|
|
929
|
+
};
|
|
930
|
+
while (true) {
|
|
931
|
+
const sessionIds = Array.from(this.sseHonoTransports.keys() || []);
|
|
932
|
+
this.logger.debug("Active Hono SSE sessions:", { sessionIds });
|
|
933
|
+
await stream.write(":keep-alive\n\n");
|
|
934
|
+
await stream.sleep(6e4);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
758
937
|
/**
|
|
759
938
|
* Close the MCP server and all its connections
|
|
760
939
|
*/
|
|
@@ -770,6 +949,12 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
770
949
|
await this.sseTransport.close?.();
|
|
771
950
|
this.sseTransport = void 0;
|
|
772
951
|
}
|
|
952
|
+
if (this.sseHonoTransports) {
|
|
953
|
+
for (const transport of this.sseHonoTransports.values()) {
|
|
954
|
+
await transport.close?.();
|
|
955
|
+
}
|
|
956
|
+
this.sseHonoTransports.clear();
|
|
957
|
+
}
|
|
773
958
|
if (this.streamableHTTPTransport) {
|
|
774
959
|
await this.streamableHTTPTransport.close?.();
|
|
775
960
|
this.streamableHTTPTransport = void 0;
|