@mastra/mcp 0.10.4-alpha.0 → 0.10.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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +34 -0
- package/dist/_tsup-dts-rollup.d.cts +2 -2
- package/dist/_tsup-dts-rollup.d.ts +2 -2
- package/dist/index.cjs +35 -44
- package/dist/index.js +27 -36
- package/integration-tests/node_modules/.bin/mastra +21 -0
- package/integration-tests/node_modules/.bin/vitest +2 -2
- package/integration-tests/package.json +3 -3
- package/integration-tests/src/server.test.ts +14 -5
- package/package.json +3 -3
- package/src/client/client.ts +33 -34
- package/src/server/server.ts +2 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/mcp@0.10.4-alpha.
|
|
2
|
+
> @mastra/mcp@0.10.4-alpha.1 build /home/runner/work/mastra/mastra/packages/mcp
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.5.0
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 20537ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.8.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/mcp/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 21141ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[32mESM[39m [1mdist/index.js [22m[32m71.
|
|
21
|
-
[32mESM[39m ⚡️ Build success in
|
|
22
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m71.
|
|
23
|
-
[32mCJS[39m ⚡️ Build success in
|
|
20
|
+
[32mESM[39m [1mdist/index.js [22m[32m71.61 KB[39m
|
|
21
|
+
[32mESM[39m ⚡️ Build success in 1942ms
|
|
22
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m71.73 KB[39m
|
|
23
|
+
[32mCJS[39m ⚡️ Build success in 1942ms
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @mastra/mcp
|
|
2
2
|
|
|
3
|
+
## 0.10.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 63f6b7d: dependencies updates:
|
|
8
|
+
- Updated dependency [`@modelcontextprotocol/sdk@^1.12.1` ↗︎](https://www.npmjs.com/package/@modelcontextprotocol/sdk/v/1.12.1) (from `^1.10.2`, in `dependencies`)
|
|
9
|
+
- Updated dependency [`hono@^4.7.11` ↗︎](https://www.npmjs.com/package/hono/v/4.7.11) (from `^4.7.4`, in `dependencies`)
|
|
10
|
+
- 36f1c36: MCP Client and Server streamable http fixes
|
|
11
|
+
- bd1674f: Change how connection promise works for client connection
|
|
12
|
+
- 69f76f7: Fix Agents as tools when building mastra mcp server
|
|
13
|
+
- Updated dependencies [63f6b7d]
|
|
14
|
+
- Updated dependencies [12a95fc]
|
|
15
|
+
- Updated dependencies [4b0f8a6]
|
|
16
|
+
- Updated dependencies [51264a5]
|
|
17
|
+
- Updated dependencies [8e6f677]
|
|
18
|
+
- Updated dependencies [d70c420]
|
|
19
|
+
- Updated dependencies [ee9af57]
|
|
20
|
+
- Updated dependencies [36f1c36]
|
|
21
|
+
- Updated dependencies [2a16996]
|
|
22
|
+
- Updated dependencies [10d352e]
|
|
23
|
+
- Updated dependencies [9589624]
|
|
24
|
+
- Updated dependencies [53d3c37]
|
|
25
|
+
- Updated dependencies [751c894]
|
|
26
|
+
- Updated dependencies [577ce3a]
|
|
27
|
+
- Updated dependencies [9260b3a]
|
|
28
|
+
- @mastra/core@0.10.6
|
|
29
|
+
|
|
30
|
+
## 0.10.4-alpha.1
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- bd1674f: Change how connection promise works for client connection
|
|
35
|
+
- 69f76f7: Fix Agents as tools when building mastra mcp server
|
|
36
|
+
|
|
3
37
|
## 0.10.4-alpha.0
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Agent } from '@mastra/core/agent';
|
|
1
|
+
import type { Agent } from '@mastra/core/agent';
|
|
2
2
|
import type { ClientCapabilities } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import type { ConvertedTool } from '@mastra/core/mcp';
|
|
4
4
|
import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -86,7 +86,7 @@ export declare class InternalMastraMCPClient extends MastraBase {
|
|
|
86
86
|
private connectStdio;
|
|
87
87
|
private connectHttp;
|
|
88
88
|
private isConnected;
|
|
89
|
-
connect(): Promise<
|
|
89
|
+
connect(): Promise<boolean>;
|
|
90
90
|
/**
|
|
91
91
|
* Get the current session ID if using the Streamable HTTP transport.
|
|
92
92
|
* Returns undefined if not connected or not using Streamable HTTP.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Agent } from '@mastra/core/agent';
|
|
1
|
+
import type { Agent } from '@mastra/core/agent';
|
|
2
2
|
import type { ClientCapabilities } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import type { ConvertedTool } from '@mastra/core/mcp';
|
|
4
4
|
import type { GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -86,7 +86,7 @@ export declare class InternalMastraMCPClient extends MastraBase {
|
|
|
86
86
|
private connectStdio;
|
|
87
87
|
private connectHttp;
|
|
88
88
|
private isConnected;
|
|
89
|
-
connect(): Promise<
|
|
89
|
+
connect(): Promise<boolean>;
|
|
90
90
|
/**
|
|
91
91
|
* Get the current session ID if using the Streamable HTTP transport.
|
|
92
92
|
* Returns undefined if not connected or not using Streamable HTTP.
|
package/dist/index.cjs
CHANGED
|
@@ -16,7 +16,6 @@ var equal = require('fast-deep-equal');
|
|
|
16
16
|
var uuid = require('uuid');
|
|
17
17
|
var crypto$1 = require('crypto');
|
|
18
18
|
var core = require('@mastra/core');
|
|
19
|
-
var agent = require('@mastra/core/agent');
|
|
20
19
|
var mcp = require('@mastra/core/mcp');
|
|
21
20
|
var runtimeContext = require('@mastra/core/runtime-context');
|
|
22
21
|
var index_js = require('@modelcontextprotocol/sdk/server/index.js');
|
|
@@ -332,42 +331,33 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
332
331
|
}
|
|
333
332
|
isConnected = null;
|
|
334
333
|
async connect() {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
let rej = () => {
|
|
338
|
-
};
|
|
339
|
-
if (this.isConnected === null) {
|
|
340
|
-
this.log("debug", `Creating new isConnected promise`);
|
|
341
|
-
this.isConnected = new Promise((resolve, reject) => {
|
|
342
|
-
res = resolve;
|
|
343
|
-
rej = reject;
|
|
344
|
-
});
|
|
345
|
-
} else if (await this.isConnected) {
|
|
346
|
-
this.log("debug", `MCP server already connected`);
|
|
347
|
-
return;
|
|
334
|
+
if (await this.isConnected) {
|
|
335
|
+
return true;
|
|
348
336
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
337
|
+
this.isConnected = new Promise(async (resolve, reject) => {
|
|
338
|
+
try {
|
|
339
|
+
const { command, url } = this.serverConfig;
|
|
340
|
+
if (command) {
|
|
341
|
+
await this.connectStdio(command);
|
|
342
|
+
} else if (url) {
|
|
343
|
+
await this.connectHttp(url);
|
|
344
|
+
} else {
|
|
345
|
+
throw new Error("Server configuration must include either a command or a url.");
|
|
346
|
+
}
|
|
347
|
+
resolve(true);
|
|
348
|
+
const originalOnClose = this.client.onclose;
|
|
349
|
+
this.client.onclose = () => {
|
|
350
|
+
this.log("debug", `MCP server connection closed`);
|
|
351
|
+
this.isConnected = null;
|
|
352
|
+
if (typeof originalOnClose === "function") {
|
|
353
|
+
originalOnClose();
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
} catch (e) {
|
|
357
|
+
this.isConnected = null;
|
|
358
|
+
reject(e);
|
|
369
359
|
}
|
|
370
|
-
};
|
|
360
|
+
});
|
|
371
361
|
exitHook.asyncExitHook(
|
|
372
362
|
async () => {
|
|
373
363
|
this.log("debug", `Disconnecting MCP server during exit`);
|
|
@@ -377,6 +367,7 @@ var InternalMastraMCPClient = class extends base.MastraBase {
|
|
|
377
367
|
);
|
|
378
368
|
process.on("SIGTERM", () => exitHook.gracefulExit());
|
|
379
369
|
this.log("debug", `Successfully connected to MCP server`);
|
|
370
|
+
return this.isConnected;
|
|
380
371
|
}
|
|
381
372
|
/**
|
|
382
373
|
* Get the current session ID if using the Streamable HTTP transport.
|
|
@@ -1089,15 +1080,15 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1089
1080
|
return agentTools;
|
|
1090
1081
|
}
|
|
1091
1082
|
for (const agentKey in agentsConfig) {
|
|
1092
|
-
const agent
|
|
1093
|
-
if (!agent
|
|
1083
|
+
const agent = agentsConfig[agentKey];
|
|
1084
|
+
if (!agent || !("generate" in agent)) {
|
|
1094
1085
|
this.logger.warn(`Agent instance for '${agentKey}' is invalid or missing a generate function. Skipping.`);
|
|
1095
1086
|
continue;
|
|
1096
1087
|
}
|
|
1097
|
-
const agentDescription = agent
|
|
1088
|
+
const agentDescription = agent.getDescription();
|
|
1098
1089
|
if (!agentDescription) {
|
|
1099
1090
|
throw new Error(
|
|
1100
|
-
`Agent '${agent
|
|
1091
|
+
`Agent '${agent.name}' (key: '${agentKey}') must have a non-empty description to be used in an MCPServer.`
|
|
1101
1092
|
);
|
|
1102
1093
|
}
|
|
1103
1094
|
const agentToolName = `ask_${agentKey}`;
|
|
@@ -1109,19 +1100,19 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1109
1100
|
}
|
|
1110
1101
|
const agentToolDefinition = core.createTool({
|
|
1111
1102
|
id: agentToolName,
|
|
1112
|
-
description: `Ask agent '${agent
|
|
1103
|
+
description: `Ask agent '${agent.name}' a question. Agent description: ${agentDescription}`,
|
|
1113
1104
|
inputSchema: zod.z.object({
|
|
1114
1105
|
message: zod.z.string().describe("The question or input for the agent.")
|
|
1115
1106
|
}),
|
|
1116
1107
|
execute: async ({ context, runtimeContext }) => {
|
|
1117
1108
|
this.logger.debug(
|
|
1118
|
-
`Executing agent tool '${agentToolName}' for agent '${agent
|
|
1109
|
+
`Executing agent tool '${agentToolName}' for agent '${agent.name}' with message: "${context.message}"`
|
|
1119
1110
|
);
|
|
1120
1111
|
try {
|
|
1121
|
-
const response = await agent
|
|
1112
|
+
const response = await agent.generate(context.message, { runtimeContext });
|
|
1122
1113
|
return response;
|
|
1123
1114
|
} catch (error) {
|
|
1124
|
-
this.logger.error(`Error executing agent tool '${agentToolName}' for agent '${agent
|
|
1115
|
+
this.logger.error(`Error executing agent tool '${agentToolName}' for agent '${agent.name}':`, error);
|
|
1125
1116
|
throw error;
|
|
1126
1117
|
}
|
|
1127
1118
|
}
|
|
@@ -1141,7 +1132,7 @@ var MCPServer = class extends mcp.MCPServerBase {
|
|
|
1141
1132
|
execute: coreTool.execute,
|
|
1142
1133
|
toolType: "agent"
|
|
1143
1134
|
};
|
|
1144
|
-
this.logger.info(`Registered agent '${agent
|
|
1135
|
+
this.logger.info(`Registered agent '${agent.name}' (key: '${agentKey}') as tool: '${agentToolName}'`);
|
|
1145
1136
|
}
|
|
1146
1137
|
return agentTools;
|
|
1147
1138
|
}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,6 @@ import equal from 'fast-deep-equal';
|
|
|
14
14
|
import { v5 } from 'uuid';
|
|
15
15
|
import { randomUUID } from 'crypto';
|
|
16
16
|
import { createTool, makeCoreTool } from '@mastra/core';
|
|
17
|
-
import { Agent } from '@mastra/core/agent';
|
|
18
17
|
import { MCPServerBase } from '@mastra/core/mcp';
|
|
19
18
|
import { RuntimeContext } from '@mastra/core/runtime-context';
|
|
20
19
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
@@ -326,42 +325,33 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
326
325
|
}
|
|
327
326
|
isConnected = null;
|
|
328
327
|
async connect() {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
let rej = () => {
|
|
332
|
-
};
|
|
333
|
-
if (this.isConnected === null) {
|
|
334
|
-
this.log("debug", `Creating new isConnected promise`);
|
|
335
|
-
this.isConnected = new Promise((resolve, reject) => {
|
|
336
|
-
res = resolve;
|
|
337
|
-
rej = reject;
|
|
338
|
-
});
|
|
339
|
-
} else if (await this.isConnected) {
|
|
340
|
-
this.log("debug", `MCP server already connected`);
|
|
341
|
-
return;
|
|
328
|
+
if (await this.isConnected) {
|
|
329
|
+
return true;
|
|
342
330
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
331
|
+
this.isConnected = new Promise(async (resolve, reject) => {
|
|
332
|
+
try {
|
|
333
|
+
const { command, url } = this.serverConfig;
|
|
334
|
+
if (command) {
|
|
335
|
+
await this.connectStdio(command);
|
|
336
|
+
} else if (url) {
|
|
337
|
+
await this.connectHttp(url);
|
|
338
|
+
} else {
|
|
339
|
+
throw new Error("Server configuration must include either a command or a url.");
|
|
340
|
+
}
|
|
341
|
+
resolve(true);
|
|
342
|
+
const originalOnClose = this.client.onclose;
|
|
343
|
+
this.client.onclose = () => {
|
|
344
|
+
this.log("debug", `MCP server connection closed`);
|
|
345
|
+
this.isConnected = null;
|
|
346
|
+
if (typeof originalOnClose === "function") {
|
|
347
|
+
originalOnClose();
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
} catch (e) {
|
|
351
|
+
this.isConnected = null;
|
|
352
|
+
reject(e);
|
|
363
353
|
}
|
|
364
|
-
};
|
|
354
|
+
});
|
|
365
355
|
asyncExitHook(
|
|
366
356
|
async () => {
|
|
367
357
|
this.log("debug", `Disconnecting MCP server during exit`);
|
|
@@ -371,6 +361,7 @@ var InternalMastraMCPClient = class extends MastraBase {
|
|
|
371
361
|
);
|
|
372
362
|
process.on("SIGTERM", () => gracefulExit());
|
|
373
363
|
this.log("debug", `Successfully connected to MCP server`);
|
|
364
|
+
return this.isConnected;
|
|
374
365
|
}
|
|
375
366
|
/**
|
|
376
367
|
* Get the current session ID if using the Streamable HTTP transport.
|
|
@@ -1084,7 +1075,7 @@ var MCPServer = class extends MCPServerBase {
|
|
|
1084
1075
|
}
|
|
1085
1076
|
for (const agentKey in agentsConfig) {
|
|
1086
1077
|
const agent = agentsConfig[agentKey];
|
|
1087
|
-
if (!agent || !(
|
|
1078
|
+
if (!agent || !("generate" in agent)) {
|
|
1088
1079
|
this.logger.warn(`Agent instance for '${agentKey}' is invalid or missing a generate function. Skipping.`);
|
|
1089
1080
|
continue;
|
|
1090
1081
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
|
+
|
|
4
|
+
case `uname` in
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
12
|
+
if [ -z "$NODE_PATH" ]; then
|
|
13
|
+
export NODE_PATH="/home/runner/work/mastra/mastra/packages/cli/dist/node_modules:/home/runner/work/mastra/mastra/packages/cli/node_modules:/home/runner/work/mastra/mastra/packages/node_modules:/home/runner/work/mastra/mastra/node_modules:/home/runner/work/mastra/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/node_modules"
|
|
14
|
+
else
|
|
15
|
+
export NODE_PATH="/home/runner/work/mastra/mastra/packages/cli/dist/node_modules:/home/runner/work/mastra/mastra/packages/cli/node_modules:/home/runner/work/mastra/mastra/packages/node_modules:/home/runner/work/mastra/mastra/node_modules:/home/runner/work/mastra/node_modules:/home/runner/work/node_modules:/home/runner/node_modules:/home/node_modules:/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
|
+
fi
|
|
17
|
+
if [ -x "$basedir/node" ]; then
|
|
18
|
+
exec "$basedir/node" "$basedir/../mastra/dist/index.js" "$@"
|
|
19
|
+
else
|
|
20
|
+
exec node "$basedir/../mastra/dist/index.js" "$@"
|
|
21
|
+
fi
|
|
@@ -10,9 +10,9 @@ case `uname` in
|
|
|
10
10
|
esac
|
|
11
11
|
|
|
12
12
|
if [ -z "$NODE_PATH" ]; then
|
|
13
|
-
export NODE_PATH="/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@
|
|
13
|
+
export NODE_PATH="/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@_3e45f0297eeb1f6a4ee30770ed0f557b/node_modules/vitest/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@_3e45f0297eeb1f6a4ee30770ed0f557b/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/node_modules"
|
|
14
14
|
else
|
|
15
|
-
export NODE_PATH="/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@
|
|
15
|
+
export NODE_PATH="/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@_3e45f0297eeb1f6a4ee30770ed0f557b/node_modules/vitest/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/vitest@3.2.3_@edge-runtime+vm@3.2.0_@types+debug@4.1.12_@types+node@20.19.0_@vitest+ui@_3e45f0297eeb1f6a4ee30770ed0f557b/node_modules:/home/runner/work/mastra/mastra/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
16
16
|
fi
|
|
17
17
|
if [ -x "$basedir/node" ]; then
|
|
18
18
|
exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
"dev": "mastra dev"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@ai-sdk/openai": "^1.3.
|
|
11
|
-
"@ai-sdk/react": "^1.2.
|
|
10
|
+
"@ai-sdk/openai": "^1.3.22",
|
|
11
|
+
"@ai-sdk/react": "^1.2.12",
|
|
12
12
|
"@mastra/client-js": "workspace:*",
|
|
13
13
|
"@mastra/mcp": "workspace:*",
|
|
14
14
|
"dotenv": "^16.5.0",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"get-port": "^7.1.0",
|
|
22
22
|
"mastra": "workspace:*",
|
|
23
23
|
"typescript": "^5.8.2",
|
|
24
|
-
"vitest": "^3.2.
|
|
24
|
+
"vitest": "^3.2.3"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@mastra/core": "^0.10.0-alpha.0"
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
-
import { createServer } from 'node:http';
|
|
3
2
|
import { MCPClient } from '@mastra/mcp';
|
|
4
3
|
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
|
5
4
|
import { ServerInfo } from '@mastra/core/mcp';
|
|
6
5
|
import getPort from 'get-port';
|
|
6
|
+
import path from 'node:path';
|
|
7
7
|
|
|
8
8
|
vi.setConfig({ testTimeout: 20000, hookTimeout: 20000 });
|
|
9
9
|
|
|
@@ -17,10 +17,19 @@ describe('MCPServer through Mastra HTTP Integration (Subprocess)', () => {
|
|
|
17
17
|
beforeAll(async () => {
|
|
18
18
|
port = await getPort();
|
|
19
19
|
|
|
20
|
-
mastraServer = spawn(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
mastraServer = spawn(
|
|
21
|
+
'pnpm',
|
|
22
|
+
[
|
|
23
|
+
path.resolve(import.meta.dirname, `..`, `..`, `..`, `cli`, `dist`, `index.js`),
|
|
24
|
+
'dev',
|
|
25
|
+
'--port',
|
|
26
|
+
port.toString(),
|
|
27
|
+
],
|
|
28
|
+
{
|
|
29
|
+
stdio: 'pipe',
|
|
30
|
+
detached: true, // Run in a new process group so we can kill it and children
|
|
31
|
+
},
|
|
32
|
+
);
|
|
24
33
|
|
|
25
34
|
// Wait for server to be ready
|
|
26
35
|
await new Promise<void>((resolve, reject) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/mcp",
|
|
3
|
-
"version": "0.10.4
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"vitest": "^3.2.3",
|
|
51
51
|
"zod": "^3.25.57",
|
|
52
52
|
"zod-to-json-schema": "^3.24.5",
|
|
53
|
-
"@internal/lint": "0.0.
|
|
54
|
-
"@mastra/core": "0.10.6
|
|
53
|
+
"@internal/lint": "0.0.13",
|
|
54
|
+
"@mastra/core": "0.10.6"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting",
|
package/src/client/client.ts
CHANGED
|
@@ -274,44 +274,42 @@ export class InternalMastraMCPClient extends MastraBase {
|
|
|
274
274
|
private isConnected: Promise<boolean> | null = null;
|
|
275
275
|
|
|
276
276
|
async connect() {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (this.isConnected === null) {
|
|
281
|
-
this.log('debug', `Creating new isConnected promise`);
|
|
282
|
-
this.isConnected = new Promise<boolean>((resolve, reject) => {
|
|
283
|
-
res = resolve;
|
|
284
|
-
rej = reject;
|
|
285
|
-
});
|
|
286
|
-
} else if (await this.isConnected) {
|
|
287
|
-
this.log('debug', `MCP server already connected`);
|
|
288
|
-
return;
|
|
277
|
+
// If a connection attempt is in progress, wait for it.
|
|
278
|
+
if (await this.isConnected) {
|
|
279
|
+
return true;
|
|
289
280
|
}
|
|
290
281
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
throw new Error('Server configuration must include either a command or a url.');
|
|
304
|
-
}
|
|
282
|
+
// Start new connection attempt.
|
|
283
|
+
this.isConnected = new Promise<boolean>(async (resolve, reject) => {
|
|
284
|
+
try {
|
|
285
|
+
const { command, url } = this.serverConfig;
|
|
286
|
+
|
|
287
|
+
if (command) {
|
|
288
|
+
await this.connectStdio(command);
|
|
289
|
+
} else if (url) {
|
|
290
|
+
await this.connectHttp(url);
|
|
291
|
+
} else {
|
|
292
|
+
throw new Error('Server configuration must include either a command or a url.');
|
|
293
|
+
}
|
|
305
294
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
295
|
+
resolve(true);
|
|
296
|
+
|
|
297
|
+
// Set up disconnect handler to reset state.
|
|
298
|
+
const originalOnClose = this.client.onclose;
|
|
299
|
+
this.client.onclose = () => {
|
|
300
|
+
this.log('debug', `MCP server connection closed`);
|
|
301
|
+
this.isConnected = null;
|
|
302
|
+
if (typeof originalOnClose === 'function') {
|
|
303
|
+
originalOnClose();
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
} catch (e) {
|
|
308
|
+
this.isConnected = null;
|
|
309
|
+
reject(e);
|
|
313
310
|
}
|
|
314
|
-
};
|
|
311
|
+
});
|
|
312
|
+
|
|
315
313
|
asyncExitHook(
|
|
316
314
|
async () => {
|
|
317
315
|
this.log('debug', `Disconnecting MCP server during exit`);
|
|
@@ -322,6 +320,7 @@ export class InternalMastraMCPClient extends MastraBase {
|
|
|
322
320
|
|
|
323
321
|
process.on('SIGTERM', () => gracefulExit());
|
|
324
322
|
this.log('debug', `Successfully connected to MCP server`);
|
|
323
|
+
return this.isConnected;
|
|
325
324
|
}
|
|
326
325
|
|
|
327
326
|
/**
|
package/src/server/server.ts
CHANGED
|
@@ -2,8 +2,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
2
2
|
import type * as http from 'node:http';
|
|
3
3
|
import type { InternalCoreTool } from '@mastra/core';
|
|
4
4
|
import { createTool, makeCoreTool } from '@mastra/core';
|
|
5
|
-
import type { ToolsInput } from '@mastra/core/agent';
|
|
6
|
-
import { Agent } from '@mastra/core/agent';
|
|
5
|
+
import type { ToolsInput, Agent } from '@mastra/core/agent';
|
|
7
6
|
import { MCPServerBase } from '@mastra/core/mcp';
|
|
8
7
|
import type {
|
|
9
8
|
MCPServerConfig,
|
|
@@ -187,7 +186,7 @@ export class MCPServer extends MCPServerBase {
|
|
|
187
186
|
|
|
188
187
|
for (const agentKey in agentsConfig) {
|
|
189
188
|
const agent = agentsConfig[agentKey];
|
|
190
|
-
if (!agent || !(
|
|
189
|
+
if (!agent || !('generate' in agent)) {
|
|
191
190
|
this.logger.warn(`Agent instance for '${agentKey}' is invalid or missing a generate function. Skipping.`);
|
|
192
191
|
continue;
|
|
193
192
|
}
|