在前三篇文章中,我们探讨了上下文对大语言模型的重要性,今天这篇内容,将重点聚焦于 MCP 协议。
MCP 全称为 Model Context Protocol,中文译作“模型上下文协议”。从字面意思不难看出,它依然归属于上下文知识体系的范畴。
为什么需要 MCP?
那么,MCP 究竟解决了哪些实际问题?
首先要理解“协议”这个核心概念。作为前端开发者,最熟悉的莫过于 HTTP 协议。HTTP 存在的根本意义在于:只要两台设备都遵循这一协议,它们就能够实现相互通信。
那 MCP 又是为哪两者服务的?答案很清晰:“模型”和“上下文”。只要一段上下文遵循 MCP 协议,它就能无缝地提供给模型使用。
在 MCP 出现之前,模型要想获取外部能力,通常依赖 Function Calling 方案。理论上是可行的,大模型借助 Function Calling 调用外部工具,再将结果作为上下文引入。但背后隐藏着一个严重的标准化问题——不同厂商的模型,Function Calling 的格式差异巨大。
简单列举几个常见的例子:
deepseek
tools = [{"type": "function","function": {"name": "get_weather","description": "Get weather of an location","parameters": {"type": "object","properties": {"location": {"type": "string","description": "The city and state, e.g. San Francisco, CA"}},"required": ["location"]},}}]
GPT
const tools = [{type: "function",name: "get_weather",description: "Get current temperature for provided coordinates in celsius.",parameters: {type: "object",properties: {latitude: { type: "number" },longitude: { type: "number" }},required: ["latitude", "longitude"],additionalProperties: false},strict: true}];
claude
"tools": [{"name": "get_weather","description": "Get the current weather in a given location","input_schema": {"type": "object","properties": {"location": {"type": "string","description": "The city and state, e.g. San Francisco, CA"}},"required": ["location"]}}],
这正是缺乏标准化带来的痛点。一位 Agent 应用开发者,为了兼容不同模型厂商,代码中需要编写大量适配逻辑。这种场景是否似曾相识?没错,这与当年适配不同浏览器的情况如出一辙。
有了 MCP,一切就变得简单得多。只要上下文遵循 MCP 协议,模型同样遵循 MCP 协议,那么这段上下文就能直接输入给模型,无需额外适配工作。
MCP核心组件
理解了其重要意义,接下来看看 MCP 的核心组件,主要有三大块:
- MCP Client
- MCP Server
- MCP Host
先回顾一下常见的网络模型。
1. Client-Server 模型
也就是“客户端/服务器端模型”。客户端负责发送请求,服务器负责处理并给出响应。
特点:
- 存在一个(或多个)中心服务器
- 客户端通常不能直接互相通信
- 所有数据与逻辑集中在服务器端
2. Peer-to-Peer 模型
即“对等网络模型”,简称 P2P 模型。每个节点既是客户端,同时也是服务器。
特点:
- 没有中心服务器
- 节点之间可以直接通信
- 数据分散在各个节点
那么,MCP 选择了哪条路径呢?
答案很明确,就是 Client-Server 网络模型。MCP Server 是提供“上下文”的一端,MCP Client 则是连接 MCP Server、从中获取“上下文”的一端。
MCP Server
MCP Server 负责提供上下文,具体能提供哪些内容?主要包含三类:
- Tools
- Resources
- Prompts
1. Tools工具
工具部分,其工作原理与 Function Calling 类似,唯一的区别在于现在基于统一的协议标准进行定义和调用,通用性和可复用性有了显著提升。
常见示例:
- 查询天气
- 查询数据库
- 下订单
- 调用第三方 API
- 执行代码
原本大语言模型只能根据训练数据回答问题,如今有了工具,就可以临时新增一段上下文。例如用户说“帮我查一下北京今天的天气”,模型本身不知道天气情况,但可以:
- 识别出需要调用
get_weather - 通过 MCP Client 调用 MCP Server 上的这个工具
- 获取结果
- 再组织成自然语言返回给用户
2. Resources资源
模型可以“读取”的数据。这类上下文与“工具”的区别在于:
- Tools 是“执行动作”
- Resources 是“提供信息”
常见的资源包括:
- 文档(公司制度、产品说明)
- 数据库内容
- 文件(PDF / Markdown / JSON)
- 外部知识源
举个例子,用户问“公司报销标准是多少?”,模型本身不知道,但可以:
- 从 MCP Server 提供的资源中
- 找到“报销制度文档”
- 把相关内容作为上下文
- 再进行回答
这和 RAG 有什么区别?简单来说,MCP Server Resources 是一种数据源,RAG 是一种数据检索策略。MCP Server Resources 完全可以作为 RAG 的数据来源。
3. Prompts提示词
这也是上下文的一种类型,提供可复用的提示词模板。很多人容易忽略这部分,但它其实至关重要。提示词本身也可以被复用、管理和标准化。比如:
- 分析报告模板
- 代码生成模板
- 总结模板
- 特定业务流程的提示结构
举个例子,你可以在 MCP Server 中定义一个 Prompt:
请根据以下信息,生成一份结构化分析报告:- 背景- 问题- 解决方案- 风险评估
模型在需要时,可以直接“调用这个模板”,无需每次都重新编写 prompt。
MCP Client
MCP Client 主要用于:
- 连接某个 MCP Server
- 完成协议握手
- 发送请求,接收 MCP Server 的响应
- 获取 MCP Server 暴露出来的能力
一个标准 MCP Client 的抽象骨架大致如下:
class MCPClient {// 连接connect(transport)// 生命周期initialize()// 能力发现listTools()listResources()listPrompts()// 能力调用callTool()readResource()getPrompt()// 通信request()notify()// 会话管理close()reconnect()}
1. 连接层
建立与 MCP Server 的连接,transport 可以是 stdio、http 或 websocket。
2. 生命周期
初始化会话,获取 server 能力,完成协议握手。本质上就是 Client 与 Server 的“首次对话”。
3. 能力发现
用于查询 MCP Server 提供了哪些能力。
4. 能力使用
真正去“使用能力”,调用 MCP Server 所提供的方法,获取对应的上下文内容。
5. 会话管理
管理连接的生命周期,处理断连与重连等场景。
MCP Host
除了 MCP Client 和 MCP Server,你可能还听说过 MCP Host。它到底是什么?
其实就是真正与用户进行交互的应用,比如:
- Claude Desktop
- Cursor / VS Code 这类 IDE
- 你自己编写的聊天应用
- 你自己的 Agent 系统
三者之间的关系如下图所示:MCP Host 是一个 Agent 应用,MCP Client 是这个应用当中的一个模块。
通信方式
最后来看 MCP 协议中的通信方式,主要涉及两个层面:通信的格式和通信的方式。
通信格式
数据传输的格式有多种:xml、json、字符串等。MCP 中采用的是 JSON-RPC 2.0,全称 JSON Remote Procedure Call,即远程函数调用。简单来说,就是用 JSON 格式来描述“远程调用”的协议。
一个典型的请求大致如下:
{"jsonrpc": "2.0","method": "callTool","params": {"name": "get_weather","arguments": {"location": "Beijing"}},"id": 1}
MCP Server 收到后,会返回:
{"jsonrpc": "2.0","result": {"temperature": 25,"condition": "sunny"},"id": 1}
由此可见,在 MCP 协议中,调用工具实际上就是一次标准化的远程请求,工具的执行在 MCP Server 上,通过 JSON 返回结果。
通信方式
MCP 中常见的通信方式主要有两类:
- stdio:本地进程通信
- http:网络通信
1. stdio
如果 MCP Client 和 MCP Server 运行在同一台机器上,通过标准输入/输出(stdin/stdout)即可直接通信。这种方式的特点是高效、简洁、没有网络开销,非常适合本地开发场景。
2. http
当 MCP Server 不在本地时,就需要通过网络进行通信。MCP Client 通过 HTTP 请求去调用 MCP Server。这种方式支持远程部署,可以做成服务化,更适合生产环境。
Streamable HTTP 是 MCP 中基于 HTTP 的通信方式,主要用于远程和 Web 场景。客户端通过 HTTP POST 发送 JSON-RPC 请求,例如 initialize、callTool、listResources。
sequenceDiagram
participant Client
participant Server
Client->>Server: POST /mcp(initialize / callTool)
Server-->>Client: JSON一次性响应 或者 SSE 流响应
服务端可以根据场景返回普通 JSON 响应(application/json)或流式 SSE 响应(text/event-stream)。
除了请求响应,客户端还可以通过 GET 请求建立 SSE 连接,用于接收服务端的通知:
sequenceDiagram
participant Client
participant Server
Client->>Server: GET /mcp(建立 SSE)
Server-->>Client: 推送 notifications(如 list_changed)
常见通知包括 notifications/resources/list_changed 和 notifications/tools/list_changed。
StreamableHTTP 的使用场景:
- 通过 HTTP 接收远程请求(如前端网页、API 网关)
- 需要支持多客户端并发访问
- 浏览器与 MCP Server 通信
- 流式响应(如 SSE 推送)需求
写在最后
回顾本篇内容,我们实际上解决了一个非常核心的问题:模型如何连接真实世界的能力?
在没有 MCP 之前,虽然可以通过 Function Calling 调用工具,但始终存在几个难题:不同模型格式不一致,不同系统接入成本高,能力无法复用。
而 MCP 所做的其实很纯粹:用一套统一的协议,将“能力”标准化。
从结构上看,本篇介绍了 MCP 的几个关键组成部分:
- MCP Server:提供能力(Tools / Resources / Prompts)
- MCP Client:连接并调用这些能力
- MCP Host:真正与用户交互的应用
以及它背后的通信方式:
- JSON-RPC:统一调用格式
- stdio / HTTP:统一通信通道
但如果再往深一层看,MCP 的意义并不只是“多了一套协议”。它真正带来的变革在于:模型不再仅“生成文本”,而是开始“调用能力”,甚至可以参与到系统运行中。换句话说,MCP 让模型从“会回答问题”,迈向“可以完成任务”。
如果说前面几篇文章,我们一直在解决如何让模型“说得更好”,那么从这一篇开始,我们进入了另一个阶段:如何让模型“做得更多”。
不过接下来,一个更关键的问题自然会浮现:这些能力,应该在何时使用?如何组合运用?由谁来决策?这,就是下一步需要解决的问题。
