Mastra.getMCPServer()
The .getMCPServer() method retrieves an MCP server instance by its registry key (the key used when registering the server in the mcpServers configuration). For retrieving by the server's intrinsic id property, use .getMCPServerById() instead.
Usage exampleDirect link to Usage example
// Register an MCP server with a registry key
const myServer = new MCPServer({
id: 'my-mcp-server',
name: 'My Server',
version: '1.0.0',
tools: {/* ... */},
})
export const mastra = new Mastra({
mcpServers: {
customKey: myServer, // 'customKey' is the registry key
},
})
// Retrieve by registry key
const server = mastra.getMCPServer('customKey')
// Alternatively, retrieve by intrinsic ID
const serverById = mastra.getMCPServerById('my-mcp-server')
ParametersDirect link to Parameters
registryKey:
ReturnsDirect link to Returns
server:
The MCPServerBase contractDirect link to the-mcpserverbase-contract
Every registered server extends MCPServerBase from @mastra/core/mcp. The MCPServer class in @mastra/mcp implements it for the MCP 2026-07-28 protocol and sets mcpVersion to 2. Tool execution, suspension, and the context.mcp shape described below are the parts of the contract a tool author sees. For the 1.x-only members that remain on the base class as deprecated stubs, see the migration guide.
Tools that ask for inputDirect link to Tools that ask for input
An MCP server runs ordinary createTool definitions. A tool that needs something from the user before it can finish declares suspendSchema and resumeSchema and calls suspend(), exactly as it would for an agent or a workflow. Core reports the suspension as { status: 'suspended', suspendPayload, resumeSchema } from executeTool. MCPServer turns that into an input_required round on the wire, and resumes the tool with the answer in resumeData.
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
const confirm = createTool({
id: 'confirm',
description: 'Ask for confirmation before charging',
inputSchema: z.object({ amount: z.number() }),
outputSchema: z.boolean(),
suspendSchema: z.object({ phase: z.literal('confirm'), amount: z.number() }),
resumeSchema: z.object({ confirmed: z.boolean() }),
execute: async ({ amount }, context) => {
if (!context.resumeData) {
await context.suspend?.({ phase: 'confirm', amount })
return
}
return context.resumeData.confirmed
},
})
On an MCP server and in direct execution, suspend, resumeData and suspendPayload sit at the top level of the tool context. Agents and workflows still nest them under context.agent and context.workflow until the next major release of @mastra/core. resumeSchema must be a flat object of primitive fields so it can be presented as an input form.
Each round is a separate request. resumeData carries only the current round's answer, validated against resumeSchema, and suspendPayload carries what the tool last suspended with. Because the framework never replays earlier rounds, handlers branch on explicit named phases, every round is re-authorized, and writes rely on domain-owned idempotency. suspendPayload is also handed back to tools resumed by agents and workflows.
The mcp contextDirect link to the-mcp-context
Tools receive context.mcp (MCPToolExecutionContext): extra with the request's signal, requestId, authInfo and _meta, plus log(level, message, data?), progress({ progress, total?, message? }) and protocolVersion ('2026-07-28'). To ask the user for input, call context.suspend() and read context.resumeData. Server-initiated requests don't exist in the protocol, so the deprecated elicitation.sendRequest, extra.sendRequest and extra.sendNotification members throw with a message naming the replacement.
Registration and executionDirect link to Registration and execution
Tools are registered on the Mastra instance when the server is registered. executeTool(toolId, args, context?) returns { status: 'completed', output } or, when the tool suspended, { status: 'suspended', suspendPayload, resumeSchema } with resumeSchema as JSON Schema. The result has no failure variant: a tool that throws, or input or resume data that fails its schema, rejects the promise. The REST execution endpoint returns the suspended shape instead of pretending the tool finished, and accepts resumeData plus the echoed suspendPayload on the next call to continue the tool.
Registering another server under an occupied registry key keeps the existing instance. Registry keys and intrinsic server IDs remain distinct.
Related methodsDirect link to Related methods
- Mastra.getMCPServerById(): Retrieve an MCP server by its intrinsic
idproperty - Mastra.listMCPServers(): List all registered MCP servers