什么是 MCP?
Model Context Protocol (MCP) 是一个开放协议,旨在实现 LLM 应用与外部数据源和工具之间的无缝集成。无论您是构建 AI 驱动的 IDE、增强聊天界面,还是创建自定义 AI 工作流,MCP 都提供了一种标准化的方式来连接 LLM 与外部世界。
简单来说,MCP 是一种客户端-服务器架构的协议,允许 LLM 应用程序(如 Claude、各种 IDE 等)通过标准化的接口访问外部数据和功能。这解决了 LLM 在实际应用中常见的一些痛点:
- LLM 无法直接访问实时数据(如天气、股票行情等)
- LLM 无法执行外部操作(如发送邮件、控制设备等)
- LLM 无法访问用户的本地文件或其他私有数据
通过 MCP,这些限制得到了优雅的解决,同时保持了安全性和可扩展性。
MCP 的核心架构
MCP 采用客户端-服务器架构,主要包含以下几个组件:
- MCP 主机(Host):如 Claude Desktop、IDE 或其他 AI 工具,通过 MCP 访问数据
- MCP 客户端(Client):与服务器保持 1:1 连接的协议客户端
- MCP 服务器(Server):轻量级程序,通过标准化的 MCP 协议公开特定功能
- 本地数据源:计算机上的文件、数据库和服务,MCP 服务器可以安全访问这些内容
- 远程服务:通过互联网可用的外部系统(例如通过 API),MCP 服务器可以连接这些服务
主机可以同时连接多个服务器,每个服务器提供不同的功能,形成一个生态系统:
主机(Claude、IDE 等)<--MCP 协议--> 服务器 A <--> 本地数据源 A
<--MCP 协议--> 服务器 B <--> 本地数据源 B
<--MCP 协议--> 服务器 C <--> 远程服务 C
MCP 的核心概念
MCP 服务器可以提供三种主要类型的功能:
- 资源(Resources):客户端可以读取的文件类数据(如 API 响应或文件内容)
- 工具(Tools):LLM 可以调用的函数(需要用户批准)
- 提示(Prompts):帮助用户完成特定任务的预写模板
资源(Resources)
资源是可以被客户端读取的文件类数据。它们可以是文本或二进制形式,并有唯一的 URI 标识。资源可以是:
- 直接资源:固定内容的资源
- 资源模板:可以通过参数动态生成的资源
例如,一个文件系统 MCP 服务器可以将本地文件作为资源提供给 LLM,使其能够读取用户的文件。
工具(Tools)
工具是 MCP 中最强大的原语之一,允许服务器向客户端公开可执行的功能。通过工具,LLM 可以与外部系统交互,执行计算,并在现实世界中采取行动。
每个工具都有明确的定义,包括:
- 名称
- 描述
- 输入参数模式(使用 JSON Schema)
- 输出格式
工具设计为由模型控制,但通常需要人类批准才能执行,这保证了安全性。
提示(Prompts)
提示是预定义的模板,可以帮助用户完成特定任务。它们可以包含动态部分,嵌入资源上下文,并支持多步工作流。
MCP 服务器开发案例:天气服务器
让我们通过一个实际例子来理解 MCP 服务器的开发。我们将构建一个简单的天气服务器,它提供两个工具:获取天气警报和获取天气预报。
步骤 1:设置环境
# 创建项目目录
uv init weather
cd weather
# 创建虚拟环境并激活
uv venv
source .venv/bin/activate # MacOS/Linux
# 或 .venv\Scripts\activate # Windows
# 安装依赖
uv add "mcp[cli]" httpx
# 创建服务器文件
touch weather.py
步骤 2:实现天气服务器
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
# 初始化 FastMCP 服务器
mcp = FastMCP("weather")
# 常量
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""向 NWS API 发送请求并进行适当的错误处理。"""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/geo+json"
}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None
def format_alert(feature: dict) -> str:
"""将警报特征格式化为可读字符串。"""
props = feature["properties"]
return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
"""
@mcp.tool()
async def get_alerts(state: str) -> str:
"""获取美国州的天气警报。
Args:
state: 美国州的两字母代码(例如 CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "无法获取警报或未找到警报。"
if not data["features"]:
return "该州没有活跃警报。"
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""获取某个位置的天气预报。
Args:
latitude: 位置的纬度
longitude: 位置的经度
"""
# 首先获取预报网格端点
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "无法获取该位置的预报数据。"
# 从 points 响应获取预报 URL
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "无法获取详细预报。"
# 将周期格式化为可读的预报
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # 仅显示接下来的 5 个周期
forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)
if __name__ == "__main__":
# 初始化并运行服务器
mcp.run(transport='stdio')
步骤 3:配置 Claude Desktop 连接服务器
要使用 Claude Desktop 连接到我们的服务器,需要编辑配置文件:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}
此配置告诉 Claude Desktop 如何启动我们的天气服务器,并使 Claude 能够使用我们实现的工具。
MCP 客户端开发案例
接下来,让我们看看如何开发一个 MCP 客户端,该客户端可以连接到任何 MCP 服务器并利用其功能。
步骤 1:设置环境
点击深入解析 Model Context Protocol (MCP):无缝连接 LLM 与外部世界的开放协议查看全文。