How to Create MCP Servers Using the mcp-builder Skill: A Complete Guide
The mcp-builder skill in the anthropics/skills repository provides ready-made templates for building Model Context Protocol (MCP) servers in Python or Node/TypeScript, complete with input validation, tool annotations, and transport configuration.
If you want to extend AI assistants with custom tools that interact with external APIs or data sources, the mcp-builder skill offers a standardized foundation. This guide walks you through creating production-ready MCP servers using the official templates, referencing specific implementation details from skills/mcp-builder/reference/python_mcp_server.md and skills/mcp-builder/reference/node_mcp_server.md.
What Is the mcp-builder Skill?
The mcp-builder skill is a scaffolding system located in the anthropics/skills repository under skills/mcp-builder/. It provides complete reference implementations for building MCP servers in two languages:
- Python: Uses the
FastMCPclass from themcp>=1.1.0SDK with Pydantic v2 for input validation - Node/TypeScript: Uses the
McpServerclass from@modelcontextprotocol/sdkwith Zod schemas for type safety
The skill includes best-practice checklists in skills/mcp-builder/SKILL.md, helper scripts for testing in skills/mcp-builder/scripts/, and detailed reference guides for each language.
Prerequisites and Installation
Before creating an MCP server with the mcp-builder skill, install the appropriate SDK and dependencies for your chosen language.
Python Setup
Install the MCP SDK and Pydantic v2:
pip install "mcp>=1.1.0" pydantic httpx
The skills/mcp-builder/scripts/requirements.txt file specifies mcp>=1.1.0 as the minimum version for Python implementations.
Node/TypeScript Setup
Initialize your project and install the required packages:
npm init -y
npm install @modelcontextprotocol/sdk zod axios
npm install --save-dev typescript @types/node
The Node reference guide in skills/mcp-builder/reference/node_mcp_server.md uses these specific packages for SDK functionality, schema validation, and HTTP requests.
Step-by-Step Guide to Creating an MCP Server
Follow these steps to implement a complete MCP server using the mcp-builder skill templates.
Step 1: Choose Your Service Name and Follow Naming Conventions
The mcp-builder skill enforces specific naming conventions based on your language choice:
- Python: Use
{service}_mcpin snake_case (e.g.,github_mcp,slack_mcp) - Node/TypeScript: Use
{service}-mcp-serverin kebab-case (e.g.,github-mcp-server,slack-mcp-server)
These conventions appear in skills/mcp-builder/reference/python_mcp_server.md and skills/mcp-builder/reference/node_mcp_server.md respectively.
Step 2: Initialize the Server
Create your server instance with the appropriate class from the MCP SDK.
Python (FastMCP):
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("example_mcp")
Node/TypeScript (McpServer):
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
const server = new McpServer({
name: "example-mcp",
version: "1.0.0"
});
Step 3: Define Input Validation Models
Input validation ensures type safety and provides clear error messages to AI models.
Python with Pydantic v2:
from pydantic import BaseModel, Field, ConfigDict
from typing import Optional
class UserSearchInput(BaseModel):
model_config = ConfigDict(str_strip_whitespace=True, validate_assignment=True, extra="forbid")
query: str = Field(..., description="Search string", min_length=2, max_length=200)
limit: Optional[int] = Field(default=20, ge=1, le=100)
offset: Optional[int] = Field(default=0, ge=0)
response_format: str = Field(default="markdown")
Node/TypeScript with Zod:
import { z } from "zod";
const UserSearchInputSchema = z.object({
query: z.string().min(2).max(200),
limit: z.number().int().min(1).max(100).default(20),
offset: z.number().int().min(0).default(0),
response_format: z.enum(["markdown", "json"]).default("markdown")
}).strict();
type UserSearchInput = z.infer<typeof UserSearchInputSchema>;
Step 4: Register Tools with Annotations
Tool annotations inform AI models about the behavior and safety characteristics of your tools.
Python:
@mcp.tool(
name="example_search_users",
annotations={
"readOnlyHint": True,
"destructiveHint": False,
"idempotentHint": True,
"openWorldHint": True,
}
)
async def example_search_users(params: UserSearchInput) -> str:
"""Search users – returns markdown or JSON."""
# Implementation here
return "results"
Node/TypeScript:
server.registerTool(
"example_search_users",
{
title: "Search Example Users",
description: "Search users by name/email/team; returns markdown or JSON.",
inputSchema: UserSearchInputSchema,
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: true
}
},
async (params: UserSearchInput) => {
// Implementation here
return { content: [{ type: "text", text: "results" }] };
}
);
The four annotation hints are defined in the reference guides:
- readOnlyHint: Indicates the tool does not modify external state
- destructiveHint: Indicates the tool does not delete or damage data
- idempotentHint: Indicates re-calling the tool has no extra effect
- openWorldHint: Set to
trueonly if the tool calls external APIs the model cannot control
Step 5: Choose a Transport Protocol
The mcp-builder skill supports two transport methods:
stdio (default): For local execution and subprocess integration streamable_http: For remote HTTP services and multiple clients
Python stdio:
if __name__ == "__main__":
mcp.run()
Python HTTP:
if __name__ == "__main__":
mcp.run(transport="streamable_http", port=8000)
Node/TypeScript stdio:
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const transport = new StdioServerTransport();
await server.connect(transport);
Node/TypeScript HTTP:
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const transport = new StreamableHTTPServerTransport();
// Additional Express setup required as shown in node_mcp_server.md
Step 6: Run the Server
Python:
python example_mcp.py
Node/TypeScript:
npm run build
node dist/index.js
Or for HTTP transport:
TRANSPORT=http node dist/index.js
Working with Resources and Lifecycles
Beyond tools, MCP servers can expose resources and manage persistent connections through lifecycle hooks.
Registering Static Resources
Resources provide read-only access to files or data URIs.
Python:
@mcp.resource("file://documents/{name}")
async def get_document(name: str) -> str:
with open(f"./docs/{name}") as f:
return f.read()
Node/TypeScript:
server.registerResource(
{
uri: "file://documents/{name}",
name: "Document Resource",
description: "Access documents by name",
mimeType: "text/plain"
},
async (uri: string) => {
const name = uri.split("/").pop()!;
const content = await Deno.readTextFile(`./docs/${name}`);
return { contents: [{ uri, mimeType: "text/plain", text: content }] };
}
);
Managing Connection Lifecycles
Use lifespan hooks for persistent connections like database pools.
Python:
from contextlib import asynccontextmanager
@asynccontextmanager
async def app_lifespan():
db = await asyncpg.create_pool(...)
yield {"db": db}
await db.close()
mcp = FastMCP("example_mcp", lifespan=app_lifespan)
Node/TypeScript:
const lifespan = async () => {
const db = await connectDb();
return { db };
};
const server = new McpServer({
name: "example-mcp",
version: "1.0.0",
lifespan
});
Testing and Evaluation
The mcp-builder skill includes utilities for testing your implementation.
The skills/mcp-builder/scripts/connections.py file provides examples for creating MCP client sessions to test your server interactively. For automated evaluation, use skills/mcp-builder/scripts/evaluation.py, which offers a CLI helper for evaluating an MCP server against a task XML file.
Before shipping, consult the best-practice checklist in skills/mcp-builder/SKILL.md. This comprehensive checklist covers strategic design, implementation quality, TypeScript-specific rules, advanced features, project configuration, and testing requirements.
Summary
- The mcp-builder skill provides complete scaffolding for MCP servers in Python (FastMCP) and Node/TypeScript (McpServer)
- Naming conventions differ by language: use
{service}_mcpfor Python and{service}-mcp-serverfor Node - Input validation uses Pydantic v2 models in Python and Zod schemas in TypeScript
- Tool annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint) are required to inform AI models about tool behavior - Transport options include
stdiofor local execution andstreamable_httpfor remote services - Reference implementations are available in
skills/mcp-builder/reference/python_mcp_server.mdandskills/mcp-builder/reference/node_mcp_server.md
Frequently Asked Questions
What is the difference between FastMCP and McpServer?
FastMCP is the Python SDK class (from mcp.server.fastmcp import FastMCP) that provides a decorator-based approach for registering tools and resources. McpServer is the Node/TypeScript SDK class (from "@modelcontextprotocol/sdk/server/mcp.js") that uses explicit method calls like server.registerTool(). Both implement the same Model Context Protocol but follow language-specific idioms—Python uses Pydantic for validation while Node uses Zod.
How do I choose between stdio and HTTP transport?
Use stdio transport when your MCP server runs as a local subprocess integrated with desktop AI applications like Claude Desktop. This is the default and most common configuration. Use streamable_http transport when deploying your server as a remote service accessible to multiple clients over the network, or when you need to integrate with existing HTTP infrastructure. The Python SDK supports mcp.run(transport="streamable_http", port=8000), while Node requires instantiating StreamableHTTPServerTransport.
What are the required tool annotations and what do they mean?
Every tool registered with the mcp-builder skill must include four boolean annotations defined in skills/mcp-builder/reference/python_mcp_server.md and skills/mcp-builder/reference/node_mcp_server.md: readOnlyHint (true if the tool doesn't modify external state), destructiveHint (true if the tool deletes or damages data), idempotentHint (true if calling multiple times has the same effect as once), and openWorldHint (true only if the tool calls external APIs the model cannot control). These hints help AI models understand tool safety and side effects.
Where can I find the complete reference documentation for implementing MCP servers?
The complete reference documentation is located in the skills/mcp-builder/reference/ directory of the anthropics/skills repository. For Python implementations, see skills/mcp-builder/reference/python_mcp_server.md, which covers FastMCP initialization, Pydantic validation, decorators, and transports. For Node/TypeScript, see skills/mcp-builder/reference/node_mcp_server.md, which details McpServer setup, Zod schemas, and HTTP transport configuration. Both files contain production-ready code examples and implementation patterns.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →