MCP Server 开发完全教程:FastMCP 3.0 + TypeScript SDK 从零跑通到上线
TL;DR —— 写一个 MCP server 在 2026 年比一年前简单太多:Python 用 FastMCP 3.0 的 @mcp.tool decorator,30 行能跑通;TypeScript 用 @modelcontextprotocol/sdk + Zod 拿类型安全;本地调试用 npx @modelcontextprotocol/inspector 一条命令。Transport 层 2025-11 spec 里 Streamable HTTP 已经取代了旧 SSE,远程部署也变干净了。本文按”30 分钟跑通 + 上线”路径走一遍,最后给 Claude Desktop / Cursor / Codex CLI 三个主流客户端的配置示例。
MCP 现在到底什么状态
Model Context Protocol 是 Anthropic 2024 年 11 月开源的协议,统一 AI 应用和外部工具/数据源之间的双向连接。2026 年 5 月的现状:
- 最新协议规范 2025-11-25
- 官方 SDK 覆盖 Python / TypeScript / Java / Kotlin / C# 五种语言
- Python 生态最常用的高层框架 FastMCP 3.0 在 2026 年 2 月 18 日发布(PrefectHQ 维护,独立于官方 SDK),加了 OAuth、OpenTelemetry、composition 等能力
- 公开 MCP server 10,000+(GitHub / npm / PyPI / Smithery / Glama / PulseMCP 等渠道),mcp-server topic 仓库 7,800+
- Transport 层 Streamable HTTP 在 2025-11 spec 里替换了旧的 SSE,写远程 server 不再要双 endpoint
也就是说协议本身已经稳了,主流 client(Claude Desktop、Cursor、Codex、各种 OpenClaw 类客户端)都支持,写 server 的成本断崖式下降。
如果对 MCP 协议本身还不熟,先看 什么是 MCP(Model Context Protocol);对协议的 agent tools 用法不熟,看 MCP 协议 + AI Agent Tools 指南。本文不重复这些基础概念,直接进入 server 开发。
Python 路线:FastMCP 3.0 的最小可用 server
环境准备 Python 3.10+,装 FastMCP 包(FastMCP 2.0/3.0 是独立包,不在官方 mcp 包里):
pip install fastmcp
下面 30 行写一个 MCP server,提供两个 tool:查询当前时间、查一个城市的天气(这里用假数据演示)。
from fastmcp import FastMCP
from datetime import datetime
mcp = FastMCP("demo-server")
@mcp.tool
def get_current_time(timezone: str = "UTC") -> str:
"""Return current time in the given timezone (IANA name)."""
return datetime.now().isoformat()
@mcp.tool
def get_weather(city: str) -> dict:
"""Get current weather for a city."""
return {"city": city, "temp_c": 22, "condition": "sunny"}
if __name__ == "__main__":
mcp.run() # 默认 stdio transport
两件事值得注意。一是 @mcp.tool 会读 type hints 和 docstring 自动生成 JSON schema,client 端拿到的 tool 描述就是这些 hint 和 docstring。所以写函数签名要认真,不要省 type annotation。二是 mcp.run() 不传参数默认走 stdio,这是给本地客户端(Claude Desktop / Cursor)用的方式。
要切 Streamable HTTP 部署到远端,改一行:
if __name__ == "__main__":
mcp.run(transport="http", host="0.0.0.0", port=8080)
FastMCP 3.x 里 Streamable HTTP 的 transport 参数名就是 "http"(兼容旧的 "streamable-http" 写法)。server 会在 http://0.0.0.0:8080/mcp 暴露统一 endpoint,client 用 HTTP POST 打过去就行,不再需要旧 SSE 的 /sse + /messages 双 endpoint。
TypeScript 路线:SDK + Zod
Node 18+ 起步:
npm i @modelcontextprotocol/sdk zod
同样两个 tool:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "demo-server", version: "0.1.0" });
server.tool("get_weather",
{ city: z.string().describe("City name") },
async ({ city }) => ({
content: [{ type: "text", text: JSON.stringify({ city, temp_c: 22 }) }],
})
);
const transport = new StdioServerTransport();
await server.connect(transport);
Zod schema 在这里干两件事:一是给 client 一份精确的 input 描述(自动转 JSON Schema),二是运行时校验 client 传过来的参数,参数不合格直接抛错,省去手写校验的脏活。
TypeScript 比 Python 啰嗦一点,但好处是大型 codebase 里类型流转更安全,team 协作场景推荐。
用 MCP Inspector 调试
Server 写完不要直接接到 Claude Desktop 去试,那边的 log 不好看、问题难定位。先用官方 Inspector:
npx @modelcontextprotocol/inspector python server.py
# 或 TypeScript:
npx @modelcontextprotocol/inspector node dist/server.js
跑起来会开一个本地 Web UI(默认 http://localhost:6274),里面能看 tool 列表、手动构造参数调用、看完整请求/响应 JSON。开发期的 bug 先在 Inspector 里复现一遍再去接客户端,能省下大量来回重启 Claude Desktop 的时间。
三个主流客户端的接入配置
Claude Desktop(macOS 路径 ~/Library/Application Support/Claude/claude_desktop_config.json,Windows 路径 %APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"demo": {
"command": "python",
"args": ["/Users/you/path/to/server.py"]
}
}
}
写绝对路径,相对路径很多时候不工作。改完重启 Claude Desktop。具体在 Claude Desktop / Claude Code 里怎么用 MCP tool,看 Claude Code 国内使用 + Opus 4.6 编程体验。
Cursor(全局配 ~/.cursor/mcp.json,项目配 .cursor/mcp.json,同名时项目优先):
{
"mcpServers": {
"demo": {
"command": "python",
"args": ["/abs/path/server.py"]
}
}
}
注意必须套一层 mcpServers 外层 key(和 Claude Desktop 同格式),漏掉这层 Cursor 不会识别。配完打开 Cursor 的 Settings → MCP,能看到 server 已 connected。
Codex CLI(~/.codex/config.toml):
[mcp_servers.demo]
command = "python"
args = ["/abs/path/server.py"]
Codex 的 MCP 支持是去年加的,配置方式和工作流细节参考 Codex CLI 真实编程工作流。
Streamable HTTP 远程部署
本地 stdio 适合个人工具,团队/生产场景要把 server 跑在云上让多个 client 共用。FastMCP 切 transport="streamable-http" 后,把进程跑在云端任意支持 HTTP 的环境(容器、Lambda、Cloudflare Workers 都行)。
client 端通常需要在客户端的 MCP 配置里指定 URL 而不是 command,比如 Cursor 的远程 MCP server 配置:
{
"mcpServers": {
"demo-remote": {
"url": "https://mcp.yourcompany.com/mcp",
"headers": {
"Authorization": "Bearer YOUR_TOKEN"
}
}
}
}
production 部署要补的两件事:一是 auth(最简单的方式是 server 检查 Authorization header 里的 token,自己接 OAuth/JWT 都行);二是请求日志和限流(FastAPI 套一层 middleware 是常见做法)。
常见报错和怎么排
| 报错 | 通常原因 | 处理 |
|---|---|---|
Server failed to start (客户端) | 命令路径不对 / 依赖没装 | 在 terminal 直接跑 python server.py 复现,看 stderr |
Tool not found | 工具名拼错 / server 加载失败 | Inspector 里看 tool 列表实际是什么 |
Validation error | 参数 schema 不匹配 | Python 检查 type hint,TS 检查 Zod schema |
Connection closed (HTTP transport) | server 进程崩了 / 网络断 | 看 server log,确认 Streamable HTTP endpoint 实际监听 |
| Claude Desktop 看不到 server | config JSON 写错 | 用 python -m json.tool < config.json 检查语法 |
进一步的 API 报错对照参考 AI API 报错大全;如果 server 里调用 LLM 又遇到模型/厂商相关报错,看 模型特定报错排查手册。
国内开发的实用建议
MCP server 本身和大模型无关,它只是给 client 提供 tool 的协议层,开发期没有任何网络问题。瓶颈在于”测试 server 时要让 client 真的调通 LLM”这一步。两个方式:
- 把 client 的 OpenAI 兼容 endpoint 切到
https://api.ofox.ai/v1,直接走国内出口。这套对 Cursor / Codex CLI / 自己写的 client 都适用,env vars 就是OPENAI_API_KEY+OPENAI_BASE_URL。 - server 内部如果需要调 LLM 做”二阶推理”(比如 server 实现一个”总结网页”的 tool,内部要打模型),同样指到 ofox 网关,调用 Claude / DeepSeek / Qwen 全统一一个 base_url。
Claude 系列的 tool use 协议是 MCP 的概念前身,理解 tool/function calling 的底层语义可以看 Claude function calling + tool use 完全教程。
进一步阅读
- 官方 MCP 规范 2025-11-25
- 官方 SDK 仓库列表
- 官方 MCP servers 集合
- 协议入门:什么是 MCP
- 客户端使用:MCP 协议 + AI Agent Tools 指南
- Tool use 底层语义:Claude function calling 教程


