MCPServer
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.
Note that if you only need to use your tools or agents directly within your Mastra application, you don’t necessarily need to create an MCP server. This API is specifically for exposing your Mastra tools and agents to external MCP clients.
It supports both stdio (subprocess) and SSE (HTTP) MCP transports .
Constructor
To create a new MCPServer
, you need to provide some basic information about your server, the tools it will offer, and optionally, any agents you want to expose as tools.
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
import { createTool } from "@mastra/core/tools";
import { MCPServer } from "@mastra/mcp";
import { z } from "zod";
import { dataProcessingWorkflow } from "../workflows/dataProcessingWorkflow";
const myAgent = new Agent({
name: "MyExampleAgent",
description: "A generalist to help with basic questions."
instructions: "You are a helpful assistant.",
model: openai("gpt-4o-mini"),
});
const weatherTool = createTool({
id: "getWeather",
description: "Gets the current weather for a location.",
inputSchema: z.object({ location: z.string() }),
execute: async ({ context }) => `Weather in ${context.location} is sunny.`,
});
const server = new MCPServer({
name: "My Custom Server",
version: "1.0.0",
tools: { weatherTool },
agents: { myAgent }, // this agent will become tool "ask_myAgent"
workflows: {
dataProcessingWorkflow, // this workflow will become tool "run_dataProcessingWorkflow"
}
});
Configuration Properties
The constructor accepts an MCPServerConfig
object with the following properties:
name:
version:
tools:
agents?:
workflows?:
id?:
description?:
repository?:
releaseDate?:
isLatest?:
packageCanonical?:
packages?:
remotes?:
resources?:
Exposing Agents as Tools
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:
-
Tool Naming: Each agent is converted into a tool named
ask_<agentKey>
, where<agentKey>
is the key you used for that agent in theagents
object. For instance, if you configureagents: { myAgentKey: myAgentInstance }
, a tool namedask_myAgentKey
will be created. -
Tool Functionality:
- Description: The generated tool’s description will be in the format: “Ask agent
<AgentName>
a question. Original agent instructions:<agent description>
”. - Input: The tool expects a single object argument with a
message
property (string):{ message: "Your question for the agent" }
. - Execution: When this tool is called, it invokes the
generate()
method of the corresponding agent, passing the providedquery
. - Output: The direct result from the agent’s
generate()
method is returned as the output of the tool.
- Description: The generated tool’s description will be in the format: “Ask agent
-
Name Collisions: If an explicit tool defined in the
tools
configuration has the same name as an agent-derived tool (e.g., you have a tool namedask_myAgentKey
and also an agent with the keymyAgentKey
), the explicitly defined tool will take precedence. The agent will not be converted into a tool in this conflicting case, and a warning will be logged.
This makes it straightforward to allow MCP clients to interact with your agents using natural language queries, just like any other tool.
Agent-to-Tool Conversion
When you provide agents in the agents
configuration property, MCPServer
will automatically create a corresponding tool for each agent. The tool will be named ask_<agentIdentifier>
, where <agentIdentifier>
is the key you used in the agents
object.
The description for this generated tool will be: “Ask agent <agent.name>
a question. Agent description: <agent.description>
”.
Important: For an agent to be converted into a tool, it must have a non-empty description
string property set in its configuration when it was instantiated (e.g., new Agent({ name: 'myAgent', description: 'This agent does X.', ... })
). If an agent is passed to MCPServer
with a missing or empty description
, an error will be thrown when the MCPServer
is instantiated, and server setup will fail.
This allows you to quickly expose the generative capabilities of your agents through the MCP, enabling clients to “ask” your agents questions directly.
Methods
These are the functions you can call on an MCPServer
instance to control its behavior and get information.
startStdio()
Use this method to start the server so it communicates using standard input and output (stdio). This is typical when running the server as a command-line program.
async startStdio(): Promise<void>
Here’s how you would start the server using stdio:
const server = new MCPServer({
// example configuration above
});
await server.startStdio();
startSSE()
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.
async startSSE({
url,
ssePath,
messagePath,
req,
res,
}: {
url: URL;
ssePath: string;
messagePath: string;
req: any;
res: any;
}): Promise<void>
Here’s an example of how you might use startSSE
within an HTTP server request handler. In this example an MCP client could connect to your MCP server at http://localhost:1234/sse
:
import http from "http";
const httpServer = http.createServer(async (req, res) => {
await server.startSSE({
url: new URL(req.url || "", `http://localhost:1234`),
ssePath: "/sse",
messagePath: "/message",
req,
res,
});
});
httpServer.listen(PORT, () => {
console.log(`HTTP server listening on port ${PORT}`);
});
Here are the details for the values needed by the startSSE
method:
url:
ssePath:
messagePath:
req:
res:
startHonoSSE()
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.
async startHonoSSE({
url,
ssePath,
messagePath,
req,
res,
}: {
url: URL;
ssePath: string;
messagePath: string;
req: any;
res: any;
}): Promise<void>
Here’s an example of how you might use startHonoSSE
within an HTTP server request handler. In this example an MCP client could connect to your MCP server at http://localhost:1234/hono-sse
:
import http from "http";
const httpServer = http.createServer(async (req, res) => {
await server.startHonoSSE({
url: new URL(req.url || "", `http://localhost:1234`),
ssePath: "/hono-sse",
messagePath: "/message",
req,
res,
});
});
httpServer.listen(PORT, () => {
console.log(`HTTP server listening on port ${PORT}`);
});
Here are the details for the values needed by the startHonoSSE
method:
url:
ssePath:
messagePath:
req:
res:
startHTTP()
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.
async startHTTP({
url,
ssePath,
messagePath,
req,
res,
}: {
url: URL;
ssePath: string;
messagePath: string;
req: any;
res: any;
}): Promise<void>
Here’s an example of how you might use startHTTP
within an HTTP server request handler. In this example an MCP client could connect to your MCP server at http://localhost:1234/http
:
import http from "http";
const httpServer = http.createServer(async (req, res) => {
await server.startHTTP({
url: new URL(req.url || "", `http://localhost:1234`),
ssePath: "/http",
messagePath: "/message",
req,
res,
});
});
httpServer.listen(PORT, () => {
console.log(`HTTP server listening on port ${PORT}`);
});
Here are the details for the values needed by the startHTTP
method:
url:
ssePath:
messagePath:
req:
res:
close()
This method closes the server and releases all resources.
async close(): Promise<void>
getServerInfo()
This method gives you a look at the server’s basic information.
getServerInfo(): ServerInfo
getServerDetail()
This method gives you a detailed look at the server’s information.
getServerDetail(): ServerDetail
getToolListInfo()
This method gives you a look at the tools that were set up when you created the server. It’s a read-only list, useful for debugging purposes.
getToolListInfo(): ToolListInfo
getToolInfo()
This method gives you detailed information about a specific tool.
getToolInfo(toolName: string): ToolInfo
executeTool()
This method executes a specific tool and returns the result.
executeTool(toolName: string, input: any): Promise<any>
getStdioTransport()
If you started the server with startStdio()
, you can use this to get the object that manages the stdio communication. This is mostly for checking things internally or for testing.
getStdioTransport(): StdioServerTransport | undefined
getSseTransport()
If you started the server with startSSE()
, you can use this to get the object that manages the SSE communication. Like getStdioTransport
, this is mainly for internal checks or testing.
getSseTransport(): SSEServerTransport | undefined
getSseHonoTransport()
If you started the server with startHonoSSE()
, you can use this to get the object that manages the SSE communication. Like getSseTransport
, this is mainly for internal checks or testing.
getSseHonoTransport(): SSETransport | undefined
getStreamableHTTPTransport()
If you started the server with startHTTP()
, you can use this to get the object that manages the HTTP communication. Like getSseTransport
, this is mainly for internal checks or testing.
getStreamableHTTPTransport(): StreamableHTTPServerTransport | undefined
tools()
Executes a specific tool provided by this MCP server.
async executeTool(
toolId: string,
args: any,
executionContext?: { messages?: any[]; toolCallId?: string },
): Promise<any>
toolId:
args:
executionContext?:
Resource Handling
What are MCP Resources?
Resources are a core primitive in the Model Context Protocol (MCP) that allow servers to expose data and content that can be read by clients and used as context for LLM interactions. They represent any kind of data that an MCP server wants to make available, such as:
- File contents
- Database records
- API responses
- Live system data
- Screenshots and images
- Log files
Resources are identified by unique URIs (e.g., file:///home/user/documents/report.pdf
, postgres://database/customers/schema
) and can contain either text (UTF-8 encoded) or binary data (base64 encoded).
Clients can discover resources through:
- Direct resources: Servers expose a list of concrete resources via a
resources/list
endpoint. - Resource templates: For dynamic resources, servers can expose URI templates (RFC 6570) that clients use to construct resource URIs.
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.
For more detailed information, refer to the official MCP documentation on Resources .
MCPServerResources
Type
The resources
option takes an object of type MCPServerResources
. This type defines the callbacks your server will use to handle resource requests:
export type MCPServerResources = {
// Callback to list available resources
listResources: () => Promise<Resource[]>;
// Callback to get the content of a specific resource
getResourceContent: ({
uri,
}: {
uri: string;
}) => Promise<MCPServerResourceContent | MCPServerResourceContent[]>;
// Optional callback to list available resource templates
resourceTemplates?: () => Promise<ResourceTemplate[]>;
};
export type MCPServerResourceContent = { text?: string } | { blob?: string };
Example:
import { MCPServer } from "@mastra/mcp";
import type {
MCPServerResourceContent,
Resource,
ResourceTemplate,
} from "@mastra/mcp";
// Resources/resource templates will generally be dynamically fetched.
const myResources: Resource[] = [
{ uri: "file://data/123.txt", name: "Data File", mimeType: "text/plain" },
];
const myResourceContents: Record<string, MCPServerResourceContent> = {
"file://data.txt/123": { text: "This is the content of the data file." },
};
const myResourceTemplates: ResourceTemplate[] = [
{
uriTemplate: "file://data/{id}",
name: "Data File",
description: "A file containing data.",
mimeType: "text/plain",
},
];
const myResourceHandlers: MCPServerResources = {
listResources: async () => myResources,
getResourceContent: async ({ uri }) => {
if (myResourceContents[uri]) {
return myResourceContents[uri];
}
throw new Error(`Resource content not found for ${uri}`);
},
resourceTemplates: async () => myResourceTemplates,
};
const serverWithResources = new MCPServer({
name: "Resourceful Server",
version: "1.0.0",
tools: {
/* ... your tools ... */
},
resources: myResourceHandlers,
});
Notifying Clients of Resource Changes
If the available resources or their content change, your server can notify connected clients that are subscribed to the specific resource.
server.resources.notifyUpdated({ uri: string })
Call this method when the content of a specific resource (identified by its uri
) has been updated. If any clients are subscribed to this URI, they will receive a notifications/resources/updated
message.
async server.resources.notifyUpdated({ uri: string }): Promise<void>
Example:
// After updating the content of 'file://data.txt'
await serverWithResources.resources.notifyUpdated({ uri: "file://data.txt" });
server.resources.notifyListChanged()
Call this method when the overall list of available resources has changed (e.g., a resource was added or removed). This will send a notifications/resources/list_changed
message to clients, prompting them to re-fetch the list of resources.
async server.resources.notifyListChanged(): Promise<void>
Example:
// After adding a new resource to the list managed by 'myResourceHandlers.listResources'
await serverWithResources.resources.notifyListChanged();
Examples
For practical examples of setting up and deploying an MCPServer, see the Deploying an MCPServer Example.
The example at the beginning of this page also demonstrates how to instantiate MCPServer
with both tools and agents.
Related Information
- For connecting to MCP servers in Mastra, see the MCPClient documentation.
- For more about the Model Context Protocol, see the @modelcontextprotocol/sdk documentation .