一、 引言:为什么需要MCP协议?

1.1 AI Agent工具链的挑战

  • 异构工具集成困难
  • 上下文管理与资源消耗
  • 安全与权限控制

1.2 MCP协议的核心价值

  • 标准化工具定义与调用
  • 解耦Agent核心与工具实现
  • 提升开发效率与可维护性

二、 MCP协议核心概念解析

2.1 协议架构概览

  • Server(工具提供方)
  • Client(Agent/调用方)
  • Transport Layer(通信层)

2.2 核心资源与工具

  • Resource(数据资源)
  • Tool(可执行操作)
  • Prompt(提示模板)

2.3 通信模型与生命周期

  • 初始化与发现
  • 请求/响应模式
  • 错误处理与状态管理

三、 实战准备:环境与工具栈

3.1 开发环境搭建

  • Node.js/Python 环境配置
  • MCP SDK 安装与初始化

3.2 核心依赖介绍

  • @modelcontextprotocol/sdk (JavaScript/TypeScript)
  • mcp (Python)
  • 调试与测试工具

四、 从零构建你的第一个MCP Server

4.1 项目初始化与配置

  • 创建项目结构
  • 定义server manifest

4.2 实现核心工具(Tool)

  • 定义工具schema(输入/输出)
  • 编写工具执行逻辑
  • 示例:天气查询工具

下面是一个完整的 Python 代码示例,演示如何实现一个天气查询工具,包含工具 schema 定义、执行逻辑和模拟 API 调用:

import asyncio
from typing import Any, Dict, Optional
from mcp import Server, Tool, ToolResult
from mcp.types import Tool as ToolSchema
class WeatherQueryTool:
"""天气查询工具实现类"""
def __init__(self, api_key: Optional[str] = None):
    """
    初始化天气查询工具
Args:
    api_key: 模拟的 API 密钥,实际项目中替换为真实天气服务 API 密钥
"""
self.api_key = api_key or "demo_key"
self.cache = {}  # 简单的缓存,避免重复查询相同城市
def get_tool_schema(self) -> ToolSchema:
"""
定义工具 schema,描述工具的输入参数和输出格式
Returns:
    ToolSchema: 工具 schema 对象
"""
return ToolSchema(
    name="get_weather",
    description="查询指定城市的当前天气信息",
    inputSchema={
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "城市名称,例如:北京、上海、New York"
            },
            "country_code": {
                "type": "string",
                "description": "国家代码(可选),例如:CN、US",
                "default": "CN"
            }
        },
        "required": ["city"]
    }
)
async def execute(self, arguments: Dict[str, Any]) -> ToolResult:
"""
执行天气查询工具
Args:
    arguments: 工具调用参数,包含 city 和可选的 country_code
    
Returns:
    ToolResult: 工具执行结果
    
Raises:
    ValueError: 当城市名称为空或无效时
"""
# 1. 参数验证与提取
city = arguments.get("city", "").strip()
country_code = arguments.get("country_code", "CN").upper()

if not city:
    raise ValueError("城市名称不能为空")

# 2. 检查缓存(模拟)
cache_key = f"{city}_{country_code}"
if cache_key in self.cache:
    return ToolResult(
        content=[{
            "type": "text",
            "text": f"【缓存结果】{city}({country_code})的天气:{self.cache[cache_key]}"
        }],
        isError=False
    )

# 3. 模拟 API 调用(实际项目中替换为真实天气 API)
try:
    weather_data = await self._simulate_weather_api_call(city, country_code)
    
    # 4. 处理 API 响应
    result_text = self._format_weather_result(weather_data)
    
    # 5. 更新缓存(模拟)
    self.cache[cache_key] = result_text
    
    return ToolResult(
        content=[{
            "type": "text",
            "text": result_text
        }],
        isError=False
    )
    
except Exception as e:
    # 6. 错误处理
    return ToolResult(
        content=[{
            "type": "text",
            "text": f"查询天气失败:{str(e)}"
        }],
        isError=True
    )
async def _simulate_weather_api_call(self, city: str, country_code: str) -> Dict[str, Any]:
"""
模拟天气 API 调用
Args:
    city: 城市名称
    country_code: 国家代码
    
Returns:
    Dict: 模拟的天气数据
    
Note:
    实际项目中应替换为真实的天气服务 API 调用,如 OpenWeatherMap、和风天气等
"""
# 模拟网络延迟
await asyncio.sleep(0.5)

