@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.
@@ -1,23 +1,23 @@
1
1
 
2
- > @mastra/mcp@0.5.0-alpha.3 build /home/runner/work/mastra/mastra/packages/mcp
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
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.4.0
8
8
  TSC Build start
9
- TSC ⚡️ Build success in 17533ms
9
+ TSC ⚡️ Build success in 18682ms
10
10
  DTS Build start
11
11
  CLI Target: es2022
12
12
  Analysis will use the bundled TypeScript version 5.8.3
13
13
  Writing package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.ts
14
14
  Analysis will use the bundled TypeScript version 5.8.3
15
15
  Writing package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.cts
16
- DTS ⚡️ Build success in 11255ms
16
+ DTS ⚡️ Build success in 14171ms
17
17
  CLI Cleaning output folder
18
18
  ESM Build start
19
19
  CJS Build start
20
- ESM dist/index.js 26.20 KB
21
- ESM ⚡️ Build success in 693ms
22
- CJS dist/index.cjs 26.57 KB
23
- CJS ⚡️ Build success in 693ms
20
+ CJS dist/index.cjs 32.75 KB
21
+ CJS ⚡️ Build success in 1159ms
22
+ ESM dist/index.js 32.45 KB
23
+ ESM ⚡️ 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
- return utils.isZodType(inputSchema) ? inputSchema : utils.resolveSerializedZodOutput(jsonSchemaToZod__default.default(inputSchema));
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
- const mastraTool = tools.createTool({
250
- id: `${this.name}_${tool.name}`,
251
- description: tool.description || "",
252
- inputSchema: this.convertInputSchema(tool.inputSchema),
253
- execute: async ({ context }) => {
254
- try {
255
- this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: context });
256
- const res = await this.client.callTool(
257
- {
258
- name: tool.name,
259
- arguments: context
260
- },
261
- types_js.CallToolResultSchema,
262
- {
263
- timeout: this.timeout
264
- }
265
- );
266
- this.log("debug", `Tool executed successfully: ${tool.name}`);
267
- return res;
268
- } catch (e) {
269
- this.log("error", `Error calling tool: ${tool.name}`, {
270
- error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
271
- toolArgs: context
272
- });
273
- throw e;
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
- if (tool.name) {
278
- toolsRes[tool.name] = mastraTool;
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;