@mastra/mcp 0.11.3-alpha.1 → 0.11.3-alpha.3

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/client/configuration.d.ts +1 -1
  3. package/dist/client/configuration.d.ts.map +1 -1
  4. package/dist/client/promptActions.d.ts +1 -1
  5. package/dist/client/promptActions.d.ts.map +1 -1
  6. package/dist/index.cjs +223 -115
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.js +225 -118
  9. package/dist/index.js.map +1 -1
  10. package/dist/server/server.d.ts +6 -5
  11. package/dist/server/server.d.ts.map +1 -1
  12. package/dist/server/types.d.ts +69 -5
  13. package/dist/server/types.d.ts.map +1 -1
  14. package/package.json +15 -2
  15. package/.turbo/turbo-build.log +0 -4
  16. package/eslint.config.js +0 -11
  17. package/integration-tests/node_modules/.bin/tsc +0 -21
  18. package/integration-tests/node_modules/.bin/tsserver +0 -21
  19. package/integration-tests/node_modules/.bin/vitest +0 -21
  20. package/integration-tests/package.json +0 -29
  21. package/integration-tests/src/mastra/agents/weather.ts +0 -34
  22. package/integration-tests/src/mastra/index.ts +0 -15
  23. package/integration-tests/src/mastra/mcp/index.ts +0 -46
  24. package/integration-tests/src/mastra/tools/weather.ts +0 -13
  25. package/integration-tests/src/server.test.ts +0 -238
  26. package/integration-tests/tsconfig.json +0 -13
  27. package/integration-tests/vitest.config.ts +0 -14
  28. package/src/__fixtures__/fire-crawl-complex-schema.ts +0 -1013
  29. package/src/__fixtures__/server-weather.ts +0 -16
  30. package/src/__fixtures__/stock-price.ts +0 -128
  31. package/src/__fixtures__/tools.ts +0 -94
  32. package/src/__fixtures__/weather.ts +0 -269
  33. package/src/client/client.test.ts +0 -585
  34. package/src/client/client.ts +0 -628
  35. package/src/client/configuration.test.ts +0 -856
  36. package/src/client/configuration.ts +0 -468
  37. package/src/client/elicitationActions.ts +0 -26
  38. package/src/client/index.ts +0 -3
  39. package/src/client/promptActions.ts +0 -70
  40. package/src/client/resourceActions.ts +0 -119
  41. package/src/index.ts +0 -2
  42. package/src/server/index.ts +0 -2
  43. package/src/server/promptActions.ts +0 -48
  44. package/src/server/resourceActions.ts +0 -90
  45. package/src/server/server-logging.test.ts +0 -181
  46. package/src/server/server.test.ts +0 -2142
  47. package/src/server/server.ts +0 -1445
  48. package/src/server/types.ts +0 -59
  49. package/tsconfig.build.json +0 -9
  50. package/tsconfig.json +0 -5
  51. package/tsup.config.ts +0 -17
  52. package/vitest.config.ts +0 -8
