封面

Day08|大模型 MCP 实战——让 AI 长出"手"来操作你的工具

前言:3 个工具,3 套对接代码

上周三晚上 9 点,我接到朋友老陈的电话。

他的 AI 客服项目要上线了,但卡在一个地方:客服助手需要能查订单、能发邮件、能读文件。三个能力,听起来不复杂。

"我先接了邮件 API,写了一套适配代码。然后接数据库查询,又写一套。现在要接文件系统,第三套。"他在电话那头叹气,"而且我们下个月可能从 GPT-4o 换成 Claude,到时候这三套全得重写。"

我说:你这不是在接工具,你是在织蜘蛛网。

他的困境不是个例。这是 2024 年之前所有 AI 应用开发者的痛——N 个模型 × M 个工具 = N×M 份适配代码。5 个模型接 8 个工具,就是 40 份代码。每换一个模型,全部重来。

上一篇 Day07 讲了记忆系统,让 AI"记住你"。但光有记忆不够——AI 还缺一样东西:。能去查数据库、能去发邮件、能去读文件的"手"。

Anthropic 在 2024 年底开源了一个协议,专门解决这个问题。它叫 MCP(Model Context Protocol)——大模型的"USB-C 接口"。

这篇文章干四件事:

  1. 讲透 MCP 是什么,为什么它能终结"集成地狱"
  2. 拆解 MCP 架构——Client、Server、Transport 各管什么
  3. 给你一个可运行的 MCP Server demo(Python,直接跑)
  4. MCP vs Function Calling——什么时候该用哪个

读完你会发现,MCP 之于 AI 工具集成,就像 HTTP 之于 Web——不是某个公司的产品,而是整个行业的协议。


PART 01:MCP 是什么——大模型的"USB-C 接口"

先看一个让人头皮发麻的数学题。

假设你有 5 个模型(GPT-4o、Claude、Gemini、通义千问、DeepSeek),要接 8 个工具(邮件、数据库、文件系统、GitHub、Slack、日历、搜索引擎、内部 API)。

没有 MCP 之前,你需要写多少份适配代码?

5 × 8 = 40 份。

每份都要处理:模型 A 的 function calling 格式和模型 B 不一样,工具 X 的参数结构和工具 Y 不一样。40 份代码,40 个维护点。

N×M集成地狱 vs MCP标准化

MCP 的核心思想简单到一句话:在模型和工具之间放一个标准协议层。

模型只需要实现 MCP Client,工具只需要实现 MCP Server。协议层负责翻译——模型说"我要查订单",协议层翻译成对应工具能理解的格式。

这样 5 × 8 = 40 份代码,变成了 5 + 8 = 13 份。模型侧 5 份 Client,工具侧 8 份 Server,互不干扰。

换个模型?Client 不变,Server 不用改。换个工具?Server 不变,Client 不用改。

MCP 三大能力

MCP 不只是"调用函数"。它定义了三类能力,覆盖 AI 与外部世界交互的几乎所有场景:

Resources(资源)——让 AI 读取数据

比如文件内容、数据库记录、API 返回值。Resources 是只读的,AI 可以"看"但不能"改"。用 URI 寻址,像 file:///users/desktop/notes.txt 这样的路径。

Tools(工具)——让 AI 执行操作

比如发邮件、写文件、创建 GitHub Issue。Tools 有副作用,执行后会改变外部状态。每个 Tool 定义自己的参数 schema(JSON Schema),AI 根据 schema 决定怎么调用。

Prompts(提示模板)——预定义交互模式

把常用的 prompt 模式封装成模板,复用。比如"代码审查"模板、"数据分析"模板,带参数,一键调用。

三类能力各司其职:Resources 管"看",Tools 管"做",Prompts 管"怎么问"。

一个类比帮你记住

Function Calling 像打电话——每次都要手动拨号(写适配代码),换号码了就得重拨。

MCP 像 USB-C——插上就能用,不用管两边是什么设备。充电、传数据、接显示器,一个接口全搞定。


PART 02:MCP 架构拆解——Client、Server、Transport

MCP 的架构不复杂,但有几个角色容易搞混。我拆开讲。

MCP架构图

四个角色

Host(宿主应用):运行 LLM 的应用程序。Claude Desktop、Cursor、Windsurf,或者你自己写的 Agent,都是 Host。Host 决定"什么时候用 MCP"。

Client(客户端):Host 内部的 MCP 连接器。每个 Client 1:1 对应一个 Server。如果你同时连了文件系统 Server、GitHub Server、数据库 Server,Host 里就有 3 个 Client,各管各的。

Server(服务端):暴露工具和资源的独立进程。每个 Server 聚焦一个能力域——文件系统 Server 管文件操作,GitHub Server 管 repo 操作,互不干涉。

