mcp-server-building
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMCP Server Building
构建MCP服务器
Build custom MCP servers to extend Claude with tools, resources, and prompts.
构建自定义MCP服务器,通过工具、资源和提示词扩展Claude的能力。
Architecture
架构
+-------------+ JSON-RPC +-------------+
| Claude |<----------------->| MCP Server |
| (Host) | stdio/SSE/WS | (Tools) |
+-------------+ +-------------+Three Primitives:
- Tools: Functions Claude can call (with user approval)
- Resources: Data Claude can read (files, API responses)
- Prompts: Pre-defined prompt templates
+-------------+ JSON-RPC +-------------+
| Claude |<----------------->| MCP Server |
| (Host) | stdio/SSE/WS | (Tools) |
+-------------+ +-------------+三大核心组件:
- Tools:Claude可调用的函数(需用户授权)
- Resources:Claude可读取的数据(文件、API响应)
- Prompts:预定义的提示词模板
Quick Start
快速开始
Minimal Python Server (stdio)
轻量Python服务器(stdio传输)
python
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
server = Server("my-tools")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="greet",
description="Greet a user by name",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "Name to greet"}
},
"required": ["name"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "greet":
return [TextContent(type="text", text=f"Hello, {arguments['name']}!")]
raise ValueError(f"Unknown tool: {name}")
async def main():
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())python
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
server = Server("my-tools")
@server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="greet",
description="Greet a user by name",
inputSchema={
"type": "object",
"properties": {
"name": {"type": "string", "description": "Name to greet"}
},
"required": ["name"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "greet":
return [TextContent(type="text", text=f"Hello, {arguments['name']}!")]
raise ValueError(f"Unknown tool: {name}")
async def main():
async with stdio_server() as (read, write):
await server.run(read, write, server.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())TypeScript Server (production)
生产环境TypeScript服务器
typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-tools", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "fetch_url",
description: "Fetch content from a URL",
inputSchema: {
type: "object",
properties: { url: { type: "string" } },
required: ["url"],
},
}],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "fetch_url") {
const { url } = request.params.arguments as { url: string };
const response = await fetch(url);
return { content: [{ type: "text", text: await response.text() }] };
}
throw new Error("Unknown tool");
});
await server.connect(new StdioServerTransport());typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{ name: "my-tools", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [{
name: "fetch_url",
description: "Fetch content from a URL",
inputSchema: {
type: "object",
properties: { url: { type: "string" } },
required: ["url"],
},
}],
}));
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name === "fetch_url") {
const { url } = request.params.arguments as { url: string };
const response = await fetch(url);
return { content: [{ type: "text", text: await response.text() }] };
}
throw new Error("Unknown tool");
});
await server.connect(new StdioServerTransport());Detailed Guides
详细指南
- Transport patterns: See references/transport-patterns.md for stdio, SSE, WebSocket
- Tool definitions: See references/tool-definitions.md for schemas, error handling, caching
- Resource patterns: See references/resource-patterns.md for files and dynamic data
- Testing: See references/testing-patterns.md for MCP Inspector and pytest
- Auto-discovery: See references/auto-discovery.md for CC 2.1.7+ optimization
- 传输模式:查看 references/transport-patterns.md 了解stdio、SSE、WebSocket的使用
- 工具定义:查看 references/tool-definitions.md 了解 schema、错误处理、缓存机制
- 资源模式:查看 references/resource-patterns.md 了解文件和动态数据的处理
- 测试方法:查看 references/testing-patterns.md 了解MCP Inspector和pytest的使用
- 自动发现:查看 references/auto-discovery.md 了解CC 2.1.7+版本的优化方案
Key Decisions
关键决策
| Decision | Choice | Rationale |
|---|---|---|
| Transport | stdio for CLI, SSE for web | stdio simplest, SSE for browsers |
| Language | TypeScript for production | Better SDK support, type safety |
| Error handling | Return errors as text | Claude can interpret and retry |
| 决策项 | 选择方案 | 决策依据 |
|---|---|---|
| 传输方式 | CLI用stdio,Web用SSE | stdio实现最简单,SSE适配浏览器场景 |
| 开发语言 | 生产环境用TypeScript | 更完善的SDK支持,类型安全 |
| 错误处理 | 以文本形式返回错误 | Claude可解析错误并重试 |
Anti-Patterns
反模式(需避免)
- Stateful tools without cleanup - Always clean up connections
- Blocking synchronous code - Use
asyncio.to_thread() - Missing input validation - Validate before processing
- Secrets in tool output - Never return credentials
- Unbounded responses - Limit response sizes
- 无清理机制的有状态工具 - 务必清理连接资源
- 阻塞式同步代码 - 使用处理
asyncio.to_thread() - 缺少输入验证 - 处理前必须验证输入
- 工具输出包含敏感信息 - 绝对不要返回凭证数据
- 无限制的响应内容 - 限制响应大小
Related Skills
相关技能
- - LLM function calling patterns
function-calling - - Agentic patterns using MCP tools
agent-loops - - Input validation for arguments
input-validation
- - 大模型函数调用模式
function-calling - - 基于MCP工具的智能体循环模式
agent-loops - - 参数输入验证
input-validation
Resources
资源链接
- MCP Specification: https://modelcontextprotocol.io/docs
- Python SDK: https://github.com/modelcontextprotocol/python-sdk
- TypeScript SDK: https://github.com/modelcontextprotocol/typescript-sdk
- MCP规范文档:https://modelcontextprotocol.io/docs
- Python SDK:https://github.com/modelcontextprotocol/python-sdk
- TypeScript SDK:https://github.com/modelcontextprotocol/typescript-sdk