HTTP 与 MCP:不是替代,而是分层
关键词:HTTP、MCP、Model Context Protocol、JSON-RPC、AI Agent、工具调用
适合读者:后端 / 平台工程师、正在给大模型接工具与数据源的同学
最近做 AI Agent、Cursor Skills、企业知识库时,「要不要用 MCP」几乎成了必问题。更常见的误区是:把 MCP 理解成「取代 HTTP 的新协议」。本文把两者放回正确位置------HTTP 是通用传输与 Web API 基石;MCP 是面向「模型上下文」的应用层协议------并讲清 MCP 的核心原理。
一、先定边界:它们不在同一层
| 维度 | HTTP | MCP |
|---|---|---|
| 全称 | HyperText Transfer Protocol | Model Context Protocol |
| 抽象层 | 传输 / Web 应用协议 | AI 应用与工具/数据源之间的能力协议 |
| 设计目标 | 资源寻址、请求响应、缓存、鉴权、生态互通 | 让 LLM 应用标准化地发现并使用工具、资源、提示模板 |
| 消息形态 | 方法 + URL + Header + Body | JSON-RPC 2.0(request / response / notification) |
| 典型调用方 | 浏览器、移动端、微服务、任意客户端 | Host(如 IDE、Chat 客户端)里的 MCP Client |
| 典型被调方 | REST / GraphQL / 任意 HTTP 服务 | MCP Server(暴露 tools / resources / prompts) |
一句话:
- HTTP:互联网上「怎么把字节可靠送到对方、怎么表达一次请求」。
- MCP:AI 场景里「模型侧需要哪些上下文能力、如何发现、如何调用、如何协商版本与能力」。
MCP 可以跑在 Streamable HTTP 之上,也可以跑在本地 stdio 上------所以「HTTP vs MCP」更像「TCP vs HTTP」那种分层对比,而不是二选一。
text
┌─────────────────────────────────────────────┐
│ Host(Cursor / Claude Desktop / 自研 Agent) │
│ └─ MCP Client │
├─────────────────────────────────────────────┤
│ MCP 数据层:JSON-RPC + Tools/Resources/... │ ← MCP 定义这里
├─────────────────────────────────────────────┤
│ Transport:stdio 或 Streamable HTTP │ ← 可用 HTTP 承载
├─────────────────────────────────────────────┤
│ TCP / 本机管道 / TLS ... │
└─────────────────────────────────────────────┘
二、HTTP 在 AI 栈里仍然干什么
即便全面拥抱 MCP,HTTP 也不会消失。企业里大量能力本来就是 HTTP:
- 开放平台:
POST /v1/chat/completions - 内部微服务:订单查询、权限校验、工单创建
- 网关鉴权:Bearer、API Key、mTLS
- 可观测:Access Log、TraceId、限流熔断
对大模型应用来说,最朴素的集成方式仍是:
text
Agent / 业务代码 ──HTTP──▶ 你的 API / 第三方 API
优点清晰:调试工具成熟、网关与安全体系现成、语言无关。
代价也同样清晰:每个工具一套 URL、一套参数文档、一套鉴权约定;模型侧要自己「知道有哪些工具、怎么拼参数」------这正是 MCP 想标准化的缺口。
三、MCP 解决的是什么问题
MCP(Model Context Protocol)是开放协议,目标是:让 LLM 应用与外部数据源、工具之间,用统一方式连接。
没有 MCP 时,常见形态是:
- 每个产品各自定义 Function Calling schema
- IDE 插件、桌面端、Bot 各自维护一份「工具清单」
- 换一个模型宿主,集成就重写一遍
有了 MCP,工具提供方实现一次 MCP Server ,多种 Host(Claude Desktop、Cursor、自研 Agent 运行时等)通过 MCP Client 接入,即可获得:
- 能力发现:有哪些 tools / resources / prompts
- 结构化调用:按协议调用工具并拿回结果
- 生命周期与能力协商:版本、能力集、初始化握手
- 可选的进度 / 通知:长任务、日志、资源变更
它解决的不是「把 JSON 从 A 送到 B」(HTTP 已经做得很好),而是「给模型用的上下文接口长什么样」。
四、对比总表(工程视角)
| 对比项 | HTTP API | MCP |
|---|---|---|
| 契约单位 | 路径 + 动词 + Schema(OpenAPI) | 方法名 + JSON-RPC params(协议原语) |
| 发现机制 | 文档 / Swagger / 人工约定 | tools/list、resources/list 等协议级发现 |
| 会话模型 | 多为无状态请求 | 有 initialize 握手与会话期能力 |
| 面向谁 | 任意程序 | 面向 LLM Host / Agent 运行时 |
| 本地集成 | 通常仍要起 HTTP 端口 | stdio:子进程管道,零端口,适合桌面/IDE |
| 远程集成 | 原生就是 HTTP | Streamable HTTP(POST + 可选 SSE) |
| 鉴权 | 成熟(OAuth2、网关) | 远程传输推荐 OAuth / Bearer 等;本地 stdio 常靠 OS 进程边界 |
| 适合暴露 | 业务 API、公网开放能力 | 「给模型用的」工具箱与只读上下文 |
互补关系(推荐心智模型):
text
业务系统 ──保持──▶ HTTP / RPC(对内对外 API)
│
▼
MCP Server(薄适配层:把 API 包装成 tool/resource)
│
▼
MCP Client(在 Host 内)──▶ LLM 决策是否调用
也就是说:HTTP 继续做业务真相源;MCP 做 AI 友好的适配与标准化外壳。
五、MCP 原理:三层角色
官方架构里有三个关键角色:
| 角色 | 含义 | 例子 |
|---|---|---|
| Host | 承载 LLM 的应用,拥有用户界面与编排权 | Cursor、Claude Desktop、自研 Copilot |
| Client | Host 内的连接器,一对一连到某个 Server | Host 为每个 MCP Server 建一个 Client |
| Server | 提供上下文与能力的程序 | 文件系统 Server、GitHub Server、你们内部「工单 MCP」 |
注意命名陷阱:MCP Server 不一定是「远程 Web 服务器」。本地用 stdio 拉起的子进程也叫 Server------它强调的是「提供能力的那一端」。
text
Host
┌──────────┐
│ LLM │
│ 编排/UI │
└────┬─────┘
│ 内嵌
┌────▼─────┐ JSON-RPC ┌────────────┐
│MCP Client│◄─────────────────►│ MCP Server │
└──────────┘ stdio 或 HTTP │ tools/... │
└────────────┘
六、MCP 原理:数据层 = JSON-RPC + 原语
6.1 消息层:JSON-RPC 2.0
MCP 数据层基于 JSON-RPC 2.0:
- Request :带
id,期待 Response - Response :成功
result或失败error - Notification :无
id,不要求响应(如日志、进度、取消)
相对「裸 HTTP REST」,好处是:
- 方法名与传输解耦(同一套方法可走 stdio 或 HTTP)
- 天然支持一对多消息形态(通知、流式进度)
- 能力协商可以做成明确的 RPC 方法,而不是散落在各个 URL
6.2 三大核心原语
| 原语 | 给谁用 | 作用 |
|---|---|---|
| Tools | 模型(常需用户授权) | 可执行动作:查库、改文件、调 API |
| Resources | 应用 / 用户(也可喂给模型) | 可读上下文:文件、单据、配置快照 |
| Prompts | 用户 / 工作流 | 可复用的提示模板与多步工作流入口 |
此外还有 Roots (工作区边界)、Sampling (Server 反请 Host 帮调模型,视实现而定)等扩展能力。工程上最常落地的是 Tools + Resources。
6.3 生命周期(简化)
一次典型连接:
text
1. 建立传输(拉起子进程 stdio,或连上远程 MCP HTTP 端点)
2. initialize:协商协议版本与 capabilities
3. initialized 通知:握手完成
4. tools/list / resources/list / prompts/list:发现能力
5. tools/call / resources/read ...:实际使用
6. 可选:notifications(进度、列表变更)、取消
7. 关闭传输 / 结束进程
这与「每次 HTTP 请求自带完整语义」不同:MCP 强调 先握手、再发现、再调用,更贴近「插件生命周期」。
6.4 Tool 调用在 Agent 里怎么转一圈
text
用户问题
→ Host 把可用 tools schema 放进模型上下文
→ 模型决定调用 tool X(args)
→ MCP Client 发 tools/call
→ MCP Server 执行(内部往往再去调你们的 HTTP API / DB)
→ 结果经 MCP 返回 Host
→ 再交给模型总结或继续下一步
对业务研发而言:你很少「重写 HTTP」,更多是 用 MCP Server 包一层,让模型用统一方式看见工具。
七、传输层:stdio 与 Streamable HTTP
协议语义相同,传输只是 binding。
7.1 stdio(本地主流)
- Client 把 Server 当 子进程 拉起
- 在 stdin / stdout 上跑 按行分隔的 JSON-RPC
- 无监听端口、延迟低,适合 IDE / 桌面端
- 安全边界主要靠:谁有权启动进程、进程能读哪些路径、环境变量里有什么密钥
7.2 Streamable HTTP(远程主流)
规范演进上,早期「HTTP + 独立 SSE 端点」已被 Streamable HTTP 取代(旧方案仅兼容):
- Server 暴露 单一 MCP 端点(同时支持 POST / GET)
- Client 用 HTTP POST 发送 JSON-RPC
- 响应可以是普通
application/json,也可以是 SSE(text/event-stream) 以支持流式与多消息 - Client 也可 GET 打开 SSE,便于 Server→Client 通知
- 鉴权可走 Bearer / API Key / 自定义头;远程场景常见推荐 OAuth
于是出现一个重要澄清:
「MCP 用了 HTTP」≠「MCP 等于 HTTP」 。
HTTP 在这里只是马车;车上装的是 JSON-RPC 与 Tools/Resources 语义。
八、一个对照例子(同一业务,两种暴露)
假设能力是:「按订单号查询物流」。
纯 HTTP
http
GET /api/orders/{id}/logistics HTTP/1.1
Authorization: Bearer ...
Agent 要自己:注册函数、写 description、维护 OpenAPI、处理错误码。
MCP Tool(逻辑等价,契约面向模型)
json
{
"name": "get_order_logistics",
"description": "根据订单号查询物流轨迹",
"inputSchema": {
"type": "object",
"properties": {
"orderId": { "type": "string", "description": "订单号" }
},
"required": ["orderId"]
}
}
Server 实现里仍然可以:
text
tools/call(get_order_logistics)
→ 内部 HTTP GET 你们的 /api/orders/{id}/logistics
→ 把结果整理成模型可读的 content
HTTP 没被替换,只是从「模型直接看见」退到了「适配层后面」。
九、怎么选:实践建议
| 场景 | 更合适 |
|---|---|
| 微服务互调、开放平台、对前端/App 暴露 | HTTP(+ OpenAPI) |
| IDE / 桌面 Agent 本地读文件、连本地 DB 工具 | MCP + stdio |
| 多个 AI Host 要复用同一套「给模型用的工具」 | MCP Server(远程可用 Streamable HTTP) |
| 已有稳定 HTTP 能力,想被 Cursor/Claude 等调用 | 保留 HTTP,外挂 MCP 适配器 |
| 只要一次脚本调 API | 不必上 MCP,HTTP SDK 足够 |
判断口诀:
- 调用方是 人写的服务 → HTTP/RPC
- 调用方是 LLM Host,且要标准化发现与工具箱 → MCP
- 两者经常 同时存在
十、小结
- HTTP 解决通用互联与 API 生态问题;MCP 解决「模型上下文与工具」的标准化问题。
- MCP = JSON-RPC 数据层 + Tools/Resources/Prompts 原语 + stdio / Streamable HTTP 传输。
- Host / Client / Server 三分法理解集成边界;Server 可以是本地子进程。
- 工程上最优解通常是:业务继续 HTTP,AI 入口加 MCP 薄封装。
如果你正在把 Spring Boot 接口接到 Cursor / 自研 Agent,下一步通常不是「重写所有 API」,而是:选 3~5 个高价值写操作与只读查询,做成 MCP Tools,并明确鉴权与审计------那才是 MCP 真正产生杠杆的地方。
参考
(文中协议细节以 MCP 官方规范为准;远程传输以现行 Streamable HTTP 为准,旧版 HTTP+SSE 仅作兼容理解。)