Transport(传输层):Client 和 Server 之间的通信管道。两种方式:

  • stdio:标准输入输出,本地进程通信。适合本地工具,启动快、零配置。
  • Streamable HTTP / SSE:基于 HTTP 的远程通信。适合云端服务,支持跨网络。

本地开发用 stdio,生产部署用 HTTP。切换 Transport 不改业务代码,只改启动配置。

三大原语怎么通信

MCP 用 JSON-RPC 2.0 协议通信。所有消息都是 JSON,格式统一。

拿 Tools 举例,通信流程是这样的:

// 1. Client 问 Server:"你有哪些工具?"
{"method": "tools/list", "params": {}}

// 2. Server 回答:"我有两个工具"
{"tools": [
  {"name": "list_directory", "description": "列出目录内容", "inputSchema": {"type": "object", "properties": {"path": {"type": "string"}}}},
  {"name": "read_file", "description": "读取文件内容", "inputSchema": {"type": "object", "properties": {"path": {"type": "string"}}}}
]}

// 3. Client(代表 LLM)说:"调用 list_directory,参数 path=/Users/desktop"
{"method": "tools/call", "params": {"name": "list_directory", "arguments": {"path": "/Users/desktop"}}}

// 4. Server 执行后返回结果
{"content": [{"type": "text", "text": "notes.txt\nreport.pdf\nphoto.jpg"}]}

Resources 和 Prompts 的通信模式类似,只是方法名不同(resources/listresources/readprompts/listprompts/get)。

核心设计理念:Server 不关心是哪个模型在调用它,模型也不关心 Server 内部怎么实现。协议层做了完全的解耦。


PART 03:动手实现一个 MCP Server(完整可运行代码)

理论讲完了,上手写代码。我们用官方 mcp Python SDK 实现一个文件系统工具 Server——让 AI 能列出目录、读文件。

MCP Server实现到调用全链路

安装依赖

pip install mcp

完整代码

"""
Day08 MCP Server Demo —— 文件系统工具
让 AI 能列出目录内容、读取文件

依赖:pip install mcp
运行:python server.py
"""
import os
from mcp.server.fastmcp import FastMCP

# 创建 MCP Server 实例
mcp = FastMCP("filesystem-tools")


# ========== 注册 Tools(可执行操作)==========

@mcp.tool()
def list_directory(path: str) -> str:
    """列出指定目录下的文件和文件夹

    Args:
        path: 目录路径,如 /Users/desktop
    """
    try:
        entries = os.listdir(path)
        # 区分文件和文件夹
        result = []
        for entry in entries:
            full_path = os.path.join(path, entry)
            if os.path.isdir(full_path):
                result.append(f"\U0001F4C1 {entry}/")
            else:
                size = os.path.getsize(full_path)
                result.append(f"\U0001F4C4 {entry} ({size} bytes)")
        return "\n".join(result) if result else "目录为空"
    except FileNotFoundError:
        return f"错误:目录不存在 {path}"
    except PermissionError:
        return f"错误:无权限访问 {path}"


@mcp.tool()
def read_file(path: str) -> str:
    """读取指定文本文件的内容

    Args:
        path: 文件路径,如 /Users/desktop/notes.txt
    """
    try:
        with open(path, "r", encoding="utf-8") as f:
            content = f.read()
        # 限制返回长度,避免超长文件撑爆上下文
        if len(content) > 10000:
            content = content[:10000] + "\n\n... (文件过长,已截断)"
        return content
    except FileNotFoundError:
        return f"错误:文件不存在 {path}"
    except UnicodeDecodeError:
        return f"错误:无法解码文件(可能是二进制文件){path}"


# ========== 注册 Resource(只读数据)==========

@mcp.resource("file://{path}")
def read_file_resource(path: str) -> str:
    """通过 URI 访问文件内容,如 file:///Users/desktop/notes.txt"""
    return read_file(path)


# ========== 启动 Server ==========

if __name__ == "__main__":
    # stdio 模式启动,适合本地工具
    mcp.run(transport="stdio")

代码不到 60 行,但功能完整:两个 Tool(列目录、读文件)+ 一个 Resource(URI 访问文件)。

几个关键点解释一下:

FastMCP 是什么? 它是官方 SDK 提供的高层 API,用装饰器注册 Tool 和 Resource,自动处理 JSON-RPC 通信细节。不用手写 JSON-RPC 消息,装饰器搞定。

inputSchema 去哪了? FastMCP 自动从函数签名和类型注解生成。path: str 自动变成 {"type": "string"},AI 看到 schema 就知道该怎么调用。

为什么限制返回长度? 文件内容直接塞进 LLM 上下文,超长文件会撑爆 token 限制。10K 字符是个安全阈值。

配置 Claude Desktop 连接

