@mastra/mcp 1.0.0-beta.3 → 1.0.0-beta.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
@@ -1,38 +1,38 @@
1
1
  'use strict';
2
2
 
3
+ var $RefParser = require('@apidevtools/json-schema-ref-parser');
3
4
  var base = require('@mastra/core/base');
4
5
  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');
9
6
  var tools = require('@mastra/core/tools');
10
7
  var utils = require('@mastra/core/utils');
11
- var index_js$1 = require('@modelcontextprotocol/sdk/client/index.js');
12
- var sse_js$1 = require('@modelcontextprotocol/sdk/client/sse.js');
13
- var stdio_js$1 = require('@modelcontextprotocol/sdk/client/stdio.js');
14
- var streamableHttp_js$1 = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
8
+ var index_js = require('@modelcontextprotocol/sdk/client/index.js');
9
+ var sse_js = require('@modelcontextprotocol/sdk/client/sse.js');
10
+ var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
11
+ var streamableHttp_js = require('@modelcontextprotocol/sdk/client/streamableHttp.js');
12
+ var protocol_js = require('@modelcontextprotocol/sdk/shared/protocol.js');
15
13
  var types_js = require('@modelcontextprotocol/sdk/types.js');
16
14
  var exitHook = require('exit-hook');
17
15
  var zod = require('zod');
18
16
  var zodFromJsonSchema = require('zod-from-json-schema');
19
17
  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
22
  var requestContext = require('@mastra/core/request-context');
23
- var index_js = require('@modelcontextprotocol/sdk/server/index.js');
24
- var sse_js = require('@modelcontextprotocol/sdk/server/sse.js');
25
- var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
26
- var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
23
+ var index_js$1 = require('@modelcontextprotocol/sdk/server/index.js');
24
+ var sse_js$1 = require('@modelcontextprotocol/sdk/server/sse.js');
25
+ var stdio_js$1 = require('@modelcontextprotocol/sdk/server/stdio.js');
26
+ var streamableHttp_js$1 = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
27
27
 
28
28
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
29
29
 
30
- var equal__default = /*#__PURE__*/_interopDefault(equal);
31
30
  var $RefParser__default = /*#__PURE__*/_interopDefault($RefParser);
31
+ var equal__default = /*#__PURE__*/_interopDefault(equal);
32
32
 
33
- // src/client/configuration.ts
33
+ // src/client/client.ts
34
34
 
35
- // src/client/elicitationActions.ts
35
+ // src/client/actions/elicitation.ts
36
36
  var ElicitationClientActions = class {
37
37
  client;
38
38
  logger;
@@ -85,6 +85,23 @@ var ElicitationClientActions = class {
85
85
  this.client.setElicitationRequestHandler(handler);
86
86
  }
87
87
  };
