MCP 基础知识:AI 应用如何标准化接入外部能力
从概念到架构系统梳理 Model Context Protocol:Host / Client / Server、Tools / Resources / Prompts、传输层与生命周期,以及和 Function Calling 的边界。
---
MCP 基础知识:AI 应用如何标准化接入外部能力
大模型越来越会「做事」:读文件、查库、调 API、走工作流。但每接一种能力,Host(IDE、桌面助手、自建 Agent)往往要各自写一套适配——工具一多,集成成本与安全边界都会失控。
MCP(Model Context Protocol,模型上下文协议) 要解决的,正是这件事:让 AI 应用用统一方式连接外部工具、数据与工作流,而不是为每个 Host 各写一套插件。
本文将从定义出发,讲清参与者、两层架构、三大原语、生命周期与一次典型调用,并辨析它与 Function Calling 的关系,最后给出安全原则与学习路径。
MCP 是什么
一句话定义
MCP 是一套开放协议:让 AI 应用用标准化的 Client ↔ Server 对话,发现并调用外部能力(工具、资源、提示模板),而不是为每个 Host 各自实现插件协议。
常被比作:AI 应用接外部能力的「USB 标准」。
它管什么、不管什么
| MCP 管 | MCP 不管 |
|---|---|
| Client ↔ Server 如何交换上下文与能力(JSON-RPC 消息、原语、传输) | Host 里怎么选模型、怎么写 Agent 循环、怎么做 UI |
| Tools / Resources / Prompts 等原语的语义 | 业务逻辑本身(查库、读文件的具体实现由 Server 作者决定) |
| 能力协商、通知、进度等横切能力 | 替换 Function Calling 在模型侧的「想调用」机制 |
一句话口诀:
Function Calling = 模型怎么表达「要调工具」;MCP = 工具/数据怎么标准化地接进应用。
为什么值得学
- 可复用:一个 Server,可被 Claude Desktop、Cursor、VS Code、自建 Host 等复用。
- 边界清晰:Host / Client / Server 职责分离,安全边界更好画。
- 生态已成事实标准:官方与社区有大量 Server;多厂商 Host 已接入。
- 与 Agent 工程衔接:你若已有 Tool Call、Workflow、Multi-Agent,MCP 是「工具接入层」的标准答案。
参与者:Host / Client / Server
MCP 采用 Host ↔(多个)Client ↔(多个)Server 结构。
┌──────────────────────── MCP Host(AI 应用)────────────────────────┐
│ 例:Cursor / Claude Desktop / VS Code / 你自己写的 Agent 程序 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Client 1 │ │ Client 2 │ │ Client 3 │ ← 每个 Server 一个 Client │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
└────────┼─────────────┼─────────────┼───────────────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────────┐
│ Server A │ │ Server B │ │ Server C │
│ 本地文件 │ │ 本地 DB │ │ 远程 SaaS │
│ (stdio) │ │ (stdio) │ │ (HTTP) │
└──────────┘ └──────────┘ └──────────────┘
| 角色 | 比喻 | 职责 |
|---|---|---|
| Host | 总指挥部 | 用户面对的 AI 应用;创建 Client、调度 LLM、决定何时把工具结果塞进对话 |
| Client | 翻译官 / 专线 | 嵌在 Host 内;与某一个 Server 维持连接、做协议握手与消息路由 |
| Server | 能力供应商 | 暴露 Tools / Resources / Prompts;可以是本地子进程,也可以是远程服务 |
需要记住的三个事实:
- 一对一连接:一个 Client 实例对应一个 Server 连接;Host 连 N 个 Server 就有 N 个 Client。
- 「Server」不等于「必须远程」:stdio 本地子进程也叫 MCP Server。
- 本地 vs 远程 主要由 Transport(传输层) 决定。
两层架构:Data Layer + Transport Layer
┌─────────────────────────────────────────┐
│ Transport Layer(外层) │
│ stdio | Streamable HTTP(+ 可选 SSE) │
│ 连接建立、消息分帧、鉴权 │
├─────────────────────────────────────────┤
│ Data Layer(内层) │
│ JSON-RPC 2.0:生命周期、原语、通知、工具调用 │
└─────────────────────────────────────────┘
| 层 | 回答的问题 | 要点 |
|---|---|---|
| Data Layer | 「说什么」 | JSON-RPC 2.0;initialize、tools/list、tools/call、notifications… |
| Transport Layer | 「怎么运」 | stdio 管道,或 HTTP POST(可带流式);同一套 JSON-RPC 载荷 |
学 MCP 时优先搞懂 Data Layer 原语;传输可以后换,语义不变。
传输方式(Transport)
当前主流两种(以官方文档为准):
| 传输 | 形态 | 典型场景 | 特点 |
|---|---|---|---|
| stdio | Host 拉起子进程,stdin/stdout 换 JSON-RPC | 本机文件、本地 git、本机 DB | 无网络面、生命周期由 Host 管、最适合入门 |
| Streamable HTTP | Server 听 HTTP;Client POST,可选 SSE 流式 | 远程共享能力、多客户端 | 可标准 HTTP 鉴权(Bearer / API Key / OAuth 等) |
关于 SSE:早期有「纯 SSE」远程传输;较新的规范以 Streamable HTTP 为主,SSE 作为流式能力的一部分或历史路径。学习与选型时优先记:
本地 → stdio;远程 → Streamable HTTP。
Server 三大原语:Tools / Resources / Prompts
这是 MCP 最该先背熟的部分。Server 可以只实现其中一类,也可以三类都有。
| 原语 | 比喻 | 是什么 | 谁通常触发 | 典型方法 |
|---|---|---|---|---|
| Tools | 可执行动作 | 带 JSON Schema 入参的函数(查库、写文件、调 API) | 模型在对话中决定调用 | tools/list → tools/call |
| Resources | 可读资料 | URI 标识的数据(文件内容、schema、配置快照) | 应用/用户注入上下文,或模型经 Host 读取 | resources/list → resources/read |
| Prompts | 预设工作流模板 | 可参数化的提示 / 少样本模板 | 用户在 Host UI 里选模板 | prompts/list → prompts/get |
怎么区分(避免混用)
| 问题 | 更像 |
|---|---|
| 会改变外部世界或执行计算? | Tool |
| 只是「把某份数据塞进上下文」? | Resource |
| 希望用户一键套用固定话术 / 流程? | Prompt |
同一业务常三者并存,例如「数据库助手」:
- Tool:
query_sql - Resource:
db://schema(表结构) - Prompt:
analyze-slow-query(带 few-shot 的分析模板)
Tool 元数据(Client / LLM 靠它选型)
tools/list 返回的每个 tool 通常包含:
| 字段 | 作用 |
|---|---|
name | 调用主键(稳定、唯一) |
title | 给人看的短名 |
description | 给模型看的「何时用」说明(写差了模型就不会调) |
inputSchema | JSON Schema:参数类型、必填、枚举 |
tools/call 的结果一般是 content 数组(可多段 text / image / resource 等),Host 再把它转成模型可读的 tool result。
Client 侧能力:Sampling / Elicitation / Roots / Logging
除了 Server「向外提供」,协议也允许 Server 反过来请求 Client / Host 做事(需在握手时声明能力)。
| 能力 | 方向 | 用途 |
|---|---|---|
| Sampling | Server → Client | Server 请求 Host 侧 LLM 补全(Server 不绑死某一模型 SDK) |
| Elicitation | Server → Client | Server 向用户要额外信息或确认(表单 / 确认框) |
| Roots | Client ↔ Server | 划定 Server 可操作的文件系统 / URI 边界 |
| Logging | Server → Client | 结构化日志,便于 Host 调试与监控 |
入门阶段:先掌握 Server 的 Tools;Sampling / Elicitation 放到进阶。
生命周期与能力协商
在当前主流有状态会话模型下,连接通常以握手开始:
Client Server
| |
|──── initialize (version, |
| capabilities, clientInfo)──►|
|◄─── result (version, |
| capabilities, serverInfo)───|
|──── notifications/initialized ─►|
| |
|──── tools/list ───────────────►|
|◄─── tools[] ───────────────────|
|──── tools/call ───────────────►|
|◄─── content[] ─────────────────|
握手解决三件事:
- 协议版本协商(对不上应断开)
- Capabilities 声明(有没有 tools、是否支持
list_changed通知等) - 身份信息(
clientInfo/serverInfo,便于调试)
之后才是发现与调用。能力未声明的方法,对方不应假定可用。
规范仍在演进(例如会话模型、HTTP 部署形态可能调整)。学习时以「握手 + 原语 + 传输」为主干;写代码时锁定某一 SDK / 协议版本并读其 changelog。
一次典型调用(心智走读)
以 Host 内嵌 LLM 为例:
- Host 启动,为每个配置的 Server 创建 Client,完成
initialize。 - Client 调
tools/list,Host 把所有 Server 的 tools 合并进统一工具表,交给模型。 - 用户提问 → 模型输出 tool call(这是 Function Calling / Tool Calling)。
- Host 根据 tool
name找到对应 MCP Client →tools/call。 - Server 执行业务逻辑,返回
content。 - Host 把结果写回对话,模型继续生成最终回答。
谁调用 LLM? 默认是 Host。Server 通常不内嵌模型;若 Server 需要模型能力,走 Sampling(进阶)。
通知与横切能力
| 能力 | 说明 |
|---|---|
| Notifications | 如 notifications/tools/list_changed:工具列表变了,Client 应再 tools/list(无 id、不要求响应) |
| Progress | 长任务进度上报 |
| Cancellation / Errors | 取消与标准错误报告 |
| Tasks(演进中) | 长时任务句柄、可延迟取结果;具体形态随规范版本变化 |
动态工具列表(权限变化、插件热加载)依赖通知;静态小 Server 可先不做。
MCP vs Function Calling vs A2A
| 概念 | 层 | 解决的问题 |
|---|---|---|
| Function / Tool Calling | 模型 ↔ Host | 模型如何结构化表达「要调哪个函数、参数是什么」 |
| MCP | Host / Client ↔ Server | 外部能力如何标准化发现与调用(可跨应用复用) |
| A2A 等 Agent 协议 | Agent ↔ Agent | 多个 Agent 之间如何协作对话(与「接工具」不同层) |
关系可以画成:
用户 ↔ Host(含 LLM)
│ Tool Calling(模型决定调什么)
▼
MCP Client ──JSON-RPC──► MCP Server(真正执行 / 提供数据)
没有 MCP 时,你也可以在 Host 里手写本地函数当 tools;有了 MCP,同一套 tools 可被多个 Host 消费,Server 也可独立演进与部署。
安全边界(写 Server 前必读)
MCP 允许任意数据访问与代码执行路径,安全是一等公民:
| 原则 | 实践提示 |
|---|---|
| 最小权限 | Tools 只暴露必要动作;危险操作要确认(Elicitation / Host 策略) |
| Roots / 沙箱 | 文件系统类 Server 限制可访问根目录 |
| 远程鉴权 | Streamable HTTP 使用 OAuth / Token;勿把密钥打进 prompt |
| 信任边界 | 不同 Server 互不可见;Host 负责隔离与用户同意 |
| 描述即攻击面 | Tool description / 返回内容可影响模型行为,需防提示注入 |
开发工具与生态入口
| 名称 | 用途 |
|---|---|
| MCP Specification | 协议权威定义 |
| 官方 SDK | TypeScript / Python 等,屏蔽 JSON-RPC 细节 |
| MCP Inspector | 图形化调试:连 Server、看 list / call,入门强烈推荐 |
| 参考 Server | 官方 / 社区示例(filesystem、git、浏览器等) |
本地学习路径建议:
Inspector 当 Client → 自己写最小 stdio Server → 再写带 LLM 的 Host。
实践路线图:如何真正学会
概念清楚之后,建议按「只换内核、场景固定」的方式动手,避免一上来就堆模型与编排复杂度。一个很好的练手场景是 本地 Docs 助手:
- 语料固定(例如一组 Markdown 文档)
- 能力语义固定:
list_docs/search_docs/read_doc - 逐步加深 MCP 内核,而不是反复改业务
可按下面五档递进:
| 阶段 | 核心问题 | 建议验证方式 |
|---|---|---|
| A · stdio + Tools | handshake / list / call 是否闭环? | MCP Inspector 与最小 Host 都能调通 |
| B · Resources / Prompts | 与 Tool 边界是否分清? | 能走「注入 resource」或「套 prompt」路径 |
| C · Streamable HTTP | 远程传输与 stdio 生命周期差异? | 无子进程、纯 HTTP 可达 |
| D · 多语言对照 | 同语义换栈是否可对照?(如 Python / TypeScript) | 同输入、同能力、仅实现语言不同 |
| E · LLM Host 工具环 | 模型选 tool 是否稳?多轮何时停? | 观察工具命中率、终止原因、调用轮次 |
共用约束建议:
- 前端尽量朴素(甚至纯 HTML),重点看 MCP 时间线(initialize / tools/list / tools/call)
- 检索算法可保持朴素关键词,本线练的是 协议与 Host,不是 RAG 深度
- 为每档准备几道「黄金题」(期望 path、是否应调某 tool),方便回归
速查口诀
- 总指挥 = Host,专线翻译 = Client,能力供应商 = Server
- 做动作 = Tools,读资料 = Resources,套模板 = Prompts
- 本地管道 = stdio,远程 HTTP = Streamable HTTP
- 内层说什么 = Data / JSON-RPC,外层怎么运 = Transport
- 模型「想调」= Tool Calling,标准化「接上」= MCP
- Server 借 Host 的脑 = Sampling,Server 问用户 = Elicitation
小结
MCP 不替代模型侧的 Tool Calling,也不替代 Agent 之间的协作协议;它补的是中间那一层——外部能力如何被标准化地发现、协商与调用。
入门顺序可以记成:
- 搞清 Host / Client / Server 与三大原语
- 用 stdio 跑通
initialize → tools/list → tools/call - 再补 Resources / Prompts 与 HTTP 传输
- 最后接到真正的 LLM Host 工具环,并始终把安全与最小权限放在前面
当你能画出「模型决定调什么 → Host 路由到哪个 MCP Client → Server 执行并返回 content」这条链路,MCP 的主干就已经在手里了。