@mastra/mcp 0.11.3-alpha.0 → 0.11.3-alpha.2

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 (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/index.cjs +7 -4
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.js +7 -4
  5. package/dist/index.js.map +1 -1
  6. package/dist/server/server.d.ts.map +1 -1
  7. package/package.json +19 -6
  8. package/.turbo/turbo-build.log +0 -4
  9. package/eslint.config.js +0 -11
  10. package/integration-tests/node_modules/.bin/tsc +0 -21
  11. package/integration-tests/node_modules/.bin/tsserver +0 -21
  12. package/integration-tests/node_modules/.bin/vitest +0 -21
  13. package/integration-tests/package.json +0 -29
  14. package/integration-tests/src/mastra/agents/weather.ts +0 -34
  15. package/integration-tests/src/mastra/index.ts +0 -15
  16. package/integration-tests/src/mastra/mcp/index.ts +0 -46
  17. package/integration-tests/src/mastra/tools/weather.ts +0 -13
  18. package/integration-tests/src/server.test.ts +0 -238
  19. package/integration-tests/tsconfig.json +0 -13
  20. package/integration-tests/vitest.config.ts +0 -14
  21. package/src/__fixtures__/fire-crawl-complex-schema.ts +0 -1013
  22. package/src/__fixtures__/server-weather.ts +0 -16
  23. package/src/__fixtures__/stock-price.ts +0 -128
  24. package/src/__fixtures__/tools.ts +0 -94
  25. package/src/__fixtures__/weather.ts +0 -269
  26. package/src/client/client.test.ts +0 -585
  27. package/src/client/client.ts +0 -628
  28. package/src/client/configuration.test.ts +0 -856
  29. package/src/client/configuration.ts +0 -468
  30. package/src/client/elicitationActions.ts +0 -26
  31. package/src/client/index.ts +0 -3
  32. package/src/client/promptActions.ts +0 -70
  33. package/src/client/resourceActions.ts +0 -119
  34. package/src/index.ts +0 -2
  35. package/src/server/index.ts +0 -2
  36. package/src/server/promptActions.ts +0 -48
  37. package/src/server/resourceActions.ts +0 -90
  38. package/src/server/server-logging.test.ts +0 -181
  39. package/src/server/server.test.ts +0 -2142
  40. package/src/server/server.ts +0 -1442
  41. package/src/server/types.ts +0 -59
  42. package/tsconfig.build.json +0 -9
  43. package/tsconfig.json +0 -5
  44. package/tsup.config.ts +0 -17
  45. package/vitest.config.ts +0 -8
@@ -1,628 +0,0 @@
1
- import $RefParser from '@apidevtools/json-schema-ref-parser';
2
- import { MastraBase } from '@mastra/core/base';
3
- import type { RuntimeContext } from '@mastra/core/di';
4
- import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';
5
- import { createTool } from '@mastra/core/tools';
6
- import { isZodType } from '@mastra/core/utils';
7
- import { Client } from '@modelcontextprotocol/sdk/client/index.js';
8
- import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
9
- import type { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';
10
- import { getDefaultEnvironment, StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
11
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
12
- import type { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
13
- import { DEFAULT_REQUEST_TIMEOUT_MSEC } from '@modelcontextprotocol/sdk/shared/protocol.js';
14
- import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
15
- import type {
16
- ClientCapabilities,
17
- ElicitRequest,
18
- ElicitResult,
19
- GetPromptResult,
20
- ListPromptsResult,
21
- LoggingLevel,
22
- } from '@modelcontextprotocol/sdk/types.js';
23
- import {
24
- CallToolResultSchema,
25
- ListResourcesResultSchema,
26
- ReadResourceResultSchema,
27
- ResourceListChangedNotificationSchema,
28
- ResourceUpdatedNotificationSchema,
29
- ListResourceTemplatesResultSchema,
30
- ListPromptsResultSchema,
31
- GetPromptResultSchema,
32
- PromptListChangedNotificationSchema,
33
- ElicitRequestSchema,
34
- } from '@modelcontextprotocol/sdk/types.js';
35
-
36
- import { asyncExitHook, gracefulExit } from 'exit-hook';
37
- import { z } from 'zod';
38
- import { convertJsonSchemaToZod } from 'zod-from-json-schema';
39
- import { convertJsonSchemaToZod as convertJsonSchemaToZodV3 } from 'zod-from-json-schema-v3';
40
- import type { JSONSchema } from 'zod-from-json-schema-v3';
41
- import { ElicitationClientActions } from './elicitationActions';
42
- import { PromptClientActions } from './promptActions';
43
- import { ResourceClientActions } from './resourceActions';
44
-
45
- // Re-export MCP SDK LoggingLevel for convenience
46
- export type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
47
-
48
- export interface LogMessage {
49
- level: LoggingLevel;
50
- message: string;
51
- timestamp: Date;
52
- serverName: string;
53
- details?: Record<string, any>;
54
- runtimeContext?: RuntimeContext | null;
55
- }
56
-
57
- export type LogHandler = (logMessage: LogMessage) => void;
58
-
59
- // Elicitation handler type
60
- export type ElicitationHandler = (request: ElicitRequest['params']) => Promise<ElicitResult>;
61
-
62
- // Base options common to all server definitions
63
- type BaseServerOptions = {
64
- logger?: LogHandler;
65
- timeout?: number;
66
- capabilities?: ClientCapabilities;
67
- enableServerLogs?: boolean;
68
- };
69
-
70
- type StdioServerDefinition = BaseServerOptions & {
71
- command: string; // 'command' is required for Stdio
72
- args?: string[];
73
- env?: Record<string, string>;
74
-
75
- url?: never; // Exclude 'url' for Stdio
76
- requestInit?: never; // Exclude HTTP options for Stdio
77
- eventSourceInit?: never; // Exclude HTTP options for Stdio
78
- authProvider?: never; // Exclude HTTP options for Stdio
79
- reconnectionOptions?: never; // Exclude Streamable HTTP specific options
80
- sessionId?: never; // Exclude Streamable HTTP specific options
81
- };
82
-
83
- // HTTP Server Definition (Streamable HTTP or SSE fallback)
84
- type HttpServerDefinition = BaseServerOptions & {
85
- url: URL; // 'url' is required for HTTP
86
-
87
- command?: never; // Exclude 'command' for HTTP
88
- args?: never; // Exclude Stdio options for HTTP
89
- env?: never; // Exclude Stdio options for HTTP
90
-
91
- // Include relevant options from SDK HTTP transport types
92
- requestInit?: StreamableHTTPClientTransportOptions['requestInit'];
93
- eventSourceInit?: SSEClientTransportOptions['eventSourceInit'];
94
- authProvider?: StreamableHTTPClientTransportOptions['authProvider'];
95
- reconnectionOptions?: StreamableHTTPClientTransportOptions['reconnectionOptions'];
96
- sessionId?: StreamableHTTPClientTransportOptions['sessionId'];
97
- };
98
-
99
- export type MastraMCPServerDefinition = StdioServerDefinition | HttpServerDefinition;
100
-
101
- /**
102
- * Convert an MCP LoggingLevel to a logger method name that exists in our logger
103
- */
104
- function convertLogLevelToLoggerMethod(level: LoggingLevel): 'debug' | 'info' | 'warn' | 'error' {
105
- switch (level) {
106
- case 'debug':
107
- return 'debug';
108
- case 'info':
109
- case 'notice':
110
- return 'info';
111
- case 'warning':
112
- return 'warn';
113
- case 'error':
114
- case 'critical':
115
- case 'alert':
116
- case 'emergency':
117
- return 'error';
118
- default:
119
- // For any other levels, default to info
120
- return 'info';
121
- }
122
- }
123
-
124
- export type InternalMastraMCPClientOptions = {
125
- name: string;
126
- server: MastraMCPServerDefinition;
127
- capabilities?: ClientCapabilities;
128
- version?: string;
129
- timeout?: number;
130
- };
131
-
132
- export class InternalMastraMCPClient extends MastraBase {
133
- name: string;
134
- private client: Client;
135
- private readonly timeout: number;
136
- private logHandler?: LogHandler;
137
- private enableServerLogs?: boolean;
138
- private serverConfig: MastraMCPServerDefinition;
139
- private transport?: Transport;
140
- private currentOperationContext: RuntimeContext | null = null;
141
- public readonly resources: ResourceClientActions;
142
- public readonly prompts: PromptClientActions;
143
- public readonly elicitation: ElicitationClientActions;
144
- constructor({
145
- name,
146
- version = '1.0.0',
147
- server,
148
- capabilities = {},
149
- timeout = DEFAULT_REQUEST_TIMEOUT_MSEC,
150
- }: InternalMastraMCPClientOptions) {
151
- super({ name: 'MastraMCPClient' });
152
- this.name = name;
153
- this.timeout = timeout;
154
- this.logHandler = server.logger;
155
- this.enableServerLogs = server.enableServerLogs ?? true;
156
- this.serverConfig = server;
157
-
158
- const clientCapabilities = { ...capabilities, elicitation: {} };
159
-
160
- this.client = new Client(
161
- {
162
- name,
163
- version,
164
- },
165
- {
166
- capabilities: clientCapabilities,
167
- },
168
- );
169
-
170
- // Set up log message capturing
171
- this.setupLogging();
172
-
173
- this.resources = new ResourceClientActions({ client: this, logger: this.logger });
174
- this.prompts = new PromptClientActions({ client: this, logger: this.logger });
175
- this.elicitation = new ElicitationClientActions({ client: this, logger: this.logger });
176
- }
177
-
178
- /**
179
- * Log a message at the specified level
180
- * @param level Log level
181
- * @param message Log message
182
- * @param details Optional additional details
183
- */
184
- private log(level: LoggingLevel, message: string, details?: Record<string, any>): void {
185
- // Convert MCP logging level to our logger method
186
- const loggerMethod = convertLogLevelToLoggerMethod(level);
187
-
188
- const msg = `[${this.name}] ${message}`;
189
-
190
- // Log to internal logger
191
- this.logger[loggerMethod](msg, details);
192
-
193
- // Send to registered handler if available
194
- if (this.logHandler) {
195
- this.logHandler({
196
- level,
197
- message: msg,
198
- timestamp: new Date(),
199
- serverName: this.name,
200
- details,
201
- runtimeContext: this.currentOperationContext,
202
- });
203
- }
204
- }
205
-
206
- private setupLogging(): void {
207
- if (this.enableServerLogs) {
208
- this.client.setNotificationHandler(
209
- z.object({
210
- method: z.literal('notifications/message'),
211
- params: z
212
- .object({
213
- level: z.string(),
214
- })
215
- .passthrough(),
216
- }),
217
- notification => {
218
- const { level, ...params } = notification.params;
219
- this.log(level as LoggingLevel, '[MCP SERVER LOG]', params);
220
- },
221
- );
222
- }
223
- }
224
-
225
- private async connectStdio(command: string) {
226
- this.log('debug', `Using Stdio transport for command: ${command}`);
227
- try {
228
- this.transport = new StdioClientTransport({
229
- command,
230
- args: this.serverConfig.args,
231
- env: { ...getDefaultEnvironment(), ...(this.serverConfig.env || {}) },
232
- });
233
- await this.client.connect(this.transport, { timeout: this.serverConfig.timeout ?? this.timeout });
234
- this.log('debug', `Successfully connected to MCP server via Stdio`);
235
- } catch (e) {
236
- this.log('error', e instanceof Error ? e.stack || e.message : JSON.stringify(e));
237
- throw e;
238
- }
239
- }
240
-
241
- private async connectHttp(url: URL) {
242
- const { requestInit, eventSourceInit, authProvider } = this.serverConfig;
243
-
244
- this.log('debug', `Attempting to connect to URL: ${url}`);
245
-
246
- // Assume /sse means sse.
247
- let shouldTrySSE = url.pathname.endsWith(`/sse`);
248
-
249
- if (!shouldTrySSE) {
250
- try {
251
- // Try Streamable HTTP transport first
252
- this.log('debug', 'Trying Streamable HTTP transport...');
253
- const streamableTransport = new StreamableHTTPClientTransport(url, {
254
- requestInit,
255
- reconnectionOptions: this.serverConfig.reconnectionOptions,
256
- authProvider: authProvider,
257
- });
258
- await this.client.connect(streamableTransport, {
259
- timeout:
260
- // this is hardcoded to 3s because the long default timeout would be extremely slow for sse backwards compat (60s)
261
- 3000,
262
- });
263
- this.transport = streamableTransport;
264
- this.log('debug', 'Successfully connected using Streamable HTTP transport.');
265
- } catch (error) {
266
- this.log('debug', `Streamable HTTP transport failed: ${error}`);
267
- shouldTrySSE = true;
268
- }
269
- }
270
-
271
- if (shouldTrySSE) {
272
- this.log('debug', 'Falling back to deprecated HTTP+SSE transport...');
273
- try {
274
- // Fallback to SSE transport
275
- const sseTransport = new SSEClientTransport(url, { requestInit, eventSourceInit, authProvider });
276
- await this.client.connect(sseTransport, { timeout: this.serverConfig.timeout ?? this.timeout });
277
- this.transport = sseTransport;
278
- this.log('debug', 'Successfully connected using deprecated HTTP+SSE transport.');
279
- } catch (sseError) {
280
- this.log(
281
- 'error',
282
- `Failed to connect with SSE transport after failing to connect to Streamable HTTP transport first. SSE error: ${sseError}`,
283
- );
284
- throw new Error('Could not connect to server with any available HTTP transport');
285
- }
286
- }
287
- }
288
-
289
- private isConnected: Promise<boolean> | null = null;
290
-
291
- async connect() {
292
- // If a connection attempt is in progress, wait for it.
293
- if (await this.isConnected) {
294
- return true;
295
- }
296
-
297
- // Start new connection attempt.
298
- this.isConnected = new Promise<boolean>(async (resolve, reject) => {
299
- try {
300
- const { command, url } = this.serverConfig;
301
-
302
- if (command) {
303
- await this.connectStdio(command);
304
- } else if (url) {
305
- await this.connectHttp(url);
306
- } else {
307
- throw new Error('Server configuration must include either a command or a url.');
308
- }
309
-
310
- resolve(true);
311
-
312
- // Set up disconnect handler to reset state.
313
- const originalOnClose = this.client.onclose;
314
- this.client.onclose = () => {
315
- this.log('debug', `MCP server connection closed`);
316
- this.isConnected = null;
317
- if (typeof originalOnClose === 'function') {
318
- originalOnClose();
319
- }
320
- };
321
- } catch (e) {
322
- this.isConnected = null;
323
- reject(e);
324
- }
325
- });
326
-
327
- asyncExitHook(
328
- async () => {
329
- this.log('debug', `Disconnecting MCP server during exit`);
330
- await this.disconnect();
331
- },
332
- { wait: 5000 },
333
- );
334
-
335
- process.on('SIGTERM', () => gracefulExit());
336
- this.log('debug', `Successfully connected to MCP server`);
337
- return this.isConnected;
338
- }
339
-
340
- /**
341
- * Get the current session ID if using the Streamable HTTP transport.
342
- * Returns undefined if not connected or not using Streamable HTTP.
343
- */
344
- get sessionId(): string | undefined {
345
- if (this.transport instanceof StreamableHTTPClientTransport) {
346
- return this.transport.sessionId;
347
- }
348
- return undefined;
349
- }
350
-
351
- async disconnect() {
352
- if (!this.transport) {
353
- this.log('debug', 'Disconnect called but no transport was connected.');
354
- return;
355
- }
356
- this.log('debug', `Disconnecting from MCP server`);
357
- try {
358
- await this.transport.close();
359
- this.log('debug', 'Successfully disconnected from MCP server');
360
- } catch (e) {
361
- this.log('error', 'Error during MCP server disconnect', {
362
- error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
363
- });
364
- throw e;
365
- } finally {
366
- this.transport = undefined;
367
- this.isConnected = Promise.resolve(false);
368
- }
369
- }
370
-
371
- async listResources() {
372
- this.log('debug', `Requesting resources from MCP server`);
373
- return await this.client.request({ method: 'resources/list' }, ListResourcesResultSchema, {
374
- timeout: this.timeout,
375
- });
376
- }
377
-
378
- async readResource(uri: string) {
379
- this.log('debug', `Reading resource from MCP server: ${uri}`);
380
- return await this.client.request({ method: 'resources/read', params: { uri } }, ReadResourceResultSchema, {
381
- timeout: this.timeout,
382
- });
383
- }
384
-
385
- async subscribeResource(uri: string) {
386
- this.log('debug', `Subscribing to resource on MCP server: ${uri}`);
387
- return await this.client.request({ method: 'resources/subscribe', params: { uri } }, z.object({}), {
388
- timeout: this.timeout,
389
- });
390
- }
391
-
392
- async unsubscribeResource(uri: string) {
393
- this.log('debug', `Unsubscribing from resource on MCP server: ${uri}`);
394
- return await this.client.request({ method: 'resources/unsubscribe', params: { uri } }, z.object({}), {
395
- timeout: this.timeout,
396
- });
397
- }
398
-
399
- async listResourceTemplates() {
400
- this.log('debug', `Requesting resource templates from MCP server`);
401
- return await this.client.request({ method: 'resources/templates/list' }, ListResourceTemplatesResultSchema, {
402
- timeout: this.timeout,
403
- });
404
- }
405
-
406
- /**
407
- * Fetch the list of available prompts from the MCP server.
408
- */
409
- async listPrompts(): Promise<ListPromptsResult> {
410
- this.log('debug', `Requesting prompts from MCP server`);
411
- return await this.client.request({ method: 'prompts/list' }, ListPromptsResultSchema, {
412
- timeout: this.timeout,
413
- });
414
- }
415
-
416
- /**
417
- * Get a prompt and its dynamic messages from the server.
418
- * @param name The prompt name
419
- * @param args Arguments for the prompt
420
- * @param version (optional) The prompt version to retrieve
421
- */
422
- async getPrompt({
423
- name,
424
- args,
425
- version,
426
- }: {
427
- name: string;
428
- args?: Record<string, any>;
429
- version?: string;
430
- }): Promise<GetPromptResult> {
431
- this.log('debug', `Requesting prompt from MCP server: ${name}`);
432
- return await this.client.request(
433
- { method: 'prompts/get', params: { name, arguments: args, version } },
434
- GetPromptResultSchema,
435
- { timeout: this.timeout },
436
- );
437
- }
438
-
439
- /**
440
- * Register a handler to be called when the prompt list changes on the server.
441
- * Use this to refresh cached prompt lists in the client/UI if needed.
442
- */
443
- setPromptListChangedNotificationHandler(handler: () => void): void {
444
- this.log('debug', 'Setting prompt list changed notification handler');
445
- this.client.setNotificationHandler(PromptListChangedNotificationSchema, () => {
446
- handler();
447
- });
448
- }
449
-
450
- setResourceUpdatedNotificationHandler(
451
- handler: (params: z.infer<typeof ResourceUpdatedNotificationSchema>['params']) => void,
452
- ): void {
453
- this.log('debug', 'Setting resource updated notification handler');
454
- this.client.setNotificationHandler(ResourceUpdatedNotificationSchema, notification => {
455
- handler(notification.params);
456
- });
457
- }
458
-
459
- setResourceListChangedNotificationHandler(handler: () => void): void {
460
- this.log('debug', 'Setting resource list changed notification handler');
461
- this.client.setNotificationHandler(ResourceListChangedNotificationSchema, () => {
462
- handler();
463
- });
464
- }
465
-
466
- setElicitationRequestHandler(handler: ElicitationHandler): void {
467
- this.log('debug', 'Setting elicitation request handler');
468
- this.client.setRequestHandler(ElicitRequestSchema, async request => {
469
- this.log('debug', `Received elicitation request: ${request.params.message}`);
470
- return handler(request.params);
471
- });
472
- }
473
-
474
- private async convertInputSchema(
475
- inputSchema: Awaited<ReturnType<Client['listTools']>>['tools'][0]['inputSchema'] | JSONSchema,
476
- ): Promise<z.ZodType> {
477
- if (isZodType(inputSchema)) {
478
- return inputSchema;
479
- }
480
-
481
- try {
482
- await $RefParser.dereference(inputSchema);
483
- const jsonSchemaToConvert = ('jsonSchema' in inputSchema ? inputSchema.jsonSchema : inputSchema) as JSONSchema;
484
- if ('toJSONSchema' in z) {
485
- // @ts-expect-error - zod type issue
486
- return convertJsonSchemaToZod(jsonSchemaToConvert);
487
- } else {
488
- return convertJsonSchemaToZodV3(jsonSchemaToConvert);
489
- }
490
- } catch (error: unknown) {
491
- let errorDetails: string | undefined;
492
- if (error instanceof Error) {
493
- errorDetails = error.stack;
494
- } else {
495
- // Attempt to stringify, fallback to String()
496
- try {
497
- errorDetails = JSON.stringify(error);
498
- } catch {
499
- errorDetails = String(error);
500
- }
501
- }
502
- this.log('error', 'Failed to convert JSON schema to Zod schema using zodFromJsonSchema', {
503
- error: errorDetails,
504
- originalJsonSchema: inputSchema,
505
- });
506
-
507
- throw new MastraError({
508
- id: 'MCP_TOOL_INPUT_SCHEMA_CONVERSION_FAILED',
509
- domain: ErrorDomain.MCP,
510
- category: ErrorCategory.USER,
511
- details: { error: errorDetails ?? 'Unknown error' },
512
- });
513
- }
514
- }
515
-
516
- private async convertOutputSchema(
517
- outputSchema: Awaited<ReturnType<Client['listTools']>>['tools'][0]['outputSchema'] | JSONSchema,
518
- ): Promise<z.ZodType | undefined> {
519
- if (!outputSchema) return;
520
- if (isZodType(outputSchema)) {
521
- return outputSchema;
522
- }
523
-
524
- try {
525
- await $RefParser.dereference(outputSchema);
526
- const jsonSchemaToConvert = ('jsonSchema' in outputSchema ? outputSchema.jsonSchema : outputSchema) as JSONSchema;
527
- if ('toJSONSchema' in z) {
528
- // @ts-expect-error - zod type issue
529
- return convertJsonSchemaToZod(jsonSchemaToConvert);
530
- } else {
531
- return convertJsonSchemaToZodV3(jsonSchemaToConvert);
532
- }
533
- } catch (error: unknown) {
534
- let errorDetails: string | undefined;
535
- if (error instanceof Error) {
536
- errorDetails = error.stack;
537
- } else {
538
- // Attempt to stringify, fallback to String()
539
- try {
540
- errorDetails = JSON.stringify(error);
541
- } catch {
542
- errorDetails = String(error);
543
- }
544
- }
545
- this.log('error', 'Failed to convert JSON schema to Zod schema using zodFromJsonSchema', {
546
- error: errorDetails,
547
- originalJsonSchema: outputSchema,
548
- });
549
-
550
- throw new MastraError({
551
- id: 'MCP_TOOL_OUTPUT_SCHEMA_CONVERSION_FAILED',
552
- domain: ErrorDomain.MCP,
553
- category: ErrorCategory.USER,
554
- details: { error: errorDetails ?? 'Unknown error' },
555
- });
556
- }
557
- }
558
-
559
- async tools() {
560
- this.log('debug', `Requesting tools from MCP server`);
561
- const { tools } = await this.client.listTools({ timeout: this.timeout });
562
- const toolsRes: Record<string, any> = {};
563
- for (const tool of tools) {
564
- this.log('debug', `Processing tool: ${tool.name}`);
565
- try {
566
- const mastraTool = createTool({
567
- id: `${this.name}_${tool.name}`,
568
- description: tool.description || '',
569
- inputSchema: await this.convertInputSchema(tool.inputSchema),
570
- outputSchema: await this.convertOutputSchema(tool.outputSchema),
571
- execute: async ({ context, runtimeContext }: { context: any; runtimeContext?: RuntimeContext | null }) => {
572
- const previousContext = this.currentOperationContext;
573
- this.currentOperationContext = runtimeContext || null; // Set current context
574
- try {
575
- this.log('debug', `Executing tool: ${tool.name}`, { toolArgs: context });
576
- const res = await this.client.callTool(
577
- {
578
- name: tool.name,
579
- arguments: context,
580
- },
581
- CallToolResultSchema,
582
- {
583
- timeout: this.timeout,
584
- },
585
- );
586
-
587
- this.log('debug', `Tool executed successfully: ${tool.name}`);
588
- return res;
589
- } catch (e) {
590
- this.log('error', `Error calling tool: ${tool.name}`, {
591
- error: e instanceof Error ? e.stack : JSON.stringify(e, null, 2),
592
- toolArgs: context,
593
- });
594
- throw e;
595
- } finally {
596
- this.currentOperationContext = previousContext; // Restore previous context
597
- }
598
- },
599
- });
600
-
601
- if (tool.name) {
602
- toolsRes[tool.name] = mastraTool;
603
- }
604
- } catch (toolCreationError: unknown) {
605
- // Catch errors during tool creation itself (e.g., if createTool has issues)
606
- this.log('error', `Failed to create Mastra tool wrapper for MCP tool: ${tool.name}`, {
607
- error: toolCreationError instanceof Error ? toolCreationError.stack : String(toolCreationError),
608
- mcpToolDefinition: tool,
609
- });
610
- }
611
- }
612
-
613
- return toolsRes;
614
- }
615
- }
616
-
617
- /**
618
- * @deprecated MastraMCPClient is deprecated and will be removed in a future release. Please use MCPClient instead.
619
- */
620
-
621
- export class MastraMCPClient extends InternalMastraMCPClient {
622
- constructor(args: InternalMastraMCPClientOptions) {
623
- super(args);
624
- this.logger.warn(
625
- '[DEPRECATION] MastraMCPClient is deprecated and will be removed in a future release. Please use MCPClient instead.',
626
- );
627
- }
628
- }