@mastra/mcp 0.10.0 → 0.10.1
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 +332 -40
- package/dist/_tsup-dts-rollup.d.ts +332 -40
- package/dist/index.cjs +599 -45
- package/dist/index.d.cts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +604 -50
- package/package.json +4 -3
- package/src/__fixtures__/fire-crawl-complex-schema.ts +1 -1
- package/src/__fixtures__/server-weather.ts +1 -1
- package/src/__fixtures__/weather.ts +122 -190
- package/src/{client.test.ts → client/client.test.ts} +27 -0
- package/src/{client.ts → client/client.ts} +58 -5
- package/src/{configuration.test.ts → client/configuration.test.ts} +133 -21
- package/src/{configuration.ts → client/configuration.ts} +64 -48
- package/src/client/resourceActions.ts +121 -0
- package/src/index.ts +4 -4
- package/src/server/resourceActions.ts +62 -0
- package/src/{server-logging.test.ts → server/server-logging.test.ts} +9 -7
- package/src/server/server.test.ts +1126 -0
- package/src/{server.ts → server/server.ts} +444 -16
- package/src/server.test.ts +0 -467
package/src/server.test.ts
DELETED
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
import http from 'node:http';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import type { ServerType } from '@hono/node-server';
|
|
4
|
-
import { serve } from '@hono/node-server';
|
|
5
|
-
import type { ToolsInput } from '@mastra/core/agent';
|
|
6
|
-
import type { MCPServerConfig, Repository, PackageInfo, RemoteInfo } from '@mastra/core/mcp';
|
|
7
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
-
import { Hono } from 'hono';
|
|
9
|
-
import { describe, it, expect, beforeAll, afterAll, afterEach, vi, beforeEach } from 'vitest';
|
|
10
|
-
import { z } from 'zod';
|
|
11
|
-
import { weatherTool } from './__fixtures__/tools';
|
|
12
|
-
import { MCPClient } from './configuration';
|
|
13
|
-
import { MCPServer } from './server';
|
|
14
|
-
|
|
15
|
-
const PORT = 9100 + Math.floor(Math.random() * 1000);
|
|
16
|
-
let server: MCPServer;
|
|
17
|
-
let httpServer: http.Server;
|
|
18
|
-
|
|
19
|
-
vi.setConfig({ testTimeout: 20000, hookTimeout: 20000 });
|
|
20
|
-
|
|
21
|
-
// Mock Date constructor for predictable release dates
|
|
22
|
-
const mockDateISO = '2024-01-01T00:00:00.000Z';
|
|
23
|
-
const mockDate = new Date(mockDateISO);
|
|
24
|
-
const OriginalDate = global.Date; // Store original Date
|
|
25
|
-
|
|
26
|
-
// Mock a simple tool
|
|
27
|
-
const mockToolExecute = vi.fn(async (args: any) => ({ result: 'tool executed', args }));
|
|
28
|
-
const mockTools: ToolsInput = {
|
|
29
|
-
testTool: {
|
|
30
|
-
description: 'A test tool',
|
|
31
|
-
parameters: z.object({ input: z.string().optional() }),
|
|
32
|
-
execute: mockToolExecute,
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
const minimalConfig: MCPServerConfig = {
|
|
37
|
-
name: 'TestServer',
|
|
38
|
-
version: '1.0.0',
|
|
39
|
-
tools: mockTools,
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
describe('MCPServer', () => {
|
|
43
|
-
beforeEach(() => {
|
|
44
|
-
vi.clearAllMocks();
|
|
45
|
-
|
|
46
|
-
// @ts-ignore - Mocking Date completely
|
|
47
|
-
global.Date = vi.fn((...args: any[]) => {
|
|
48
|
-
if (args.length === 0) {
|
|
49
|
-
// new Date()
|
|
50
|
-
return mockDate;
|
|
51
|
-
}
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
return new OriginalDate(...args); // new Date('some-string') or new Date(timestamp)
|
|
54
|
-
}) as any;
|
|
55
|
-
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
global.Date.now = vi.fn(() => mockDate.getTime());
|
|
58
|
-
// @ts-ignore
|
|
59
|
-
global.Date.prototype.toISOString = vi.fn(() => mockDateISO);
|
|
60
|
-
// @ts-ignore // Static Date.toISOString() might be used by some libraries
|
|
61
|
-
global.Date.toISOString = vi.fn(() => mockDateISO);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe('Constructor and Metadata Initialization', () => {
|
|
65
|
-
it('should initialize with default metadata if not provided', () => {
|
|
66
|
-
const server = new MCPServer(minimalConfig);
|
|
67
|
-
expect(server.id).toBeDefined();
|
|
68
|
-
expect(server.name).toBe('TestServer');
|
|
69
|
-
expect(server.version).toBe('1.0.0');
|
|
70
|
-
expect(server.description).toBeUndefined();
|
|
71
|
-
expect(server.repository).toBeUndefined();
|
|
72
|
-
// MCPServerBase stores releaseDate as string, compare directly or re-parse
|
|
73
|
-
expect(server.releaseDate).toBe(mockDateISO);
|
|
74
|
-
expect(server.isLatest).toBe(true);
|
|
75
|
-
expect(server.packageCanonical).toBeUndefined();
|
|
76
|
-
expect(server.packages).toBeUndefined();
|
|
77
|
-
expect(server.remotes).toBeUndefined();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should initialize with custom metadata when provided', () => {
|
|
81
|
-
const repository: Repository = { url: 'https://github.com/test/repo', source: 'github', id: 'repo-id' };
|
|
82
|
-
const packages: PackageInfo[] = [{ registry_name: 'npm', name: 'test-package', version: '1.0.0' }];
|
|
83
|
-
const remotes: RemoteInfo[] = [{ transport_type: 'sse', url: 'https://test.com/sse' }];
|
|
84
|
-
const customReleaseDate = '2023-12-31T00:00:00.000Z';
|
|
85
|
-
const customConfig: MCPServerConfig = {
|
|
86
|
-
...minimalConfig,
|
|
87
|
-
id: 'custom-id-doesnt-need-uuid-format-if-set-explicitly',
|
|
88
|
-
description: 'A custom server description',
|
|
89
|
-
repository,
|
|
90
|
-
releaseDate: customReleaseDate,
|
|
91
|
-
isLatest: false,
|
|
92
|
-
packageCanonical: 'npm',
|
|
93
|
-
packages,
|
|
94
|
-
remotes,
|
|
95
|
-
};
|
|
96
|
-
const server = new MCPServer(customConfig);
|
|
97
|
-
|
|
98
|
-
expect(server.id).toBe('custom-id-doesnt-need-uuid-format-if-set-explicitly');
|
|
99
|
-
expect(server.description).toBe('A custom server description');
|
|
100
|
-
expect(server.repository).toEqual(repository);
|
|
101
|
-
expect(server.releaseDate).toBe(customReleaseDate);
|
|
102
|
-
expect(server.isLatest).toBe(false);
|
|
103
|
-
expect(server.packageCanonical).toBe('npm');
|
|
104
|
-
expect(server.packages).toEqual(packages);
|
|
105
|
-
expect(server.remotes).toEqual(remotes);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe('getServerInfo()', () => {
|
|
110
|
-
it('should return correct ServerInfo with default metadata', () => {
|
|
111
|
-
const server = new MCPServer(minimalConfig);
|
|
112
|
-
const serverInfo = server.getServerInfo();
|
|
113
|
-
|
|
114
|
-
expect(serverInfo).toEqual({
|
|
115
|
-
id: expect.any(String),
|
|
116
|
-
name: 'TestServer',
|
|
117
|
-
description: undefined,
|
|
118
|
-
repository: undefined,
|
|
119
|
-
version_detail: {
|
|
120
|
-
version: '1.0.0',
|
|
121
|
-
release_date: mockDateISO,
|
|
122
|
-
is_latest: true,
|
|
123
|
-
},
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should return correct ServerInfo with custom metadata', () => {
|
|
128
|
-
const repository: Repository = { url: 'https://github.com/test/repo', source: 'github', id: 'repo-id' };
|
|
129
|
-
const customReleaseDate = '2023-11-01T00:00:00.000Z';
|
|
130
|
-
const customConfig: MCPServerConfig = {
|
|
131
|
-
...minimalConfig,
|
|
132
|
-
id: 'custom-id-for-info',
|
|
133
|
-
description: 'Custom description',
|
|
134
|
-
repository,
|
|
135
|
-
releaseDate: customReleaseDate,
|
|
136
|
-
isLatest: false,
|
|
137
|
-
};
|
|
138
|
-
const server = new MCPServer(customConfig);
|
|
139
|
-
const serverInfo = server.getServerInfo();
|
|
140
|
-
|
|
141
|
-
expect(serverInfo).toEqual({
|
|
142
|
-
id: 'custom-id-for-info',
|
|
143
|
-
name: 'TestServer',
|
|
144
|
-
description: 'Custom description',
|
|
145
|
-
repository,
|
|
146
|
-
version_detail: {
|
|
147
|
-
version: '1.0.0',
|
|
148
|
-
release_date: customReleaseDate,
|
|
149
|
-
is_latest: false,
|
|
150
|
-
},
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
describe('getServerDetail()', () => {
|
|
156
|
-
it('should return correct ServerDetailInfo with default metadata', () => {
|
|
157
|
-
const server = new MCPServer(minimalConfig);
|
|
158
|
-
const serverDetail = server.getServerDetail();
|
|
159
|
-
|
|
160
|
-
expect(serverDetail).toEqual({
|
|
161
|
-
id: expect.any(String),
|
|
162
|
-
name: 'TestServer',
|
|
163
|
-
description: undefined,
|
|
164
|
-
repository: undefined,
|
|
165
|
-
version_detail: {
|
|
166
|
-
version: '1.0.0',
|
|
167
|
-
release_date: mockDateISO,
|
|
168
|
-
is_latest: true,
|
|
169
|
-
},
|
|
170
|
-
package_canonical: undefined,
|
|
171
|
-
packages: undefined,
|
|
172
|
-
remotes: undefined,
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should return correct ServerDetailInfo with custom metadata', () => {
|
|
177
|
-
const repository: Repository = { url: 'https://github.com/test/repo', source: 'github', id: 'repo-id' };
|
|
178
|
-
const packages: PackageInfo[] = [{ registry_name: 'npm', name: 'test-package', version: '1.0.0' }];
|
|
179
|
-
const remotes: RemoteInfo[] = [{ transport_type: 'sse', url: 'https://test.com/sse' }];
|
|
180
|
-
const customReleaseDate = '2023-10-01T00:00:00.000Z';
|
|
181
|
-
const customConfig: MCPServerConfig = {
|
|
182
|
-
...minimalConfig,
|
|
183
|
-
id: 'custom-id-for-detail',
|
|
184
|
-
description: 'Custom detail description',
|
|
185
|
-
repository,
|
|
186
|
-
releaseDate: customReleaseDate,
|
|
187
|
-
isLatest: true,
|
|
188
|
-
packageCanonical: 'docker',
|
|
189
|
-
packages,
|
|
190
|
-
remotes,
|
|
191
|
-
};
|
|
192
|
-
const server = new MCPServer(customConfig);
|
|
193
|
-
const serverDetail = server.getServerDetail();
|
|
194
|
-
|
|
195
|
-
expect(serverDetail).toEqual({
|
|
196
|
-
id: 'custom-id-for-detail',
|
|
197
|
-
name: 'TestServer',
|
|
198
|
-
description: 'Custom detail description',
|
|
199
|
-
repository,
|
|
200
|
-
version_detail: {
|
|
201
|
-
version: '1.0.0',
|
|
202
|
-
release_date: customReleaseDate,
|
|
203
|
-
is_latest: true,
|
|
204
|
-
},
|
|
205
|
-
package_canonical: 'docker',
|
|
206
|
-
packages,
|
|
207
|
-
remotes,
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
describe('MCPServer SSE transport', () => {
|
|
213
|
-
let sseRes: Response | undefined;
|
|
214
|
-
let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
|
|
215
|
-
|
|
216
|
-
beforeAll(async () => {
|
|
217
|
-
server = new MCPServer({
|
|
218
|
-
name: 'Test MCP Server',
|
|
219
|
-
version: '0.1.0',
|
|
220
|
-
tools: { weatherTool },
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
httpServer = http.createServer(async (req, res) => {
|
|
224
|
-
const url = new URL(req.url || '', `http://localhost:${PORT}`);
|
|
225
|
-
await server.startSSE({
|
|
226
|
-
url,
|
|
227
|
-
ssePath: '/sse',
|
|
228
|
-
messagePath: '/message',
|
|
229
|
-
req,
|
|
230
|
-
res,
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
await new Promise<void>(resolve => httpServer.listen(PORT, () => resolve()));
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
afterAll(async () => {
|
|
238
|
-
await new Promise<void>(resolve => httpServer.close(() => resolve()));
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
afterEach(async () => {
|
|
242
|
-
if (reader) {
|
|
243
|
-
try {
|
|
244
|
-
await reader.cancel();
|
|
245
|
-
} catch {}
|
|
246
|
-
reader = undefined;
|
|
247
|
-
}
|
|
248
|
-
if (sseRes && 'body' in sseRes && sseRes.body) {
|
|
249
|
-
try {
|
|
250
|
-
await sseRes.body.cancel();
|
|
251
|
-
} catch {}
|
|
252
|
-
sseRes = undefined;
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('should parse SSE stream and contain tool output', async () => {
|
|
257
|
-
sseRes = await fetch(`http://localhost:${PORT}/sse`, {
|
|
258
|
-
headers: { Accept: 'text/event-stream' },
|
|
259
|
-
});
|
|
260
|
-
expect(sseRes.status).toBe(200);
|
|
261
|
-
reader = sseRes.body?.getReader();
|
|
262
|
-
expect(reader).toBeDefined();
|
|
263
|
-
await fetch(`http://localhost:${PORT}/message`, {
|
|
264
|
-
method: 'POST',
|
|
265
|
-
headers: { 'Content-Type': 'application/json' },
|
|
266
|
-
body: JSON.stringify({ tool: 'weatherTool', input: { location: 'Austin' } }),
|
|
267
|
-
});
|
|
268
|
-
if (reader) {
|
|
269
|
-
const { value } = await reader.read();
|
|
270
|
-
const text = value ? new TextDecoder().decode(value) : '';
|
|
271
|
-
expect(text).toMatch(/data:/);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('should return 503 if message sent before SSE connection', async () => {
|
|
276
|
-
(server as any).sseTransport = undefined;
|
|
277
|
-
const res = await fetch(`http://localhost:${PORT}/message`, {
|
|
278
|
-
method: 'POST',
|
|
279
|
-
headers: { 'Content-Type': 'application/json' },
|
|
280
|
-
body: JSON.stringify({ tool: 'weatherTool', input: { location: 'Austin' } }),
|
|
281
|
-
});
|
|
282
|
-
expect(res.status).toBe(503);
|
|
283
|
-
});
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
describe('MCPServer stdio transport', () => {
|
|
287
|
-
it('should connect and expose stdio transport', async () => {
|
|
288
|
-
await server.startStdio();
|
|
289
|
-
expect(server.getStdioTransport()).toBeInstanceOf(StdioServerTransport);
|
|
290
|
-
});
|
|
291
|
-
it('should use stdio transport to get tools', async () => {
|
|
292
|
-
const existingConfig = new MCPClient({
|
|
293
|
-
servers: {
|
|
294
|
-
weather: {
|
|
295
|
-
command: 'npx',
|
|
296
|
-
args: ['-y', 'tsx', path.join(__dirname, '__fixtures__/server-weather.ts')],
|
|
297
|
-
env: {
|
|
298
|
-
FAKE_CREDS: 'test',
|
|
299
|
-
},
|
|
300
|
-
},
|
|
301
|
-
},
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
const tools = await existingConfig.getTools();
|
|
305
|
-
expect(Object.keys(tools).length).toBeGreaterThan(0);
|
|
306
|
-
expect(Object.keys(tools)[0]).toBe('weather_weatherTool');
|
|
307
|
-
await existingConfig.disconnect();
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
describe('MCPServer HTTP Transport', () => {
|
|
311
|
-
let server: MCPServer;
|
|
312
|
-
let client: MCPClient;
|
|
313
|
-
const PORT = 9200 + Math.floor(Math.random() * 1000);
|
|
314
|
-
|
|
315
|
-
beforeAll(async () => {
|
|
316
|
-
server = new MCPServer({
|
|
317
|
-
name: 'Test MCP Server',
|
|
318
|
-
version: '0.1.0',
|
|
319
|
-
tools: { weatherTool },
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
httpServer = http.createServer(async (req: http.IncomingMessage, res: http.ServerResponse) => {
|
|
323
|
-
const url = new URL(req.url || '', `http://localhost:${PORT}`);
|
|
324
|
-
await server.startHTTP({
|
|
325
|
-
url,
|
|
326
|
-
httpPath: '/http',
|
|
327
|
-
req,
|
|
328
|
-
res,
|
|
329
|
-
options: {
|
|
330
|
-
sessionIdGenerator: undefined,
|
|
331
|
-
enableJsonResponse: true,
|
|
332
|
-
},
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
await new Promise<void>(resolve => httpServer.listen(PORT, () => resolve()));
|
|
337
|
-
|
|
338
|
-
client = new MCPClient({
|
|
339
|
-
servers: {
|
|
340
|
-
local: {
|
|
341
|
-
url: new URL(`http://localhost:${PORT}/http`),
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
});
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
afterAll(async () => {
|
|
348
|
-
httpServer.closeAllConnections?.();
|
|
349
|
-
await new Promise<void>(resolve =>
|
|
350
|
-
httpServer.close(() => {
|
|
351
|
-
resolve();
|
|
352
|
-
}),
|
|
353
|
-
);
|
|
354
|
-
await server.close();
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
it('should return 404 for wrong path', async () => {
|
|
358
|
-
const res = await fetch(`http://localhost:${PORT}/wrong`);
|
|
359
|
-
expect(res.status).toBe(404);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it('should respond to HTTP request using client', async () => {
|
|
363
|
-
const tools = await client.getTools();
|
|
364
|
-
const tool = tools['local_weatherTool'];
|
|
365
|
-
expect(tool).toBeDefined();
|
|
366
|
-
|
|
367
|
-
// Call the tool
|
|
368
|
-
const result = await tool.execute({ context: { location: 'Austin' } });
|
|
369
|
-
|
|
370
|
-
// Check the result
|
|
371
|
-
expect(result).toBeDefined();
|
|
372
|
-
expect(result.content).toBeInstanceOf(Array);
|
|
373
|
-
expect(result.content.length).toBeGreaterThan(0);
|
|
374
|
-
|
|
375
|
-
const toolOutput = result.content[0];
|
|
376
|
-
expect(toolOutput.type).toBe('text');
|
|
377
|
-
const toolResult = JSON.parse(toolOutput.text);
|
|
378
|
-
expect(toolResult.location).toEqual('Austin');
|
|
379
|
-
expect(toolResult).toHaveProperty('temperature');
|
|
380
|
-
expect(toolResult).toHaveProperty('feelsLike');
|
|
381
|
-
expect(toolResult).toHaveProperty('humidity');
|
|
382
|
-
expect(toolResult).toHaveProperty('conditions');
|
|
383
|
-
expect(toolResult).toHaveProperty('windSpeed');
|
|
384
|
-
expect(toolResult).toHaveProperty('windGust');
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
describe('MCPServer Hono SSE Transport', () => {
|
|
389
|
-
let server: MCPServer;
|
|
390
|
-
let hono: Hono;
|
|
391
|
-
let honoServer: ServerType;
|
|
392
|
-
let client: MCPClient;
|
|
393
|
-
const PORT = 9300 + Math.floor(Math.random() * 1000);
|
|
394
|
-
|
|
395
|
-
beforeAll(async () => {
|
|
396
|
-
server = new MCPServer({
|
|
397
|
-
name: 'Test MCP Server',
|
|
398
|
-
version: '0.1.0',
|
|
399
|
-
tools: { weatherTool },
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
hono = new Hono();
|
|
403
|
-
|
|
404
|
-
hono.get('/sse', async c => {
|
|
405
|
-
const url = new URL(c.req.url, `http://localhost:${PORT}`);
|
|
406
|
-
return await server.startHonoSSE({
|
|
407
|
-
url,
|
|
408
|
-
ssePath: '/sse',
|
|
409
|
-
messagePath: '/message',
|
|
410
|
-
context: c,
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
hono.post('/message', async c => {
|
|
415
|
-
// Use MCPServer's startHonoSSE to handle message endpoint
|
|
416
|
-
const url = new URL(c.req.url, `http://localhost:${PORT}`);
|
|
417
|
-
return await server.startHonoSSE({
|
|
418
|
-
url,
|
|
419
|
-
ssePath: '/sse',
|
|
420
|
-
messagePath: '/message',
|
|
421
|
-
context: c,
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
honoServer = serve({ fetch: hono.fetch, port: PORT });
|
|
426
|
-
|
|
427
|
-
// Initialize MCPClient with SSE endpoint
|
|
428
|
-
client = new MCPClient({
|
|
429
|
-
servers: {
|
|
430
|
-
local: {
|
|
431
|
-
url: new URL(`http://localhost:${PORT}/sse`),
|
|
432
|
-
},
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
afterAll(async () => {
|
|
438
|
-
honoServer.close();
|
|
439
|
-
await server.close();
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
it('should respond to SSE connection and tool call', async () => {
|
|
443
|
-
// Get tools from the client
|
|
444
|
-
const tools = await client.getTools();
|
|
445
|
-
const tool = tools['local_weatherTool'];
|
|
446
|
-
expect(tool).toBeDefined();
|
|
447
|
-
|
|
448
|
-
// Call the tool using the MCPClient (SSE transport)
|
|
449
|
-
const result = await tool.execute({ context: { location: 'Austin' } });
|
|
450
|
-
|
|
451
|
-
expect(result).toBeDefined();
|
|
452
|
-
expect(result.content).toBeInstanceOf(Array);
|
|
453
|
-
expect(result.content.length).toBeGreaterThan(0);
|
|
454
|
-
|
|
455
|
-
const toolOutput = result.content[0];
|
|
456
|
-
expect(toolOutput.type).toBe('text');
|
|
457
|
-
const toolResult = JSON.parse(toolOutput.text);
|
|
458
|
-
expect(toolResult.location).toEqual('Austin');
|
|
459
|
-
expect(toolResult).toHaveProperty('temperature');
|
|
460
|
-
expect(toolResult).toHaveProperty('feelsLike');
|
|
461
|
-
expect(toolResult).toHaveProperty('humidity');
|
|
462
|
-
expect(toolResult).toHaveProperty('conditions');
|
|
463
|
-
expect(toolResult).toHaveProperty('windSpeed');
|
|
464
|
-
expect(toolResult).toHaveProperty('windGust');
|
|
465
|
-
});
|
|
466
|
-
});
|
|
467
|
-
});
|