Skip to main content

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 example
Direct 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')

Parameters
Direct link to Parameters

registryKey:

string
The registry key used when registering the MCP server in the mcpServers configuration object. It is the configuration key in the key-value pair, not the server's intrinsic id property.

Returns
Direct link to Returns

server:

MCPServerBase | undefined
The MCP server instance with the specified registry key, or undefined if not found.

The MCPServerBase contract
Direct 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 input
Direct 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 context
Direct 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 execution
Direct 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.

See also
Direct link to See also