**摘要:**本文全面介绍了MCP(模型控制协议)的核心概念、架构设计与实战应用。MCP是由Anthropic提出的标准化协议,旨在解决AI应用与外部工具集成时的碎片化问题。文章首先阐述了MCP的背景、设计渊源和核心价值,然后详细解析了其基于JSON-RPC的通信架构、三大核心能力(Tools、Resources、Prompts),以及streamableHTTP和stdio两种通信方式。最后通过Python代码示例展示了如何开发MCP服务器,包括工具定义、资源管理和提示词模板的实现,为开发者提供了从理论到实践的完整指南。
1. 概述与背景
1.1 什么是MCP?
MCP(Model Control Protocol,模型控制协议) 是一种专为大语言模型设计的外部工具调用和业务系统交互的接口协议。它旨在为AI模型提供一种标准化、高效、安全的通信机制,使模型能够灵活地调用外部工具、访问业务系统或与其他服务进行数据交换。
1.2 为什么需要MCP?
在MCP出现之前,每个AI应用都需要为每个数据源(数据库、API、本地文件、GitHub等)单独编写连接代码,导致:
- 集成成本极高:每接入一个新工具,都需要重新开发适配层
- 重复造轮子:同样的数据库连接逻辑,在不同项目中反复实现
- 缺乏统一标准:每个AI工具都有自己的插件/工具调用方式,互不兼容
MCP的定位 :可以类比为AI领域的 "USB-C接口" ------ 一个统一的开放标准,让AI模型能够以一致的方式连接任何数据源和工具。
1.3 设计渊源
MCP的设计受到了微软 LSP(Language Server Protocol,语言服务器协议) 的启发。正如LSP统一了IDE与编程语言的交互方式,MCP旨在统一AI模型与外部工具的交互方式。
1.4 提出方
MCP由AI公司 Anthropic (Claude系列模型的开发商)于2024年11月首次提出并开源。
2. 核心概念
2.1 架构角色
MCP协议基于 JSON-RPC 2.0 消息格式进行通信,定义了三个主要角色:
|-----------------|-------------------|---------------------------------|
| 角色 | 说明 | 示例 |
| 主机(Host) | 发起连接的LLM应用程序 | Claude Desktop、Cursor、VS Code插件 |
| 客户端(Client) | 主机内部的协议连接器 | MCP SDK中的Client实现 |
| 服务器(Server) | 提供工具/资源/提示词的轻量级程序 | 文件系统服务器、GitHub服务器 |
2.2 通信流程
一个完整的MCP通信包含以下生命周期:
1. 初始化(Initialize)
Client → Server: 发送初始化请求,交换协议版本和能力信息
能力交换(List)
Client → Server: 请求获取可用的工具/资源/提示词列表
Server → Client: 返回能力清单
正常调用(Call)
Client → Server: 调用指定工具/读取资源/获取提示词
Server → Client: 返回执行结果
关闭(Shutdown)
Client → Server: 发送关闭通知
2.3 服务器三大核心能力
MCP Server可以提供以下三种类型的标准能力:
|--------------------|------------------|-------------------|
| 能力类型 | 说明 | 适用场景 |
| Tools(工具) | 可执行的函数/操作,需要用户确认 | 执行操作、修改数据、调用外部API |
| Resources(资源) | 只读的数据源,类似文件或数据库 | 读取文件内容、查询数据、获取文档 |
| Prompts(提示词模板) | 预定义的提示词模板 | 标准化交互流程、复用常用指令 |
3. 快速开始
3.1 在Claude Code中配置MCP
方式一:命令行添加
claude mcp add <服务器名称> -- <命令> <参数...>
示例:
# 添加 filesystem 工具
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/workspace
添加 GitHub 工具
claude mcp add github -- npx -y @modelcontextprotocol/server-github
添加 PostgreSQL
claude mcp add postgres -- npx -y @modelcontextprotocol/server-postgres postgresql://user:pass@localhost:5432/db
方式二:配置文件添加
在 .claude/setting.json 文件中添加配置:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/path/to/workspace"
]
}
}
}
3.2 其他兼容客户端
以下客户端/平台已支持或正在集成MCP:
- Claude Desktop(官方原生支持)
- Cursor(通过MCP插件)
- VS Code(通过Copilot或Continue扩展)
- Continue.dev(开源AI编程助手)
- Sourcegraph Cody
- codex
4.MCP服务器的通信方式
MCP(Model Communication Protocol,模型通信协议)的实现方式可以通过多种通信机制来达成,其中包括 streamableHTTP 和 stdio 两种主要方式。下面是对这两种实现方式的说明:
4.1. streamableHTTP
streamableHTTP 是一种基于 HTTP 协议的通信方式,支持流式数据传输(Streaming),特别适合用于模型与客户端之间的实时、连续交互。这种方式通常用于远程调用,允许客户端通过 HTTP 请求与模型服务进行通信,并接收模型逐步生成的响应。
4.2. stdio(标准输入输出)
stdio 是一种本地进程间通信的方式,常用于在同一台机器上运行的模型与客户端之间的交互。它通过标准输入(stdin)和标准输出(stdout)进行数据交换,通常用于命令行工具或本地脚本中。
4.3.总结对比:
|--------|----------------|-----------------|
| 特性 | streamableHTTP | stdio |
| 通信方式 | 网络通信(HTTP) | 本地进程间通信(标准输入输出) |
| 是否支持流式 | 是 | 是 |
| 跨平台能力 | 强 | 弱(局限于本地) |
| 部署复杂度 | 较高 | 低 |
| 适用场景 | 分布式系统、远程服务 | 本地开发、调试、脚本集成 |
这两种实现方式可以根据实际需求进行选择:如果需要远程访问、分布式部署或网页集成,streamableHTTP 是更优的选择;如果只是本地调试或快速集成,stdio 则更为简洁高效。
5.MCP Server端实现
根据MCP协议定义,Server可以提供三种类型的标准能力,分别是Tools,Resources,Prompts.
|--------------------|------------------|--------------------|
| 能力类型 | 说明 | 适用场景 |
| Tools(工具) | 可执行的函数/操作,需要用户确认 | 执行操作、修改数据、调用外部 API |
| Resources(资源) | 只读的数据源,类似文件或数据库 | 读取文件内容、查询数据、获取文档 |
| Prompts(提示词模板) | 预定义的提示词模板 | 标准化交互流程、复用常用指令 |
接下来为大家介绍一下tools的使用方式。
5.1Tools(工具)
最常用的能力,用于执行具体操作。下面使用python代码为大家展示:
5.1.1tools属性解析
使用Python开发时,可以通过注解(Annotations)为工具添加行为提示:
python
from mcp.server.fastmcp import FastMCP, Context
from typing import Optional, Any
from pydantic import BaseModel
# ============================================
# 1. 注解常量定义
# ============================================
# 只读操作注解(最安全)
READ_ONLY_ANNOTATIONS = {
"readOnlyHint": True, # 是否只读:True=只读,False=可修改
"destructiveHint": False, # 是否破坏数据:True=危险,False=安全
"idempotentHint": True, # 是否幂等:True=可重试,False=不可重试
"openWorldHint": True, # 是否依赖外部:True=结果会变,False=可预测
}
# 修改操作注解(安全但会改变数据)
MODIFY_ANNOTATIONS = {
"readOnlyHint": False, # 可修改数据
"destructiveHint": False, # 不破坏数据(只是更新)
"idempotentHint": True, # 幂等(多次执行结果相同)
"openWorldHint": False, # 结果可预测
}
# 危险操作注解(需要警告)
DANGEROUS_ANNOTATIONS = {
"readOnlyHint": False, # 可修改数据
"destructiveHint": True, # ⚠️ 可能破坏数据!
"idempotentHint": False, # 不可重试
"openWorldHint": False, # 结果可预测
}
# ============================================
# 2. 创建 MCP 实例
# ============================================
mcp = FastMCP(
name="my-mcp-server", # 服务器名称
version="1.0.0", # 版本号
description="我的 MCP 服务器" # 描述
)
# ============================================
# 3. 定义工具函数
# ============================================
@mcp.tool(
# ---------- 基础属性 ----------
name="get_user_info", # ① 工具唯一标识符(Client调用时使用)
# - 建议显式指定,避免函数改名影响调用
# - 使用小写+下划线,如:get_user_info
title="获取用户信息", # ② UI中显示的名称
# - Claude Desktop等界面显示
# - 用户友好的名称,支持中文
description="根据用户ID获取用户详细信息", # ③ 工具描述
# - 也可以用函数的 docstring
# - 帮助LLM理解何时使用
# ---------- 注解属性 ----------
annotations={ # ④ 行为注解(重要!)
"title": "获取用户信息", # 在UI中显示
**READ_ONLY_ANNOTATIONS # 展开只读注解常量
},
# ---------- 可选属性 ----------
icons=[ # ⑤ 图标(可选)
# Icon(name="user", type="emoji", value="👤")
],
meta={ # ⑥ 元数据(可选)
"category": "user", # 分类
"version": "1.0.0", # 版本
"author": "dev-team", # 作者
"tags": ["用户", "查询"], # 标签
"deprecated": False, # 是否废弃
},
structured_output=False, # ⑦ 结构化输出
# - True: 返回Pydantic模型,自动验证
# - False: 返回普通字符串
)
async def get_user_info(
# ---------- 函数参数 ----------
user_id: str, # ⑧ 工具参数(自动生成schema)
# - 类型提示会自动转为JSON Schema
# - 支持:str, int, bool, list, dict, Optional
include_details: bool = False, # ⑨ 带默认值的参数
# - 自动变为可选参数
ctx: Context = None, # ⑩ 上下文对象(FastMCP自动注入)
# - 用于访问共享资源
# - 报告进度
# - 记录日志
# - 检查取消
) -> str: # ⑪ 返回类型
"""
根据用户ID获取用户详细信息。
Args:
user_id: 用户唯一标识符
include_details: 是否包含详细信息(订单、偏好等)
Returns:
用户信息的JSON字符串
Examples:
>>> get_user_info("user123")
'{"id": "user123", "name": "张三", "email": "zhangsan@example.com"}'
"""
# ============================================
# 4. 工具实现代码
# ============================================
# 4.1 获取共享资源
# es = ctx.request_context.lifespan_context.get("es")
# db = ctx.request_context.lifespan_context.get("db")
# 4.2 报告进度(可选)
# await ctx.report_progress(0, 100, "开始查询")
# 4.3 记录日志(可选)
# await ctx.log_info(f"查询用户: {user_id}")
# 4.4 检查是否被取消(可选)
# if await ctx.is_cancelled():
# return "操作已取消"
# 4.5 业务逻辑
# user = await db.fetch("SELECT * FROM users WHERE id = $1", user_id)
# 4.6 错误处理
# try:
# result = await query_user(user_id)
# except Exception as e:
# await ctx.log_error(f"查询失败: {str(e)}")
# return f'{{"error": "{str(e)}"}}'
# 4.7 返回结果
return f'{{"id": "{user_id}", "name": "张三", "email": "zhangsan@example.com"}}'
5.1.2完整开发模板
python
from mcp.server.fastmcp import FastMCP
# 创建 MCP 实例
mcp = FastMCP("my-server")
@mcp.tool()
def my_tool(param1: str, param2: int = 10) -> str:
"""工具描述:说明这个工具做什么
Args:
param1: 参数1说明
param2: 参数2说明(默认10)
Returns:
返回结果说明
"""
# 实现逻辑
result = f"处理: {param1}, {param2}"
return result
if __name__ == "__main__":
mcp.run(transport="stdio")
5.2 Resources(资源)
Resource是只读的数据源,由Server主动提供给Client。Resources(资源) = AI 想"看"某份资料,Server 直接提供
5.2.1 资源定义示例
python
from mcp.server.fastmcp import FastMCP
from mcp.types import Resource
mcp = FastMCP("my-server")
@mcp.resource(
uri="file:///logs/app.log",
name="应用日志",
description="当前应用的运行日志",
mime_type="text/plain"
)
async def get_app_log() -> str:
"""读取应用日志文件"""
with open("/var/log/app.log", "r") as f:
return f.read()
@mcp.resource(
uri="db://users/active",
name="活跃用户",
description="当前活跃用户列表",
mime_type="application/json"
)
async def get_active_users() -> str:
"""查询活跃用户"""
# users = await db.fetch("SELECT * FROM users WHERE active = true")
# return json.dumps(users)
return '{"users": [{"id": "1", "name": "张三"}]}'
5.2.2 资源订阅(自动更新)
python
@mcp.resource(
uri="file:///config/app.json",
name="应用配置",
description="应用配置文件(自动更新)",
subscribe=True # 启用订阅,文件变化时自动通知Client
)
async def get_config() -> str:
with open("/app/config.json", "r") as f:
return f.read()
5.2.3具体案例
AI 想排查 Bug,需要看最新的错误日志:
python
# Server端定义 Resource
@mcp.resource(
uri="file:///logs/error.log", # 唯一标识
name="错误日志",
description="最近100条错误日志",
mime_type="text/plain"
)
def get_error_log() -> str:
# 读取日志文件(只读,不修改)
with open("/var/log/error.log", "r") as f:
lines = f.readlines()
return "".join(lines[-100:]) # 返回最近100行
5.3 Prompts(提示词模板)
Prompt用于标准化交互流程,复用常用指令。Prompts 是 Server 提前定义好的"提示词配方",AI 可以像调用函数一样使用它们,快速生成高质量的提示词。
5.3.1 提示词模板定义示例
python
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.prompt(
name="git-commit",
title="生成Git提交信息",
description="根据变更内容生成符合规范的Git提交信息"
)
async def git_commit(
changes: str, # 参数会自动转为模板变量
type: str = "feat" # 默认值
) -> str:
"""
生成Git提交信息模板
使用方法:
1. 描述你做的变更
2. 选择提交类型(feat/fix/docs/style/refactor/test/chore)
3. AI将生成标准的commit message
"""
return f"""
请根据以下变更生成符合 Conventional Commits 规范的提交信息:
变更描述:{changes}
提交类型:{type}
格式要求:
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
请直接输出commit message,不要额外解释。
"""
@mcp.prompt(
name="code-review",
title="代码审查助手",
description="对代码进行全面的安全性和质量审查"
)
async def code_review(code: str) -> str:
"""生成代码审查提示词"""
return f"""
请对以下代码进行全面的审查,重点关注:
1. 安全性问题(SQL注入、XSS、权限绕过等)
2. 性能问题(N+1查询、内存泄漏等)
3. 代码质量问题(可读性、设计模式等)
4. 潜在的边界条件Bug