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 FastMCP class from the mcp>=1.1.0 SDK with Pydantic v2 for input validation
  • Node/TypeScript: Uses the McpServer class from @modelcontextprotocol/sdk with 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}_mcp in snake_case (e.g., github_mcp, slack_mcp)
  • Node/TypeScript: Use {service}-mcp-server in 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 true only 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}_mcp for Python and {service}-mcp-server for 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 stdio for local execution and streamable_http for remote services
  • Reference implementations are available in skills/mcp-builder/reference/python_mcp_server.md and skills/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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →