AI Agent 框架 + MCP 集成保姆级教程:从零搭建可调用外部工具的智能体
🛒 面向开发者,从环境准备、MCP Server 编写到 LangGraph 联调的一站式入门教程。
教程目标
本教程带你从零搭建一个“能调用外部工具”的 AI Agent:先用 Python 编写一个符合 MCP 标准的工具服务(MCP Server),再用 LangGraph 把它接进一个可对话的智能体。学完你不仅能跑通示例,还能把自家系统的 API 封装成工具接入 Agent。
前置准备 Checklist
- [ ] 一台可联网的开发机(macOS / Linux / Windows 均可),Python 3.10 及以上。
- [ ] 安装 uv(推荐,用于管理 Python 环境与依赖):
curl -LsSf https://astral.sh/uv/install.sh | sh,然后source ~/.zshrc。 - [ ] 一个可用的 LLM API Key(OpenAI / Anthropic / 国产大模型均可,本教程以 OpenAI 兼容接口为例)。
- [ ] 准备一个“真实工具”示例:本教程用“读取本地文件”作为工具,你也可以换成天气 API、数据库查询。
- [ ] (可选)安装 MCP Inspector 可视化调试工具。
版本提示:MCP SDK 与 LangGraph 迭代较快,以下命令中的版本号以官方实时页面为准;安装失败时优先看报错中的提示。
第一步:创建项目与虚拟环境
mkdir mcp-agent-demo && cd mcp-agent-demo
uv init --python 3.11
uv add "mcp[cli]" langgraph langchain-openai python-dotenv
说明:uv init 会生成 pyproject.toml 与 main.py;mcp[cli] 提供 MCP 运行时与调试命令。
第二步:编写第一个 MCP Server
创建 server.py,实现一个“读取本地文件内容”的工具:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("file-reader")
@mcp.tool()
def read_file(path: str) -> str:
"""读取指定路径的文本文件内容。用于演示 Agent 调用外部工具。"""
try:
with open(path, "r", encoding="utf-8") as f:
return f.read(2000)
except Exception as e:
return f"读取失败: {e}"
if __name__ == "__main__":
mcp.run()
关键点:@mcp.tool() 装饰器把普通函数注册为工具,函数的参数与文档字符串会自动生成给模型看的 tool schema——描述写清楚,模型才知道什么时候该调用它。
第三步:用 MCP Inspector 验证 Server
uv run mcp dev server.py
浏览器打开 http://localhost:6274,在 Inspector 里:
- 选中
read_file工具。 - 输入参数
{"path": "README.md"}(在项目里先建一个 README.md)。 - 点击调用,右侧应返回文件内容。
这一步能确认“工具本身可用”,把模型层面的问题先隔离掉。
第四步:用 LangGraph 构建 Agent 并连接 MCP 工具
创建 agent.py:
import asyncio
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main():
async with MultiServerMCPClient(
{"file-reader": {"command": "uv", "args": ["run", "server.py"], "transport": "stdio"}}
) as client:
tools = client.get_tools()
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
agent = create_react_agent(model, tools)
result = await agent.ainvoke({"messages": [("user", "请读取项目里的 README.md 并总结前三行")]})
print(result["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())
运行:
export OPENAI_API_KEY="你的Key"
uv run python agent.py
预期输出:模型先调用 read_file 工具读取文件,再基于返回内容给出总结——这就是一次完整的“Agent → MCP → 真实工具”链路。
第五步:接入一个真实业务工具(示例:查询 SQLite)
把 server.py 扩展一个“查数据库”工具:
import sqlite3
@mcp.tool()
def query_sqlite(db_path: str, sql: str) -> str:
"""对 SQLite 数据库执行只读 SELECT 查询并返回结果。"""
if not sql.strip().lower().startswith("select"):
return "仅允许 SELECT 查询"
conn = sqlite3.connect(db_path)
try:
rows = conn.execute(sql).fetchmany(10)
return "\n".join(str(r) for r in rows)
except Exception as e:
return f"查询失败: {e}"
finally:
conn.close()
在企业落地时,把这条只读查询换成“带权限校验的内部 API 封装”,就是生产级工具的最小形态。
第六步:配置、日志与常见报错
- 日志:在
agent.py里给ChatOpenAI与 agent 加上verbose=True,可观察每一步的工具调用。 - 超时:MCP 工具调用可在客户端配置超时,避免 Agent 卡死。
- 常见报错与处理:
| 报错现象 | 可能原因 | 处理 |
|---|---|---|
connection refused |
服务端未启动或 stdio 路径不对 | 用 uv run mcp dev server.py 先验证 |
| 模型不调用工具 | tool 描述不清或模型太弱 | 重写工具描述,换更强模型 |
Tool not found |
MCP 客户端未成功注册工具 | 检查 get_tools() 返回列表 |
| 中文乱码 | 编码问题 | 文件读写统一 encoding="utf-8" |
验证方法
- 工具层验证:MCP Inspector 单测每个工具。
- 链路验证:让 Agent 完成 3 个不同任务,确认每次都能正确选择工具。
- 回归验证:把用例固化为脚本,改动后重跑。
常见问题(FAQ)
-
MCP 必须用 Python 吗?
不是。官方 SDK 支持 Python 与 TypeScript,Node 环境用
@modelcontextprotocol/sdk。 -
本地没有 GPU 能用这个教程吗?
能。本教程的 LLM 走 API,只有大模型推理需要算力,本地只跑轻量工具服务。
-
Agent 一直不调用工具怎么办?
先检查 tool 描述是否包含“何时调用”的触发条件,其次确认模型具备 function calling 能力,最后用更简单的 prompt 测试。
-
生产环境 MCP Server 怎么部署?
可把 Server 作为独立进程/容器部署,用 streamable HTTP transport 替代 stdio,并接入统一鉴权。
-
多工具之间会不会互相干扰?
每个工具独立命名空间与 schema,只要描述清晰、权限最小化,通常不会干扰;建议对高并发场景做限流。
进阶与扩展
- 多 Agent 编排:用 LangGraph 的状态机把“规划—执行—复核”拆成多个角色。
- MCP Registry:搭建内部工具注册中心,统一版本与权限。
- 评测集:把业务用例沉淀为自动化回归,防止行为漂移。
- 私有化:把 LLM 换成本地部署模型(如
Ollama),实现全链路内网运行。
用户评价