@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.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
|
|
12
|
-
var sse_js
|
|
13
|
-
var stdio_js
|
|
14
|
-
var 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/
|
|
33
|
+
// src/client/client.ts
|
|
34
34
|
|
|
35
|
-
// src/client/
|
|
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;
|
|
@@ -398,17 +415,21 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
398
415
|
timeout;
|
|
399
416
|
logHandler;
|
|
400
417
|
enableServerLogs;
|
|
418
|
+
enableProgressTracking;
|
|
401
419
|
serverConfig;
|
|
402
420
|
transport;
|
|
403
421
|
currentOperationContext = null;
|
|
404
422
|
exitHookUnsubscribe;
|
|
405
423
|
sigTermHandler;
|
|
424
|
+
_roots;
|
|
406
425
|
/** Provides access to resource operations (list, read, subscribe, etc.) */
|
|
407
426
|
resources;
|
|
408
427
|
/** Provides access to prompt operations (list, get, notifications) */
|
|
409
428
|
prompts;
|
|
410
429
|
/** Provides access to elicitation operations (request handling) */
|
|
411
430
|
elicitation;
|
|
431
|
+
/** Provides access to progress operations (notifications) */
|
|
432
|
+
progress;
|
|
412
433
|
/**
|
|
413
434
|
* @internal
|
|
414
435
|
*/
|
|
@@ -425,8 +446,16 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
425
446
|
this.logHandler = server.logger;
|
|
426
447
|
this.enableServerLogs = server.enableServerLogs ?? true;
|
|
427
448
|
this.serverConfig = server;
|
|
428
|
-
|
|
429
|
-
this.
|
|
449
|
+
this.enableProgressTracking = !!server.enableProgressTracking;
|
|
450
|
+
this._roots = server.roots ?? [];
|
|
451
|
+
const hasRoots = this._roots.length > 0 || !!capabilities.roots;
|
|
452
|
+
const clientCapabilities = {
|
|
453
|
+
...capabilities,
|
|
454
|
+
elicitation: {},
|
|
455
|
+
// Auto-enable roots capability if roots are provided
|
|
456
|
+
...hasRoots ? { roots: { listChanged: true, ...capabilities.roots ?? {} } } : {}
|
|
457
|
+
};
|
|
458
|
+
this.client = new index_js.Client(
|
|
430
459
|
{
|
|
431
460
|
name,
|
|
432
461
|
version
|
|
@@ -436,9 +465,13 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
436
465
|
}
|
|
437
466
|
);
|
|
438
467
|
this.setupLogging();
|
|
468
|
+
if (hasRoots) {
|
|
469
|
+
this.setupRootsHandler();
|
|
470
|
+
}
|
|
439
471
|
this.resources = new ResourceClientActions({ client: this, logger: this.logger });
|
|
440
472
|
this.prompts = new PromptClientActions({ client: this, logger: this.logger });
|
|
441
473
|
this.elicitation = new ElicitationClientActions({ client: this, logger: this.logger });
|
|
474
|
+
this.progress = new ProgressClientActions({ client: this, logger: this.logger });
|
|
442
475
|
}
|
|
443
476
|
/**
|
|
444
477
|
* Log a message at the specified level
|
|
@@ -477,13 +510,70 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
477
510
|
);
|
|
478
511
|
}
|
|
479
512
|
}
|
|
513
|
+
/**
|
|
514
|
+
* Set up handler for roots/list requests from the server.
|
|
515
|
+
*
|
|
516
|
+
* Per MCP spec (https://modelcontextprotocol.io/specification/2025-11-25/client/roots):
|
|
517
|
+
* When a server sends a roots/list request, the client responds with the configured roots.
|
|
518
|
+
*/
|
|
519
|
+
setupRootsHandler() {
|
|
520
|
+
this.log("debug", "Setting up roots/list request handler");
|
|
521
|
+
this.client.setRequestHandler(types_js.ListRootsRequestSchema, async () => {
|
|
522
|
+
this.log("debug", `Responding to roots/list request with ${this._roots.length} roots`);
|
|
523
|
+
return { roots: this._roots };
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Get the currently configured roots.
|
|
528
|
+
*
|
|
529
|
+
* @returns Array of configured filesystem roots
|
|
530
|
+
*/
|
|
531
|
+
get roots() {
|
|
532
|
+
return [...this._roots];
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Update the list of filesystem roots and notify the server.
|
|
536
|
+
*
|
|
537
|
+
* Per MCP spec, when roots change, the client sends a `notifications/roots/list_changed`
|
|
538
|
+
* notification to inform the server that it should re-fetch the roots list.
|
|
539
|
+
*
|
|
540
|
+
* @param roots - New list of filesystem roots
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
* ```typescript
|
|
544
|
+
* await client.setRoots([
|
|
545
|
+
* { uri: 'file:///home/user/projects', name: 'Projects' },
|
|
546
|
+
* { uri: 'file:///tmp', name: 'Temp' }
|
|
547
|
+
* ]);
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
async setRoots(roots) {
|
|
551
|
+
this.log("debug", `Updating roots to ${roots.length} entries`);
|
|
552
|
+
this._roots = [...roots];
|
|
553
|
+
await this.sendRootsListChanged();
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Send a roots/list_changed notification to the server.
|
|
557
|
+
*
|
|
558
|
+
* Per MCP spec, clients that support `listChanged` MUST send this notification
|
|
559
|
+
* when the list of roots changes. The server will then call roots/list to get
|
|
560
|
+
* the updated list.
|
|
561
|
+
*/
|
|
562
|
+
async sendRootsListChanged() {
|
|
563
|
+
if (!this.transport) {
|
|
564
|
+
this.log("debug", "Cannot send roots/list_changed: not connected");
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
this.log("debug", "Sending notifications/roots/list_changed");
|
|
568
|
+
await this.client.notification({ method: "notifications/roots/list_changed" });
|
|
569
|
+
}
|
|
480
570
|
async connectStdio(command) {
|
|
481
571
|
this.log("debug", `Using Stdio transport for command: ${command}`);
|
|
482
572
|
try {
|
|
483
|
-
this.transport = new stdio_js
|
|
573
|
+
this.transport = new stdio_js.StdioClientTransport({
|
|
484
574
|
command,
|
|
485
575
|
args: this.serverConfig.args,
|
|
486
|
-
env: { ...stdio_js
|
|
576
|
+
env: { ...stdio_js.getDefaultEnvironment(), ...this.serverConfig.env || {} }
|
|
487
577
|
});
|
|
488
578
|
await this.client.connect(this.transport, { timeout: this.serverConfig.timeout ?? this.timeout });
|
|
489
579
|
this.log("debug", `Successfully connected to MCP server via Stdio`);
|
|
@@ -499,7 +589,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
499
589
|
if (!shouldTrySSE) {
|
|
500
590
|
try {
|
|
501
591
|
this.log("debug", "Trying Streamable HTTP transport...");
|
|
502
|
-
const streamableTransport = new streamableHttp_js
|
|
592
|
+
const streamableTransport = new streamableHttp_js.StreamableHTTPClientTransport(url, {
|
|
503
593
|
requestInit,
|
|
504
594
|
reconnectionOptions: this.serverConfig.reconnectionOptions,
|
|
505
595
|
authProvider
|
|
@@ -517,7 +607,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
517
607
|
if (shouldTrySSE) {
|
|
518
608
|
this.log("debug", "Falling back to deprecated HTTP+SSE transport...");
|
|
519
609
|
try {
|
|
520
|
-
const sseTransport = new sse_js
|
|
610
|
+
const sseTransport = new sse_js.SSEClientTransport(url, { requestInit, eventSourceInit, authProvider });
|
|
521
611
|
await this.client.connect(sseTransport, { timeout: this.serverConfig.timeout ?? this.timeout });
|
|
522
612
|
this.transport = sseTransport;
|
|
523
613
|
this.log("debug", "Successfully connected using deprecated HTTP+SSE transport.");
|
|
@@ -596,7 +686,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
596
686
|
* @internal
|
|
597
687
|
*/
|
|
598
688
|
get sessionId() {
|
|
599
|
-
if (this.transport instanceof streamableHttp_js
|
|
689
|
+
if (this.transport instanceof streamableHttp_js.StreamableHTTPClientTransport) {
|
|
600
690
|
return this.transport.sessionId;
|
|
601
691
|
}
|
|
602
692
|
return void 0;
|
|
@@ -617,7 +707,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
617
707
|
throw e;
|
|
618
708
|
} finally {
|
|
619
709
|
this.transport = void 0;
|
|
620
|
-
this.isConnected =
|
|
710
|
+
this.isConnected = null;
|
|
621
711
|
if (this.exitHookUnsubscribe) {
|
|
622
712
|
this.exitHookUnsubscribe();
|
|
623
713
|
this.exitHookUnsubscribe = void 0;
|
|
@@ -628,6 +718,53 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
628
718
|
}
|
|
629
719
|
}
|
|
630
720
|
}
|
|
721
|
+
/**
|
|
722
|
+
* Checks if an error indicates a session invalidation that requires reconnection.
|
|
723
|
+
*
|
|
724
|
+
* Common session-related errors include:
|
|
725
|
+
* - "No valid session ID provided" (HTTP 400)
|
|
726
|
+
* - "Server not initialized" (HTTP 400)
|
|
727
|
+
* - Connection refused errors
|
|
728
|
+
*
|
|
729
|
+
* @param error - The error to check
|
|
730
|
+
* @returns true if the error indicates a session problem requiring reconnection
|
|
731
|
+
*
|
|
732
|
+
* @internal
|
|
733
|
+
*/
|
|
734
|
+
isSessionError(error) {
|
|
735
|
+
if (!(error instanceof Error)) {
|
|
736
|
+
return false;
|
|
737
|
+
}
|
|
738
|
+
const errorMessage = error.message.toLowerCase();
|
|
739
|
+
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");
|
|
740
|
+
}
|
|
741
|
+
/**
|
|
742
|
+
* Forces a reconnection to the MCP server by disconnecting and reconnecting.
|
|
743
|
+
*
|
|
744
|
+
* This is useful when the session becomes invalid (e.g., after server restart)
|
|
745
|
+
* and the client needs to establish a fresh connection.
|
|
746
|
+
*
|
|
747
|
+
* @returns Promise resolving when reconnection is complete
|
|
748
|
+
* @throws {Error} If reconnection fails
|
|
749
|
+
*
|
|
750
|
+
* @internal
|
|
751
|
+
*/
|
|
752
|
+
async forceReconnect() {
|
|
753
|
+
this.log("debug", "Forcing reconnection to MCP server...");
|
|
754
|
+
try {
|
|
755
|
+
if (this.transport) {
|
|
756
|
+
await this.transport.close();
|
|
757
|
+
}
|
|
758
|
+
} catch (e) {
|
|
759
|
+
this.log("debug", "Error during force disconnect (ignored)", {
|
|
760
|
+
error: e instanceof Error ? e.message : String(e)
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
this.transport = void 0;
|
|
764
|
+
this.isConnected = null;
|
|
765
|
+
await this.connect();
|
|
766
|
+
this.log("debug", "Successfully reconnected to MCP server");
|
|
767
|
+
}
|
|
631
768
|
async listResources() {
|
|
632
769
|
this.log("debug", `Requesting resources from MCP server`);
|
|
633
770
|
return await this.client.request({ method: "resources/list" }, types_js.ListResourcesResultSchema, {
|
|
@@ -714,6 +851,12 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
714
851
|
return handler(request.params);
|
|
715
852
|
});
|
|
716
853
|
}
|
|
854
|
+
setProgressNotificationHandler(handler) {
|
|
855
|
+
this.log("debug", "Setting progress notification handler");
|
|
856
|
+
this.client.setNotificationHandler(types_js.ProgressNotificationSchema, (notification) => {
|
|
857
|
+
handler(notification.params);
|
|
858
|
+
});
|
|
859
|
+
}
|
|
717
860
|
async convertInputSchema(inputSchema) {
|
|
718
861
|
if (utils.isZodType(inputSchema)) {
|
|
719
862
|
return inputSchema;
|
|
@@ -787,7 +930,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
787
930
|
}
|
|
788
931
|
async tools() {
|
|
789
932
|
this.log("debug", `Requesting tools from MCP server`);
|
|
790
|
-
const { tools: tools$1 } = await this.client.listTools({ timeout: this.timeout });
|
|
933
|
+
const { tools: tools$1 } = await this.client.listTools({}, { timeout: this.timeout });
|
|
791
934
|
const toolsRes = {};
|
|
792
935
|
for (const tool of tools$1) {
|
|
793
936
|
this.log("debug", `Processing tool: ${tool.name}`);
|
|
@@ -800,12 +943,14 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
800
943
|
execute: async (input, context) => {
|
|
801
944
|
const previousContext = this.currentOperationContext;
|
|
802
945
|
this.currentOperationContext = context?.requestContext || null;
|
|
803
|
-
|
|
804
|
-
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input });
|
|
946
|
+
const executeToolCall = async () => {
|
|
947
|
+
this.log("debug", `Executing tool: ${tool.name}`, { toolArgs: input, runId: context?.runId });
|
|
805
948
|
const res = await this.client.callTool(
|
|
806
949
|
{
|
|
807
950
|
name: tool.name,
|
|
808
|
-
arguments: input
|
|
951
|
+
arguments: input,
|
|
952
|
+
// Use runId as progress token if available, otherwise generate a random UUID
|
|
953
|
+
...this.enableProgressTracking ? { _meta: { progressToken: context?.runId || crypto.randomUUID() } } : {}
|
|
809
954
|
},
|
|
810
955
|
types_js.CallToolResultSchema,
|
|
811
956
|
{
|
|
@@ -817,7 +962,27 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
817
962
|
return res.structuredContent;
|
|
818
963
|
}
|
|
819
964
|
return res;
|
|
965
|
+
};
|
|
966
|
+
try {
|
|
967
|
+
return await executeToolCall();
|
|
820
968
|
} catch (e) {
|
|
969
|
+
if (this.isSessionError(e)) {
|
|
970
|
+
this.log("debug", `Session error detected for tool ${tool.name}, attempting reconnection...`, {
|
|
971
|
+
error: e instanceof Error ? e.message : String(e)
|
|
972
|
+
});
|
|
973
|
+
try {
|
|
974
|
+
await this.forceReconnect();
|
|
975
|
+
this.log("debug", `Retrying tool ${tool.name} after reconnection...`);
|
|
976
|
+
return await executeToolCall();
|
|
977
|
+
} catch (reconnectError) {
|
|
978
|
+
this.log("error", `Reconnection or retry failed for tool ${tool.name}`, {
|
|
979
|
+
originalError: e instanceof Error ? e.message : String(e),
|
|
980
|
+
reconnectError: reconnectError instanceof Error ? reconnectError.stack : String(reconnectError),
|
|
981
|
+
toolArgs: input
|
|
982
|
+
});
|
|
983
|
+
throw e;
|
|
984
|
+
}
|
|
985
|
+
}
|
|
821
986
|
this.log("error", `Error calling tool: ${tool.name}`, {
|
|
822
987
|
error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
|
|
823
988
|
toolArgs: input
|
|
@@ -841,8 +1006,6 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
841
1006
|
return toolsRes;
|
|
842
1007
|
}
|
|
843
1008
|
};
|
|
844
|
-
|
|
845
|
-
// src/client/configuration.ts
|
|
846
1009
|
var mcpClientInstances = /* @__PURE__ */ new Map();
|
|
847
1010
|
var MCPClient = class extends base.MastraBase {
|
|
848
1011
|
serverConfigs = {};
|
|
@@ -915,6 +1078,48 @@ To fix this you have three different options:
|
|
|
915
1078
|
this.addToInstanceCache();
|
|
916
1079
|
return this;
|
|
917
1080
|
}
|
|
1081
|
+
/**
|
|
1082
|
+
* Provides access to progress-related operations for tracking long-running operations.
|
|
1083
|
+
*
|
|
1084
|
+
* Progress tracking allows MCP servers to send updates about the status of ongoing operations,
|
|
1085
|
+
* providing real-time feedback to users about task completion and current state.
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* ```typescript
|
|
1089
|
+
* // Set up handler for progress updates from a server
|
|
1090
|
+
* await mcp.progress.onUpdate('serverName', (params) => {
|
|
1091
|
+
* console.log(`Progress: ${params.progress}%`);
|
|
1092
|
+
* console.log(`Status: ${params.message}`);
|
|
1093
|
+
*
|
|
1094
|
+
* if (params.total) {
|
|
1095
|
+
* console.log(`Completed ${params.progress} of ${params.total} items`);
|
|
1096
|
+
* }
|
|
1097
|
+
* });
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
get progress() {
|
|
1101
|
+
this.addToInstanceCache();
|
|
1102
|
+
return {
|
|
1103
|
+
onUpdate: async (serverName, handler) => {
|
|
1104
|
+
try {
|
|
1105
|
+
const internalClient = await this.getConnectedClientForServer(serverName);
|
|
1106
|
+
return internalClient.progress.onUpdate(handler);
|
|
1107
|
+
} catch (err) {
|
|
1108
|
+
throw new error.MastraError(
|
|
1109
|
+
{
|
|
1110
|
+
id: "MCP_CLIENT_ON_UPDATE_PROGRESS_FAILED",
|
|
1111
|
+
domain: error.ErrorDomain.MCP,
|
|
1112
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1113
|
+
details: {
|
|
1114
|
+
serverName
|
|
1115
|
+
}
|
|
1116
|
+
},
|
|
1117
|
+
err
|
|
1118
|
+
);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
918
1123
|
/**
|
|
919
1124
|
* Provides access to elicitation-related operations for interactive user input collection.
|
|
920
1125
|
*
|
|
@@ -2160,7 +2365,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2160
2365
|
if (opts.prompts) {
|
|
2161
2366
|
capabilities.prompts = { listChanged: true };
|
|
2162
2367
|
}
|
|
2163
|
-
this.server = new index_js.Server({ name: this.name, version: this.version }, { capabilities });
|
|
2368
|
+
this.server = new index_js$1.Server({ name: this.name, version: this.version }, { capabilities });
|
|
2164
2369
|
this.logger.info(
|
|
2165
2370
|
`Initialized MCPServer '${this.name}' v${this.version} (ID: ${this.id}) with tools: ${Object.keys(this.convertedTools).join(", ")} and resources. Capabilities: ${JSON.stringify(capabilities)}`
|
|
2166
2371
|
);
|
|
@@ -2205,6 +2410,41 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2205
2410
|
this.logger.debug(`Received elicitation response: ${JSON.stringify(response)}`);
|
|
2206
2411
|
return response;
|
|
2207
2412
|
}
|
|
2413
|
+
/**
|
|
2414
|
+
* Reads and parses the JSON body from an HTTP request.
|
|
2415
|
+
* If the request body was already parsed by middleware (e.g., express.json()),
|
|
2416
|
+
* it uses the pre-parsed body from req.body. Otherwise, it reads from the stream.
|
|
2417
|
+
*
|
|
2418
|
+
* This allows the MCP server to work with Express apps that use express.json()
|
|
2419
|
+
* globally without requiring special route exclusions.
|
|
2420
|
+
*
|
|
2421
|
+
* @param req - The incoming HTTP request
|
|
2422
|
+
* @param options - Optional configuration
|
|
2423
|
+
* @param options.preParsedOnly - If true, only return pre-parsed body from middleware,
|
|
2424
|
+
* returning undefined if not available. This allows the caller to fall back to
|
|
2425
|
+
* their own body reading logic (e.g., SDK's getRawBody with size limits).
|
|
2426
|
+
*/
|
|
2427
|
+
async readJsonBody(req, options) {
|
|
2428
|
+
const reqWithBody = req;
|
|
2429
|
+
if (reqWithBody.body !== void 0) {
|
|
2430
|
+
return reqWithBody.body;
|
|
2431
|
+
}
|
|
2432
|
+
if (options?.preParsedOnly) {
|
|
2433
|
+
return void 0;
|
|
2434
|
+
}
|
|
2435
|
+
return new Promise((resolve, reject) => {
|
|
2436
|
+
let data = "";
|
|
2437
|
+
req.on("data", (chunk) => data += chunk);
|
|
2438
|
+
req.on("end", () => {
|
|
2439
|
+
try {
|
|
2440
|
+
resolve(JSON.parse(data));
|
|
2441
|
+
} catch (e) {
|
|
2442
|
+
reject(e);
|
|
2443
|
+
}
|
|
2444
|
+
});
|
|
2445
|
+
req.on("error", reject);
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2208
2448
|
/**
|
|
2209
2449
|
* Creates a new Server instance configured with all handlers for HTTP sessions.
|
|
2210
2450
|
* Each HTTP client connection gets its own Server instance to avoid routing conflicts.
|
|
@@ -2221,7 +2461,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
2221
2461
|
if (this.promptOptions) {
|
|
2222
2462
|
capabilities.prompts = { listChanged: true };
|
|
2223
2463
|
}
|
|
2224
|
-
const serverInstance = new index_js.Server({ name: this.name, version: this.version }, { capabilities });
|
|
2464
|
+
const serverInstance = new index_js$1.Server({ name: this.name, version: this.version }, { capabilities });
|
|
2225
2465
|
this.registerHandlersOnServer(serverInstance);
|
|
2226
2466
|
return serverInstance;
|
|
2227
2467
|
}
|
|
@@ -2593,7 +2833,9 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2593
2833
|
try {
|
|
2594
2834
|
const proxiedContext = context?.requestContext || new requestContext.RequestContext();
|
|
2595
2835
|
if (context?.mcp?.extra) {
|
|
2596
|
-
|
|
2836
|
+
Object.entries(context.mcp.extra).forEach(([key, value]) => {
|
|
2837
|
+
proxiedContext.set(key, value);
|
|
2838
|
+
});
|
|
2597
2839
|
}
|
|
2598
2840
|
const response = await agent.generate(inputData.message, {
|
|
2599
2841
|
...context ?? {},
|
|
@@ -2662,10 +2904,16 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2662
2904
|
inputData
|
|
2663
2905
|
);
|
|
2664
2906
|
try {
|
|
2665
|
-
const
|
|
2907
|
+
const proxiedContext = context?.requestContext || new requestContext.RequestContext();
|
|
2908
|
+
if (context?.mcp?.extra) {
|
|
2909
|
+
Object.entries(context.mcp.extra).forEach(([key, value]) => {
|
|
2910
|
+
proxiedContext.set(key, value);
|
|
2911
|
+
});
|
|
2912
|
+
}
|
|
2913
|
+
const run2 = await workflow.createRun({ runId: proxiedContext?.get("runId") });
|
|
2666
2914
|
const response = await run2.start({
|
|
2667
2915
|
inputData,
|
|
2668
|
-
requestContext:
|
|
2916
|
+
requestContext: proxiedContext,
|
|
2669
2917
|
tracingContext: context?.tracingContext
|
|
2670
2918
|
});
|
|
2671
2919
|
return response;
|
|
@@ -2784,7 +3032,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2784
3032
|
* ```
|
|
2785
3033
|
*/
|
|
2786
3034
|
async startStdio() {
|
|
2787
|
-
this.stdioTransport = new stdio_js.StdioServerTransport();
|
|
3035
|
+
this.stdioTransport = new stdio_js$1.StdioServerTransport();
|
|
2788
3036
|
try {
|
|
2789
3037
|
await this.server.connect(this.stdioTransport);
|
|
2790
3038
|
} catch (error$1) {
|
|
@@ -2821,7 +3069,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2821
3069
|
*
|
|
2822
3070
|
* @example
|
|
2823
3071
|
* ```typescript
|
|
2824
|
-
* import http from 'http';
|
|
3072
|
+
* import http from 'node:http';
|
|
2825
3073
|
*
|
|
2826
3074
|
* const httpServer = http.createServer(async (req, res) => {
|
|
2827
3075
|
* await server.startSSE({
|
|
@@ -2852,7 +3100,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2852
3100
|
res.end("SSE connection not established");
|
|
2853
3101
|
return;
|
|
2854
3102
|
}
|
|
2855
|
-
await this.
|
|
3103
|
+
const parsedBody = await this.readJsonBody(req, { preParsedOnly: true });
|
|
3104
|
+
await this.sseTransport.handlePostMessage(req, res, parsedBody);
|
|
2856
3105
|
} else {
|
|
2857
3106
|
this.logger.debug("Unknown path:", { path: url.pathname });
|
|
2858
3107
|
res.writeHead(404);
|
|
@@ -2979,8 +3228,8 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
2979
3228
|
*
|
|
2980
3229
|
* @example
|
|
2981
3230
|
* ```typescript
|
|
2982
|
-
* import http from 'http';
|
|
2983
|
-
* import { randomUUID } from 'crypto';
|
|
3231
|
+
* import http from 'node:http';
|
|
3232
|
+
* import { randomUUID } from 'node:crypto';
|
|
2984
3233
|
*
|
|
2985
3234
|
* const httpServer = http.createServer(async (req, res) => {
|
|
2986
3235
|
* await server.startHTTP({
|
|
@@ -3059,38 +3308,16 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3059
3308
|
`startHTTP: Handling GET request for existing session ${sessionId}. Calling transport.handleRequest.`
|
|
3060
3309
|
);
|
|
3061
3310
|
}
|
|
3062
|
-
const body = req.method === "POST" ? await
|
|
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;
|
|
3311
|
+
const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
|
|
3074
3312
|
await transport.handleRequest(req, res, body);
|
|
3075
3313
|
} else {
|
|
3076
3314
|
this.logger.debug(`startHTTP: No existing Streamable HTTP session ID found. ${req.method}`);
|
|
3077
3315
|
if (req.method === "POST") {
|
|
3078
|
-
const body = await
|
|
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
|
-
});
|
|
3316
|
+
const body = await this.readJsonBody(req);
|
|
3090
3317
|
const { isInitializeRequest } = await import('@modelcontextprotocol/sdk/types.js');
|
|
3091
3318
|
if (isInitializeRequest(body)) {
|
|
3092
3319
|
this.logger.debug("startHTTP: Received Streamable HTTP initialize request, creating new transport.");
|
|
3093
|
-
transport = new streamableHttp_js.StreamableHTTPServerTransport({
|
|
3320
|
+
transport = new streamableHttp_js$1.StreamableHTTPServerTransport({
|
|
3094
3321
|
...mergedOptions,
|
|
3095
3322
|
sessionIdGenerator: mergedOptions.sessionIdGenerator,
|
|
3096
3323
|
onsessioninitialized: (id) => {
|
|
@@ -3196,24 +3423,13 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3196
3423
|
async handleServerlessRequest(req, res) {
|
|
3197
3424
|
try {
|
|
3198
3425
|
this.logger.debug(`handleServerlessRequest: Received ${req.method} request`);
|
|
3199
|
-
const body = req.method === "POST" ? await
|
|
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;
|
|
3426
|
+
const body = req.method === "POST" ? await this.readJsonBody(req) : void 0;
|
|
3211
3427
|
this.logger.debug(`handleServerlessRequest: Processing ${req.method} request`, {
|
|
3212
3428
|
method: body?.method,
|
|
3213
3429
|
id: body?.id
|
|
3214
3430
|
});
|
|
3215
3431
|
const transientServer = this.createServerInstance();
|
|
3216
|
-
const tempTransport = new streamableHttp_js.StreamableHTTPServerTransport({
|
|
3432
|
+
const tempTransport = new streamableHttp_js$1.StreamableHTTPServerTransport({
|
|
3217
3433
|
sessionIdGenerator: void 0,
|
|
3218
3434
|
enableJsonResponse: true
|
|
3219
3435
|
});
|
|
@@ -3275,7 +3491,7 @@ Provided arguments: ${JSON.stringify(request.params.arguments, null, 2)}`
|
|
|
3275
3491
|
}) {
|
|
3276
3492
|
try {
|
|
3277
3493
|
this.logger.debug("Received SSE connection");
|
|
3278
|
-
this.sseTransport = new sse_js.SSEServerTransport(messagePath, res);
|
|
3494
|
+
this.sseTransport = new sse_js$1.SSEServerTransport(messagePath, res);
|
|
3279
3495
|
await this.server.connect(this.sseTransport);
|
|
3280
3496
|
this.server.onclose = async () => {
|
|
3281
3497
|
this.sseTransport = void 0;
|
|
@@ -3638,6 +3854,7 @@ Provided arguments: ${JSON.stringify(args, null, 2)}`,
|
|
|
3638
3854
|
}
|
|
3639
3855
|
};
|
|
3640
3856
|
|
|
3857
|
+
exports.InternalMastraMCPClient = InternalMastraMCPClient;
|
|
3641
3858
|
exports.MCPClient = MCPClient;
|
|
3642
3859
|
exports.MCPServer = MCPServer;
|
|
3643
3860
|
//# sourceMappingURL=index.cjs.map
|