MCP Server Building Skill
You now have expertise in building MCP (Model Context Protocol) servers. MCP enables Claude to interact with external services through a standardized protocol.
What is MCP?
MCP servers expose:
-
Tools: Functions Claude can call (like API endpoints)
-
Resources: Data Claude can read (like files or database records)
-
Prompts: Pre-built prompt templates
Quick Start: Python MCP Server
- Project Setup
Create project
mkdir my-mcp-server && cd my-mcp-server python3 -m venv venv && source venv/bin/activate
Install MCP SDK
pip install mcp
- Basic Server Template
#!/usr/bin/env python3 """my_server.py - A simple MCP server"""
from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent
Create server instance
server = Server("my-server")
Define a tool
@server.tool() async def hello(name: str) -> str: """Say hello to someone.
Args:
name: The name to greet
"""
return f"Hello, {name}!"
@server.tool() async def add_numbers(a: int, b: int) -> str: """Add two numbers together.
Args:
a: First number
b: Second number
"""
return str(a + b)
Run server
async def main(): async with stdio_server() as (read, write): await server.run(read, write)
if name == "main": import asyncio asyncio.run(main())
- Register with Claude
Add to ~/.claude/mcp.json :
{ "mcpServers": { "my-server": { "command": "python3", "args": ["/path/to/my_server.py"] } } }
TypeScript MCP Server
- Setup
mkdir my-mcp-server && cd my-mcp-server npm init -y npm install @modelcontextprotocol/sdk
- Template
// src/index.ts import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({ name: "my-server", version: "1.0.0", });
// Define tools server.setRequestHandler("tools/list", async () => ({ tools: [ { name: "hello", description: "Say hello to someone", inputSchema: { type: "object", properties: { name: { type: "string", description: "Name to greet" }, }, required: ["name"], }, }, ], }));
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name === "hello") {
const name = request.params.arguments.name;
return { content: [{ type: "text", text: Hello, ${name}! }] };
}
throw new Error("Unknown tool");
});
// Start server const transport = new StdioServerTransport(); server.connect(transport);
Advanced Patterns
External API Integration
import httpx from mcp.server import Server
server = Server("weather-server")
@server.tool() async def get_weather(city: str) -> str: """Get current weather for a city.""" async with httpx.AsyncClient() as client: resp = await client.get( f"https://api.weatherapi.com/v1/current.json", params={"key": "YOUR_API_KEY", "q": city} ) data = resp.json() return f"{city}: {data['current']['temp_c']}C, {data['current']['condition']['text']}"
Database Access
import sqlite3 from mcp.server import Server
server = Server("db-server")
@server.tool() async def query_db(sql: str) -> str: """Execute a read-only SQL query.""" if not sql.strip().upper().startswith("SELECT"): return "Error: Only SELECT queries allowed"
conn = sqlite3.connect("data.db")
cursor = conn.execute(sql)
rows = cursor.fetchall()
conn.close()
return str(rows)
Resources (Read-only Data)
@server.resource("config://settings") async def get_settings() -> str: """Application settings.""" return open("settings.json").read()
@server.resource("file://{path}") async def read_file(path: str) -> str: """Read a file from the workspace.""" return open(path).read()
Testing
Test with MCP Inspector
npx @anthropics/mcp-inspector python3 my_server.py
Or send test messages directly
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | python3 my_server.py
Best Practices
-
Clear tool descriptions: Claude uses these to decide when to call tools
-
Input validation: Always validate and sanitize inputs
-
Error handling: Return meaningful error messages
-
Async by default: Use async/await for I/O operations
-
Security: Never expose sensitive operations without auth
-
Idempotency: Tools should be safe to retry