# 模拟不同城市的天气数据
weather_templates = {
    "北京": {"temp": 25, "humidity": 60, "condition": "晴", "wind_speed": 3.5},
    "上海": {"temp": 28, "humidity": 75, "condition": "多云", "wind_speed": 4.2},
    "广州": {"temp": 32, "humidity": 80, "condition": "阵雨", "wind_speed": 5.0},
    "深圳": {"temp": 30, "humidity": 78, "condition": "阴", "wind_speed": 3.8},
    "杭州": {"temp": 27, "humidity": 70, "condition": "晴转多云", "wind_speed": 2.5}
}

# 返回模拟数据或默认数据
if city in weather_templates:
    return weather_templates[city]
else:
    # 默认模拟数据
    return {
        "temp": 26 + hash(city) % 10,  # 模拟温度变化
        "humidity": 65 + hash(city) % 20,
        "condition": ["晴", "多云", "阴", "小雨"][hash(city) % 4],
        "wind_speed": 3.0 + (hash(city) % 30) / 10
    }
def _format_weather_result(self, weather_data: Dict[str, Any]) -> str:
"""
格式化天气查询结果
Args:
    weather_data: 原始天气数据
    
Returns:
    str: 格式化的天气信息字符串
"""
return f"""🌤️ 天气查询结果:
• 温度:{weather_data['temp']}°C
• 湿度:{weather_data['humidity']}%
• 天气状况:{weather_data['condition']}
• 风速:{weather_data['wind_speed']} m/s
(数据来源:模拟天气服务,实际使用时请接入真实 API)"""
示例:在 MCP Server 中注册工具
async def create_weather_server():
"""创建包含天气查询工具的 MCP Server"""
server = Server("weather-server")
weather_tool = WeatherQueryTool(api_key="your_api_key_here")
注册工具
await server.register_tool(
name=weather_tool.get_tool_schema().name,
description=weather_tool.get_tool_schema().description,
input_schema=weather_tool.get_tool_schema().inputSchema,
handler=weather_tool.execute
)
return server
if name == "main":
启动服务器示例
server = asyncio.run(create_weather_server())
print("天气查询 MCP Server 已启动")

代码说明:

  1. 工具 Schema 定义:通过 get_tool_schema() 方法定义工具的输入参数(城市名称、国家代码)和输出格式。
  2. 执行逻辑execute() 方法包含完整的工具执行流程:参数验证 → 缓存检查 → API 调用 → 结果处理 → 错误处理。
  3. 模拟 API 调用_simulate_weather_api_call() 模拟了真实的网络请求和延迟,实际项目中可替换为 OpenWeatherMap、和风天气等真实 API。
  4. MCP 集成create_weather_server() 展示了如何在 MCP Server 中注册这个工具,使其能够被 Client 发现和调用。
  5. 错误处理:包含参数验证、API 调用异常处理,确保工具的健壮性。

4.3 暴露数据资源(Resource)

  • 定义资源URI与元数据
  • 实现资源读取逻辑
  • 示例:项目文档资源

4.4 集成与测试

  • 本地启动Server
  • 使用MCP Inspector进行调试

五、 开发功能完备的MCP Client (AI Agent)

5.1 Client架构设计

  • 工具发现与加载
  • 上下文管理策略

5.2 集成MCP Server

  • 建立连接与初始化
  • 动态工具调用封装

5.3 实现智能工具调用逻辑

  • 基于LLM的意图识别与工具选择
  • 参数提取与验证
  • 错误处理与重试机制

5.4 构建端到端Agent工作流

  • 串联多个工具调用
  • 状态保持与会话管理
  • 示例:旅行规划Agent

六、 高级主题与最佳实践

6.1 性能优化

  • 工具调用缓存
  • 异步与并行处理

6.2 安全增强

  • 工具权限分级
  • 输入验证与沙箱

6.3 可观测性与监控

  • 日志记录
  • 指标收集与告警

6.4 部署与运维

  • 容器化部署
  • 配置管理与版本控制

七、 生态与未来展望

7.1 现有MCP工具生态

  • 官方与社区工具库
  • 集成案例(Claude Desktop, Cursor等)

7.2 扩展协议的可能性

  • 自定义传输协议
  • 插件化架构

7.3 总结与学习路径建议

  • 核心要点回顾
  • 推荐学习资源与下一步
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