写好 Server 后,让 Claude Desktop 连上它。编辑配置文件:

// macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "filesystem-tools": {
      "command": "python",
      "args": ["/path/to/your/server.py"]
    }
  }
}

重启 Claude Desktop,左下角会出现一个工具图标,表示 MCP Server 已连接。

测试效果

在 Claude Desktop 里输入:

列出我桌面上的文件

Claude 会自动识别意图,调用 list_directory 工具,拿到结果后用自然语言总结:

您的桌面上有以下文件: - 📁 Screenshots/ - 📄 notes.txt (1,204 bytes) - 📄 report.pdf (2,856,432 bytes) - 📷 photo.jpg (3,201,564 bytes)

整个过程你不需要写任何 prompt 来"教"模型用工具——MCP 协议自动完成了工具发现、参数填充、结果回传。

这就是 MCP 的威力:一次开发,任何支持 MCP 的 Host 都能用你的工具。今天 Claude Desktop 能用,明天 Cursor 能用,后天你自己写的 Agent 也能用。


PART 04:MCP vs Function Calling——什么时候用哪个

到这里你可能会问:我已经在用 Function Calling 了,为什么要换 MCP?

先说结论:不是替代关系,是不同层级的方案。

MCP vs Function Calling决策树

核心区别

维度 Function Calling MCP
是什么 模型原生能力 应用层标准协议
开发成本 低(写个函数 + JSON Schema) 中(实现一个 Server)
复用性 差(每模型 API 格式不同) 好(一次开发,处处可用)
生态 各模型各自为政 开放协议,社区共建
跨模型 不支持(GPT 和 Claude 格式不同) 原生支持(协议统一)
适合场景 单模型、少量工具 多模型、多工具、需复用

判断框架

问自己三个问题:

1. 你用几个模型?

只用一个模型 → Function Calling 够了。你的代码和这个模型绑定了,但短期内没有切换需求。

多个模型(或未来可能切换)→ MCP。协议层隔离了模型差异,换模型不改工具代码。

2. 你有几个工具?

1~3 个工具 → Function Calling。直接写函数,简单直接。

5 个以上工具 → MCP。工具多了,统一管理比散落各处强。MCP Server 可以按域分组(文件系统一组、数据库一组、通信一组)。

3. 工具需要跨项目复用吗?

不需要 → Function Calling。每个项目自己管自己的工具。

需要 → MCP。一个 Server 写好,多个项目复用。团队 A 的 GitHub Server,团队 B 直接拿来用。

现状与生态

截至 2026 年中,MCP 生态已经相当成熟:

  • Claude Desktop / Cursor / Windsurf:原生支持 MCP,开箱即用
  • 官方 Server:文件系统、GitHub、PostgreSQL、Google Drive、Slack 等数十个
  • 社区 Server:涵盖 Notion、Linear、Jira、Figma 等主流工具
  • OpenAI:尚未官方支持 MCP,但社区已有适配层(如 mcp-openai-adapter

趋势很明确:MCP 正在成为 AI 工具集成的标准协议。就像 HTTP 统一了 Web 通信一样,MCP 正在统一 AI 与工具的通信。


结尾:AI 的"HTTP 时刻"

回头看这篇文章的核心:

  • MCP 是什么:模型和工具之间的标准协议层,把 N×M 适配问题变成 N+M
  • 架构四角色:Host 管调度、Client 管连接、Server 管能力、Transport 管通信
  • 三大原语:Resources 管"看"、Tools 管"做"、Prompts 管"怎么问"
  • 选型框架:单模型少量工具用 Function Calling,多模型多工具用 MCP

Day07 讲记忆时我说,记忆是 AI 从"工具"变"伙伴"的分水岭。MCP 解决的是另一个问题——让 AI 从"只会说话"变成"能做事"。

一个只能生成文字的 AI,再聪明也只是个百科全书。一个能调用工具的 AI,才是真正的助手——能帮你查数据、发邮件、管文件、操作系统。

老陈后来把三个工具用 MCP Server 重构了。现在他换模型只需要改一行配置,工具代码一行不用动。电话那头的叹气声变成了"早知道有这东西,我那三周白熬了"。

MCP 之于 AI 工具集成,就像 HTTP 之于 Web——不是某个公司的产品,而是整个行业的协议。

当协议统一的那一刻,生态就开始爆发。这就是 MCP 正在做的事。

互动时间:你的 AI 应用里,工具调用用的 Function Calling 还是 MCP?遇到过"集成地狱"吗?欢迎评论区聊聊。


下一篇 Day09 预告:大模型前置之数据清洗——数据是 AI 的粮食,垃圾进则垃圾出。关注小刘檀木,不错过每一篇。

— END —

小刘檀木 · 帮普通人把 AI 学进简历

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