88
+
89
+ // src/client/actions/progress.ts
90
+ var ProgressClientActions = class {
91
+ client;
92
+ logger;
93
+ constructor({ client, logger }) {
94
+ this.client = client;
95
+ this.logger = logger;
96
+ }
97
+ /**
98
+ * Set a notification handler for progress updates.
99
+ * @param handler The callback function to handle progress notifications.
100
+ */
101
+ onUpdate(handler) {
102
+ this.client.setProgressNotificationHandler(handler);
103
+ }
104
+ };
88
105
  var PromptClientActions = class {
89
106
  client;
90
107
  logger;
@@ -374,6 +391,7 @@ var ResourceClientActions = class {
374
391
 
375
392
  // src/client/client.ts
376
393
  var DEFAULT_SERVER_CONNECT_TIMEOUT_MSEC = 3e3;
394
+ var SSE_FALLBACK_STATUS_CODES = [400, 404, 405];
377
395
  function convertLogLevelToLoggerMethod(level) {
378
396
  switch (level) {
379
397
  case "debug":
@@ -398,17 +416,21 @@ var InternalMastraMCPClient = class extends base.MastraBase {
398
416
  timeout;
399
417
  logHandler;
400
418
  enableServerLogs;
419
+ enableProgressTracking;
401
420
  serverConfig;
402
421
  transport;
403
422
  currentOperationContext = null;
404
423
  exitHookUnsubscribe;
405
424
  sigTermHandler;
425
+ _roots;
406
426
  /** Provides access to resource operations (list, read, subscribe, etc.) */
407
427
  resources;
408
428
  /** Provides access to prompt operations (list, get, notifications) */
409
429
  prompts;
410
430
  /** Provides access to elicitation operations (request handling) */
411
431
  elicitation;
432
+ /** Provides access to progress operations (notifications) */
433
+ progress;
412
434
  /**
413
435
  * @internal
414
436
  */
@@ -425,8 +447,16 @@ var InternalMastraMCPClient = class extends base.MastraBase {
425
447
  this.logHandler = server.logger;
426
448
  this.enableServerLogs = server.enableServerLogs ?? true;
427
449
  this.serverConfig = server;
428
- const clientCapabilities = { ...capabilities, elicitation: {} };
429
- this.client = new index_js$1.Client(
450
+ this.enableProgressTracking = !!server.enableProgressTracking;
451
+ this._roots = server.roots ?? [];
452
+ const hasRoots = this._roots.length > 0 || !!capabilities.roots;
453
+ const clientCapabilities = {
454
+ ...capabilities,
455
+ elicitation: {},
456
+ // Auto-enable roots capability if roots are provided
457
+ ...hasRoots ? { roots: { listChanged: true, ...capabilities.roots ?? {} } } : {}
458
+ };
459
+ this.client = new index_js.Client(
430
460
  {
431
461
  name,
432
462
  version
@@ -436,9 +466,13 @@ var InternalMastraMCPClient = class extends base.MastraBase {
436
466
  }
437
467
  );
438
468
  this.setupLogging();
469
+ if (hasRoots) {
470
+ this.setupRootsHandler();
471
+ }
439
472
  this.resources = new ResourceClientActions({ client: this, logger: this.logger });
440
473
  this.prompts = new PromptClientActions({ client: this, logger: this.logger });
441
474
  this.elicitation = new ElicitationClientActions({ client: this, logger: this.logger });
475
+ this.progress = new ProgressClientActions({ client: this, logger: this.logger });
442
476
  }
443
477
  /**
444
478
  * Log a message at the specified level
@@ -477,13 +511,70 @@ var InternalMastraMCPClient = class extends base.MastraBase {
477
511
  );
478
512
  }
479
513
  }
514
+ /**
515
+ * Set up handler for roots/list requests from the server.
516
+ *
517
+ * Per MCP spec (https://modelcontextprotocol.io/specification/2025-11-25/client/roots):
518
+ * When a server sends a roots/list request, the client responds with the configured roots.
519
+ */
520
+ setupRootsHandler() {
521
+ this.log("debug", "Setting up roots/list request handler");
522
+ this.client.setRequestHandler(types_js.ListRootsRequestSchema, async () => {
523
+ this.log("debug", `Responding to roots/list request with ${this._roots.length} roots`);
524
+ return { roots: this._roots };
525
+ });
526
+ }
527
+ /**
528
+ * Get the currently configured roots.
529
+ *
530
+ * @returns Array of configured filesystem roots
531
+ */
532
+ get roots() {
533
+ return [...this._roots];
534
+ }
535
+ /**
536
+ * Update the list of filesystem roots and notify the server.
537
+ *
538
+ * Per MCP spec, when roots change, the client sends a `notifications/roots/list_changed`
539
+ * notification to inform the server that it should re-fetch the roots list.
540
+ *
541
+ * @param roots - New list of filesystem roots
542
+ *
543
+ * @example
544
+ * ```typescript
545
+ * await client.setRoots([
546
+ * { uri: 'file:///home/user/projects', name: 'Projects' },
547
+ * { uri: 'file:///tmp', name: 'Temp' }
548
+ * ]);
549
+ * ```
550
+ */
551
+ async setRoots(roots) {
552
+ this.log("debug", `Updating roots to ${roots.length} entries`);
553
+ this._roots = [...roots];
554
+ await this.sendRootsListChanged();
555
+ }
556
+ /**
557
+ * Send a roots/list_changed notification to the server.
558
+ *
559
+ * Per MCP spec, clients that support `listChanged` MUST send this notification
560
+ * when the list of roots changes. The server will then call roots/list to get
561
+ * the updated list.
562
+ */
563
+ async sendRootsListChanged() {
564
+ if (!this.transport) {
565
+ this.log("debug", "Cannot send roots/list_changed: not connected");
566
+ return;
567
+ }
568
+ this.log("debug", "Sending notifications/roots/list_changed");
569
+ await this.client.notification({ method: "notifications/roots/list_changed" });
570
+ }
480
571
  async connectStdio(command) {
481
572
  this.log("debug", `Using Stdio transport for command: ${command}`);
482
573
  try {
483
- this.transport = new stdio_js$1.StdioClientTransport({
574
+ this.transport = new stdio_js.StdioClientTransport({
484
575
  command,
485
576
  args: this.serverConfig.args,
486
- env: { ...stdio_js$1.getDefaultEnvironment(), ...this.serverConfig.env || {} }
577
+ env: { ...stdio_js.getDefaultEnvironment(), ...this.serverConfig.env || {} }
487
578
  });
488
579
  await this.client.connect(this.transport, { timeout: this.serverConfig.timeout ?? this.timeout });
489
580
  this.log("debug", `Successfully connected to MCP server via Stdio`);
@@ -493,16 +584,17 @@ var InternalMastraMCPClient = class extends base.MastraBase {
493
584
  }
494
585
  }
495
586
  async connectHttp(url) {
496
- const { requestInit, eventSourceInit, authProvider, connectTimeout } = this.serverConfig;
587
+ const { requestInit, eventSourceInit, authProvider, connectTimeout, fetch } = this.serverConfig;
497
588
  this.log("debug", `Attempting to connect to URL: ${url}`);
498
589
  let shouldTrySSE = url.pathname.endsWith(`/sse`);
499
590
  if (!shouldTrySSE) {
500
591
  try {
501
592
  this.log("debug", "Trying Streamable HTTP transport...");
502
- const streamableTransport = new streamableHttp_js$1.StreamableHTTPClientTransport(url, {
593
+ const streamableTransport = new streamableHttp_js.StreamableHTTPClientTransport(url, {
503
594
  requestInit,
504
595
  reconnectionOptions: this.serverConfig.reconnectionOptions,
505
- authProvider
596
+ authProvider,
597
+ fetch
506
598
  });
507
599
  await this.client.connect(streamableTransport, {
508
600
  timeout: connectTimeout ?? DEFAULT_SERVER_CONNECT_TIMEOUT_MSEC
@@ -511,13 +603,23 @@ var InternalMastraMCPClient = class extends base.MastraBase {
511
603
  this.log("debug", "Successfully connected using Streamable HTTP transport.");
512
604
  } catch (error) {
513
605
  this.log("debug", `Streamable HTTP transport failed: ${error}`);
606
+ const status = error?.code;
607
+ if (status !== void 0 && !SSE_FALLBACK_STATUS_CODES.includes(status)) {
608
+ throw error;
609
+ }
514
610
  shouldTrySSE = true;
515
611
  }
516
612
  }
517
613
  if (shouldTrySSE) {
518
614
  this.log("debug", "Falling back to deprecated HTTP+SSE transport...");
519
615
  try {
520
- const sseTransport = new sse_js$1.SSEClientTransport(url, { requestInit, eventSourceInit, authProvider });
616
+ const sseEventSourceInit = fetch ? { ...eventSourceInit, fetch } : eventSourceInit;
617
+ const sseTransport = new sse_js.SSEClientTransport(url, {
618
+ requestInit,
619
+ eventSourceInit: sseEventSourceInit,
620
+ authProvider,
621
+ fetch
622
+ });
521
623
  await this.client.connect(sseTransport, { timeout: this.serverConfig.timeout ?? this.timeout });
522
624
  this.transport = sseTransport;
523
625
  this.log("debug", "Successfully connected using deprecated HTTP+SSE transport.");
@@ -596,7 +698,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
596
698
  * @internal
597
699
  */
598
700
  get sessionId() {
599
- if (this.transport instanceof streamableHttp_js$1.StreamableHTTPClientTransport) {
701
+ if (this.transport instanceof streamableHttp_js.StreamableHTTPClientTransport) {
600
702
  return this.transport.sessionId;
601
703
  }
602
704
  return void 0;
@@ -617,7 +719,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
617
719
  throw e;
618
720
  } finally {
619
721
  this.transport = void 0;
620
- this.isConnected = Promise.resolve(false);
722
+ this.isConnected = null;
621
723
  if (this.exitHookUnsubscribe) {
622
724
  this.exitHookUnsubscribe();
623
725
  this.exitHookUnsubscribe = void 0;
@@ -628,6 +730,53 @@ var InternalMastraMCPClient = class extends base.MastraBase {
628
730
  }
629
731
  }
630
732
  }
733
+ /**
734
+ * Checks if an error indicates a session invalidation that requires reconnection.
735
+ *
736
+ * Common session-related errors include:
737
+ * - "No valid session ID provided" (HTTP 400)
738
+ * - "Server not initialized" (HTTP 400)
739
+ * - Connection refused errors
740
+ *
741
+ * @param error - The error to check
742
+ * @returns true if the error indicates a session problem requiring reconnection
743
+ *
744
+ * @internal
745
+ */
746
+ isSessionError(error) {
747
+ if (!(error instanceof Error)) {
748
+ return false;
749
+ }
750
+ const errorMessage = error.message.toLowerCase();
751
+ return errorMessage.includes("no valid session") || errorMessage.includes("session") || errorMessage.includes("server not initialized") || errorMessage.includes("http 400") || errorMessage.includes("http 401") || errorMessage.includes("http 403") || errorMessage.includes("econnrefused") || errorMessage.includes("fetch failed") || errorMessage.includes("connection refused");
752
+ }
753
+ /**
754
+ * Forces a reconnection to the MCP server by disconnecting and reconnecting.
755
+ *
756
+ * This is useful when the session becomes invalid (e.g., after server restart)
757
+ * and the client needs to establish a fresh connection.
758
+ *
759
+ * @returns Promise resolving when reconnection is complete
760
+ * @throws {Error} If reconnection fails
761
+ *
762
+ * @internal
763
+ */
764
+ async forceReconnect() {
765
+ this.log("debug", "Forcing reconnection to MCP server...");
766
+ try {
767
+ if (this.transport) {
768
+ await this.transport.close();
769
+ }
770
+ } catch (e) {
771
+ this.log("debug", "Error during force disconnect (ignored)", {
772
+ error: e instanceof Error ? e.message : String(e)
773
+ });
774
+ }
775
+ this.transport = void 0;
776
+ this.isConnected = null;
777
+ await this.connect();
778
+ this.log("debug", "Successfully reconnected to MCP server");
779
+ }
631
780
  async listResources() {
632
781
  this.log("debug", `Requesting resources from MCP server`);
633
782
  return await this.client.request({ method: "resources/list" }, types_js.ListResourcesResultSchema, {
@@ -714,6 +863,12 @@ var InternalMastraMCPClient = class extends base.MastraBase {
714
863
  return handler(request.params);
715
864
  });
716
865
  }
866
+ setProgressNotificationHandler(handler) {
867
+ this.log("debug", "Setting progress notification handler");
868
+ this.client.setNotificationHandler(types_js.ProgressNotificationSchema, (notification) => {
869
+ handler(notification.params);
870
+ });
871
+ }
717
872
  async convertInputSchema(inputSchema) {
718
873
  if (utils.isZodType(inputSchema)) {
719
874
  return inputSchema;
@@ -787,7 +942,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
787
942
  }
788
943
  async tools() {
789
944
  this.log("debug", `Requesting tools from MCP server`);
790
- const { tools: tools$1 } = await this.client.listTools({ timeout: this.timeout });
945
+ const { tools: tools$1 } = await this.client.listTools({}, { timeout: this.timeout });
791
946
  const toolsRes = {};
792
947
  for (const tool of tools$1) {
793
948
  this.log("debug", `Processing tool: ${tool.name}`);
@@ -800,12 +955,14 @@ var InternalMastraMCPClient = class extends base.MastraBase {
800
955
  execute: async (input, context) => {
801
956
  const previousContext = this.currentOperationContext;
802
957
  this.currentOperationContext = context?.requestContext || null;
803
- try {
804
- this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input });
958
+ const executeToolCall = async () => {
959
+ this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input, runId: context?.runId });
805
960
  const res = await this.client.callTool(
806
961
  {
807
962
  name: tool.name,
808
- arguments: input
963
+ arguments: input,
964
+ // Use runId as progress token if available, otherwise generate a random UUID
965
+ ...this.enableProgressTracking ? { _meta: { progressToken: context?.runId || crypto.randomUUID() } } : {}
809
966
  },
810
967
  types_js.CallToolResultSchema,
811
968
  {
@@ -817,7 +974,27 @@ var InternalMastraMCPClient = class extends base.MastraBase {
817
974
  return res.structuredContent;
818
975
  }
819
976
  return res;
977
+ };
978
+ try {
979
+ return await executeToolCall();
820
980
  } catch (e) {
981
+ if (this.isSessionError(e)) {
982
+ this.log("debug", `Session error detected for tool ${tool.name}, attempting reconnection...`, {
983
+ error: e instanceof Error ? e.message : String(e)
984
+ });
985
+ try {
986
+ await this.forceReconnect();
987
+ this.log("debug", `Retrying tool ${tool.name} after reconnection...`);
988
+ return await executeToolCall();
989
+ } catch (reconnectError) {
990
+ this.log("error", `Reconnection or retry failed for tool ${tool.name}`, {
991
+ originalError: e instanceof Error ? e.message : String(e),
992
+ reconnectError: reconnectError instanceof Error ? reconnectError.stack : String(reconnectError),
993
+ toolArgs: input
994
+ });
995
+ throw e;
996
+ }
997
+ }
821
998
  this.log("error", `Error calling tool: ${tool.name}`, {
822
999
  error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
823
1000
  toolArgs: input
@@ -841,8 +1018,6 @@ var InternalMastraMCPClient = class extends base.MastraBase {
841
1018
  return toolsRes;
842
1019
  }
843
1020
  };
844
-
845
- // src/client/configuration.ts
846
1021
  var mcpClientInstances = /* @__PURE__ */ new Map();
847
1022
  var MCPClient = class extends base.MastraBase {
848
1023
  serverConfigs = {};
@@ -915,6 +1090,48 @@ To fix this you have three different options:
915
1090
  this.addToInstanceCache();
916
1091
  return this;
917
1092
  }
1093
+ /**
1094
+ * Provides access to progress-related operations for tracking long-running operations.
1095
+ *
1096
+ * Progress tracking allows MCP servers to send updates about the status of ongoing operations,
1097
+ * providing real-time feedback to users about task completion and current state.
1098
+ *
1099
+ * @example
1100
+ * ```typescript
1101
+ * // Set up handler for progress updates from a server
1102
+ * await mcp.progress.onUpdate('serverName', (params) => {
1103
+ * console.log(`Progress: ${params.progress}%`);
1104
+ * console.log(`Status: ${params.message}`);
1105
+ *
1106
+ * if (params.total) {
1107
+ * console.log(`Completed ${params.progress} of ${params.total} items`);
1108
+ * }
1109
+ * });
1110
+ * ```
1111
+ */
1112
+ get progress() {
1113
+ this.addToInstanceCache();
1114
+ return {
1115
+ onUpdate: async (serverName, handler) => {
1116
+ try {
1117
+ const internalClient = await this.getConnectedClientForServer(serverName);
1118
+ return internalClient.progress.onUpdate(handler);
1119
+ } catch (err) {
1120
+ throw new error.MastraError(
1121
+ {
1122
+ id: "MCP_CLIENT_ON_UPDATE_PROGRESS_FAILED",
1123
+ domain: error.ErrorDomain.MCP,
1124
+ category: error.ErrorCategory.THIRD_PARTY,
1125
+ details: {
1126
+ serverName
1127
+ }
1128
+ },
1129
+ err
1130
+ );
1131
+ }
1132
+ }
1133
+ };
1134
+ }
918
1135
  /**
919
1136
  * Provides access to elicitation-related operations for interactive user input collection.
920
1137
  *
@@ -2160,7 +2377,7 @@ var MCPServer = class extends mcp.MCPServerBase {
2160
2377
  if (opts.prompts) {
2161
2378
  capabilities.prompts = { listChanged: true };
2162
2379
  }
2163
- this.server = new index_js.Server({ name: this.name, version: this.version }, { capabilities });
2380
+ this.server = new index_js$1.Server({ name: this.name, version: this.version }, { capabilities });
2164
2381
  this.logger.info(
2165
2382
  `Initialized MCPServer '${this.name}' v${this.version} (ID: ${this.id}) with tools: ${Object.keys(this.convertedTools).join(", ")} and resources. Capabilities: ${JSON.stringify(capabilities)}`
2166
2383
  );
@@ -2185,8 +2402,8 @@ var MCPServer = class extends mcp.MCPServerBase {
2185
2402
  }
2186
2403
  });
2187
2404
  this.elicitation = {
2188
- sendRequest: async (request) => {
2189
- return this.handleElicitationRequest(request);
2405
+ sendRequest: async (request, options) => {
2406
+ return this.handleElicitationRequest(request, void 0, options);
2190
2407
  }
2191
2408
  };
2192
2409
  }
@@ -2196,15 +2413,51 @@ var MCPServer = class extends mcp.MCPServerBase {
2196
2413
  *
2197
2414
  * @param request - The elicitation request containing message and schema
2198
2415
  * @param serverInstance - Optional server instance to use; defaults to main server for backward compatibility
2416
+ * @param options - Optional request options (timeout, signal, etc.)
2199
2417
  * @returns Promise that resolves to the client's response
2200
2418
  */
2201
- async handleElicitationRequest(request, serverInstance) {
2419
+ async handleElicitationRequest(request, serverInstance, options) {
2202
2420
  this.logger.debug(`Sending elicitation request: ${request.message}`);
2203
2421
  const server = serverInstance || this.server;
2204
- const response = await server.elicitInput(request);
2422
+ const response = await server.elicitInput(request, options);
2205
2423
  this.logger.debug(`Received elicitation response: ${JSON.stringify(response)}`);
2206
2424
  return response;
2207
2425
  }
2426
+ /**
2427
+ * Reads and parses the JSON body from an HTTP request.
2428
+ * If the request body was already parsed by middleware (e.g., express.json()),
2429
+ * it uses the pre-parsed body from req.body. Otherwise, it reads from the stream.
2430
+ *
2431
+ * This allows the MCP server to work with Express apps that use express.json()
2432
+ * globally without requiring special route exclusions.
2433
+ *
2434
+ * @param req - The incoming HTTP request
2435
+ * @param options - Optional configuration
2436
+ * @param options.preParsedOnly - If true, only return pre-parsed body from middleware,
2437
+ * returning undefined if not available. This allows the caller to fall back to
2438
+ * their own body reading logic (e.g., SDK's getRawBody with size limits).
2439
+ */
2440
+ async readJsonBody(req, options) {
2441
+ const reqWithBody = req;
2442
+ if (reqWithBody.body !== void 0) {
2443
+ return reqWithBody.body;
2444
+ }
2445
+ if (options?.preParsedOnly) {
2446
+ return void 0;
2447
+ }
2448
+ return new Promise((resolve, reject) => {
2449
+ let data = "";
2450
+ req.on("data", (chunk) => data += chunk);
2451
+ req.on("end", () => {
2452
+ try {
2453
+ resolve(JSON.parse(data));
2454
+ } catch (e) {
2455
+ reject(e);
2456
+ }
2457
+ });
2458
+ req.on("error", reject);
2459
+ });
2460
+ }
2208
2461
  /**
2209
2462
  * Creates a new Server instance configured with all handlers for HTTP sessions.
2210
2463
  * Each HTTP client connection gets its own Server instance to avoid routing conflicts.
@@ -2221,7 +2474,7 @@ var MCPServer = class extends mcp.MCPServerBase {
2221
2474
  if (this.promptOptions) {
2222
2475
  capabilities.prompts = { listChanged: true };
2223
2476
  }
2224
- const serverInstance = new index_js.Server({ name: this.name, version: this.version }, { capabilities });
2477
+ const serverInstance = new index_js$1.Server({ name: this.name, version: this.version }, { capabilities });
2225
2478
  this.registerHandlersOnServer(serverInstance);
2226
2479
  return serverInstance;
2227
2480
  }
@@ -2290,8 +2543,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2290
2543
  };
2291
2544
  }
2292
2545
  const sessionElicitation = {
2293
- sendRequest: async (request2) => {
2294
- return this.handleElicitationRequest(request2, serverInstance);
2546
+ sendRequest: async (request2, options) => {
2547
+ return this.handleElicitationRequest(request2, serverInstance, options);
2295
2548
  }
2296
2549
  };
2297
2550
  const mcpOptions = {
@@ -2593,7 +2846,9 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2593
2846
  try {
2594
2847
  const proxiedContext = context?.requestContext || new requestContext.RequestContext();
2595
2848
  if (context?.mcp?.extra) {
2596
- proxiedContext.set("mcp.extra", context.mcp.extra);
2849
+ Object.entries(context.mcp.extra).forEach(([key, value]) => {
2850
+ proxiedContext.set(key, value);
2851
+ });
2597
2852
  }
2598
2853
  const response = await agent.generate(inputData.message, {
2599
2854
  ...context ?? {},
@@ -2662,10 +2917,16 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2662
2917
  inputData
2663
2918
  );
2664
2919
  try {
2665
- const run2 = await workflow.createRun({ runId: context?.requestContext?.get("runId") });
2920
+ const proxiedContext = context?.requestContext || new requestContext.RequestContext();
2921
+ if (context?.mcp?.extra) {
2922
+ Object.entries(context.mcp.extra).forEach(([key, value]) => {
2923
+ proxiedContext.set(key, value);
2924
+ });
2925
+ }
2926
+ const run2 = await workflow.createRun({ runId: proxiedContext?.get("runId") });
2666
2927
  const response = await run2.start({
2667
2928
  inputData,
2668
- requestContext: context?.requestContext,
2929
+ requestContext: proxiedContext,
2669
2930
  tracingContext: context?.tracingContext
2670
2931
  });
2671
2932
  return response;
@@ -2784,7 +3045,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2784
3045
  * ```
2785
3046
  */
2786
3047
  async startStdio() {
2787
- this.stdioTransport = new stdio_js.StdioServerTransport();
3048
+ this.stdioTransport = new stdio_js$1.StdioServerTransport();
2788
3049
  try {
2789
3050
  await this.server.connect(this.stdioTransport);
2790
3051
  } catch (error$1) {
@@ -2821,7 +3082,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2821
3082
  *
2822
3083
  * @example
2823
3084
  * ```typescript
2824
- * import http from 'http';
3085
+ * import http from 'node:http';
2825
3086
  *
2826
3087
  * const httpServer = http.createServer(async (req, res) => {
2827
3088
  * await server.startSSE({
@@ -2852,7 +3113,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2852
3113
  res.end("SSE connection not established");
2853
3114
  return;
2854
3115
  }
2855
- await this.sseTransport.handlePostMessage(req, res);
3116
+ const parsedBody = await this.readJsonBody(req, { preParsedOnly: true });
3117
+ await this.sseTransport.handlePostMessage(req, res, parsedBody);
2856
3118
  } else {
2857
3119
  this.logger.debug("Unknown path:", { path: url.pathname });
2858
3120
  res.writeHead(404);
@@ -2979,8 +3241,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
2979
3241
  *
2980
3242
  * @example
2981
3243
  * ```typescript
2982
- * import http from 'http';
2983
- * import { randomUUID } from 'crypto';
3244
+ * import http from 'node:http';
3245
+ * import { randomUUID } from 'node:crypto';
2984
3246
  *
2985
3247
  * const httpServer = http.createServer(async (req, res) => {
2986
3248
  * await server.startHTTP({
@@ -3059,38 +3321,16 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
3059
3321
  `startHTTP: Handling GET request for existing session ${sessionId}. Calling transport.handleRequest.`
3060
3322
  );
3061
3323
  }
3062
- const body = req.method === "POST" ? await new Promise((resolve, reject) => {
3063
- let data = "";
3064
- req.on("data", (chunk) => data += chunk);
3065
- req.on("end", () => {
3066
- try {
3067
- resolve(JSON.parse(data));
3068
- } catch (e) {
3069
- reject(e);
3070
- }
3071
- });
3072
- req.on("error", reject);
3073
- }) : void 0;
3324
+ const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
3074
3325
  await transport.handleRequest(req, res, body);
3075
3326
  } else {
3076
3327
  this.logger.debug(`startHTTP: No existing Streamable HTTP session ID found. ${req.method}`);
3077
3328
  if (req.method === "POST") {
3078
- const body = await new Promise((resolve, reject) => {
3079
- let data = "";
3080
- req.on("data", (chunk) => data += chunk);
3081
- req.on("end", () => {
3082
- try {
3083
- resolve(JSON.parse(data));
3084
- } catch (e) {
3085
- reject(e);
3086
- }
3087
- });
3088
- req.on("error", reject);
3089
- });
3329
+ const body = await this.readJsonBody(req);
3090
3330
  const { isInitializeRequest } = await import('@modelcontextprotocol/sdk/types.js');
3091
3331
  if (isInitializeRequest(body)) {
3092
3332
  this.logger.debug("startHTTP: Received Streamable HTTP initialize request, creating new transport.");
3093
- transport = new streamableHttp_js.StreamableHTTPServerTransport({
3333
+ transport = new streamableHttp_js$1.StreamableHTTPServerTransport({
3094
3334
  ...mergedOptions,
3095
3335
  sessionIdGenerator: mergedOptions.sessionIdGenerator,
3096
3336
  onsessioninitialized: (id) => {
@@ -3196,24 +3436,13 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
3196
3436
  async handleServerlessRequest(req, res) {
3197
3437
  try {
3198
3438
  this.logger.debug(`handleServerlessRequest: Received ${req.method} request`);
3199
- const body = req.method === "POST" ? await new Promise((resolve, reject) => {
3200
- let data = "";
3201
- req.on("data", (chunk) => data += chunk);
3202
- req.on("end", () => {
3203
- try {
3204
- resolve(JSON.parse(data));
3205
- } catch (e) {
3206
- reject(new Error(`Invalid JSON in request body: ${e instanceof Error ? e.message : String(e)}`));
3207
- }
3208
- });
3209
- req.on("error", reject);
3210
- }) : void 0;
3439
+ const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
3211
3440
  this.logger.debug(`handleServerlessRequest: Processing ${req.method} request`, {
3212
3441
  method: body?.method,
3213
3442
  id: body?.id
3214
3443
  });
3215
3444
  const transientServer = this.createServerInstance();
3216
- const tempTransport = new streamableHttp_js.StreamableHTTPServerTransport({
3445
+ const tempTransport = new streamableHttp_js$1.StreamableHTTPServerTransport({
3217
3446
  sessionIdGenerator: void 0,
3218
3447
  enableJsonResponse: true
3219
3448
  });
@@ -3275,7 +3504,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
3275
3504
  }) {
3276
3505
  try {
3277
3506
  this.logger.debug("Received SSE connection");
3278
- this.sseTransport = new sse_js.SSEServerTransport(messagePath, res);
3507
+ this.sseTransport = new sse_js$1.SSEServerTransport(messagePath, res);
3279
3508
  await this.server.connect(this.sseTransport);
3280
3509
  this.server.onclose = async () => {
3281
3510
  this.sseTransport = void 0;
@@ -3638,6 +3867,7 @@ Provided arguments: ${JSON.stringify(args, null, 2)}`,
3638
3867
  }
3639
3868
  };
3640
3869
 
3870
+ exports.InternalMastraMCPClient = InternalMastraMCPClient;
3641
3871
  exports.MCPClient = MCPClient;
3642
3872
  exports.MCPServer = MCPServer;
3643
3873
  //# sourceMappingURL=index.cjs.map