@mastra/mcp 1.0.0-beta.3 → 1.0.0-beta.4
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 +83 -0
- package/dist/client/{elicitationActions.d.ts → actions/elicitation.d.ts} +2 -2
- package/dist/client/actions/elicitation.d.ts.map +1 -0
- package/dist/client/actions/progress.d.ts +23 -0
- package/dist/client/actions/progress.d.ts.map +1 -0
- package/dist/client/{promptActions.d.ts → actions/prompt.d.ts} +2 -2
- package/dist/client/actions/prompt.d.ts.map +1 -0
- package/dist/client/{resourceActions.d.ts → actions/resource.d.ts} +2 -2
- package/dist/client/actions/resource.d.ts.map +1 -0
- package/dist/client/client.d.ts +76 -138
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/configuration.d.ts +23 -1
- package/dist/client/configuration.d.ts.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/types.d.ts +188 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/index.cjs +295 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +276 -60
- package/dist/index.js.map +1 -1
- package/dist/server/server.d.ts +18 -3
- package/dist/server/server.d.ts.map +1 -1
- package/package.json +3 -3
- package/dist/client/elicitationActions.d.ts.map +0 -1
- package/dist/client/promptActions.d.ts.map +0 -1
- package/dist/client/resourceActions.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
+
import $RefParser from '@apidevtools/json-schema-ref-parser';
|
|
1
2
|
import { MastraBase } from '@mastra/core/base';
|
|
2
3
|
import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
|
|
3
|
-
import { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
4
|
-
import equal from 'fast-deep-equal';
|
|
5
|
-
import { v5 } from 'uuid';
|
|
6
|
-
import $RefParser from '@apidevtools/json-schema-ref-parser';
|
|
7
4
|
import { createTool } from '@mastra/core/tools';
|
|
8
|
-
import {
|
|
5
|
+
import { isZodType, makeCoreTool } from '@mastra/core/utils';
|
|
9
6
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
10
7
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
11
8
|
import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
12
9
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
13
|
-
import {
|
|
10
|
+
import { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
11
|
+
import { ListRootsRequestSchema, ListResourcesResultSchema, ReadResourceResultSchema, ListResourceTemplatesResultSchema, ListPromptsResultSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ResourceUpdatedNotificationSchema, ResourceListChangedNotificationSchema, ElicitRequestSchema, ProgressNotificationSchema, ListToolsRequestSchema, CallToolRequestSchema, SetLevelRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, SubscribeRequestSchema, UnsubscribeRequestSchema, ListPromptsRequestSchema, PromptSchema, GetPromptRequestSchema, CallToolResultSchema, ErrorCode, JSONRPCMessageSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
14
12
|
import { asyncExitHook, gracefulExit } from 'exit-hook';
|
|
15
13
|
import { z } from 'zod';
|
|
16
14
|
import { convertJsonSchemaToZod } from 'zod-from-json-schema';
|
|
17
15
|
import { convertJsonSchemaToZod as convertJsonSchemaToZod$1 } from 'zod-from-json-schema-v3';
|
|
16
|
+
import equal from 'fast-deep-equal';
|
|
17
|
+
import { v5 } from 'uuid';
|
|
18
18
|
import { randomUUID } from 'crypto';
|
|
19
19
|
import { MCPServerBase } from '@mastra/core/mcp';
|
|
20
20
|
import { RequestContext } from '@mastra/core/request-context';
|
|
@@ -23,9 +23,9 @@ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
|
23
23
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
24
24
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
25
25
|
|
|
26
|
-
// src/client/
|
|
26
|
+
// src/client/client.ts
|
|
27
27
|
|
|
28
|
-
// src/client/
|
|
28
|
+
// src/client/actions/elicitation.ts
|
|
29
29
|
var ElicitationClientActions = class {
|
|
30
30
|
client;
|
|
31
31
|
logger;
|
|
@@ -78,6 +78,23 @@ var ElicitationClientActions = class {
|
|
|
78
78
|
this.client.setElicitationRequestHandler(handler);
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
|
+
|
|
82
|
+
// src/client/actions/progress.ts
|
|
83
|
+
var ProgressClientActions = class {
|
|
84
|
+
client;
|
|
85
|
+
logger;
|
|
86
|
+
constructor({ client, logger }) {
|
|
87
|
+
this.client = client;
|
|
88
|
+
this.logger = logger;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Set a notification handler for progress updates.
|
|
92
|
+
* @param handler The callback function to handle progress notifications.
|
|
93
|
+
*/
|
|
94
|
+
onUpdate(handler) {
|
|
95
|
+
this.client.setProgressNotificationHandler(handler);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
81
98
|
var PromptClientActions = class {
|
|
82
99
|
client;
|
|
83
100
|
logger;
|
|
@@ -391,17 +408,21 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
391
408
|
timeout;
|
|
392
409
|
logHandler;
|
|
393
410
|
enableServerLogs;
|
|
411
|
+
enableProgressTracking;
|
|
394
412
|
serverConfig;
|
|
395
413
|
transport;
|
|
396
414
|
currentOperationContext = null;
|
|
397
415
|
exitHookUnsubscribe;
|
|
398
416
|
sigTermHandler;
|
|
417
|
+
_roots;
|
|
399
418
|
/** Provides access to resource operations (list, read, subscribe, etc.) */
|
|
400
419
|
resources;
|
|
401
420
|
/** Provides access to prompt operations (list, get, notifications) */
|
|
402
421
|
prompts;
|
|
403
422
|
/** Provides access to elicitation operations (request handling) */
|
|
404
423
|
elicitation;
|
|
424
|
+
/** Provides access to progress operations (notifications) */
|
|
425
|
+
progress;
|
|
405
426
|
/**
|
|
406
427
|
* @internal
|
|
407
428
|
*/
|
|
@@ -418,7 +439,15 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
418
439
|
this.logHandler = server.logger;
|
|
419
440
|
this.enableServerLogs = server.enableServerLogs ?? true;
|
|
420
441
|
this.serverConfig = server;
|
|
421
|
-
|
|
442
|
+
this.enableProgressTracking = !!server.enableProgressTracking;
|
|
443
|
+
this._roots = server.roots ?? [];
|
|
444
|
+
const hasRoots = this._roots.length > 0 || !!capabilities.roots;
|
|
445
|
+
const clientCapabilities = {
|
|
446
|
+
...capabilities,
|
|
447
|
+
elicitation: {},
|
|
448
|
+
// Auto-enable roots capability if roots are provided
|
|
449
|
+
...hasRoots ? { roots: { listChanged: true, ...capabilities.roots ?? {} } } : {}
|
|
450
|
+
};
|
|
422
451
|
this.client = new Client(
|
|
423
452
|
{
|
|
424
453
|
name,
|
|
@@ -429,9 +458,13 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
429
458
|
}
|
|
430
459
|
);
|
|
431
460
|
this.setupLogging();
|
|
461
|
+
if (hasRoots) {
|
|
462
|
+
this.setupRootsHandler();
|
|
463
|
+
}
|
|
432
464
|
this.resources = new ResourceClientActions({ client: this, logger: this.logger });
|
|
433
465
|
this.prompts = new PromptClientActions({ client: this, logger: this.logger });
|
|
434
466
|
this.elicitation = new ElicitationClientActions({ client: this, logger: this.logger });
|
|
467
|
+
this.progress = new ProgressClientActions({ client: this, logger: this.logger });
|
|
435
468
|
}
|
|
436
469
|
/**
|
|
437
470
|
* Log a message at the specified level
|
|
@@ -470,6 +503,63 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
470
503
|
);
|
|
471
504
|
}
|
|
472
505
|
}
|
|
506
|
+
/**
|
|
507
|
+
* Set up handler for roots/list requests from the server.
|
|
508
|
+
*
|
|
509
|
+
* Per MCP spec (https://modelcontextprotocol.io/specification/2025-11-25/client/roots):
|
|
510
|
+
* When a server sends a roots/list request, the client responds with the configured roots.
|
|
511
|
+
*/
|
|
512
|
+
setupRootsHandler() {
|
|
513
|
+
this.log("debug", "Setting up roots/list request handler");
|
|
514
|
+
this.client.setRequestHandler(ListRootsRequestSchema, async () => {
|
|
515
|
+
this.log("debug", `Responding to roots/list request with ${this._roots.length} roots`);
|
|
516
|
+
return { roots: this._roots };
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Get the currently configured roots.
|
|
521
|
+
*
|
|
522
|
+
* @returns Array of configured filesystem roots
|
|
523
|
+
*/
|
|
524
|
+
get roots() {
|
|
525
|
+
return [...this._roots];
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Update the list of filesystem roots and notify the server.
|
|
529
|
+
*
|
|
530
|
+
* Per MCP spec, when roots change, the client sends a `notifications/roots/list_changed`
|
|
531
|
+
* notification to inform the server that it should re-fetch the roots list.
|
|
532
|
+
*
|
|
533
|
+
* @param roots - New list of filesystem roots
|
|
534
|
+
*
|
|
535
|
+
* @example
|
|
536
|
+
* ```typescript
|
|
537
|
+
* await client.setRoots([
|
|
538
|
+
* { uri: 'file:///home/user/projects', name: 'Projects' },
|
|
539
|
+
* { uri: 'file:///tmp', name: 'Temp' }
|
|
540
|
+
* ]);
|
|
541
|
+
* ```
|
|
542
|
+
*/
|
|
543
|
+
async setRoots(roots) {
|
|
544
|
+
this.log("debug", `Updating roots to ${roots.length} entries`);
|
|
545
|
+
this._roots = [...roots];
|
|
546
|
+
await this.sendRootsListChanged();
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Send a roots/list_changed notification to the server.
|
|
550
|
+
*
|
|
551
|
+
* Per MCP spec, clients that support `listChanged` MUST send this notification
|
|
552
|
+
* when the list of roots changes. The server will then call roots/list to get
|
|
553
|
+
* the updated list.
|
|
554
|
+
*/
|
|
555
|
+
async sendRootsListChanged() {
|
|
556
|
+
if (!this.transport) {
|
|
557
|
+
this.log("debug", "Cannot send roots/list_changed: not connected");
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
this.log("debug", "Sending notifications/roots/list_changed");
|
|
561
|
+
await this.client.notification({ method: "notifications/roots/list_changed" });
|
|
562
|
+
}
|
|
473
563
|
async connectStdio(command) {
|
|
474
564
|
this.log("debug", `Using Stdio transport for command: ${command}`);
|
|
475
565
|
try {
|
|
@@ -610,7 +700,7 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
610
700
|
throw e;
|
|
611
701
|
} finally {
|
|
612
702
|
this.transport = void 0;
|
|
613
|
-
this.isConnected =
|
|
703
|
+
this.isConnected = null;
|
|
614
704
|
if (this.exitHookUnsubscribe) {
|
|
615
705
|
this.exitHookUnsubscribe();
|
|
616
706
|
this.exitHookUnsubscribe = void 0;
|
|
@@ -621,6 +711,53 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
621
711
|
}
|
|
622
712
|
}
|
|
623
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Checks if an error indicates a session invalidation that requires reconnection.
|
|
716
|
+
*
|
|
717
|
+
* Common session-related errors include:
|
|
718
|
+
* - "No valid session ID provided" (HTTP 400)
|
|
719
|
+
* - "Server not initialized" (HTTP 400)
|
|
720
|
+
* - Connection refused errors
|
|
721
|
+
*
|
|
722
|
+
* @param error - The error to check
|
|
723
|
+
* @returns true if the error indicates a session problem requiring reconnection
|
|
724
|
+
*
|
|
725
|
+
* @internal
|
|
726
|
+
*/
|
|
727
|
+
isSessionError(error) {
|
|
728
|
+
if (!(error instanceof Error)) {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
const errorMessage = error.message.toLowerCase();
|
|
732
|
+
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");
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Forces a reconnection to the MCP server by disconnecting and reconnecting.
|
|
736
|
+
*
|
|
737
|
+
* This is useful when the session becomes invalid (e.g., after server restart)
|
|
738
|
+
* and the client needs to establish a fresh connection.
|
|
739
|
+
*
|
|
740
|
+
* @returns Promise resolving when reconnection is complete
|
|
741
|
+
* @throws {Error} If reconnection fails
|
|
742
|
+
*
|
|
743
|
+
* @internal
|
|
744
|
+
*/
|
|
745
|
+
async forceReconnect() {
|
|
746
|
+
this.log("debug", "Forcing reconnection to MCP server...");
|
|
747
|
+
try {
|
|
748
|
+
if (this.transport) {
|
|
749
|
+
await this.transport.close();
|
|
750
|
+
}
|
|
751
|
+
} catch (e) {
|
|
752
|
+
this.log("debug", "Error during force disconnect (ignored)", {
|
|
753
|
+
error: e instanceof Error ? e.message : String(e)
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
this.transport = void 0;
|
|
757
|
+
this.isConnected = null;
|
|
758
|
+
await this.connect();
|
|
759
|
+
this.log("debug", "Successfully reconnected to MCP server");
|
|
760
|
+
}
|
|
624
761
|
async listResources() {
|
|
625
762
|
this.log("debug", `Requesting resources from MCP server`);
|
|
626
763
|
return await this.client.request({ method: "resources/list" }, ListResourcesResultSchema, {
|
|
@@ -707,6 +844,12 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
707
844
|
return handler(request.params);
|
|
708
845
|
});
|
|
709
846
|
}
|
|
847
|
+
setProgressNotificationHandler(handler) {
|
|
848
|
+
this.log("debug", "Setting progress notification handler");
|
|
849
|
+
this.client.setNotificationHandler(ProgressNotificationSchema, (notification) => {
|
|
850
|
+
handler(notification.params);
|
|
851
|
+
});
|
|
852
|
+
}
|
|
710
853
|
async convertInputSchema(inputSchema) {
|
|
711
854
|
if (isZodType(inputSchema)) {
|
|
712
855
|
return inputSchema;
|
|
@@ -780,7 +923,7 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
780
923
|
}
|
|
781
924
|
async tools() {
|
|
782
925
|
this.log("debug", `Requesting tools from MCP server`);
|
|
783
|
-
const { tools } = await this.client.listTools({ timeout: this.timeout });
|
|
926
|
+
const { tools } = await this.client.listTools({}, { timeout: this.timeout });
|
|
784
927
|
const toolsRes = {};
|
|
785
928
|
for (const tool of tools) {
|
|
786
929
|
this.log("debug", `Processing tool: ${tool.name}`);
|
|
@@ -793,12 +936,14 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
793
936
|
execute: async (input, context) => {
|
|
794
937
|
const previousContext = this.currentOperationContext;
|
|
795
938
|
this.currentOperationContext = context?.requestContext || null;
|
|
796
|
-
|
|
797
|
-
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input });
|
|
939
|
+
const executeToolCall = async () => {
|
|
940
|
+
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input, runId: context?.runId });
|
|
798
941
|
const res = await this.client.callTool(
|
|
799
942
|
{
|
|
800
943
|
name: tool.name,
|
|
801
|
-
arguments: input
|
|
944
|
+
arguments: input,
|
|
945
|
+
// Use runId as progress token if available, otherwise generate a random UUID
|
|
946
|
+
...this.enableProgressTracking ? { _meta: { progressToken: context?.runId || crypto.randomUUID() } } : {}
|
|
802
947
|
},
|
|
803
948
|
CallToolResultSchema,
|
|
804
949
|
{
|
|
@@ -810,7 +955,27 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
810
955
|
return res.structuredContent;
|
|
811
956
|
}
|
|
812
957
|
return res;
|
|
958
|
+
};
|
|
959
|
+
try {
|
|
960
|
+
return await executeToolCall();
|
|
813
961
|
} catch (e) {
|
|
962
|
+
if (this.isSessionError(e)) {
|
|
963
|
+
this.log("debug", `Session error detected for tool ${tool.name}, attempting reconnection...`, {
|
|
964
|
+
error: e instanceof Error ? e.message : String(e)
|
|
965
|
+
});
|
|
966
|
+
try {
|
|
967
|
+
await this.forceReconnect();
|
|
968
|
+
this.log("debug", `Retrying tool ${tool.name} after reconnection...`);
|
|
969
|
+
return await executeToolCall();
|
|
970
|
+
} catch (reconnectError) {
|
|
971
|
+
this.log("error", `Reconnection or retry failed for tool ${tool.name}`, {
|
|
972
|
+
originalError: e instanceof Error ? e.message : String(e),
|
|
973
|
+
reconnectError: reconnectError instanceof Error ? reconnectError.stack : String(reconnectError),
|
|
974
|
+
toolArgs: input
|
|
975
|
+
});
|
|
976
|
+
throw e;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
814
979
|
this.log("error", `Error calling tool: ${tool.name}`, {
|
|
815
980
|
error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
|
|
816
981
|
toolArgs: input
|
|
@@ -834,8 +999,6 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
834
999
|
return toolsRes;
|
|
835
1000
|
}
|
|
836
1001
|
};
|
|
837
|
-
|
|
838
|
-
// src/client/configuration.ts
|
|
839
1002
|
var mcpClientInstances = /* @__PURE__ */ new Map();
|
|
840
1003
|
var MCPClient = class extends MastraBase {
|
|
841
1004
|
serverConfigs = {};
|
|
@@ -908,6 +1071,48 @@ To fix this you have three different options:
|
|
|
908
1071
|
this.addToInstanceCache();
|
|
909
1072
|
return this;
|
|
910
1073
|
}
|
|
1074
|
+
/**
|
|
1075
|
+
* Provides access to progress-related operations for tracking long-running operations.
|
|
1076
|
+
*
|
|
1077
|
+
* Progress tracking allows MCP servers to send updates about the status of ongoing operations,
|
|
1078
|
+
* providing real-time feedback to users about task completion and current state.
|
|
1079
|
+
*
|
|
1080
|
+
* @example
|
|
1081
|
+
* ```typescript
|
|
1082
|
+
* // Set up handler for progress updates from a server
|
|
1083
|
+
* await mcp.progress.onUpdate('serverName', (params) => {
|
|
1084
|
+
* console.log(`Progress: ${params.progress}%`);
|
|
1085
|
+
* console.log(`Status: ${params.message}`);
|
|
1086
|
+
*
|
|
1087
|
+
* if (params.total) {
|
|
1088
|
+
* console.log(`Completed ${params.progress} of ${params.total} items`);
|
|
1089
|
+
* }
|
|
1090
|
+
* });
|
|
1091
|
+
* ```
|
|
1092
|
+
*/
|
|
1093
|
+
get progress() {
|
|
1094
|
+
this.addToInstanceCache();
|
|
1095
|
+
return {
|
|
1096
|
+
onUpdate: async (serverName, handler) => {
|
|
1097
|
+
try {
|
|
1098
|
+
const internalClient = await this.getConnectedClientForServer(serverName);
|
|
1099
|
+
return internalClient.progress.onUpdate(handler);
|
|
1100
|
+
} catch (err) {
|
|
1101
|
+
throw new MastraError(
|
|
1102
|
+
{
|
|
1103
|
+
id: "MCP_CLIENT_ON_UPDATE_PROGRESS_FAILED",
|
|
1104
|
+
domain: ErrorDomain.MCP,
|
|
1105
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
1106
|
+
details: {
|
|
1107
|
+
serverName
|
|
1108
|
+
}
|
|
1109
|
+
},
|
|
1110
|
+
err
|
|
1111
|
+
);
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
911
1116
|
/**
|
|
912
1117
|
* Provides access to elicitation-related operations for interactive user input collection.
|
|
913
1118
|
*
|
|
@@ -2198,6 +2403,41 @@ var MCPServer = class extends MCPServerBase {
|
|
|
2198
2403
|
this.logger.debug(`Received elicitation response: ${JSON.stringify(response)}`);
|
|
2199
2404
|
return response;
|
|
2200
2405
|
}
|
|
2406
|
+
/**
|
|
2407
|
+
* Reads and parses the JSON body from an HTTP request.
|
|
2408
|
+
* If the request body was already parsed by middleware (e.g., express.json()),
|
|
2409
|
+
* it uses the pre-parsed body from req.body. Otherwise, it reads from the stream.
|
|
2410
|
+
*
|
|
2411
|
+
* This allows the MCP server to work with Express apps that use express.json()
|
|
2412
|
+
* globally without requiring special route exclusions.
|
|
2413
|
+
*
|
|
2414
|
+
* @param req - The incoming HTTP request
|
|
2415
|
+
* @param options - Optional configuration
|
|
2416
|
+
* @param options.preParsedOnly - If true, only return pre-parsed body from middleware,
|
|
2417
|
+
* returning undefined if not available. This allows the caller to fall back to
|
|
2418
|
+
* their own body reading logic (e.g., SDK's getRawBody with size limits).
|
|
2419
|
+
*/
|
|
2420
|
+
async readJsonBody(req, options) {
|
|
2421
|
+
const reqWithBody = req;
|
|
2422
|
+
if (reqWithBody.body !== void 0) {
|
|
2423
|
+
return reqWithBody.body;
|
|
2424
|
+
}
|
|
2425
|
+
if (options?.preParsedOnly) {
|
|
2426
|
+
return void 0;
|
|
2427
|
+
}
|
|
2428
|
+
return new Promise((resolve, reject) => {
|
|
2429
|
+
let data = "";
|
|
2430
|
+
req.on("data", (chunk) => data += chunk);
|
|
2431
|
+
req.on("end", () => {
|
|
2432
|
+
try {
|
|
2433
|
+
resolve(JSON.parse(data));
|
|
2434
|
+
} catch (e) {
|
|
2435
|
+
reject(e);
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
req.on("error", reject);
|
|
2439
|
+
});
|
|
2440
|
+
}
|
|
2201
2441
|
/**
|
|
2202
2442
|
* Creates a new Server instance configured with all handlers for HTTP sessions.
|
|
2203
2443
|
* Each HTTP client connection gets its own Server instance to avoid routing conflicts.
|
|
@@ -2586,7 +2826,9 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2586
2826
|
try {
|
|
2587
2827
|
const proxiedContext = context?.requestContext || new RequestContext();
|
|
2588
2828
|
if (context?.mcp?.extra) {
|
|
2589
|
-
|
|
2829
|
+
Object.entries(context.mcp.extra).forEach(([key, value]) => {
|
|
2830
|
+
proxiedContext.set(key, value);
|
|
2831
|
+
});
|
|
2590
2832
|
}
|
|
2591
2833
|
const response = await agent.generate(inputData.message, {
|
|
2592
2834
|
...context ?? {},
|
|
@@ -2655,10 +2897,16 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2655
2897
|
inputData
|
|
2656
2898
|
);
|
|
2657
2899
|
try {
|
|
2658
|
-
const
|
|
2900
|
+
const proxiedContext = context?.requestContext || new RequestContext();
|
|
2901
|
+
if (context?.mcp?.extra) {
|
|
2902
|
+
Object.entries(context.mcp.extra).forEach(([key, value]) => {
|
|
2903
|
+
proxiedContext.set(key, value);
|
|
2904
|
+
});
|
|
2905
|
+
}
|
|
2906
|
+
const run2 = await workflow.createRun({ runId: proxiedContext?.get("runId") });
|
|
2659
2907
|
const response = await run2.start({
|
|
2660
2908
|
inputData,
|
|
2661
|
-
requestContext:
|
|
2909
|
+
requestContext: proxiedContext,
|
|
2662
2910
|
tracingContext: context?.tracingContext
|
|
2663
2911
|
});
|
|
2664
2912
|
return response;
|
|
@@ -2814,7 +3062,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2814
3062
|
*
|
|
2815
3063
|
* @example
|
|
2816
3064
|
* ```typescript
|
|
2817
|
-
* import http from 'http';
|
|
3065
|
+
* import http from 'node:http';
|
|
2818
3066
|
*
|
|
2819
3067
|
* const httpServer = http.createServer(async (req, res) => {
|
|
2820
3068
|
* await server.startSSE({
|
|
@@ -2845,7 +3093,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2845
3093
|
res.end("SSE connection not established");
|
|
2846
3094
|
return;
|
|
2847
3095
|
}
|
|
2848
|
-
await this.
|
|
3096
|
+
const parsedBody = await this.readJsonBody(req, { preParsedOnly: true });
|
|
3097
|
+
await this.sseTransport.handlePostMessage(req, res, parsedBody);
|
|
2849
3098
|
} else {
|
|
2850
3099
|
this.logger.debug("Unknown path:", { path: url.pathname });
|
|
2851
3100
|
res.writeHead(404);
|
|
@@ -2972,8 +3221,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2972
3221
|
*
|
|
2973
3222
|
* @example
|
|
2974
3223
|
* ```typescript
|
|
2975
|
-
* import http from 'http';
|
|
2976
|
-
* import { randomUUID } from 'crypto';
|
|
3224
|
+
* import http from 'node:http';
|
|
3225
|
+
* import { randomUUID } from 'node:crypto';
|
|
2977
3226
|
*
|
|
2978
3227
|
* const httpServer = http.createServer(async (req, res) => {
|
|
2979
3228
|
* await server.startHTTP({
|
|
@@ -3052,34 +3301,12 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3052
3301
|
`startHTTP: Handling GET request for existing session ${sessionId}. Calling transport.handleRequest.`
|
|
3053
3302
|
);
|
|
3054
3303
|
}
|
|
3055
|
-
const body = req.method === "POST" ? await
|
|
3056
|
-
let data = "";
|
|
3057
|
-
req.on("data", (chunk) => data += chunk);
|
|
3058
|
-
req.on("end", () => {
|
|
3059
|
-
try {
|
|
3060
|
-
resolve(JSON.parse(data));
|
|
3061
|
-
} catch (e) {
|
|
3062
|
-
reject(e);
|
|
3063
|
-
}
|
|
3064
|
-
});
|
|
3065
|
-
req.on("error", reject);
|
|
3066
|
-
}) : void 0;
|
|
3304
|
+
const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
|
|
3067
3305
|
await transport.handleRequest(req, res, body);
|
|
3068
3306
|
} else {
|
|
3069
3307
|
this.logger.debug(`startHTTP: No existing Streamable HTTP session ID found. ${req.method}`);
|
|
3070
3308
|
if (req.method === "POST") {
|
|
3071
|
-
const body = await
|
|
3072
|
-
let data = "";
|
|
3073
|
-
req.on("data", (chunk) => data += chunk);
|
|
3074
|
-
req.on("end", () => {
|
|
3075
|
-
try {
|
|
3076
|
-
resolve(JSON.parse(data));
|
|
3077
|
-
} catch (e) {
|
|
3078
|
-
reject(e);
|
|
3079
|
-
}
|
|
3080
|
-
});
|
|
3081
|
-
req.on("error", reject);
|
|
3082
|
-
});
|
|
3309
|
+
const body = await this.readJsonBody(req);
|
|
3083
3310
|
const { isInitializeRequest } = await import('@modelcontextprotocol/sdk/types.js');
|
|
3084
3311
|
if (isInitializeRequest(body)) {
|
|
3085
3312
|
this.logger.debug("startHTTP: Received Streamable HTTP initialize request, creating new transport.");
|
|
@@ -3189,18 +3416,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3189
3416
|
async handleServerlessRequest(req, res) {
|
|
3190
3417
|
try {
|
|
3191
3418
|
this.logger.debug(`handleServerlessRequest: Received ${req.method} request`);
|
|
3192
|
-
const body = req.method === "POST" ? await
|
|
3193
|
-
let data = "";
|
|
3194
|
-
req.on("data", (chunk) => data += chunk);
|
|
3195
|
-
req.on("end", () => {
|
|
3196
|
-
try {
|
|
3197
|
-
resolve(JSON.parse(data));
|
|
3198
|
-
} catch (e) {
|
|
3199
|
-
reject(new Error(`Invalid JSON in request body: ${e instanceof Error ? e.message : String(e)}`));
|
|
3200
|
-
}
|
|
3201
|
-
});
|
|
3202
|
-
req.on("error", reject);
|
|
3203
|
-
}) : void 0;
|
|
3419
|
+
const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
|
|
3204
3420
|
this.logger.debug(`handleServerlessRequest: Processing ${req.method} request`, {
|
|
3205
3421
|
method: body?.method,
|
|
3206
3422
|
id: body?.id
|
|
@@ -3631,6 +3847,6 @@ Provided arguments: ${JSON.stringify(args, null, 2)}`,
|
|
|
3631
3847
|
}
|
|
3632
3848
|
};
|
|
3633
3849
|
|
|
3634
|
-
export { MCPClient, MCPServer };
|
|
3850
|
+
export { InternalMastraMCPClient, MCPClient, MCPServer };
|
|
3635
3851
|
//# sourceMappingURL=index.js.map
|
|
3636
3852
|
//# sourceMappingURL=index.js.map
|