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.tomlmain.pymcp[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 里:

  1. 选中 read_file 工具。
  2. 输入参数 {"path": "README.md"}(在项目里先建一个 README.md)。
  3. 点击调用,右侧应返回文件内容。

这一步能确认“工具本身可用”,把模型层面的问题先隔离掉。

第四步:用 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"

验证方法

  1. 工具层验证:MCP Inspector 单测每个工具。
  2. 链路验证:让 Agent 完成 3 个不同任务,确认每次都能正确选择工具。
  3. 回归验证:把用例固化为脚本,改动后重跑。

常见问题(FAQ)

  1. MCP 必须用 Python 吗?

    不是。官方 SDK 支持 Python 与 TypeScript,Node 环境用 @modelcontextprotocol/sdk

  2. 本地没有 GPU 能用这个教程吗?

    能。本教程的 LLM 走 API,只有大模型推理需要算力,本地只跑轻量工具服务。

  3. Agent 一直不调用工具怎么办?

    先检查 tool 描述是否包含“何时调用”的触发条件,其次确认模型具备 function calling 能力,最后用更简单的 prompt 测试。

  4. 生产环境 MCP Server 怎么部署?

    可把 Server 作为独立进程/容器部署,用 streamable HTTP transport 替代 stdio,并接入统一鉴权。

  5. 多工具之间会不会互相干扰?

    每个工具独立命名空间与 schema,只要描述清晰、权限最小化,通常不会干扰;建议对高并发场景做限流。

进阶与扩展

  • 多 Agent 编排:用 LangGraph 的状态机把“规划—执行—复核”拆成多个角色。
  • MCP Registry:搭建内部工具注册中心,统一版本与权限。
  • 评测集:把业务用例沉淀为自动化回归,防止行为漂移。
  • 私有化:把 LLM 换成本地部署模型(如 Ollama),实现全链路内网运行。

用户评价

  • 加载评价中...