MCP开发基础教程
MCP 开发基础教程
适用对象:想了解 MCP 是什么、怎么来的,以及如何从零上手开发自己的 MCP Server / Client 的开发者。
读完你将掌握:MCP 解决什么问题、整体结构、发展脉络,以及一套可直接落地的工程最佳实践(含可运行示例)。
一、MCP 的来源
1. 它解决什么问题
在 MCP 出现之前,让 LLM 连接外部系统是一件很痛苦的事:每个 AI 应用都要为每个外部系统单独写一套定制集成代码。
假设你有 N 个 AI 应用(IDE、聊天助手、Agent 框架……)和 M 个外部系统(数据库、文件系统、CRM、天气 API……),就需要维护 N × M 个定制连接。每新增一个模型或一个工具,集成数量就翻倍增长——这就是业界常说的 "N × M 问题"。
MCP(Model Context Protocol,模型上下文协议)就是 Anthropic 于 2024 年 11 月发布并开源的开放标准,用来解决这个痛点。它把上面的组合爆炸压缩成 N + M:
- 每个 AI 应用实现一个 MCP Client
- 每个外部系统实现一个 MCP Server
两者通过统一的标准协议通信,任意组合即可互联,不必为每种组合单独写代码。人们常把它比喻成 "AI 世界的 USB-C 接口"——一个通用标准,所有设备都能插。
2. 一句话定义
MCP 是一个开放式协议,为 AI 应用(LLM)连接外部数据源和工具提供标准化的接口。
在 MCP 之前,LLM 的知识只来自训练数据,无法访问实时信息、无法执行具体动作。MCP 让 LLM 变成能检索信息、更能执行动作的动态代理,而不是只会聊天的静态模型。
3. MCP 与相关概念的区别
| 概念 | 是什么 | 与 MCP 的关系 |
|---|---|---|
| Function Calling / 工具调用 | 让模型生成结构化的工具调用 | MCP 标准化了工具描述、调用协议,是工具调用的"通用化封装" |
| RAG | 检索并注入信息来增强生成 | RAG 侧重"取信息",MCP 侧重"取信息 + 执行动作"的更广交互 |
| API | 程序间的通用接口 | 每个系统一套自定义 API;MCP 是给 LLM 用的统一标准协议 |
| MCP 里的 Tool | 服务器暴露给模型执行的函数 | 是 MCP 的核心原语之一(详见第二节) |
二、MCP 的结构
1. 三个参与方:Host / Client / Server
MCP 采用客户端-服务器架构,包含三个角色:
┌─────────────────────────────────────────┐
│ MCP Host │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ Client 1 │ │ Client 2 │ ... │
│ └─────┬────┘ └─────┬────┘ │
└─────────┼──────────────┼────────────────┘
│ 1:1 │ 1:1
┌────┴────┐ ┌────┴────┐
│Server A │ │ Server B│
│ (local) │ │ (remote)│
│ stdio │ │ HTTP │
└─────────┘ └─────────┘
| 角色 | 是什么 | 职责 |
|---|---|---|
| Host(宿主) | AI 应用本身,如 Claude Desktop、VS Code (Copilot)、Cursor | 创建和管理多个 Client;执行安全策略(如工具调用需用户确认);处理用户交互 |
| Client(客户端) | Host 内为每个 Server 连接创建的组件,与 Server 保持 1:1 连接 | 处理协议协商与能力交换;双向路由消息;维护安全边界(通常不用你写,Host 自动创建) |
| Server(服务器) | 提供工具/数据/提示词的外部程序 | 通过 MCP 原语暴露能力;可以是本地进程或远程服务 |
大多数开发者需要构建的是 Server 部分——这也是本文第四节的核心。
2. 三个核心概念:Tools / Resources / Prompts
Server 通过下面三种原语(Primitive)向 Client 暴露能力:
| 原语 | 谁控制 | 发现方法 | 执行方法 | 用途 |
|---|---|---|---|---|
| Tools(工具) | 模型控制 | tools/list |
tools/call |
可执行函数:查数据库、调 API、发消息等 |
| Resources(资源) | 应用控制 | resources/list |
resources/read |
数据源:文件、记录、API 响应等 |
| Prompts(提示词) | 用户控制 | prompts/list |
prompts/get |
可复用的交互模板 / 工作流 |
对应地,Client 也可以向 Server 暴露能力:
| 原语 | 方法 | 用途 |
|---|---|---|
| Sampling(采样) | sampling/createMessage |
Server 反向请求 Host 的 LLM 帮忙推理 |
| Roots(根路径) | roots/list |
Server 查询 Client 的文件系统边界(哪些目录可访问) |
| Elicitation(引导) | elicitation/request |
Server 请求 Client 向用户询问信息 |
3. 通信基础:JSON-RPC 2.0 与消息类型
MCP 基于 JSON-RPC 2.0 消息格式,建立有状态连接。只有三种核心消息类型:
| 消息类型 | 说明 |
|---|---|
| 请求(Request) | 双向发送,带方法+参数,期待响应 |
| 响应(Response) | 匹配特定请求 ID 的成功结果或错误 |
| 通知(Notification) | 单向发送,不需要响应的消息 |
4. 能力协商(Capability Negotiation)
连接建立时,Client 和 Server 通过 initialize 阶段互相声明支持的能力:
- Server 声明提供什么(
tools、resources、prompts) - Client 声明支持什么(
sampling、roots、elicitation) - 双方只使用对方声明支持的能力;协议版本必须一致,否则初始化失败
5. 连接生命周期
MCP 是有状态协议,一个连接分三个阶段:
- 初始化(Initialization):Client 发
initialize请求 → 双方协商协议版本和能力 → Client 发initialized通知确认 → 连接就绪。 - 操作(Operation):正常消息交换,Client 可发现并调用 Server 的能力(如
tools/list、tools/call)。 - 关闭(Shutdown):任一方可关闭连接,未完成请求被取消、资源被清理。
三、MCP 的发展
时间线
| 时间 | 里程碑 |
|---|---|
| 2024-11 | Anthropic 发布并开源 MCP,协议修订 2024-11-05;早期只支持 stdio 与 HTTP + SSE 传输 |
| 2025-03 | 协议修订 2025-03-26;HTTP + SSE 被标记为弃用,为 Streamable HTTP 让路 |
| 2025-11 | 协议修订 2025-11-25;Streamable HTTP 正式取代 SSE,成为远程部署的标准传输方式 |
| 2026-02 | FastMCP 3.0 发布(PrefectHQ 维护的独立高层框架),加入 OAuth、OpenTelemetry 等能力 |
| 至今 | 官方 SDK 覆盖 Python / TypeScript / Java / Kotlin / C# 五种语言;公开 MCP Server 10,000+ |
发展主线
从"每个系统一套定制 API" → "统一、标准化的连接协议" → "更稳定、更可扩展、更安全的传输与认证体系"。
驱动逻辑始终是:降低 AI 应用接入外部系统的成本,同时提升集成的一致性和安全性。
关键演进点:
- 传输层:
stdio(本地进程)始终是本地首选;远程从HTTP+SSE演进为 Streamable HTTP——一个统一端点,既支持简单 JSON 响应,也支持 SSE 流式推送,部署更干净。 - 认证:引入基于 OAuth 2.1(RFC 9728) 的授权框架,满足生产环境的访问控制需求。
- 框架:从底层官方 SDK 衍生出更易用的高层框架(如 Python 的 FastMCP),用装饰器几行就能跑通一个 server。
四、上手开发(工程最佳实践)
1. 选型:语言与框架
| 语言 | 推荐框架 | 适用场景 | 备注 |
|---|---|---|---|
| Python | FastMCP 3.x / 官方 mcp SDK |
Python 生态工具集成 | pip install fastmcp,装饰器即可;想要底层控制用官方 mcp.server.Server |
| TypeScript | @modelcontextprotocol/sdk + Zod |
Node.js / 前端生态工具集成 | McpServer + Zod 拿类型安全 |
快捷选择:Python + FastMCP 上手最快,本文示例以此为主。
2. 选择传输方式(Transport)
| 传输方式 | 推荐场景 |
|---|---|
| stdio | 本地首选:Claude Desktop / Cursor 等本地客户端。零配置、最快、不占端口、能访问本地文件 |
| Streamable HTTP | 生产/远程首选:多客户端共用、团队共享、需要认证与日志。走 HTTP POST + GET,可流式 |
| 已弃用(2025-03 起),新项目不要再选 |
建议路径:先用 stdio 跑通本地 → 再切 Streamable HTTP 部署远程并加认证。
3. 最小可运行 Server(Python + FastMCP)
# server.py
from fastmcp import FastMCP
mcp = FastMCP("demo-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
@mcp.tool()
def get_weather(city: str) -> str:
"""Get weather for a city (demo)"""
return f"Weather in {city}: 22°C, sunny"
if __name__ == "__main__":
mcp.run() # 默认 stdio
# 远程部署改一行:
# mcp.run(transport="http", host="0.0.0.0", port=8080)
@mcp.tool()会自动读取类型注解和 docstring 生成 JSON Schema。所以写函数签名要认真:类型注解 + 一句话 docstring,缺一不可——Client 端拿到的工具描述就来自这里。
4. 最小可运行 Client
# client.py
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
server_params = StdioServerParameters(command="python", args=["server.py"])
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print("Available tools:", [t.name for t in tools.tools])
result = await session.call_tool("add", {"a": 1, "b": 2})
print("add(1,2) =", result.content[0].text)
asyncio.run(main())
远程调用只需把
stdio_client换成streamablehttp_client(url="https://.../mcp"),客户端会按 URL 自动选择传输方式。
5. 工程最佳实践清单
Server 侧
- 单一职责:一个 Server 专注一个领域,别把所有工具塞进一个 Server。
- 输入校验:对参数做类型、长度、格式校验——尤其是 SQL 和文件路径,这是注入重灾区。
- 异步优先:I/O 操作全部异步化;数据库用连接池。
- 错误可观测:统一异常处理、结构化日志、可追踪的 request ID。
Client 侧
- 严格生命周期:统一用
async with管理连接和会话。 - 重试与退避:网络错误用指数退避重试,并设最大次数。
- 超时治理:连接超时、请求超时都显式配置。
- 降级策略:远程失败时可降级为本地缓存结果或提示人工介入。
安全与权限
- 密钥不硬编码:走环境变量或密钥管理服务。
- 高危工具二次确认:写库、删文件、发消息等工具,务必让用户确认。
- 最小权限:Server 不要拥有过大的系统权限;远程部署加
Authorization认证(推荐 OAuth 2.1 / JWT)。
测试与验收
- 工具级单测:每个 tool 至少覆盖成功、失败、边界三类用例。
- 传输层联调:stdio、Streamable HTTP 各跑一条回归链路。
- 观测指标:把错误率、延迟、超时率、重试率纳入监控。
6. 常见问题排查
| 报错 / 现象 | 通常原因 | 处理 |
|---|---|---|
initialize() 失败 |
Server 没启动 / 传输方式不一致 / 协议版本不匹配 | 先确认 Server 监听端点、传输方式与 Client 一致;看 Server 日志首个异常栈,别只看 Client 报错 |
| Tool not found | 工具名拼错 / Server 加载失败 | 用 Inspector 看实际工具列表 |
| Validation error | 参数 schema 不匹配 | Python 检查 type hint,TS 检查 Zod schema |
| Connection closed(HTTP) | Server 进程崩了 / 网络断 | 看 Server log,确认 Streamable HTTP 端点实际在监听 |
| 客户端看不到 Server | 配置 JSON 写错 | 用 python -m json.tool < config.json 校验语法 |
7. 调试工具
官方提供 MCP Inspector,一条命令启动可视化调试:
# TypeScript
npx @modelcontextprotocol/inspector
# Python
mcp dev server.py # 开发模式,支持热重载
mcp install server.py # 安装到 Claude Desktop
mcp run server.py # 直接运行
附:一页速查
- 是什么 → 让 LLM 连接外部系统的统一开放协议,AI 界的"USB-C"。
- 解决什么 → 把 N×M 个定制集成,压缩成 N+M 的标准连接。
- 谁在用 → Host(AI 应用)/ Client(连接器)/ Server(能力提供方)三方协作。
- 核心原语 → Tools / Resources / Prompts(Server 端)+ Sampling / Roots / Elicitation(Client 端)。
- 传输怎么选 → 本地 stdio;远程 Streamable HTTP(别再用已弃用的 SSE)。
- 怎么上手 → Python + FastMCP,
@mcp.tool()+mcp.run()约 30 行跑通;再补校验、认证、测试、监控。

浙公网安备 33010602011771号