MCP (Model Context Protocol) 技术分析
技术背景
MCP(Model Context Protocol)是一种模型上下文协议,旨在通过本地运行的MCP服务器扩展系统的能力。MCP服务器提供额外的工具和资源,使系统能够更有效地完成任务。MCP的核心思想是通过非交互式环境中的服务器,提供动态的操作和数据处理能力。
工作原理
MCP服务器通过标准输入输出(stdio)与系统进行通信,采用基于JSON的协议格式。通信过程遵循请求-响应模式,系统发送请求到MCP服务器,服务器处理请求并返回响应。
MCP整体架构
资源处理流程
工具调用流程
通信机制
MCP采用基于JSON的轻量级通信协议,通过标准输入输出(stdio)进行数据传输。整个通信过程类似于客户-服务器模式,但更加轻量和高效。
1. 连接建立
- MCP服务器启动时,通过StdioServerTransport建立与系统的连接
- 类似于电话拨号,建立稳定的双向通信通道
- 示例:服务器启动后,等待系统发送请求
2. 请求处理
系统发送JSON格式的请求,包含以下关键信息:
- 操作类型(如获取资源、调用工具)
- 请求参数
- 请求ID(用于匹配请求和响应)
示例请求:
{
"type": "CallTool",
"id": "12345",
"name": "get_forecast",
"arguments": {
"city": "Beijing",
"days": 3
}
}
3. 响应返回
服务器处理请求后,返回JSON格式的响应,包含:
- 请求ID(与请求匹配)
- 操作结果
- 状态码(成功或错误)
成功响应示例:
{
"id": "12345",
"status": "success",
"result": {
"forecast": [
{
"date": "2025-05-12",
"temperature": 22,
"condition": "sunny"
},
{
"date": "2025-05-13",
"temperature": 20,
"condition": "cloudy"
}
]
}
}
错误响应示例:
{
"id": "12345",
"status": "error",
"code": "INVALID_PARAM",
"message": "City parameter is required"
}
4. 实际应用场景
场景1:获取天气信息
- 系统发送获取天气请求
- MCP服务器调用OpenWeather API
- 返回格式化后的天气数据
场景2:执行数据分析
- 系统发送数据分析请求
- MCP服务器调用数据处理模块
- 返回分析结果和可视化数据
5. 错误处理机制
- 参数验证错误:返回INVALID_PARAM错误
- 资源不存在:返回RESOURCE_NOT_FOUND错误
- 服务器内部错误:返回INTERNAL_ERROR错误
- 超时处理:设置合理的超时时间,返回TIMEOUT错误
资源(Resources)
资源是MCP服务器提供的数据实体,分为两种类型:
- 静态资源:通过唯一的URI标识,可以直接访问。例如:
weather://San Francisco/current
- 动态资源:使用URI模板(遵循RFC 6570标准),允许动态生成资源内容。例如:
weather://{city}/current
资源处理流程:
- 系统发送ListResourcesRequest或ListResourceTemplatesRequest获取资源列表
- 服务器返回可用资源或资源模板信息
- 系统发送ReadResourceRequest读取具体资源内容
- 服务器返回资源数据,格式为UTF-8编码的文本
工具(Tools)
工具是MCP服务器提供的可执行功能,具有以下特点:
- 动态性:可以接收参数并返回动态结果
- 交互性:能够与外部系统进行交互
- 状态修改:可以修改系统或外部系统的状态
工具调用流程:
- 系统发送ListToolsRequest获取可用工具列表
- 服务器返回工具信息,包括名称、描述和输入参数schema
- 系统发送CallToolRequest调用具体工具
- 服务器执行工具逻辑并返回结果
工具参数通过JSON Schema定义,支持以下特性:
- 参数类型验证(string, number, object等)
- 参数范围限制(最小值、最大值)
- 必填参数标记
- 参数描述信息
架构
MCP服务器的架构包括以下几个关键组件:
- Server类:管理MCP服务器的生命周期,处理请求和响应。
- Transport层:负责与系统的通信,通常使用stdio作为传输层。
- 资源和工具处理器:定义和实现资源和工具的具体逻辑。
- 错误处理:通过McpError类处理服务器运行中的错误。
创建MCP服务器(Python版)
创建MCP服务器的基本步骤包括:
1. 初始化项目
mkdir mcp-server
cd mcp-server
python -m venv venv
source venv/bin/activate
pip install fastapi uvicorn pydantic
2. 创建项目结构
touch main.py
mkdir resources
mkdir tools
3. 定义资源和工具
在main.py
中定义资源和工具的处理逻辑,示例:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 资源示例
@app.get("/resources")
async def list_resources():
return {
"resources": [{
"uri": "example://resource1",
"name": "Example Resource",
"mimeType": "application/json"
}]
}
# 工具示例
class ToolRequest(BaseModel):
param1: str
param2: int
@app.post("/tools/example-tool")
async def example_tool(request: ToolRequest):
return {
"result": f"Processed {request.param1} with {request.param2}"
}
4. 运行服务器
uvicorn main:app --reload
5. 配置MCP设置
在MCP设置文件中添加服务器配置:
{
"mcpServers": {
"python-example": {
"command": "uvicorn",
"args": ["main:app", "--host", "0.0.0.0", "--port", "8000"],
"env": {
"PYTHONPATH": "."
}
}
}
}
6. 测试服务器
使用curl或Postman测试API:
curl -X GET http://localhost:8000/resources
curl -X POST http://localhost:8000/tools/example-tool -H "Content-Type: application/json" -d '{"param1": "test", "param2": 123}'
示例:天气服务器
以下是一个简单的MCP服务器示例,提供天气数据功能:
依赖库
pip install fastapi uvicorn requests pydantic
Python实现
from fastapi import FastAPI
from pydantic import BaseModel
import requests
import os
import uvicorn
app = FastAPI()
class WeatherRequest(BaseModel):
city: str
days: int = 3
class WeatherServer:
def __init__(self):
self.api_key = os.getenv('OPENWEATHER_API_KEY')
self.base_url = "http://api.openweathermap.org/data/2.5"
self.setup_routes()
def setup_routes(self):
@app.get("/resources")
async def list_resources():
return {
"resources": [{
"uri": "weather://San Francisco/current",
"name": "Current weather in San Francisco",
"mimeType": "application/json"
}]
}
@app.get("/resource-templates")
async def list_resource_templates():
return {
"resourceTemplates": [{
"uriTemplate": "weather://{city}/current",
"name": "Current weather for a given city",
"mimeType": "application/json"
}]
}
@app.get("/weather/{city}")
async def get_weather(city: str):
response = requests.get(
f"{self.base_url}/weather",
params={
"q": city,
"appid": self.api_key,
"units": "metric"
}
)
return response.json()
@app.post("/forecast")
async def get_forecast(request: WeatherRequest):
response = requests.get(
f"{self.base_url}/forecast",
params={
"q": request.city,
"cnt": request.days * 8,
"appid": self.api_key,
"units": "metric"
}
)
return response.json()
if __name__ == "__main__":
server = WeatherServer()
uvicorn.run(app, host="0.0.0.0", port=8000)
总结
MCP通过本地服务器扩展系统的能力,提供资源和工具的动态操作功能。通过定义资源和工具,MCP服务器能够与外部系统交互,执行复杂的任务。创建MCP服务器的过程包括初始化项目、定义处理逻辑、编译运行和配置设置文件。