@@ -1,238 +0,0 @@
1
- import { spawn } from 'node:child_process';
2
- import { MCPClient } from '@mastra/mcp';
3
- import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
4
- import { ServerInfo } from '@mastra/core/mcp';
5
- import path from 'node:path';
6
-
7
- vi.setConfig({ testTimeout: 20000, hookTimeout: 20000 });
8
-
9
- describe('MCPServer through Mastra HTTP Integration (Subprocess)', () => {
10
- let mastraServer: ReturnType<typeof spawn>;
11
- const port: number = 4114;
12
- const mcpServerId = 'myMcpServer';
13
- const testToolId = 'calculator';
14
- let client: MCPClient;
15
-
16
- beforeAll(async () => {
17
- mastraServer = spawn(
18
- 'pnpm',
19
- [
20
- path.resolve(import.meta.dirname, `..`, `..`, `..`, `cli`, `dist`, `index.js`),
21
- 'dev',
22
- '--port',
23
- port.toString(),
24
- ],
25
- {
26
- stdio: 'pipe',
27
- detached: true, // Run in a new process group so we can kill it and children
28
- },
29
- );
30
-
31
- // Wait for server to be ready
32
- await new Promise<void>((resolve, reject) => {
33
- let output = '';
34
- mastraServer.stdout?.on('data', data => {
35
- output += data.toString();
36
- console.log(output);
37
- if (output.includes('http://localhost:')) {
38
- resolve();
39
- }
40
- });
41
- mastraServer.stderr?.on('data', data => {
42
- console.error('Mastra server error:', data.toString());
43
- });
44
-
45
- setTimeout(() => reject(new Error('Mastra server failed to start')), 100000);
46
- });
47
-
48
- client = new MCPClient({
49
- servers: {
50
- [mcpServerId]: {
51
- url: new URL(`http://localhost:${port}/api/mcp/${mcpServerId}/mcp`),
52
- },
53
- },
54
- });
55
- });
56
-
57
- afterAll(() => {
58
- // Kill the server and its process group
59
- if (mastraServer?.pid) {
60
- try {
61
- process.kill(-mastraServer.pid, 'SIGTERM');
62
- } catch (e) {
63
- console.error('Failed to kill Mastra server:', e);
64
- }
65
- }
66
- });
67
-
68
- it('should allow an HTTP client to call a tool via Mastra MCP endpoint (Subprocess)', async () => {
69
- const toolCallPayload = {
70
- jsonrpc: '2.0',
71
- id: `test-${Date.now()}`,
72
- method: 'CallTool',
73
- params: {
74
- name: testToolId,
75
- args: { num1: 10, num2: 5, operation: 'add' },
76
- },
77
- };
78
-
79
- const tools = await client.getTools();
80
- console.log('Tools:', tools);
81
-
82
- const tool = tools['myMcpServer_calculator'];
83
- console.log('Tool:', tool);
84
-
85
- const result = await tool.execute({ context: toolCallPayload.params.args });
86
- console.log('Result:', result);
87
-
88
- expect(result).toBeDefined();
89
- expect(result.isError).toBe(false);
90
- expect(result.content).toBeInstanceOf(Array);
91
- expect(result.content.length).toBeGreaterThan(0);
92
-
93
- const toolOutput = result.content[0];
94
- expect(toolOutput.type).toBe('text');
95
-
96
- const expectedToolResult = 15;
97
- expect(JSON.parse(toolOutput.text)).toEqual(expectedToolResult);
98
- }, 25000);
99
-
100
- it('should allow a client to call a tool via Mastra MCP SSE endpoints (Subprocess)', async () => {
101
- const sseUrl = new URL(`http://localhost:${port}/api/mcp/${mcpServerId}/sse`);
102
-
103
- // Configure MCPClient for SSE transport
104
- const sseClient = new MCPClient({
105
- servers: {
106
- [mcpServerId]: {
107
- url: sseUrl, // URL for establishing SSE connection
108
- },
109
- },
110
- });
111
-
112
- const toolCallPayloadParams = { num1: 10, num2: 5, operation: 'add' };
113
-
114
- // Get tools (this will connect the client internally if not already connected)
115
- const tools = await sseClient.getTools();
116
-
117
- const toolName = `${mcpServerId}_${testToolId}`;
118
- const tool = tools[toolName];
119
- expect(tool, `Tool '${toolName}' should be available via SSE client`).toBeDefined();
120
-
121
- // Execute the tool
122
- const result = await tool.execute({ context: toolCallPayloadParams });
123
-
124
- expect(result).toBeDefined();
125
- expect(result.isError).toBe(false);
126
- expect(result.content).toBeInstanceOf(Array);
127
- expect(result.content.length).toBeGreaterThan(0);
128
-
129
- const toolOutput = result.content[0];
130
- expect(toolOutput.type).toBe('text');
131
-
132
- const expectedToolResult = 15; // 10 + 5
133
- expect(JSON.parse(toolOutput.text)).toEqual(expectedToolResult);
134
- }, 25000);
135
-
136
- // --- New tests for MCP Registry API Style Routes ---
137
- describe('MCP Registry API Style Endpoints', () => {
138
- const defaultMcpServerLogicalId = 'myMcpServer'; // Assuming this is the ID of the default server
139
-
140
- it('GET /api/mcp/v0/servers - should list available MCP servers', async () => {
141
- const response = await fetch(`http://localhost:${port}/api/mcp/v0/servers`);
142
- expect(response.status).toBe(200);
143
- expect(response.headers.get('content-type')).toContain('application/json');
144
- const body = await response.json();
145
-
146
- expect(body).toHaveProperty('servers');
147
- expect(body).toHaveProperty('total_count');
148
- expect(Array.isArray(body.servers)).toBe(true);
149
- expect(body.total_count).toBeGreaterThanOrEqual(1); // Expect at least the default server
150
-
151
- const defaultServerInfo: ServerInfo = body.servers.find((s: ServerInfo) => s.id === defaultMcpServerLogicalId);
152
- expect(defaultServerInfo).toBeDefined();
153
- expect(defaultServerInfo).toHaveProperty('name');
154
- expect(defaultServerInfo).toHaveProperty('version_detail');
155
- // Based on default mastra dev setup, if myMcpServer is the key, its id becomes 'myMcpServer'
156
- // And its name might be something like 'my-mcp-server' if not explicitly set in MCPServerConfig for it.
157
- // For this test, we assume the `id` is the key used in Mastra config.
158
- expect(defaultServerInfo.id).toBe(defaultMcpServerLogicalId);
159
- });
160
-
161
- it('GET /api/mcp/v0/servers/:id - should get specific server details', async () => {
162
- // First, get all servers to find the actual version of the default server
163
- const listResponse = await fetch(`http://localhost:${port}/api/mcp/v0/servers`);
164
- const listBody = await listResponse.json();
165
- const defaultServer = listBody.servers.find((s: any) => s.id === defaultMcpServerLogicalId);
166
- expect(defaultServer).toBeDefined();
167
- const actualVersion = defaultServer.version_detail.version;
168
-
169
- const response = await fetch(`http://localhost:${port}/api/mcp/v0/servers/${defaultMcpServerLogicalId}`);
170
- expect(response.status).toBe(200);
171
- const body = await response.json();
172
-
173
- expect(body.id).toBe(defaultMcpServerLogicalId);
174
- expect(body).toHaveProperty('name');
175
- expect(body).toHaveProperty('version_detail');
176
- expect(body.version_detail.version).toBe(actualVersion);
177
- // Add more assertions for package_canonical, packages, remotes if they are expected for the default server
178
- });
179
-
180
- it('GET /api/mcp/v0/servers/:id - should get specific server version if it matches', async () => {
181
- const listResponse = await fetch(`http://localhost:${port}/api/mcp/v0/servers`);
182
- const listBody = await listResponse.json();
183
- const defaultServer = listBody.servers.find((s: any) => s.id === defaultMcpServerLogicalId);
184
- expect(defaultServer).toBeDefined();
185
- const actualVersion = defaultServer.version_detail.version;
186
-
187
- const response = await fetch(
188
- `http://localhost:${port}/api/mcp/v0/servers/${defaultMcpServerLogicalId}?version=${actualVersion}`,
189
- );
190
- expect(response.status).toBe(200);
191
- const body = await response.json();
192
- expect(body.id).toBe(defaultMcpServerLogicalId);
193
- expect(body.version_detail.version).toBe(actualVersion);
194
- });
195
-
196
- it('GET /api/mcp/v0/servers/:id - should return 404 if specific server version does not match', async () => {
197
- const nonExistentVersion = '0.0.0-nonexistent';
198
- const response = await fetch(
199
- `http://localhost:${port}/api/mcp/v0/servers/${defaultMcpServerLogicalId}?version=${nonExistentVersion}`,
200
- );
201
- expect(response.status).toBe(404);
202
- const body = await response.json();
203
- expect(body).toHaveProperty('error');
204
- expect(body.error).toContain(`but not version '${nonExistentVersion}'`);
205
- });
206
-
207
- it('GET /api/mcp/v0/servers/:id - should return 404 for a non-existent server ID', async () => {
208
- const nonExistentId = 'non-existent-server-id-12345';
209
- const response = await fetch(`http://localhost:${port}/api/mcp/v0/servers/${nonExistentId}`);
210
- expect(response.status).toBe(404);
211
- const body = await response.json();
212
- expect(body).toHaveProperty('error');
213
- expect(body.error).toContain(`MCP server with ID '${nonExistentId}' not found`);
214
- });
215
-
216
- it('GET /api/mcp/v0/servers - should handle pagination (limit=1, offset=0)', async () => {
217
- const response = await fetch(`http://localhost:${port}/api/mcp/v0/servers?limit=1&offset=0`);
218
- expect(response.status).toBe(200);
219
- const body = await response.json();
220
- expect(body.servers.length).toBe(1);
221
- expect(body.total_count).toBeGreaterThanOrEqual(1);
222
- if (body.total_count > 1) {
223
- expect(body.next).not.toBeNull();
224
- } else {
225
- expect(body.next).toBeNull();
226
- }
227
- });
228
-
229
- it('Should be able to get lazy loaded tools', async () => {
230
- const agent = await fetch(`http://localhost:${port}/api/agents/test`);
231
- const agentJson = await agent.json();
232
- const tools = agentJson.tools;
233
-
234
- expect(tools).toHaveProperty('weather_fetchWeather');
235
- expect(Object.keys(tools).length).toBe(4);
236
- });
237
- });
238
- });
@@ -1,13 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2020",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "forceConsistentCasingInFileNames": true
10
- },
11
- "include": ["src/**/*"],
12
- "exclude": ["node_modules"]
13
- }
@@ -1,14 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- globals: true,
6
- environment: 'node',
7
- testTimeout: 60000,
8
- hookTimeout: 30000,
9
- coverage: {
10
- provider: 'v8',
11
- reporter: ['text', 'json', 'html'],
12
- },
13
- },
14
- });