@mastra/mcp 1.15.1 → 1.16.0-alpha.0

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 +59 -0
  2. package/dist/client/actions/elicitation.d.ts +1 -1
  3. package/dist/client/actions/elicitation.d.ts.map +1 -1
  4. package/dist/client/actions/progress.d.ts +1 -1
  5. package/dist/client/actions/progress.d.ts.map +1 -1
  6. package/dist/client/actions/prompt.d.ts +1 -1
  7. package/dist/client/actions/prompt.d.ts.map +1 -1
  8. package/dist/client/actions/resource.d.ts +38 -11
  9. package/dist/client/actions/resource.d.ts.map +1 -1
  10. package/dist/client/client.d.ts +3 -2
  11. package/dist/client/client.d.ts.map +1 -1
  12. package/dist/client/configuration.d.ts +50 -14
  13. package/dist/client/configuration.d.ts.map +1 -1
  14. package/dist/client/types.d.ts +65 -10
  15. package/dist/client/types.d.ts.map +1 -1
  16. package/dist/client/url-policy.d.ts +67 -0
  17. package/dist/client/url-policy.d.ts.map +1 -0
  18. package/dist/docs/SKILL.md +3 -3
  19. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  20. package/dist/docs/references/docs-connections-overview.md +94 -0
  21. package/dist/docs/references/docs-mcp-overview.md +229 -278
  22. package/dist/docs/references/reference-tools-mcp-client.md +54 -0
  23. package/dist/docs/references/reference-tools-mcp-server.md +1 -1
  24. package/dist/index.cjs +2435 -275
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +2403 -243
  27. package/dist/index.js.map +1 -1
  28. package/dist/server/__tests__/mock-extra.d.ts +15 -0
  29. package/dist/server/__tests__/mock-extra.d.ts.map +1 -0
  30. package/dist/server/notificationBroadcast.d.ts +1 -1
  31. package/dist/server/notificationBroadcast.d.ts.map +1 -1
  32. package/dist/server/promptActions.d.ts +1 -1
  33. package/dist/server/promptActions.d.ts.map +1 -1
  34. package/dist/server/resourceActions.d.ts +1 -1
  35. package/dist/server/resourceActions.d.ts.map +1 -1
  36. package/dist/server/server.d.ts +10 -12
  37. package/dist/server/server.d.ts.map +1 -1
  38. package/dist/server/toolActions.d.ts +1 -1
  39. package/dist/server/toolActions.d.ts.map +1 -1
  40. package/dist/server/types.d.ts +7 -7
  41. package/dist/server/types.d.ts.map +1 -1
  42. package/dist/shared/oauth-types.d.ts +8 -6
  43. package/dist/shared/oauth-types.d.ts.map +1 -1
  44. package/package.json +18 -14
  45. package/dist/docs/references/docs-mcp-mcp-apps.md +0 -306
@@ -2,18 +2,13 @@
2
2
 
3
3
  # MCP overview
4
4
 
5
- Mastra supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open standard for connecting AI agents to external tools and resources. It's a universal plugin system, enabling agents to call tools regardless of language or hosting environment.
5
+ Mastra supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction), an open standard for connecting AI agents to external tools and resources.
6
6
 
