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,

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