AI Agent 的工具生态:MCP协议与外部工具集成
AI Agent 的工具生态:MCP协议与外部工具集成
摘要:AI Agent 的能力边界不再局限于大语言模型(LLM)自身的知识储备,而是通过调用外部工具来扩展其行动半径。本文深入探讨 MCP(Model Context Protocol)协议的核心架构,对比 Function Calling 的差异,并给出基于 Python 的自定义工具构建实战代码。
---
一、为什么 AI Agent 需要调用外部工具?
大语言模型本质上是静态知识库。尽管 GPT-4、Claude 3.5 等模型在参数量和训练数据上不断突破,它们仍然面临三个根本性限制: 1. 知识时效性:模型训练数据存在截止日期,无法获取实时信息(如今天的天气、最新股价)。 2. 无法执行动作:模型不能直接操作文件系统、调用 API、查询数据库或发送邮件。 3. 计算边界:复杂数学运算、代码执行等任务,模型可能产生"幻觉",无法保证结果精确性。 因此,工具调用(Tool Calling) 成为 AI Agent 架构中不可或缺的环节。Agent 通过将任务分解,把超出自身能力的子任务委托给专门的外部工具(如计算器、搜索引擎、代码解释器),从而突破"只会说话"的局限,真正具备感知-决策-执行的闭环能力。 ---
二、MCP 协议:统一工具集成的标准化方案
2.1 什么是 MCP?
MCP(Model Context Protocol,模型上下文协议)是由 Anthropic 于 2024 年底推出的开放协议,旨在为 LLM 与外部数据源、工具之间提供一套标准化的通信接口。 在 MCP 出现之前,每个 AI 应用都需要为不同的工具编写特定的集成代码——从 Slack API 到 PostgreSQL 查询,集成方式杂乱无章。MCP 的核心愿景是:一次实现,随处使用。任何遵循 MCP 标准的工具或数据源,都可以被任何兼容 MCP 的 Agent 无缝调用。
2.2 MCP 的架构设计
MCP 采用 客户端-服务器 架构,主要包含三个核心角色:
┌─────────────────┐
│ MCP Host │ ← AI 应用(如 Claude Desktop、Cursor、IDE)
│ (MCP Client) │
└────────┬────────┘
│ MCP Protocol (JSON-RPC)
▼
┌─────────────────┐
│ MCP Server │ ← 工具提供者(如文件系统、数据库、搜索API)
│ (Resources) │
└─────────────────┘
核心组件解析: | 组件 | 职责 | |------|------| | Resources | 可被 LLM 读取的数据源,如文件、数据库记录、API 响应 | | Tools | 可被 LLM 调用的执行函数,如执行 Shell 命令、发送 HTTP 请求 | | Prompts | 预定义的提示模板,帮助用户快速完成特定任务 | MCP Server 通过 JSON-RPC 2.0 与 Host 通信,所有交互都是类型安全的。Server 在启动时通过 tools/list 方法声明自己支持的工具集合,包括每个工具的名称、描述和参数 Schema(基于 JSON Schema)。 ---
三、Function Calling vs MCP:关键差异对比
Function Calling(函数调用)是 OpenAI 在 2023 年推出的功能,允许模型生成调用外部函数的参数。MCP 与 Function Calling 并非竞争关系,而是不同抽象层次的解决方案: | 维度 | Function Calling | MCP 协议 | |------|------------------|----------| | 定位 | LLM 输出格式规范 | 工具生态基础设施 | | 标准归属 | OpenAI 私有规范 | 开放协议(Anthropic 主导) | | 工具发现 | 开发者手动注册 | Server 自动声明(tools/list) | | 可移植性 | 绑定特定模型 | 跨模型、跨平台通用 | | 通信方式 | 单次请求-响应 | 持久连接,支持流式更新 | | 复杂度 | 简单,适合单工具场景 | 稍复杂,适合多工具生态 | 关键洞察:Function Calling 解决的是"如何让模型输出函数参数",而 MCP 解决的是"如何让工具发现、调用和管理变得标准化"。在实际项目中,两者可以协同使用:MCP 负责工具生态的标准化接入,Function Calling 负责模型与工具的交互细节。 ---
四、实战:为 Agent 构建自定义 MCP 工具
下面通过 Python 实现一个自定义 MCP Server,该工具能够查询模拟的股票实时价格,供 Agent 调用。
4.1 环境准备
pip install mcp
4.2 实现 MCP Server
stock_server.py
from mcp.server import Server from mcp.types import TextContent, Tool import json
创建 MCP Server 实例
app = Server("stock-price-server")
模拟股票数据
MOCK_STOCKS = { "AAPL": {"price": 189.50, "currency": "USD"}, "MSFT": {"price": 420.30, "currency": "USD"}, "TSLA": {"price": 245.80, "currency": "USD"}, "0700.HK": {"price": 380.20, "currency": "HKD"}, } @app.list_tools() async def list_tools() -> list[Tool]: """声明 Server 支持的工具列表""" return [ Tool( name="get_stock_price", description="查询指定股票的实时价格", inputSchema={ "type": "object", "properties": { "symbol": { "type": "string", "description": "股票代码,如 AAPL、MSFT" } }, "required": ["symbol"] } ) ] @app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: """处理工具调用请求""" if name == "get_stock_price": symbol = arguments.get("symbol", "").upper() stock = MOCK_STOCKS.get(symbol) if stock: result = json.dumps({ "symbol": symbol, "price": stock["price"], "currency": stock["currency"], "status": "success" }, ensure_ascii=False) else: result = json.dumps({ "symbol": symbol, "error": f"未找到股票 {symbol} 的数据", "status": "error" }, ensure_ascii=False) return [TextContent(type="text", text=result)] raise ValueError(f"未知工具: {name}") if __name__ == "__main__": # 使用 stdio 传输方式运行 Server from mcp.server.stdio import stdio_server import asyncio async def main(): async with stdio_server() as (read_stream, write_stream): await app.run( read_stream,
更多推荐



所有评论(0)