feat: build an AI agent from 0 to 1 -- 11 progressive sessions
- 11 sessions from basic agent loop to autonomous teams - Python MVP implementations for each session - Mental-model-first docs in en/zh/ja - Interactive web platform with step-through visualizations - Incremental architecture: each session adds one mechanism
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
---
|
||||
name: mcp-builder
|
||||
description: Build MCP (Model Context Protocol) servers that give Claude new capabilities. Use when user wants to create an MCP server, add tools to Claude, or integrate external services.
|
||||
---
|
||||
|
||||
# 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
|
||||
|
||||
### 1. Project Setup
|
||||
|
||||
```bash
|
||||
# Create project
|
||||
mkdir my-mcp-server && cd my-mcp-server
|
||||
python3 -m venv venv && source venv/bin/activate
|
||||
|
||||
# Install MCP SDK
|
||||
pip install mcp
|
||||
```
|
||||
|
||||
### 2. Basic Server Template
|
||||
|
||||
```python
|
||||
#!/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())
|
||||
```
|
||||
|
||||
### 3. Register with Claude
|
||||
|
||||
Add to `~/.claude/mcp.json`:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"my-server": {
|
||||
"command": "python3",
|
||||
"args": ["/path/to/my_server.py"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript MCP Server
|
||||
|
||||
### 1. Setup
|
||||
|
||||
```bash
|
||||
mkdir my-mcp-server && cd my-mcp-server
|
||||
npm init -y
|
||||
npm install @modelcontextprotocol/sdk
|
||||
```
|
||||
|
||||
### 2. Template
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
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)
|
||||
|
||||
```python
|
||||
@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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
1. **Clear tool descriptions**: Claude uses these to decide when to call tools
|
||||
2. **Input validation**: Always validate and sanitize inputs
|
||||
3. **Error handling**: Return meaningful error messages
|
||||
4. **Async by default**: Use async/await for I/O operations
|
||||
5. **Security**: Never expose sensitive operations without auth
|
||||
6. **Idempotency**: Tools should be safe to retry
|
||||
Reference in New Issue
Block a user