7
- Mastra can also be used to author MCP servers, exposing agents, tools, and other structured resources via the MCP interface. These can then be accessed by any system or agent that supports the protocol.
7
+ Use [`MCPClient`](https://mastra.ai/reference/tools/mcp-client) to connect to MCP servers. Use [`MCPServer`](https://mastra.ai/reference/tools/mcp-server) to expose Mastra agents, tools, workflows, prompts, and resources to other MCP-compatible systems.
8
8
 
9
- Mastra currently supports two MCP classes:
9
+ ## Connect to MCP servers
10
10
 
11
- 1. `MCPClient`: Connects to one or many MCP servers to access their tools, resources, prompts, and handle elicitation requests.
12
- 2. `MCPServer`: Exposes Mastra tools, agents, workflows, prompts, and resources to MCP-compatible clients.
13
-
14
- ## Get started
15
-
16
- To use MCP, install the required dependency:
11
+ Install the MCP package:
17
12
 
18
13
  **npm**:
19
14
 
@@ -39,382 +34,338 @@ yarn add @mastra/mcp@latest
39
34
  bun add @mastra/mcp@latest
40
35
  ```
41
36
 
42
- ## Configuring `MCPClient`
43
-
44
- The `MCPClient` connects Mastra primitives to external MCP servers, which can be local packages (invoked using `npx`) or remote HTTP(S) endpoints. Each server must be configured with either a `command` or a `url`, depending on how it's hosted.
37
+ Configure each server with a local command or remote URL:
45
38
 
46
39
  ```typescript
47
40
  import { MCPClient } from '@mastra/mcp'
48
41
 
49
- export const testMcpClient = new MCPClient({
50
- id: 'test-mcp-client',
42
+ export const mcpClient = new MCPClient({
43
+ id: 'my-mcp-client',
51
44
  servers: {
52
45
  wikipedia: {
53
46
  command: 'npx',
54
47
  args: ['-y', 'wikipedia-mcp'],
55
48
  },
56
49
  weather: {
57
- url: new URL(
58
- `https://server.smithery.ai/@smithery-ai/national-weather-service/mcp?api_key=${process.env.SMITHERY_API_KEY}`,
59
- ),
50
+ url: new URL('https://weather.example.com/mcp'),
51
+ requestInit: {
52
+ headers: {
53
+ Authorization: `Bearer ${process.env.WEATHER_API_KEY}`,
54
+ },
55
+ },
60
56
  },
61
57
  },
62
58
  })
63
59
  ```
64
60
 
65
- Visit [MCPClient](https://mastra.ai/reference/tools/mcp-client) for a full list of configuration options.
66
-
67
- > **Authentication:** For connecting to OAuth-protected MCP servers, including completing the browser-based authorization flow with `authenticate()`, see the [OAuth Authentication](https://mastra.ai/reference/tools/mcp-client) section.
68
-
69
- ## Using `MCPClient` with an agent
61
+ > **Authentication:** For OAuth-protected servers, use `authenticate()` to complete the browser-based authorization flow. Visit [OAuth authentication](https://mastra.ai/reference/tools/mcp-client) for configuration details.
70
62
 
71
- To use tools from an MCP server in an agent, import your `MCPClient` and call `.listTools()` in the `tools` parameter. This loads from the defined MCP servers, making them available to the agent.
63
+ Pass tools from the configured servers to an agent:
72
64
 
73
65
  ```typescript
74
66
  import { Agent } from '@mastra/core/agent'
75
- import { testMcpClient } from '../mcp/test-mcp-client'
67
+ import { mcpClient } from '../mcp/client'
76
68
 
77
- export const testAgent = new Agent({
78
- id: 'test-agent',
79
- name: 'Test Agent',
80
- description: 'You are a helpful AI assistant',
69
+ export const assistant = new Agent({
70
+ id: 'assistant',
71
+ name: 'Assistant',
81
72
  instructions: `
82
- You are a helpful assistant that has access to the following MCP Servers.
83
- - Wikipedia MCP Server
84
- - US National Weather Service
85
-
86
- Answer questions using the information you find using the MCP Servers.`,
73
+ Use the available MCP tools to answer questions.
74
+ Include the source of any information you retrieve.
75
+ `,
87
76
  model: 'openai/gpt-5.6-sol',
88
- tools: await testMcpClient.listTools(),
77
+ tools: await mcpClient.listTools(),
89
78
  })
90
79
  ```
91
80
 
92
- Visit [Agent Class](https://mastra.ai/reference/agents/agent) for a full list of configuration options.
81
+ ### Static and runtime tools
82
+
83
+ Choose how to load tools based on whether the server configuration changes between requests:
84
+
85
+ | | Static tools | Runtime toolsets |
86
+ | ----------- | ---------------------------------- | ---------------------------------------- |
87
+ | Method | `await mcpClient.listTools()` | `await mcpClient.listToolsets()` |
88
+ | Use case | Shared, fixed configuration | Per-user or per-request configuration |
89
+ | Credentials | Shared by all requests | Can vary between requests |
90
+ | Agent API | `tools` in the `Agent` constructor | `toolsets` in `generate()` or `stream()` |
91
+
92
+ The preceding agent example uses static tools. For runtime credentials, create a client for the request and pass its toolsets when calling the agent:
93
+
94
+ ```typescript
95
+ import { MCPClient } from '@mastra/mcp'
96
+ import { mastra } from './mastra'
97
+
98
+ export async function handleRequest(prompt: string, apiKey: string) {
99
+ const userMcpClient = new MCPClient({
100
+ servers: {
101
+ weather: {
102
+ url: new URL('https://weather.example.com/mcp'),
103
+ requestInit: {
104
+ headers: { Authorization: `Bearer ${apiKey}` },
105
+ },
106
+ },
107
+ },
108
+ })
109
+
110
+ const agent = mastra.getAgent('assistant')
111
+ const response = await agent.generate(prompt, {
112
+ toolsets: await userMcpClient.listToolsets(),
113
+ })
114
+
115
+ await userMcpClient.disconnect()
116
+ return response.text
117
+ }
118
+ ```
119
+
120
+ Visit [`listTools()`](https://mastra.ai/reference/tools/mcp-client) and [`listToolsets()`](https://mastra.ai/reference/tools/mcp-client) for their full APIs.
93
121
 
94
- ## Tool approval
122
+ ### Tool approval
95
123
 
96
- You can require human approval before MCP tools are executed by setting `requireToolApproval` on a server definition. This integrates with the existing [human-in-the-loop](https://mastra.ai/docs/workflows/human-in-the-loop) approval flow.
124
+ Set `requireToolApproval` on a server to require approval for all its tools:
97
125
 
98
126
  ```typescript
99
- export const mcp = new MCPClient({
127
+ const mcpClient = new MCPClient({
100
128
  servers: {
101
129
  github: {
102
- url: new URL('http://localhost:3000/mcp'),
130
+ url: new URL('https://github.example.com/mcp'),
103
131
  requireToolApproval: true,
104
132
  },
105
133
  },
106
134
  })
107
135
  ```
108
136
 
109
- You can also pass a function to decide per runtime-call. See the [MCPClient reference](https://mastra.ai/reference/tools/mcp-client) for the full API.
110
-
111
- ## Configuring `MCPServer`
112
-
113
- To expose agents, tools, and workflows from your Mastra application to external systems over HTTP(S) use the `MCPServer` class. This makes them accessible to any system or agent that supports the protocol.
137
+ You can also provide a function that decides based on the tool name, arguments, or annotations:
114
138
 
115
139
  ```typescript
116
- import { MCPServer } from '@mastra/mcp'
117
-
118
- import { testAgent } from '../agents/test-agent'
119
- import { testWorkflow } from '../workflows/test-workflow'
120
- import { testTool } from '../tools/test-tool'
121
-
122
- export const testMcpServer = new MCPServer({
123
- id: 'test-mcp-server',
124
- name: 'Test Server',
125
- version: '1.0.0',
126
- agents: { testAgent },
127
- tools: { testTool },
128
- workflows: { testWorkflow },
129
- })
140
+ requireToolApproval: ({ toolName }) => toolName.startsWith('delete_')
130
141
  ```
131
142
 
132
- Visit [MCPServer](https://mastra.ai/reference/tools/mcp-server) for a full list of configuration options.
143
+ Treat tool annotations from servers you don't control as untrusted hints. Visit [tool approval](https://mastra.ai/reference/tools/mcp-client) for the callback context and security guidance.
133
144
 
134
- > **Authentication:** To protect your MCP server with OAuth, see the [OAuth Protection](https://mastra.ai/reference/tools/mcp-server) section.
145
+ ### Security
135
146
 
136
- ## Registering an `MCPServer`
147
+ MCP servers run code and return content on your agent's behalf, so configure them with the same care as any other external dependency:
137
148
 
138
- To make an MCP server available to other systems or agents that support the protocol, register it in the main `Mastra` instance using `mcpServers`.
149
+ - **Stdio subprocess environment**: subprocesses inherit only the MCP SDK's curated environment whitelist (for example `PATH` and `HOME` on POSIX), not the full parent environment. Set `inheritDefaultEnv: false` on a server to pass only the variables you list in `env`.
150
+ - **Outbound host restriction**: when HTTP server URLs come from untrusted configuration, set `allowedHosts` to restrict which hosts the client will contact. On the default fetch path this also blocks redirect hops before they're sent; a custom `fetch` gets its final response URL validated after the request runs, so it must enforce redirect policy itself when preventing outbound contact is required.
151
+ - **Tool response trust**: tool results are untrusted model input. Use [input and output processors](https://mastra.ai/docs/agents/processors) to inspect or sanitize content before it reaches the model, and `requireToolApproval` to gate sensitive tools.
139
152
 
140
- ```typescript
141
- import { Mastra } from '@mastra/core/mastra'
153
+ Visit the [MCPClient security reference](https://mastra.ai/reference/tools/mcp-client) for enforcement details of each option.
142
154
 
143
- import { testMcpServer } from './mcp/test-mcp-server'
155
+ ### MCP registries
144
156
 
145
- export const mastra = new Mastra({
146
- mcpServers: { testMcpServer },
147
- })
148
- ```
157
+ Registries provide hosted or packaged MCP servers. The client configuration above works with registry endpoints and commands.
149
158
 
150
- ## Static and runtime tools
159
+ | Registry | Connection | Notes |
160
+ | ----------------------------------------------- | ----------------- | --------------------------------------------- |
161
+ | [Klavis AI](https://klavis.ai) | Hosted HTTP | Enterprise authentication and managed servers |
162
+ | [mcp.run](https://www.mcp.run/) | Signed SSE URL | Treat the profile URL as a secret |
163
+ | [Composio](https://mcp.composio.dev) | Hosted SSE URL | URLs are often tied to one user account |
164
+ | [Smithery](https://smithery.ai) | CLI or hosted URL | Run local packages through `npx` |
165
+ | [Apify](https://mcp.apify.com) | Hosted HTTP | Authenticate with an Apify API token |
166
+ | [Ampersand](https://docs.withampersand.com/mcp) | SSE or stdio | Connect to configured SaaS integrations |
151
167
 
152
- `MCPClient` offers two approaches to retrieving tools from connected servers, suitable for different application architectures:
168
+ Store signed URLs, API keys, and tokens in environment variables. Follow the registry's documentation to obtain the endpoint, command, and credentials for each server.
153
169
 
154
- | Feature | Static Configuration (`await mcp.listTools()`) | Dynamic Configuration (`await mcp.listToolsets()`) |
155
- | ----------------- | ---------------------------------------------- | ---------------------------------------------------- |
156
- | **Use Case** | Single-user, static config (e.g., CLI tool) | Multi-user, runtime config (e.g., SaaS app) |
157
- | **Configuration** | Fixed at agent initialization | Per-request, runtime |
158
- | **Credentials** | Shared across all uses | Can vary per user/request |
159
- | **Agent Setup** | Tools added in `Agent` constructor | Tools passed in `.generate()` or `.stream()` options |
170
+ ## Expose a Mastra MCP server
160
171
 
161
- ### Static tools
162
-
163
- Use the `.listTools()` method to fetch tools from all configured MCP servers. This is suitable when configuration (such as API keys) is static and consistent across users or requests. Call it once and pass the result to the `tools` property when defining your agent. Visit [listTools()](https://mastra.ai/reference/tools/mcp-client) for more information.
172
+ Create an `MCPServer` to expose Mastra primitives to external MCP clients:
164
173
 
165
174
  ```typescript
166
- import { Agent } from '@mastra/core/agent'
167
-
168
- import { testMcpClient } from '../mcp/test-mcp-client'
175
+ import { MCPServer } from '@mastra/mcp'
176
+ import { assistant } from '../agents/assistant'
177
+ import { weatherTool } from '../tools/weather'
178
+ import { weatherWorkflow } from '../workflows/weather'
169
179
 
170
- export const testAgent = new Agent({
171
- id: 'test-agent',
172
- tools: await testMcpClient.listTools(),
180
+ export const mcpServer = new MCPServer({
181
+ id: 'my-mcp-server',
182
+ name: 'My MCP Server',
183
+ version: '1.0.0',
184
+ agents: { assistant },
185
+ tools: { weatherTool },
186
+ workflows: { weatherWorkflow },
173
187
  })
174
188
  ```
175
189
 
176
- ### Dynamic tools
177
-
178
- Use the `.listToolsets()` method when tool configuration may vary by request or user, such as in a multi-tenant system where each user provides their own API key. This method returns toolsets that can be passed to the `toolsets` option in the agent's `.generate()` or `.stream()` calls.
190
+ Register the server on the main `Mastra` instance:
179
191
 
180
192
  ```typescript
181
- import { MCPClient } from '@mastra/mcp'
182
- import { mastra } from './mastra'
183
-
184
- async function handleRequest(userPrompt: string, userApiKey: string) {
185
- const userMcp = new MCPClient({
186
- servers: {
187
- weather: {
188
- url: new URL('http://localhost:8080/mcp'),
189
- requestInit: {
190
- headers: {
191
- Authorization: `Bearer ${userApiKey}`,
192
- },
193
- },
194
- },
195
- },
196
- })
197
-
198
- const agent = mastra.getAgent('testAgent')
193
+ import { Mastra } from '@mastra/core/mastra'
194
+ import { mcpServer } from './mcp/server'
199
195
 
200
- const response = await agent.generate(userPrompt, {
201
- toolsets: await userMcp.listToolsets(),
202
- })
196
+ export const mastra = new Mastra({
197
+ mcpServers: { mcpServer },
198
+ })
199
+ ```
203
200
 
204
- await userMcp.disconnect()
201
+ > **Authentication:** Protect HTTP MCP servers with OAuth middleware. Visit [OAuth protection](https://mastra.ai/reference/tools/mcp-server) for setup instructions.
205
202
 
206
- return Response.json({
207
- data: response.text,
208
- })
209
- }
210
- ```
203
+ Visit the [`MCPServer` reference](https://mastra.ai/reference/tools/mcp-server) for prompts, resources, transports, and other server options.
211
204
 
212
- Visit [listToolsets()](https://mastra.ai/reference/tools/mcp-client) for more information.
205
+ ## Build MCP Apps
213
206
 
214
- ## Connecting to an MCP registry
207
+ The [MCP Apps extension](https://github.com/modelcontextprotocol/ext-apps) lets MCP tools serve interactive HTML interfaces through `ui://` resources. Mastra Studio renders these apps in sandboxed iframes on tool pages and in agent chat.
215
208
 
216
- MCP servers can be discovered through registries. Here's how to connect to some popular ones using `MCPClient`:
209
+ Use an MCP App when a tool result benefits from interaction, such as a form, calculator, color picker, or data visualization.
217
210
 
218
- **Klavis AI**:
211
+ ### Define an app resource
219
212
 
220
- [Klavis AI](https://klavis.ai) provides hosted, enterprise-authenticated, high-quality MCP servers.
213
+ Return a short `content` summary for the model and place UI data in `structuredContent`. Link the tool to its app by setting `_meta.ui.resourceUri` to the same `ui://` URI used in `appResources`:
221
214
 
222
215
  ```typescript
223
- import { MCPClient } from '@mastra/mcp'
216
+ import { MCPServer } from '@mastra/mcp'
217
+ import { createTool } from '@mastra/core/tools'
218
+ import { z } from 'zod'
219
+
220
+ export const calculatorTool = createTool({
221
+ id: 'calculatorWithUI',
222
+ description: 'Calculate the sum of two numbers',
223
+ inputSchema: z.object({
224
+ num1: z.number(),
225
+ num2: z.number(),
226
+ }),
227
+ execute: async ({ num1, num2 }) => ({
228
+ content: [{ type: 'text', text: 'The result is displayed in the calculator app.' }],
229
+ structuredContent: { result: num1 + num2 },
230
+ }),
231
+ })
224
232
 
225
- const mcp = new MCPClient({
226
- servers: {
227
- salesforce: {
228
- url: new URL(
229
- 'https://salesforce-mcp-server.klavis.ai/mcp/?instance_id={private-instance-id}',
230
- ),
231
- },
232
- hubspot: {
233
- url: new URL('https://hubspot-mcp-server.klavis.ai/mcp/?instance_id={private-instance-id}'),
233
+ calculatorTool._meta = {
234
+ ui: { resourceUri: 'ui://calculator/main' },
235
+ }
236
+
237
+ export const calculatorMcpServer = new MCPServer({
238
+ id: 'calculator-app-server',
239
+ name: 'Calculator App Server',
240
+ version: '1.0.0',
241
+ tools: { calculatorTool },
242
+ appResources: {
243
+ 'ui://calculator/main': {
244
+ name: 'Calculator',
245
+ htmlPath: './src/mastra/mcp/calculator.html',
234
246
  },
235
247
  },
236
248
  })
237
249
  ```
238
250
 
239
- Klavis AI offers enterprise-grade authentication and security for production deployments.
251
+ The model sees `content`, while the app receives `structuredContent`. Visit [`appResources`](https://mastra.ai/reference/tools/mcp-server) for inline HTML, file paths, metadata, and content security policy options.
240
252
 
241
- For more details on how to integrate Mastra with Klavis, check out their [documentation](https://docs.klavis.ai/documentation/ai-platform-integration/mastra).
253
+ ### Connect the app to Studio
242
254
 
243
- **mcp.run**:
255
+ Use the `App` class from `@modelcontextprotocol/ext-apps` inside the HTML resource. Register event handlers before calling `connect()`:
244
256
 
245
- [mcp.run](https://www.mcp.run/) provides pre-authenticated, managed MCP servers. Tools are grouped into Profiles, each with a unique, signed URL.
257
+ ```html
258
+ <!doctype html>
259
+ <html>
260
+ <body>
261
+ <p id="result">Waiting for input</p>
262
+ <button id="recalculate">Recalculate</button>
246
263
 
247
- ```typescript
248
- import { MCPClient } from '@mastra/mcp'
249
-
250
- const mcp = new MCPClient({
251
- servers: {
252
- marketing: {
253
- // Example profile name
254
- url: new URL(process.env.MCP_RUN_SSE_URL!), // Get URL from mcp.run profile
255
- },
256
- },
257
- })
258
- ```
264
+ <script type="module">
265
+ import { App } from 'https://cdn.jsdelivr.net/npm/@modelcontextprotocol/ext-apps/+esm'
259
266
 
260
- > **Requirement:** Treat the mcp.run SSE URL like a password. Store it securely, for example, in an environment variable.
261
- >
262
- > ```bash
263
- > MCP_RUN_SSE_URL=https://www.mcp.run/api/mcp/sse?nonce=...
264
- > ```
267
+ const app = new App({ name: 'Calculator', version: '1.0.0' })
268
+ let toolInput
265
269
 
266
- **Composio.dev**:
270
+ app.ontoolinput = params => {
271
+ toolInput = params.arguments
272
+ }
267
273
 
268
- [Composio.dev](https://composio.dev) offers a registry of [SSE-based MCP servers](https://mcp.composio.dev). You can use the SSE URL generated for tools like Cursor directly.
274
+ document.querySelector('#recalculate').addEventListener('click', async () => {
275
+ const result = await app.callServerTool({
276
+ name: 'calculatorWithUI',
277
+ arguments: toolInput,
278
+ })
279
+ document.querySelector('#result').textContent = JSON.stringify(result)
269
280
 
270
- ```typescript
271
- import { MCPClient } from '@mastra/mcp'
281
+ await app.sendMessage({
282
+ role: 'user',
283
+ content: [{ type: 'text', text: 'Explain the recalculated result.' }],
284
+ })
285
+ })
272
286
 
273
- const mcp = new MCPClient({
274
- servers: {
275
- googleSheets: {
276
- url: new URL('https://mcp.composio.dev/googlesheets/[private-url-path]'),
277
- },
278
- gmail: {
279
- url: new URL('https://mcp.composio.dev/gmail/[private-url-path]'),
280
- },
281
- },
282
- })
287
+ await app.connect()
288
+ </script>
289
+ </body>
290
+ </html>
283
291
  ```
284
292
 
285
- Authentication with services like Google Sheets often happens interactively through the agent conversation.
286
-
287
- _Note: Composio URLs are typically tied to a single user account, making them best suited for personal automation rather than multi-tenant applications._
293
+ The guest-side APIs serve different parts of the interaction:
288
294
 
289
- **Smithery.ai**:
295
+ | API | Purpose |
296
+ | ---------------------- | ----------------------------------------------------- |
297
+ | `app.ontoolinput` | Receive the arguments from the host tool call |
298
+ | `app.callServerTool()` | Call an MCP tool from inside the iframe |
299
+ | `app.sendMessage()` | Add a user message to chat and start a new model turn |
300
+ | `app.connect()` | Connect to the host after registering event handlers |
290
301
 
291
- [Smithery.ai](https://smithery.ai) provides a registry accessible via their CLI.
302
+ The interaction follows this sequence:
292
303
 
293
- ```typescript
294
- // Unix/Mac
295
- import { MCPClient } from '@mastra/mcp'
304
+ 1. The agent calls the tool.
305
+ 2. The tool returns model-facing `content` and UI-facing `structuredContent`.
306
+ 3. Studio renders the associated app resource.
307
+ 4. The app receives tool input and can call server tools or send chat messages.
296
308
 
297
- const mcp = new MCPClient({
298
- servers: {
299
- sequentialThinking: {
300
- command: 'npx',
301
- args: [
302
- '-y',
303
- '@smithery/cli@latest',
304
- 'run',
305
- '@smithery-ai/server-sequential-thinking',
306
- '--config',
307
- '{}',
308
- ],
309
- },
310
- },
311
- })
312
- ```
313
-
314
- ```typescript
315
- // Windows
316
- import { MCPClient } from '@mastra/mcp'
317
-
318
- const mcp = new MCPClient({
319
- servers: {
320
- sequentialThinking: {
321
- command: 'npx',
322
- args: [
323
- '-y',
324
- '@smithery/cli@latest',
325
- 'run',
326
- '@smithery-ai/server-sequential-thinking',
327
- '--config',
328
- '{}',
329
- ],
330
- },
331
- },
332
- })
333
- ```
309
+ Visit the external [`App` API reference](https://apps.extensions.modelcontextprotocol.io/api/classes/app.App.html) for all guest-side methods and lifecycle hooks.
334
310
 
335
- **Apify**:
311
+ ### Register MCP Apps
336
312
 
337
- [Apify](https://apify.com) is the largest marketplace of tools for AI, with thousands of ready-made [Actors](https://apify.com/store) to extract real-time data from any website, track competitors, generate leads, analyze sentiment, or orchestrate your apps. Connect your agent through the [Apify MCP Server](https://mcp.apify.com).
313
+ For a local app, pass the tool to an agent and register its MCP server on `Mastra`:
338
314
 
339
315
  ```typescript
340
- import { MCPClient } from '@mastra/mcp'
316
+ import { Agent } from '@mastra/core/agent'
317
+ import { Mastra } from '@mastra/core/mastra'
318
+ import { calculatorMcpServer, calculatorTool } from './mcp/calculator'
319
+
320
+ const calculatorAgent = new Agent({
321
+ id: 'calculator-agent',
322
+ name: 'Calculator Agent',
323
+ instructions: 'Use the calculator tool for arithmetic.',
324
+ model: 'openai/gpt-5-mini',
325
+ tools: { calculatorTool },
326
+ })
341
327
 
342
- export const mcp = new MCPClient({
343
- servers: {
344
- apify: {
345
- url: new URL('https://mcp.apify.com'),
346
- requestInit: {
347
- headers: {
348
- Authorization: `Bearer ${process.env.APIFY_TOKEN}`,
349
- },
350
- },
351
- },
352
- },
328
+ export const mastra = new Mastra({
329
+ agents: { calculatorAgent },
330
+ mcpServers: { calculatorMcpServer },
353
331
  })
354
332
  ```
355
333
 
356
- Get your API token from the [Apify Console](https://console.apify.com/settings/integrations) and store it as `APIFY_TOKEN` in your environment.
334
+ For an external MCP server that implements MCP Apps, load its tools with `MCPClient.listTools()` and register its proxy so Studio can resolve the remote app resources:
357
335
 
358
- To pick specific Actors and tools, use the [Apify MCP server configurator](https://mcp.apify.com) and copy the generated URL.
359
-
360
- **Ampersand**:
336
+ ```typescript
337
+ import { Agent } from '@mastra/core/agent'
338
+ import { Mastra } from '@mastra/core/mastra'
339
+ import { mcpClient } from './mcp/client'
361
340
 
362
- [Ampersand](https://withampersand.com?utm_source=mastra-docs) offers an [MCP Server](https://docs.withampersand.com/mcp) that allows you to connect your agent to 150+ integrations with SaaS products like Salesforce, Hubspot, and Zendesk.
341
+ const tools = await mcpClient.listTools()
342
+ const mcpServers = mcpClient.toMCPServerProxies()
363
343
 
364
- ```typescript
365
- // MCPClient with Ampersand MCP Server using SSE
366
- export const mcp = new MCPClient({
367
- servers: {
368
- '@amp-labs/mcp-server': {
369
- url: `https://mcp.withampersand.com/v1/sse?${new URLSearchParams({
370
- apiKey: process.env.AMPERSAND_API_KEY,
371
- project: process.env.AMPERSAND_PROJECT_ID,
372
- integrationName: process.env.AMPERSAND_INTEGRATION_NAME,
373
- groupRef: process.env.AMPERSAND_GROUP_REF,
374
- })}`,
375
- },
376
- },
344
+ const agent = new Agent({
345
+ id: 'remote-app-agent',
346
+ name: 'Remote App Agent',
347
+ instructions: 'Use the available remote tools.',
348
+ model: 'openai/gpt-5-mini',
349
+ tools,
377
350
  })
378
- ```
379
351
 
380
- ```typescript
381
- // If you prefer to run the MCP server locally:
382
- import { MCPClient } from '@mastra/mcp'
383
-
384
- // MCPClient with Ampersand MCP Server using stdio transport
385
- export const mcp = new MCPClient({
386
- servers: {
387
- '@amp-labs/mcp-server': {
388
- command: 'npx',
389
- args: [
390
- '-y',
391
- '@amp-labs/mcp-server@latest',
392
- '--transport',
393
- 'stdio',
394
- '--project',
395
- process.env.AMPERSAND_PROJECT_ID,
396
- '--integrationName',
397
- process.env.AMPERSAND_INTEGRATION_NAME,
398
- '--groupRef',
399
- process.env.AMPERSAND_GROUP_REF, // optional
400
- ],
401
- env: {
402
- AMPERSAND_API_KEY: process.env.AMPERSAND_API_KEY,
403
- },
404
- },
405
- },
352
+ export const mastra = new Mastra({
353
+ agents: { agent },
354
+ mcpServers,
406
355
  })
407
356
  ```
408
357
 
409
- As an alternative to MCP, Ampersand's AI SDK also has an adapter for Mastra, so you can [directly import Ampersand tools](https://docs.withampersand.com/ai-sdk#use-with-mastra) for your agent to access.
358
+ Tools loaded through `listTools()` include a `serverId` in `_meta.ui`, allowing Studio to resolve each app resource without scanning every server. Visit [`toMCPServerProxies()`](https://mastra.ai/reference/tools/mcp-client) for proxy configuration details.
359
+
360
+ ### Sandbox security
410
361
 
411
- ## MCP Apps
362
+ Mastra Studio uses [`@mcp-ui/client`](https://www.npmjs.com/package/@mcp-ui/client) to load app HTML through a sandbox proxy and communicate over JSON-RPC with `postMessage`.
412
363
 
413
- MCP servers can serve interactive HTML UIs via the MCP Apps extension. Tools with associated `ui://` resources render sandboxed iframes in Studio, both on tool detail pages and inline in agent chat. The app iframe can call server tools and inject messages into the conversation. Visit [MCP Apps](https://mastra.ai/docs/mcp/mcp-apps) for setup instructions and the app bridge API.
364
+ App iframes allow scripts, forms, and popups. They can't access the parent page's DOM, cookies, or storage. The host controls all communication with the guest app.
414
365
 
415
- ## Related
366
+ ## Next steps
416
367
 
417
- - [MCP Apps](https://mastra.ai/docs/mcp/mcp-apps)
418
- - [Using Tools](https://mastra.ai/docs/agents/using-tools)
419
- - [MCPClient](https://mastra.ai/reference/tools/mcp-client)
420
- - [MCPServer](https://mastra.ai/reference/tools/mcp-server)
368
+ - [Use tools with agents](https://mastra.ai/docs/agents/using-tools)
369
+ - [`MCPClient` reference](https://mastra.ai/reference/tools/mcp-client)
370
+ - [`MCPServer` reference](https://mastra.ai/reference/tools/mcp-server)
371
+ - [MCP Apps extension specification](https://github.com/modelcontextprotocol/ext-apps)