@mastra/mcp 1.0.0 → 1.0.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.
@@ -1,957 +1,4 @@
1
- # Tools API Reference
2
-
3
- > API reference for tools - 3 entries
4
-
5
-
6
- ---
7
-
8
- ## Reference: MCPClient
9
-
10
- > API Reference for MCPClient - A class for managing multiple Model Context Protocol servers and their tools.
11
-
12
- The `MCPClient` class provides a way to manage multiple MCP server connections and their tools in a Mastra application. It handles connection lifecycle, tool namespacing, and provides access to tools across all configured servers.
13
-
14
- This class replaces the deprecated [`MastraMCPClient`](https://mastra.ai/reference/v1/tools/client).
15
-
16
- ## Constructor
17
-
18
- Creates a new instance of the MCPClient class.
19
-
20
- ```typescript
21
- constructor({
22
- id?: string;
23
- servers: Record<string, MastraMCPServerDefinition>;
24
- timeout?: number;
25
- }: MCPClientOptions)
26
- ```
27
-
28
- ### MCPClientOptions
29
-
30
- <br />
31
-
32
- ### MastraMCPServerDefinition
33
-
34
- Each server in the `servers` map is configured using the `MastraMCPServerDefinition` type. The transport type is detected based on the provided parameters:
35
-
36
- - If `command` is provided, it uses the Stdio transport.
37
- - If `url` is provided, it first attempts to use the Streamable HTTP transport and falls back to the legacy SSE transport if the initial connection fails.
38
-
39
- <br />
40
-
41
- ## Methods
42
-
43
- ### listTools()
44
-
45
- Retrieves all tools from all configured servers, with tool names namespaced by their server name (in the format `serverName_toolName`) to prevent conflicts.
46
- Intended to be passed onto an Agent definition.
47
-
48
- ```ts
49
- new Agent({ id: "agent", tools: await mcp.listTools() });
50
- ```
51
-
52
- ### listToolsets()
53
-
54
- Returns an object mapping namespaced tool names (in the format `serverName.toolName`) to their tool implementations.
55
- Intended to be passed dynamically into the generate or stream method.
56
-
57
- ```typescript
58
- const res = await agent.stream(prompt, {
59
- toolsets: await mcp.listToolsets(),
60
- });
61
- ```
62
-
63
- ### disconnect()
64
-
65
- Disconnects from all MCP servers and cleans up resources.
66
-
67
- ```typescript
68
- async disconnect(): Promise<void>
69
- ```
70
-
71
- ### `resources` Property
72
-
73
- The `MCPClient` instance has a `resources` property that provides access to resource-related operations.
74
-
75
- ```typescript
76
- const mcpClient = new MCPClient({
77
- /* ...servers configuration... */
78
- });
79
-
80
- // Access resource methods via mcpClient.resources
81
- const allResourcesByServer = await mcpClient.resources.list();
82
- const templatesByServer = await mcpClient.resources.templates();
83
- // ... and so on for other resource methods.
84
- ```
85
-
86
- #### `resources.list()`
87
-
88
- Retrieves all available resources from all connected MCP servers, grouped by server name.
89
-
90
- ```typescript
91
- async list(): Promise<Record<string, Resource[]>>
92
- ```
93
-
94
- Example:
95
-
96
- ```typescript
97
- const resourcesByServer = await mcpClient.resources.list();
98
- for (const serverName in resourcesByServer) {
99
- console.log(`Resources from ${serverName}:`, resourcesByServer[serverName]);
100
- }
101
- ```
102
-
103
- #### `resources.templates()`
104
-
105
- Retrieves all available resource templates from all connected MCP servers, grouped by server name.
106
-
107
- ```typescript
108
- async templates(): Promise<Record<string, ResourceTemplate[]>>
109
- ```
110
-
111
- Example:
112
-
113
- ```typescript
114
- const templatesByServer = await mcpClient.resources.templates();
115
- for (const serverName in templatesByServer) {
116
- console.log(`Templates from ${serverName}:`, templatesByServer[serverName]);
117
- }
118
- ```
119
-
120
- #### `resources.read(serverName: string, uri: string)`
121
-
122
- Reads the content of a specific resource from a named server.
123
-
124
- ```typescript
125
- async read(serverName: string, uri: string): Promise<ReadResourceResult>
126
- ```
127
-
128
- - `serverName`: The identifier of the server (key used in the `servers` constructor option).
129
- - `uri`: The URI of the resource to read.
130
-
131
- Example:
132
-
133
- ```typescript
134
- const content = await mcpClient.resources.read(
135
- "myWeatherServer",
136
- "weather://current",
137
- );
138
- console.log("Current weather:", content.contents[0].text);
139
- ```
140
-
141
- #### `resources.subscribe(serverName: string, uri: string)`
142
-
143
- Subscribes to updates for a specific resource on a named server.
144
-
145
- ```typescript
146
- async subscribe(serverName: string, uri: string): Promise<object>
147
- ```
148
-
149
- Example:
150
-
151
- ```typescript
152
- await mcpClient.resources.subscribe("myWeatherServer", "weather://current");
153
- ```
154
-
155
- #### `resources.unsubscribe(serverName: string, uri: string)`
156
-
157
- Unsubscribes from updates for a specific resource on a named server.
158
-
159
- ```typescript
160
- async unsubscribe(serverName: string, uri: string): Promise<object>
161
- ```
162
-
163
- Example:
164
-
165
- ```typescript
166
- await mcpClient.resources.unsubscribe("myWeatherServer", "weather://current");
167
- ```
168
-
169
- #### `resources.onUpdated(serverName: string, handler: (params: { uri: string }) => void)`
170
-
171
- Sets a notification handler that will be called when a subscribed resource on a specific server is updated.
172
-
173
- ```typescript
174
- async onUpdated(serverName: string, handler: (params: { uri: string }) => void): Promise<void>
175
- ```
176
-
177
- Example:
178
-
179
- ```typescript
180
- mcpClient.resources.onUpdated("myWeatherServer", (params) => {
181
- console.log(`Resource updated on myWeatherServer: ${params.uri}`);
182
- // You might want to re-fetch the resource content here
183
- // await mcpClient.resources.read("myWeatherServer", params.uri);
184
- });
185
- ```
186
-
187
- #### `resources.onListChanged(serverName: string, handler: () => void)`
188
-
189
- Sets a notification handler that will be called when the overall list of available resources changes on a specific server.
190
-
191
- ```typescript
192
- async onListChanged(serverName: string, handler: () => void): Promise<void>
193
- ```
194
-
195
- Example:
196
-
197
- ```typescript
198
- mcpClient.resources.onListChanged("myWeatherServer", () => {
199
- console.log("Resource list changed on myWeatherServer.");
200
- // You should re-fetch the list of resources
201
- // await mcpClient.resources.list();
202
- });
203
- ```
204
-
205
- ### `elicitation` Property
206
-
207
- The `MCPClient` instance has an `elicitation` property that provides access to elicitation-related operations. Elicitation allows MCP servers to request structured information from users.
208
-
209
- ```typescript
210
- const mcpClient = new MCPClient({
211
- /* ...servers configuration... */
212
- });
213
-
214
- // Set up elicitation handler
215
- mcpClient.elicitation.onRequest("serverName", async (request) => {
216
- // Handle elicitation request from server
217
- console.log("Server requests:", request.message);
218
- console.log("Schema:", request.requestedSchema);
219
-
220
- // Return user response
221
- return {
222
- action: "accept",
223
- content: { name: "John Doe", email: "john@example.com" },
224
- };
225
- });
226
- ```
227
-
228
- #### `elicitation.onRequest(serverName: string, handler: ElicitationHandler)`
229
-
230
- Sets up a handler function that will be called when any connected MCP server sends an elicitation request. The handler receives the request and must return a response.
231
-
232
- **ElicitationHandler Function:**
233
-
234
- The handler function receives a request object with:
235
-
236
- - `message`: A human-readable message describing what information is needed
237
- - `requestedSchema`: A JSON schema defining the structure of the expected response
238
-
239
- The handler must return an `ElicitResult` with:
240
-
241
- - `action`: One of `'accept'`, `'decline'`, or `'cancel'`
242
- - `content`: The user's data (only when action is `'accept'`)
243
-
244
- **Example:**
245
-
246
- ```typescript
247
- mcpClient.elicitation.onRequest("serverName", async (request) => {
248
- console.log(`Server requests: ${request.message}`);
249
-
250
- // Example: Simple user input collection
251
- if (request.requestedSchema.properties.name) {
252
- // Simulate user accepting and providing data
253
- return {
254
- action: "accept",
255
- content: {
256
- name: "Alice Smith",
257
- email: "alice@example.com",
258
- },
259
- };
260
- }
261
-
262
- // Simulate user declining the request
263
- return { action: "decline" };
264
- });
265
- ```
266
-
267
- **Complete Interactive Example:**
268
-
269
- ```typescript
270
- import { MCPClient } from "@mastra/mcp";
271
- import { createInterface } from "readline";
272
-
273
- const readline = createInterface({
274
- input: process.stdin,
275
- output: process.stdout,
276
- });
277
-
278
- function askQuestion(question: string): Promise<string> {
279
- return new Promise((resolve) => {
280
- readline.question(question, (answer) => resolve(answer.trim()));
281
- });
282
- }
283
-
284
- const mcpClient = new MCPClient({
285
- servers: {
286
- interactiveServer: {
287
- url: new URL("http://localhost:3000/mcp"),
288
- },
289
- },
290
- });
291
-
292
- // Set up interactive elicitation handler
293
- await mcpClient.elicitation.onRequest("interactiveServer", async (request) => {
294
- console.log(`\n📋 Server Request: ${request.message}`);
295
- console.log("Required information:");
296
-
297
- const schema = request.requestedSchema;
298
- const properties = schema.properties || {};
299
- const required = schema.required || [];
300
- const content: Record<string, any> = {};
301
-
302
- // Collect input for each field
303
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
304
- const field = fieldSchema as any;
305
- const isRequired = required.includes(fieldName);
306
-
307
- let prompt = `${field.title || fieldName}`;
308
- if (field.description) prompt += ` (${field.description})`;
309
- if (isRequired) prompt += " *required*";
310
- prompt += ": ";
311
-
312
- const answer = await askQuestion(prompt);
313
-
314
- // Handle cancellation
315
- if (answer.toLowerCase() === "cancel") {
316
- return { action: "cancel" };
317
- }
318
-
319
- // Validate required fields
320
- if (answer === "" && isRequired) {
321
- console.log(`❌ ${fieldName} is required`);
322
- return { action: "decline" };
323
- }
324
-
325
- if (answer !== "") {
326
- content[fieldName] = answer;
327
- }
328
- }
329
-
330
- // Confirm submission
331
- console.log("\n📝 You provided:");
332
- console.log(JSON.stringify(content, null, 2));
333
-
334
- const confirm = await askQuestion(
335
- "\nSubmit this information? (yes/no/cancel): ",
336
- );
337
-
338
- if (confirm.toLowerCase() === "yes" || confirm.toLowerCase() === "y") {
339
- return { action: "accept", content };
340
- } else if (confirm.toLowerCase() === "cancel") {
341
- return { action: "cancel" };
342
- } else {
343
- return { action: "decline" };
344
- }
345
- });
346
- ```
347
-
348
- ### `prompts` Property
349
-
350
- The `MCPClient` instance has a `prompts` property that provides access to prompt-related operations.
351
-
352
- ```typescript
353
- const mcpClient = new MCPClient({
354
- /* ...servers configuration... */
355
- });
356
-
357
- // Access prompt methods via mcpClient.prompts
358
- const allPromptsByServer = await mcpClient.prompts.list();
359
- const { prompt, messages } = await mcpClient.prompts.get({
360
- serverName: "myWeatherServer",
361
- name: "current",
362
- });
363
- ```
364
-
365
- #### `prompts.list()`
366
-
367
- Retrieves all available prompts from all connected MCP servers, grouped by server name.
368
-
369
- ```typescript
370
- async list(): Promise<Record<string, Prompt[]>>
371
- ```
372
-
373
- Example:
374
-
375
- ```typescript
376
- const promptsByServer = await mcpClient.prompts.list();
377
- for (const serverName in promptsByServer) {
378
- console.log(`Prompts from ${serverName}:`, promptsByServer[serverName]);
379
- }
380
- ```
381
-
382
- #### `prompts.get({ serverName, name, args?, version? })`
383
-
384
- Retrieves a specific prompt and its messages from a server.
385
-
386
- ```typescript
387
- async get({
388
- serverName,
389
- name,
390
- args?,
391
- version?,
392
- }: {
393
- serverName: string;
394
- name: string;
395
- args?: Record<string, any>;
396
- version?: string;
397
- }): Promise<{ prompt: Prompt; messages: PromptMessage[] }>
398
- ```
399
-
400
- Example:
401
-
402
- ```typescript
403
- const { prompt, messages } = await mcpClient.prompts.get({
404
- serverName: "myWeatherServer",
405
- name: "current",
406
- args: { location: "London" },
407
- });
408
- console.log(prompt);
409
- console.log(messages);
410
- ```
411
-
412
- #### `prompts.onListChanged(serverName: string, handler: () => void)`
413
-
414
- Sets a notification handler that will be called when the list of available prompts changes on a specific server.
415
-
416
- ```typescript
417
- async onListChanged(serverName: string, handler: () => void): Promise<void>
418
- ```
419
-
420
- Example:
421
-
422
- ```typescript
423
- mcpClient.prompts.onListChanged("myWeatherServer", () => {
424
- console.log("Prompt list changed on myWeatherServer.");
425
- // You should re-fetch the list of prompts
426
- // await mcpClient.prompts.list();
427
- });
428
- ```
429
-
430
- ### `progress` Property
431
-
432
- The `MCPClient` instance has a `progress` property for subscribing to progress notifications emitted by MCP servers while tools execute.
433
-
434
- ```typescript
435
- const mcpClient = new MCPClient({
436
- servers: {
437
- myServer: {
438
- url: new URL('http://localhost:4111/api/mcp/myServer/mcp'),
439
- // Enabled by default; set to false to disable
440
- enableProgressTracking: true,
441
- },
442
- },
443
- });
444
-
445
- // Subscribe to progress updates for a specific server
446
- await mcpClient.progress.onUpdate('myServer', (params) => {
447
- console.log('📊 Progress:', params.progress, '/', params.total);
448
- if (params.message) console.log('Message:', params.message);
449
- if (params.progressToken) console.log('Token:', params.progressToken);
450
- });
451
- ```
452
-
453
- #### `progress.onUpdate(serverName: string, handler)`
454
-
455
- Registers a handler function to receive progress updates from the specified server.
456
-
457
- ```typescript
458
- async onUpdate(
459
- serverName: string,
460
- handler: (params: {
461
- progressToken: string;
462
- progress: number;
463
- total?: number;
464
- message?: string;
465
- }) => void,
466
- ): Promise<void>
467
- ```
468
-
469
- Notes:
470
-
471
- - When `enableProgressTracking` is true (default), tool calls include a `progressToken` so you can correlate updates to a specific run.
472
- - If you pass a `runId` when executing a tool, it will be used as the `progressToken`.
473
-
474
- To disable progress tracking for a server:
475
-
476
- ```typescript
477
- const mcpClient = new MCPClient({
478
- servers: {
479
- myServer: {
480
- url: new URL('http://localhost:4111/api/mcp/myServer/mcp'),
481
- enableProgressTracking: false,
482
- },
483
- },
484
- });
485
- ```
486
-
487
- ## Elicitation
488
-
489
- Elicitation is a feature that allows MCP servers to request structured information from users. When a server needs additional data, it can send an elicitation request that the client handles by prompting the user. A common example is during a tool call.
490
-
491
- ### How Elicitation Works
492
-
493
- 1. **Server Request**: An MCP server tool calls `server.elicitation.sendRequest()` with a message and schema
494
- 2. **Client Handler**: Your elicitation handler function is called with the request
495
- 3. **User Interaction**: Your handler collects user input (via UI, CLI, etc.)
496
- 4. **Response**: Your handler returns the user's response (accept/decline/cancel)
497
- 5. **Tool Continuation**: The server tool receives the response and continues execution
498
-
499
- ### Setting Up Elicitation
500
-
501
- You must set up an elicitation handler before tools that use elicitation are called:
502
-
503
- ```typescript
504
- import { MCPClient } from "@mastra/mcp";
505
-
506
- const mcpClient = new MCPClient({
507
- servers: {
508
- interactiveServer: {
509
- url: new URL("http://localhost:3000/mcp"),
510
- },
511
- },
512
- });
513
-
514
- // Set up elicitation handler
515
- mcpClient.elicitation.onRequest("interactiveServer", async (request) => {
516
- // Handle the server's request for user input
517
- console.log(`Server needs: ${request.message}`);
518
-
519
- // Your logic to collect user input
520
- const userData = await collectUserInput(request.requestedSchema);
521
-
522
- return {
523
- action: "accept",
524
- content: userData,
525
- };
526
- });
527
- ```
528
-
529
- ### Response Types
530
-
531
- Your elicitation handler must return one of three response types:
532
-
533
- - **Accept**: User provided data and confirmed submission
534
-
535
- ```typescript
536
- return {
537
- action: "accept",
538
- content: { name: "John Doe", email: "john@example.com" },
539
- };
540
- ```
541
-
542
- - **Decline**: User explicitly declined to provide the information
543
-
544
- ```typescript
545
- return { action: "decline" };
546
- ```
547
-
548
- - **Cancel**: User dismissed or cancelled the request
549
- ```typescript
550
- return { action: "cancel" };
551
- ```
552
-
553
- ### Schema-Based Input Collection
554
-
555
- The `requestedSchema` provides structure for the data the server needs:
556
-
557
- ```typescript
558
- await mcpClient.elicitation.onRequest("interactiveServer", async (request) => {
559
- const { properties, required = [] } = request.requestedSchema;
560
- const content: Record<string, any> = {};
561
-
562
- for (const [fieldName, fieldSchema] of Object.entries(properties || {})) {
563
- const field = fieldSchema as any;
564
- const isRequired = required.includes(fieldName);
565
-
566
- // Collect input based on field type and requirements
567
- const value = await promptUser({
568
- name: fieldName,
569
- title: field.title,
570
- description: field.description,
571
- type: field.type,
572
- required: isRequired,
573
- format: field.format,
574
- enum: field.enum,
575
- });
576
-
577
- if (value !== null) {
578
- content[fieldName] = value;
579
- }
580
- }
581
-
582
- return { action: "accept", content };
583
- });
584
- ```
585
-
586
- ### Best Practices
587
-
588
- - **Always handle elicitation**: Set up your handler before calling tools that might use elicitation
589
- - **Validate input**: Check that required fields are provided
590
- - **Respect user choice**: Handle decline and cancel responses gracefully
591
- - **Clear UI**: Make it obvious what information is being requested and why
592
- - **Security**: Never auto-accept requests for sensitive information
593
-
594
- ## OAuth Authentication
595
-
596
- For connecting to MCP servers that require OAuth authentication per the [MCP Auth Specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization), use the `MCPOAuthClientProvider`:
597
-
598
- ```typescript
599
- import { MCPClient, MCPOAuthClientProvider } from "@mastra/mcp";
600
-
601
- // Create an OAuth provider
602
- const oauthProvider = new MCPOAuthClientProvider({
603
- redirectUrl: "http://localhost:3000/oauth/callback",
604
- clientMetadata: {
605
- redirect_uris: ["http://localhost:3000/oauth/callback"],
606
- client_name: "My MCP Client",
607
- grant_types: ["authorization_code", "refresh_token"],
608
- response_types: ["code"],
609
- },
610
- onRedirectToAuthorization: (url) => {
611
- // Handle authorization redirect (open browser, redirect response, etc.)
612
- console.log(`Please visit: ${url}`);
613
- },
614
- });
615
-
616
- // Use the provider with MCPClient
617
- const client = new MCPClient({
618
- servers: {
619
- protectedServer: {
620
- url: new URL("https://mcp.example.com/mcp"),
621
- authProvider: oauthProvider,
622
- },
623
- },
624
- });
625
- ```
626
-
627
- ### Quick Token Provider
628
-
629
- For testing or when you already have a valid access token:
630
-
631
- ```typescript
632
- import { MCPClient, createSimpleTokenProvider } from "@mastra/mcp";
633
-
634
- const provider = createSimpleTokenProvider("your-access-token", {
635
- redirectUrl: "http://localhost:3000/callback",
636
- clientMetadata: {
637
- redirect_uris: ["http://localhost:3000/callback"],
638
- client_name: "Test Client",
639
- },
640
- });
641
-
642
- const client = new MCPClient({
643
- servers: {
644
- testServer: {
645
- url: new URL("https://mcp.example.com/mcp"),
646
- authProvider: provider,
647
- },
648
- },
649
- });
650
- ```
651
-
652
- ### Custom Token Storage
653
-
654
- For persistent token storage across sessions, implement the `OAuthStorage` interface:
655
-
656
- ```typescript
657
- import { MCPOAuthClientProvider, OAuthStorage } from "@mastra/mcp";
658
-
659
- class DatabaseOAuthStorage implements OAuthStorage {
660
- constructor(private db: Database, private userId: string) {}
661
-
662
- async set(key: string, value: string): Promise<void> {
663
- await this.db.query(
664
- "INSERT INTO oauth_tokens (user_id, key, value) VALUES (?, ?, ?) ON CONFLICT DO UPDATE SET value = ?",
665
- [this.userId, key, value, value]
666
- );
667
- }
668
-
669
- async get(key: string): Promise<string | undefined> {
670
- const result = await this.db.query(
671
- "SELECT value FROM oauth_tokens WHERE user_id = ? AND key = ?",
672
- [this.userId, key]
673
- );
674
- return result?.[0]?.value;
675
- }
676
-
677
- async delete(key: string): Promise<void> {
678
- await this.db.query(
679
- "DELETE FROM oauth_tokens WHERE user_id = ? AND key = ?",
680
- [this.userId, key]
681
- );
682
- }
683
- }
684
-
685
- const provider = new MCPOAuthClientProvider({
686
- redirectUrl: "http://localhost:3000/callback",
687
- clientMetadata: { /* ... */ },
688
- storage: new DatabaseOAuthStorage(db, "user-123"),
689
- });
690
- ```
691
-
692
- ## Examples
693
-
694
- ### Static Tool Configuration
695
-
696
- For tools where you have a single connection to the MCP server for you entire app, use `listTools()` and pass the tools to your agent:
697
-
698
- ```typescript
699
- import { MCPClient } from "@mastra/mcp";
700
- import { Agent } from "@mastra/core/agent";
701
-
702
- const mcp = new MCPClient({
703
- servers: {
704
- stockPrice: {
705
- command: "npx",
706
- args: ["tsx", "stock-price.ts"],
707
- env: {
708
- API_KEY: "your-api-key",
709
- },
710
- log: (logMessage) => {
711
- console.log(`[${logMessage.level}] ${logMessage.message}`);
712
- },
713
- },
714
- weather: {
715
- url: new URL("http://localhost:8080/sse"),
716
- },
717
- },
718
- timeout: 30000, // Global 30s timeout
719
- });
720
-
721
- // Create an agent with access to all tools
722
- const agent = new Agent({
723
- id: "multi-tool-agent",
724
- name: "Multi-tool Agent",
725
- instructions: "You have access to multiple tool servers.",
726
- model: "openai/gpt-5.1",
727
- tools: await mcp.listTools(),
728
- });
729
-
730
- // Example of using resource methods
731
- async function checkWeatherResource() {
732
- try {
733
- const weatherResources = await mcp.resources.list();
734
- if (weatherResources.weather && weatherResources.weather.length > 0) {
735
- const currentWeatherURI = weatherResources.weather[0].uri;
736
- const weatherData = await mcp.resources.read(
737
- "weather",
738
- currentWeatherURI,
739
- );
740
- console.log("Weather data:", weatherData.contents[0].text);
741
- }
742
- } catch (error) {
743
- console.error("Error fetching weather resource:", error);
744
- }
745
- }
746
- checkWeatherResource();
747
-
748
- // Example of using prompt methods
749
- async function checkWeatherPrompt() {
750
- try {
751
- const weatherPrompts = await mcp.prompts.list();
752
- if (weatherPrompts.weather && weatherPrompts.weather.length > 0) {
753
- const currentWeatherPrompt = weatherPrompts.weather.find(
754
- (p) => p.name === "current",
755
- );
756
- if (currentWeatherPrompt) {
757
- console.log("Weather prompt:", currentWeatherPrompt);
758
- } else {
759
- console.log("Current weather prompt not found");
760
- }
761
- }
762
- } catch (error) {
763
- console.error("Error fetching weather prompt:", error);
764
- }
765
- }
766
- checkWeatherPrompt();
767
- ```
768
-
769
- ### Dynamic toolsets
770
-
771
- When you need a new MCP connection for each user, use `listToolsets()` and add the tools when calling stream or generate:
772
-
773
- ```typescript
774
- import { Agent } from "@mastra/core/agent";
775
- import { MCPClient } from "@mastra/mcp";
776
-
777
- // Create the agent first, without any tools
778
- const agent = new Agent({
779
- id: "multi-tool-agent",
780
- name: "Multi-tool Agent",
781
- instructions: "You help users check stocks and weather.",
782
- model: "openai/gpt-5.1",
783
- });
784
-
785
- // Later, configure MCP with user-specific settings
786
- const mcp = new MCPClient({
787
- servers: {
788
- stockPrice: {
789
- command: "npx",
790
- args: ["tsx", "stock-price.ts"],
791
- env: {
792
- API_KEY: "user-123-api-key",
793
- },
794
- timeout: 20000, // Server-specific timeout
795
- },
796
- weather: {
797
- url: new URL("http://localhost:8080/sse"),
798
- requestInit: {
799
- headers: {
800
- Authorization: `Bearer user-123-token`,
801
- },
802
- },
803
- },
804
- },
805
- });
806
-
807
- // Pass all toolsets to stream() or generate()
808
- const response = await agent.stream(
809
- "How is AAPL doing and what is the weather?",
810
- {
811
- toolsets: await mcp.listToolsets(),
812
- },
813
- );
814
- ```
815
-
816
- ## Instance Management
817
-
818
- The `MCPClient` class includes built-in memory leak prevention for managing multiple instances:
819
-
820
- 1. Creating multiple instances with identical configurations without an `id` will throw an error to prevent memory leaks
821
- 2. If you need multiple instances with identical configurations, provide a unique `id` for each instance
822
- 3. Call `await configuration.disconnect()` before recreating an instance with the same configuration
823
- 4. If you only need one instance, consider moving the configuration to a higher scope to avoid recreation
824
-
825
- For example, if you try to create multiple instances with the same configuration without an `id`:
826
-
827
- ```typescript
828
- // First instance - OK
829
- const mcp1 = new MCPClient({
830
- servers: {
831
- /* ... */
832
- },
833
- });
834
-
835
- // Second instance with same config - Will throw an error
836
- const mcp2 = new MCPClient({
837
- servers: {
838
- /* ... */
839
- },
840
- });
841
-
842
- // To fix, either:
843
- // 1. Add unique IDs
844
- const mcp3 = new MCPClient({
845
- id: "instance-1",
846
- servers: {
847
- /* ... */
848
- },
849
- });
850
-
851
- // 2. Or disconnect before recreating
852
- await mcp1.disconnect();
853
- const mcp4 = new MCPClient({
854
- servers: {
855
- /* ... */
856
- },
857
- });
858
- ```
859
-
860
- ## Server Lifecycle
861
-
862
- MCPClient handles server connections gracefully:
863
-
864
- 1. Automatic connection management for multiple servers
865
- 2. Graceful server shutdown to prevent error messages during development
866
- 3. Proper cleanup of resources when disconnecting
867
-
868
- ## Using Custom Fetch for Dynamic Authentication
869
-
870
- For HTTP servers, you can provide a custom `fetch` function to handle dynamic authentication, request interception, or other custom behavior. This is particularly useful when you need to refresh tokens on each request or customize request behavior.
871
-
872
- When `fetch` is provided, `requestInit`, `eventSourceInit`, and `authProvider` become optional, as you can handle these concerns within your custom fetch function.
873
-
874
- ```typescript
875
- const mcpClient = new MCPClient({
876
- servers: {
877
- apiServer: {
878
- url: new URL("https://api.example.com/mcp"),
879
- fetch: async (url, init) => {
880
- // Refresh token on each request
881
- const token = await getAuthToken(); // Your token refresh logic
882
-
883
- return fetch(url, {
884
- ...init,
885
- headers: {
886
- ...init?.headers,
887
- Authorization: `Bearer ${token}`,
888
- },
889
- });
890
- },
891
- },
892
- },
893
- });
894
- ```
895
-
896
- ## Using SSE Request Headers
897
-
898
- When using the legacy SSE MCP transport, you must configure both `requestInit` and `eventSourceInit` due to a bug in the MCP SDK. Alternatively, you can use a custom `fetch` function which will be automatically used for both POST requests and SSE connections:
899
-
900
- ```ts
901
- // Option 1: Using requestInit and eventSourceInit (required for SSE)
902
- const sseClient = new MCPClient({
903
- servers: {
904
- exampleServer: {
905
- url: new URL("https://your-mcp-server.com/sse"),
906
- // Note: requestInit alone isn't enough for SSE
907
- requestInit: {
908
- headers: {
909
- Authorization: "Bearer your-token",
910
- },
911
- },
912
- // This is also required for SSE connections with custom headers
913
- eventSourceInit: {
914
- fetch(input: Request | URL | string, init?: RequestInit) {
915
- const headers = new Headers(init?.headers || {});
916
- headers.set("Authorization", "Bearer your-token");
917
- return fetch(input, {
918
- ...init,
919
- headers,
920
- });
921
- },
922
- },
923
- },
924
- },
925
- });
926
-
927
- // Option 2: Using custom fetch (simpler, works for both Streamable HTTP and SSE)
928
- const sseClientWithFetch = new MCPClient({
929
- servers: {
930
- exampleServer: {
931
- url: new URL("https://your-mcp-server.com/sse"),
932
- fetch: async (url, init) => {
933
- const headers = new Headers(init?.headers || {});
934
- headers.set("Authorization", "Bearer your-token");
935
- return fetch(url, {
936
- ...init,
937
- headers,
938
- });
939
- },
940
- },
941
- },
942
- });
943
- ```
944
-
945
- ## Related Information
946
-
947
- - For creating MCP servers, see the [MCPServer documentation](./mcp-server).
948
- - For more about the Model Context Protocol, see the [@modelcontextprotocol/sdk documentation](https://github.com/modelcontextprotocol/typescript-sdk).
949
-
950
- ---
951
-
952
- ## Reference: MCPServer
953
-
954
- > API Reference for MCPServer - A class for exposing Mastra tools and capabilities as a Model Context Protocol server.
1
+ # MCPServer
955
2
 
956
3
  The `MCPServer` class provides the functionality to expose your existing Mastra tools and Agents as a Model Context Protocol (MCP) server. This allows any MCP client (like Cursor, Windsurf, or Claude Desktop) to connect to these capabilities and make them available to an agent.
957
4
 
@@ -1003,6 +50,38 @@ const server = new MCPServer({
1003
50
 
1004
51
  The constructor accepts an `MCPServerConfig` object with the following properties:
1005
52
 
53
+ **id:** (`string`): Unique identifier for the server. This ID is preserved when the server is registered with Mastra and can be used to retrieve the server via getMCPServerById().
54
+
55
+ **name:** (`string`): A descriptive name for your server (e.g., 'My Weather and Agent Server').
56
+
57
+ **version:** (`string`): The semantic version of your server (e.g., '1.0.0').
58
+
59
+ **tools:** (`ToolsInput`): An object where keys are tool names and values are Mastra tool definitions (created with \`createTool\` or Vercel AI SDK). These tools will be directly exposed.
60
+
61
+ **agents?:** (`Record<string, Agent>`): An object where keys are agent identifiers and values are Mastra Agent instances. Each agent will be automatically converted into a tool named \`ask\_\<agentIdentifier>\`. The agent \*\*must\*\* have a non-empty \`description\` string property defined in its constructor configuration. This description will be used in the tool's description. If an agent's description is missing or empty, an error will be thrown during MCPServer initialization.
62
+
63
+ **workflows?:** (`Record<string, Workflow>`): An object where keys are workflow identifiers and values are Mastra Workflow instances. Each workflow is converted into a tool named \`run\_\<workflowKey>\`. The workflow's \`inputSchema\` becomes the tool's input schema. The workflow \*\*must\*\* have a non-empty \`description\` string property, which is used for the tool's description. If a workflow's description is missing or empty, an error will be thrown. The tool executes the workflow by calling \`workflow\.createRun()\` followed by \`run.start({ inputData: \<tool\_input> })\`. If a tool name derived from an agent or workflow (e.g., \`ask\_myAgent\` or \`run\_myWorkflow\`) collides with an explicitly defined tool name or another derived name, the explicitly defined tool takes precedence, and a warning is logged. Agents/workflows leading to subsequent collisions are skipped.
64
+
65
+ **description?:** (`string`): Optional description of what the MCP server does.
66
+
67
+ **instructions?:** (`string`): Optional instructions describing how to use the server and its features.
68
+
69
+ **repository?:** (`Repository`): Optional repository information for the server's source code.
70
+
71
+ **releaseDate?:** (`string`): Optional release date of this server version (ISO 8601 string). Defaults to the time of instantiation if not provided.
72
+
73
+ **isLatest?:** (`boolean`): Optional flag indicating if this is the latest version. Defaults to true if not provided.
74
+
75
+ **packageCanonical?:** (`'npm' | 'docker' | 'pypi' | 'crates' | string`): Optional canonical packaging format if the server is distributed as a package (e.g., 'npm', 'docker').
76
+
77
+ **packages?:** (`PackageInfo[]`): Optional list of installable packages for this server.
78
+
79
+ **remotes?:** (`RemoteInfo[]`): Optional list of remote access points for this server.
80
+
81
+ **resources?:** (`MCPServerResources`): An object defining how the server should handle MCP resources. See Resource Handling section for details.
82
+
83
+ **prompts?:** (`MCPServerPrompts`): An object defining how the server should handle MCP prompts. See Prompt Handling section for details.
84
+
1006
85
  ## Exposing Agents as Tools
1007
86
 
1008
87
  A powerful feature of `MCPServer` is its ability to automatically expose your Mastra Agents as callable tools. When you provide agents in the `agents` property of the configuration:
@@ -1010,6 +89,7 @@ A powerful feature of `MCPServer` is its ability to automatically expose your Ma
1010
89
  - **Tool Naming**: Each agent is converted into a tool named `ask_<agentKey>`, where `<agentKey>` is the key you used for that agent in the `agents` object. For instance, if you configure `agents: { myAgentKey: myAgentInstance }`, a tool named `ask_myAgentKey` will be created.
1011
90
 
1012
91
  - **Tool Functionality**:
92
+
1013
93
  - **Description**: The generated tool's description will be in the format: "Ask agent `<AgentName>` a question. Original agent instructions: `<agent description>`".
1014
94
  - **Input**: The tool expects a single object argument with a `message` property (string): `{ message: "Your question for the agent" }`.
1015
95
  - **Execution**: When this tool is called, it invokes the `generate()` method of the corresponding agent, passing the provided `query`.
@@ -1033,12 +113,13 @@ This allows you to quickly expose the generative capabilities of your agents thr
1033
113
 
1034
114
  Tools exposed through `MCPServer` can access MCP request context (authentication, session IDs, etc.) via two different properties depending on how the tool is invoked:
1035
115
 
1036
- | Call Pattern | Access Method |
1037
- |-------------|---------------|
1038
- | Direct tool call | `context?.mcp?.extra` |
1039
- | Agent tool call | `context?.requestContext?.get("mcp.extra")` |
116
+ | Call Pattern | Access Method |
117
+ | ---------------- | ------------------------------------------- |
118
+ | Direct tool call | `context?.mcp?.extra` |
119
+ | Agent tool call | `context?.requestContext?.get("mcp.extra")` |
1040
120
 
1041
121
  **Universal pattern** (works in both contexts):
122
+
1042
123
  ```typescript
1043
124
  const mcpExtra = context?.mcp?.extra ?? context?.requestContext?.get("mcp.extra");
1044
125
  const authInfo = mcpExtra?.authInfo;
@@ -1144,6 +225,16 @@ httpServer.listen(PORT, () => {
1144
225
 
1145
226
  Here are the details for the values needed by the `startSSE` method:
1146
227
 
228
+ **url:** (`URL`): The web address the user is requesting.
229
+
230
+ **ssePath:** (`string`): The specific part of the URL where clients will connect for SSE (e.g., '/sse').
231
+
232
+ **messagePath:** (`string`): The specific part of the URL where clients will send messages (e.g., '/message').
233
+
234
+ **req:** (`any`): The incoming request object from your web server.
235
+
236
+ **res:** (`any`): The response object from your web server, used to send data back.
237
+
1147
238
  ### startHonoSSE()
1148
239
 
1149
240
  This method helps you integrate the MCP server with an existing web server to use Server-Sent Events (SSE) for communication. You'll call this from your web server's code when it receives a request for the SSE or message paths.
@@ -1186,6 +277,16 @@ httpServer.listen(PORT, () => {
1186
277
 
1187
278
  Here are the details for the values needed by the `startHonoSSE` method:
1188
279
 
280
+ **url:** (`URL`): The web address the user is requesting.
281
+
282
+ **ssePath:** (`string`): The specific part of the URL where clients will connect for SSE (e.g., '/hono-sse').
283
+
284
+ **messagePath:** (`string`): The specific part of the URL where clients will send messages (e.g., '/message').
285
+
286
+ **req:** (`any`): The incoming request object from your web server.
287
+
288
+ **res:** (`any`): The response object from your web server, used to send data back.
289
+
1189
290
  ### startHTTP()
1190
291
 
1191
292
  This method helps you integrate the MCP server with an existing web server to use streamable HTTP for communication. You'll call this from your web server's code when it receives HTTP requests.
@@ -1268,37 +369,58 @@ serve(async (req) => {
1268
369
  });
1269
370
  ```
1270
371
 
1271
- > **Note:**
372
+ > **Info:** **When to use `serverless: true`**
373
+ >
374
+ > Use `serverless: true` when deploying to environments where each request runs in a fresh, stateless execution context:
375
+ >
376
+ > - Supabase Edge Functions
377
+ > - Cloudflare Workers
378
+ > - Vercel Edge Functions
379
+ > - Netlify Edge Functions
380
+ > - AWS Lambda
381
+ > - Deno Deploy
382
+ >
383
+ > Use the default session-based mode (without `serverless: true`) for:
384
+ >
385
+ > - Long-lived Node.js servers
386
+ > - Docker containers
387
+ > - Traditional hosting (VPS, dedicated servers)
388
+ >
389
+ > The serverless mode disables session management and creates fresh server instances per request, which is necessary for stateless environments where memory doesn't persist between invocations.
390
+ >
391
+ > **Note:** The following MCP features require session state or persistent connections and will **not work** in serverless mode:
392
+ >
393
+ > - **Elicitation** - Interactive user input requests during tool execution require session management to route responses back to the correct client
394
+ > - **Resource subscriptions** - `resources/subscribe` and `resources/unsubscribe` need persistent connections to maintain subscription state
395
+ > - **Resource update notifications** - `resources.notifyUpdated()` requires active subscriptions and persistent connections to notify clients
396
+ > - **Prompt list change notifications** - `prompts.notifyListChanged()` requires persistent connections to push updates to clients
397
+ >
398
+ > These features work normally in long-lived server environments (Node.js servers, Docker containers, etc.).
1272
399
 
1273
- **When to use `serverless: true`**
1274
-
1275
- Use `serverless: true` when deploying to environments where each request runs in a fresh, stateless execution context:
1276
- - Supabase Edge Functions
1277
- - Cloudflare Workers
1278
- - Vercel Edge Functions
1279
- - Netlify Edge Functions
1280
- - AWS Lambda
1281
- - Deno Deploy
400
+ Here are the details for the values needed by the `startHTTP` method:
1282
401
 
1283
- Use the default session-based mode (without `serverless: true`) for:
1284
- - Long-lived Node.js servers
1285
- - Docker containers
1286
- - Traditional hosting (VPS, dedicated servers)
402
+ **url:** (`URL`): The web address the user is requesting.
1287
403
 
1288
- The serverless mode disables session management and creates fresh server instances per request, which is necessary for stateless environments where memory doesn't persist between invocations.
404
+ **httpPath:** (`string`): The specific part of the URL where the MCP server will handle HTTP requests (e.g., '/mcp').
1289
405
 
1290
- **Note:** The following MCP features require session state or persistent connections and will **not work** in serverless mode:
1291
- - **Elicitation** - Interactive user input requests during tool execution require session management to route responses back to the correct client
1292
- - **Resource subscriptions** - `resources/subscribe` and `resources/unsubscribe` need persistent connections to maintain subscription state
1293
- - **Resource update notifications** - `resources.notifyUpdated()` requires active subscriptions and persistent connections to notify clients
1294
- - **Prompt list change notifications** - `prompts.notifyListChanged()` requires persistent connections to push updates to clients
406
+ **req:** (`http.IncomingMessage`): The incoming request object from your web server.
1295
407
 
1296
- These features work normally in long-lived server environments (Node.js servers, Docker containers, etc.).
408
+ **res:** (`http.ServerResponse`): The response object from your web server, used to send data back.
1297
409
 
1298
- Here are the details for the values needed by the `startHTTP` method:
410
+ **options:** (`StreamableHTTPServerTransportOptions`): Optional configuration for the HTTP transport. See the options table below for more details.
1299
411
 
1300
412
  The `StreamableHTTPServerTransportOptions` object allows you to customize the behavior of the HTTP transport. Here are the available options:
1301
413
 
414
+ **serverless:** (`boolean`): If \`true\`, runs in stateless mode without session management. Each request is handled independently with a fresh server instance. Essential for serverless environments (Cloudflare Workers, Supabase Edge Functions, Vercel Edge, etc.) where sessions cannot persist between invocations. Defaults to \`false\`.
415
+
416
+ **sessionIdGenerator:** (`(() => string) | undefined`): A function that generates a unique session ID. This should be a cryptographically secure, globally unique string. Return \`undefined\` to disable session management.
417
+
418
+ **onsessioninitialized:** (`(sessionId: string) => void`): A callback that is invoked when a new session is initialized. This is useful for tracking active MCP sessions.
419
+
420
+ **enableJsonResponse:** (`boolean`): If \`true\`, the server will return plain JSON responses instead of using Server-Sent Events (SSE) for streaming. Defaults to \`false\`.
421
+
422
+ **eventStore:** (`EventStore`): An event store for message resumability. Providing this enables clients to reconnect and resume message streams.
423
+
1302
424
  ### close()
1303
425
 
1304
426
  This method closes the server and releases all resources.
@@ -1391,6 +513,12 @@ async executeTool(
1391
513
  ): Promise<any>
1392
514
  ```
1393
515
 
516
+ **toolId:** (`string`): The ID/name of the tool to execute.
517
+
518
+ **args:** (`any`): The arguments to pass to the tool's execute function.
519
+
520
+ **executionContext?:** (`object`): Optional context for the tool execution, like messages or a toolCallId.
521
+
1394
522
  ## Resource Handling
1395
523
 
1396
524
  ### What are MCP Resources?
@@ -1408,8 +536,8 @@ Resources are identified by unique URIs (e.g., `file:///home/user/documents/repo
1408
536
 
1409
537
  Clients can discover resources through:
1410
538
 
1411
- 1. **Direct resources**: Servers expose a list of concrete resources via a `resources/list` endpoint.
1412
- 2. **Resource templates**: For dynamic resources, servers can expose URI templates (RFC 6570) that clients use to construct resource URIs.
539
+ 1. **Direct resources**: Servers expose a list of concrete resources via a `resources/list` endpoint.
540
+ 2. **Resource templates**: For dynamic resources, servers can expose URI templates (RFC 6570) that clients use to construct resource URIs.
1413
541
 
1414
542
  To read a resource, clients make a `resources/read` request with the URI. Servers can also notify clients about changes to the resource list (`notifications/resources/list_changed`) or updates to specific resource content (`notifications/resources/updated`) if a client has subscribed to that resource.
1415
543
 
@@ -1643,11 +771,11 @@ await serverWithPrompts.prompts.notifyListChanged();
1643
771
  - Handle errors with informative messages.
1644
772
  - Document argument expectations and available versions.
1645
773
 
1646
- ---
774
+ ***
1647
775
 
1648
776
  ## Examples
1649
777
 
1650
- For practical examples of setting up and deploying an MCPServer, see the [Publishing an MCP Server guide](https://mastra.ai/docs/v1/mcp/publishing-mcp-server).
778
+ For practical examples of setting up and deploying an MCPServer, see the [Publishing an MCP Server guide](https://mastra.ai/docs/mcp/publishing-mcp-server).
1651
779
 
1652
780
  The example at the beginning of this page also demonstrates how to instantiate `MCPServer` with both tools and agents.
1653
781
 
@@ -1949,6 +1077,18 @@ const customMiddleware = createOAuthMiddleware({
1949
1077
 
1950
1078
  ### OAuth Middleware Options
1951
1079
 
1080
+ **oauth.resource:** (`string`): The canonical URL of your MCP server. This is returned in Protected Resource Metadata.
1081
+
1082
+ **oauth.authorizationServers:** (`string[]`): URLs of authorization servers that can issue tokens for this resource.
1083
+
1084
+ **oauth.scopesSupported?:** (`string[]`): Scopes supported by this MCP server. (Default: `['mcp:read', 'mcp:write']`)
1085
+
1086
+ **oauth.resourceName?:** (`string`): Human-readable name for this resource server.
1087
+
1088
+ **oauth.validateToken?:** (`(token: string, resource: string) => Promise<TokenValidationResult>`): Function to validate access tokens. If not provided, tokens are accepted without validation (NOT recommended for production).
1089
+
1090
+ **mcpPath?:** (`string`): Path where the MCP endpoint is served. Only requests to this path require authentication. (Default: `'/mcp'`)
1091
+
1952
1092
  ## Authentication Context
1953
1093
 
1954
1094
  Tools can access request metadata via `context.mcp.extra` when using HTTP-based transports. This allows you to pass authentication info, user context, or any custom data from your HTTP middleware to your MCP tools.
@@ -1957,7 +1097,7 @@ Tools can access request metadata via `context.mcp.extra` when using HTTP-based
1957
1097
 
1958
1098
  Whatever you set on `req.auth` in your HTTP middleware becomes available as `context.mcp.extra.authInfo` in your tools:
1959
1099
 
1960
- ```
1100
+ ```text
1961
1101
  req.auth = { ... } → context?.mcp?.extra?.authInfo.extra = { ... }
1962
1102
  ```
1963
1103
 
@@ -2017,17 +1157,46 @@ execute: async (inputData, context) => {
2017
1157
  };
2018
1158
  ```
2019
1159
 
1160
+ ### Passing `RequestContext` through to agent
1161
+
1162
+ ```typescript
1163
+ execute: async (inputData, context) => {
1164
+ // Access the auth data you set in middleware
1165
+ const authInfo = context?.mcp?.extra?.authInfo;
1166
+
1167
+ const requestContext = context.requestContext || new RequestContext().set('someKey', authInfo)
1168
+
1169
+ if (!authInfo?.extra?.userId) {
1170
+ return { error: "Authentication required" };
1171
+ }
1172
+
1173
+ // Use the auth data
1174
+ console.log("User ID:", authInfo.extra.userId);
1175
+ console.log("Email:", authInfo.extra.email);
1176
+
1177
+ const agent = context?.mastra?.getAgentById('some-agent-id');
1178
+
1179
+ if (!agent) {
1180
+ return { error: "Agent 'some-agent-id' not found" }
1181
+ }
1182
+
1183
+ const response = await agent.generate(prompt, { requestContext })
1184
+
1185
+ return response.text
1186
+ };
1187
+ ```
1188
+
2020
1189
  ### The `extra` Object
2021
1190
 
2022
1191
  The full `context.mcp.extra` object contains:
2023
1192
 
2024
- | Property | Description |
2025
- |----------|-------------|
2026
- | `authInfo` | Whatever you set on `req.auth` in your middleware |
2027
- | `sessionId` | Session identifier for the MCP connection |
2028
- | `signal` | AbortSignal for request cancellation |
2029
- | `sendNotification` | MCP protocol function for sending notifications |
2030
- | `sendRequest` | MCP protocol function for sending requests |
1193
+ | Property | Description |
1194
+ | ------------------ | ------------------------------------------------- |
1195
+ | `authInfo` | Whatever you set on `req.auth` in your middleware |
1196
+ | `sessionId` | Session identifier for the MCP connection |
1197
+ | `signal` | AbortSignal for request cancellation |
1198
+ | `sendNotification` | MCP protocol function for sending notifications |
1199
+ | `sendRequest` | MCP protocol function for sending requests |
2031
1200
 
2032
1201
  ### Complete Example
2033
1202
 
@@ -2102,205 +1271,5 @@ app.listen(3000);
2102
1271
 
2103
1272
  ## Related Information
2104
1273
 
2105
- - For connecting to MCP servers in Mastra, see the [MCPClient documentation](./mcp-client).
2106
- - For more about the Model Context Protocol, see the [@modelcontextprotocol/sdk documentation](https://github.com/modelcontextprotocol/typescript-sdk).
2107
-
2108
- ---
2109
-
2110
- ## Reference: MastraMCPClient (Deprecated)
2111
-
2112
- > API Reference for MastraMCPClient - A client implementation for the Model Context Protocol.
2113
-
2114
- The `MastraMCPClient` class provides a client implementation for interacting with Model Context Protocol (MCP) servers. It handles connection management, resource discovery, and tool execution through the MCP protocol.
2115
-
2116
- ## Deprecation notice
2117
-
2118
- `MastraMCPClient` is being deprecated in favour of [`MCPClient`](./mcp-client). Rather than having two different interfaces for managing a single MCP server vs multiple MCP servers, we opted to recommend using the interface to manage multiple even when using a single MCP server.
2119
-
2120
- ## Constructor
2121
-
2122
- Creates a new instance of the MastraMCPClient.
2123
-
2124
- ```typescript
2125
- constructor({
2126
- name,
2127
- version = '1.0.0',
2128
- server,
2129
- capabilities = {},
2130
- timeout = 60000,
2131
- }: {
2132
- name: string;
2133
- server: MastraMCPServerDefinition;
2134
- capabilities?: ClientCapabilities;
2135
- version?: string;
2136
- timeout?: number;
2137
- })
2138
- ```
2139
-
2140
- ### Parameters
2141
-
2142
- <br />
2143
-
2144
- ### MastraMCPServerDefinition
2145
-
2146
- MCP servers can be configured using this definition. The client automatically detects the transport type based on the provided parameters:
2147
-
2148
- - If `command` is provided, it uses the Stdio transport.
2149
- - If `url` is provided, it first attempts to use the Streamable HTTP transport and falls back to the legacy SSE transport if the initial connection fails.
2150
-
2151
- <br />
2152
-
2153
- ### LogHandler
2154
-
2155
- The `LogHandler` function takes a `LogMessage` object as its parameter and returns void. The `LogMessage` object has the following properties. The `LoggingLevel` type is a string enum with values: `debug`, `info`, `warn`, and `error`.
2156
-
2157
- <br />
2158
-
2159
- ## Methods
2160
-
2161
- ### connect()
2162
-
2163
- Establishes a connection with the MCP server.
2164
-
2165
- ```typescript
2166
- async connect(): Promise<void>
2167
- ```
2168
-
2169
- ### disconnect()
2170
-
2171
- Closes the connection with the MCP server.
2172
-
2173
- ```typescript
2174
- async disconnect(): Promise<void>
2175
- ```
2176
-
2177
- ### resources()
2178
-
2179
- Retrieves the list of available resources from the server.
2180
-
2181
- ```typescript
2182
- async resources(): Promise<ListResourcesResult>
2183
- ```
2184
-
2185
- ### tools()
2186
-
2187
- Fetches and initializes available tools from the server, converting them into Mastra-compatible tool formats.
2188
-
2189
- ```typescript
2190
- async tools(): Promise<Record<string, Tool>>
2191
- ```
2192
-
2193
- Returns an object mapping tool names to their corresponding Mastra tool implementations.
2194
-
2195
- ## Examples
2196
-
2197
- ### Using with Mastra Agent
2198
-
2199
- #### Example with Stdio Server
2200
-
2201
- ```typescript
2202
- import { Agent } from "@mastra/core/agent";
2203
- import { MastraMCPClient } from "@mastra/mcp";
2204
-
2205
- // Initialize the MCP client using mcp/fetch as an example https://hub.docker.com/r/mcp/fetch
2206
- // Visit https://github.com/docker/mcp-servers for other reference docker mcp servers
2207
- const fetchClient = new MastraMCPClient({
2208
- name: "fetch",
2209
- server: {
2210
- command: "docker",
2211
- args: ["run", "-i", "--rm", "mcp/fetch"],
2212
- logger: (logMessage) => {
2213
- console.log(`[${logMessage.level}] ${logMessage.message}`);
2214
- },
2215
- },
2216
- });
2217
-
2218
- // Create a Mastra Agent
2219
- const agent = new Agent({
2220
- name: "Fetch agent",
2221
- instructions:
2222
- "You are able to fetch data from URLs on demand and discuss the response data with the user.",
2223
- model: "openai/gpt-5.1",
2224
- });
2225
-
2226
- try {
2227
- // Connect to the MCP server
2228
- await fetchClient.connect();
2229
-
2230
- // Gracefully handle process exits so the docker subprocess is cleaned up
2231
- process.on("exit", () => {
2232
- fetchClient.disconnect();
2233
- });
2234
-
2235
- // Get available tools
2236
- const tools = await fetchClient.tools();
2237
-
2238
- // Use the agent with the MCP tools
2239
- const response = await agent.generate(
2240
- "Tell me about mastra.ai/docs. Tell me generally what this page is and the content it includes.",
2241
- {
2242
- toolsets: {
2243
- fetch: tools,
2244
- },
2245
- },
2246
- );
2247
-
2248
- console.log("\n\n" + response.text);
2249
- } catch (error) {
2250
- console.error("Error:", error);
2251
- } finally {
2252
- // Always disconnect when done
2253
- await fetchClient.disconnect();
2254
- }
2255
- ```
2256
-
2257
- ### Example with SSE Server
2258
-
2259
- ```typescript
2260
- // Initialize the MCP client using an SSE server
2261
- const sseClient = new MastraMCPClient({
2262
- name: "sse-client",
2263
- server: {
2264
- url: new URL("https://your-mcp-server.com/sse"),
2265
- // Optional fetch request configuration - Note: requestInit alone isn't enough for SSE
2266
- requestInit: {
2267
- headers: {
2268
- Authorization: "Bearer your-token",
2269
- },
2270
- },
2271
- // Required for SSE connections with custom headers
2272
- eventSourceInit: {
2273
- fetch(input: Request | URL | string, init?: RequestInit) {
2274
- const headers = new Headers(init?.headers || {});
2275
- headers.set("Authorization", "Bearer your-token");
2276
- return fetch(input, {
2277
- ...init,
2278
- headers,
2279
- });
2280
- },
2281
- },
2282
- // Optional additional logging configuration
2283
- logger: (logMessage) => {
2284
- console.log(
2285
- `[${logMessage.level}] ${logMessage.serverName}: ${logMessage.message}`,
2286
- );
2287
- },
2288
- // Disable server logs
2289
- enableServerLogs: false,
2290
- },
2291
- });
2292
-
2293
- // The rest of the usage is identical to the stdio example
2294
- ```
2295
-
2296
- ### Important Note About SSE Authentication
2297
-
2298
- When using SSE connections with authentication or custom headers, you need to configure both `requestInit` and `eventSourceInit`. This is because SSE connections use the browser's EventSource API, which doesn't support custom headers directly.
2299
-
2300
- The `eventSourceInit` configuration allows you to customize the underlying fetch request used for the SSE connection, ensuring your authentication headers are properly included.
2301
- Without `eventSourceInit`, authentication headers specified in `requestInit` won't be included in the connection request, leading to 401 Unauthorized errors.
2302
-
2303
- ## Related Information
2304
-
2305
- - For managing multiple MCP servers in your application, see the [MCPClient documentation](./mcp-client)
2306
- - For more details about the Model Context Protocol, see the [@modelcontextprotocol/sdk documentation](https://github.com/modelcontextprotocol/typescript-sdk).
1274
+ - For connecting to MCP servers in Mastra, see the [MCPClient documentation](https://mastra.ai/reference/tools/mcp-client).
1275
+ - For more about the Model Context Protocol, see the [@modelcontextprotocol/sdk documentation](https://github.com/modelcontextprotocol/typescript-sdk).