一、传输的本质
1. Stdio (Standard Input/Output)
协议本质:
- 基于 进程间通信(IPC) 的经典模式
- 利用 Unix/Linux 的管道机制(pipe)
- 消息格式:JSON-RPC 2.0 over newline-delimited JSON
工作流程:
使用场景:
- ✅ 本地命令行工具(如
npx
,python
,node
) - ✅ 开发者工具(LSP、formatter、linter)
- ✅ 离线场景(无网络依赖)
- ✅ 需要环境变量隔离的工具
优点:
- 零网络开销:直接进程通信,延迟 < 1ms
- 安全性高:不暴露端口,不受网络攻击
- 简单直接:spawn 一个进程就能用
- 资源控制精确:可以随时 kill 进程
缺点:
- 只能本地:无法跨机器调用
- 进程启动开销:每次调用可能需要启动新进程(如 npx 需要下载依赖)
- 无法共享实例:每个客户端都启动独立进程,浪费资源
- 调试困难:错误信息只能从 stderr 获取
典型实现:
- Claude Desktop 的本地 MCP 工具
- VS Code Extension 的 Language Server Protocol (LSP)
- Git 的
filter-branch
等管道命令
2. SSE (Server-Sent Events)
协议本质:
- 基于 HTTP 的 单向推送 协议
- 服务器主动向客户端发送事件流
- 底层是 HTTP 长连接(Content-Type: text/event-stream)
工作流程:
消息格式:
js
event: message
data: {"type":"tool_update","payload":{...}}
id: 12345
event: notification
data: {"message":"Task completed"}
使用场景:
- ✅ 实时通知推送(如日志流、系统监控)
- ✅ 服务器状态更新(如 MCP 工具列表变更)
- ✅ 进度反馈(如长时间任务的进度条)
- ✅ 需要自动重连的场景(浏览器原生支持)
优点:
- 自动重连:断线后浏览器会自动重新连接
- 轻量级:比 WebSocket 简单,适合单向推送
- 跨域友好:支持 CORS
- 事件 ID 机制:支持断线续传(Last-Event-ID)
缺点:
- 单向通信:只能服务器 → 客户端,客户端发请求需要额外 HTTP
- 浏览器限制:有些浏览器对同域 SSE 连接数有限制(如 6 个)
- 代理问题:某些企业代理会缓冲 SSE 流
- 不适合双向交互:如果需要频繁发送请求,不如用 WebSocket
典型实现:
- ChatGPT 的流式输出(早期使用 SSE)
- GitHub Actions 的日志流
- 股票行情推送
3. HTTP (Request-Response)
协议本质:
- 经典的 请求-响应 模式
- 每次交互都是独立的 HTTP POST 请求
- 无状态、可缓存、易于水平扩展
工作流程:
使用场景:
- ✅ 云端 API 服务(如天气 API、翻译 API)
- ✅ 跨机器、跨网络调用
- ✅ 多客户端共享同一服务(如数据库、知识库)
- ✅ 需要负载均衡、CDN、缓存等基础设施
优点:
- 生态成熟:HTTP 工具链完善(nginx、HAProxy、CDN)
- 易于部署:标准 Web 服务,容器化、K8s 友好
- 无状态:每个请求独立,易于水平扩展
- 易于调试:curl、Postman、浏览器都能测试
- 防火墙友好:几乎所有网络环境都允许 HTTP
缺点:
- 连接开销大:每次请求都需要 TCP 三次握手、TLS 握手
- 延迟高:相比本地 IPC,网络延迟 10-100ms
- 无法主动推送:服务器无法主动通知客户端(需要轮询或 webhook)
- 不适合高频调用:每秒上千次请求会很低效
典型实现:
- RESTful API(如 GitHub API、Stripe API)
- 微服务架构(Spring Cloud、gRPC Gateway)
- Serverless Functions(AWS Lambda HTTP endpoint)
4. Streamable HTTP
协议本质:
- HTTP + SSE 的 混合模式
- 请求用 HTTP POST,响应可以是流式(SSE)或普通 JSON
- 通过
mcp-session-id
header 维持会话状态
工作流程:
使用场景:
- ✅ 长时间任务(如代码生成、视频转码)
- ✅ 需要进度反馈(如文件上传、批量处理)
- ✅ 大文件传输(分块流式发送)
- ✅ 有状态的会话管理(如多轮对话)
优点:
- 双向能力:请求用 HTTP,响应可以流式
- 会话管理:通过 session ID 维护上下文
- 渐进式响应:适合生成式 AI 的流式输出
- 兼容性好:基于标准 HTTP/SSE,无需特殊协议
缺点:
- 复杂度高:需要服务端管理 session 状态
- 内存开销:服务端需要存储会话信息
- 不如 WebSocket 实时:仍然是 HTTP 请求-响应,有延迟
- 支持度低:较新的协议,工具链不成熟
典型实现:
- OpenAI Streaming API(GPT-4 的流式输出)
- Anthropic Claude API(支持 streaming)
- AWS Bedrock 的流式推理
二、协议选择决策树
js
是否需要远程调用?
├─ 否 → stdio
│ └─ 简单、快速、安全
│
└─ 是 → 是否需要服务器主动推送?
├─ 是 → 是否需要客户端频繁发送请求?
│ ├─ 是 → streamable_http 或 WebSocket
│ │ └─ 长时间任务 + 进度反馈
│ │
│ └─ 否 → sse
│ └─ 单向推送(日志、通知)
│
└─ 否 → 是否需要会话状态?
├─ 是 → streamable_http
│ └─ 多轮对话、状态保持
│
└─ 否 → http
└─ 无状态 API、RESTful
三、各大 Agent 的协议选择策略
1. Claude Desktop
-
主要协议:stdio
-
设计哲学:本地优先、隐私保护
-
原因:
- 用户数据不离开本地
- 工具生态以 npm 包为主(
npx @modelcontextprotocol/server-*
) - 简化部署(无需配置网络)
2. Google Gemini CLI
-
支持协议:stdio, sse, http
-
设计哲学:混合架构(本地 + 云端)
-
原因:
- stdio:本地工具(文件系统、代码分析)
- http:调用 Google Cloud API(知识图谱、企业数据)
- sse:实时接收 Gemini 模型的流式输出
3. 企业级 Agent(如 iFlow)
-
支持协议:stdio, sse, http, streamable_http
-
设计哲学:全场景覆盖
-
原因:
- stdio:开发环境的本地工具
- http:与企业内部系统集成(ERP、CRM、数据库)
- sse:实时监控、告警推送
- streamable_http:长时间分析任务(如财务报表生成)
四、Stdio 的底层实现原理
1. Unix/Linux 的管道机制(Pipe)
内核层面的实现:
js
// Linux Kernel Source: fs/pipe.c
struct pipe_inode_info {
struct mutex mutex; // 互斥锁
wait_queue_head_t rd_wait; // 读等待队列
wait_queue_head_t wr_wait; // 写等待队列
unsigned int head; // 写指针
unsigned int tail; // 读指针
unsigned int max_usage; // 最大缓冲区大小
unsigned int ring_size; // 环形缓冲区大小
struct pipe_buffer *bufs; // 缓冲区数组
};
关键特性:
- 环形缓冲区(Ring Buffer) :典型大小 64KB
- 零拷贝(Zero-Copy) :内核态直接传输数据,无需用户态拷贝
- 阻塞/非阻塞模式:支持同步/异步 I/O
- 原子性写入 :小于
PIPE_BUF
(通常 4096 字节)的写入是原子的
为什么快?
js
传统网络 I/O:
User Space [App]
↓ (system call)
Kernel Space [Socket Buffer]
↓ (network stack: TCP/IP)
Network Card [Hardware]
↓ (network transmission)
Remote Machine
Stdio Pipe:
Parent Process [App] Child Process [MCP Server]
↓ ↑
Kernel [Pipe Buffer 64KB]
直接内存共享,无网络开销!
2. 进程间通信(IPC)的性能对比
IPC 机制 | 延迟 | 吞吐量 | 适用场景 |
---|---|---|---|
Pipe/Stdio | 0.1-1 μs | 1-5 GB/s | 父子进程通信 |
Unix Domain Socket | 1-5 μs | 500 MB/s - 2 GB/s | 本地进程通信 |
TCP Loopback (127.0.0.1) | 10-50 μs | 100-500 MB/s | 本地网络通信 |
TCP Remote | 1-100 ms | 取决于网络 | 跨机器通信 |
HTTP (本地) | 50-200 μs | 50-200 MB/s | RESTful API |
gRPC (本地) | 20-100 μs | 200-500 MB/s | 微服务 |
实际测试数据(同一台机器):
c
# 测试 1: Pipe 传输 1GB 数据
$ dd if=/dev/zero bs=1M count=1024 | cat > /dev/null
1073741824 bytes (1.1 GB) copied, 0.2 s, 5.4 GB/s
# 测试 2: TCP Loopback 传输 1GB 数据
$ iperf3 -c 127.0.0.1
[ ID] Interval Transfer Bitrate
[ 5] 0.00-10.00 sec 3.28 GBytes 2.82 Gbits/sec (355 MB/s)
# 测试 3: HTTP 传输 1GB 数据
$ curl -X POST http://localhost:8080/upload --data-binary @1GB.bin
Speed: 150 MB/s
结论:Pipe 是本地通信最快的方式,比 TCP 快 10-100 倍!
3. JSON-RPC over Stdio 的协议栈
完整的协议栈:
js
┌─────────────────────────────────────┐
│ Application Layer │
│ MCP Protocol (JSON-RPC 2.0) │
│ {"jsonrpc":"2.0","method":"init"} │
├─────────────────────────────────────┤
│ Serialization Layer │
│ JSON (text-based) │
│ newline-delimited (\n) │
├─────────────────────────────────────┤
│ Transport Layer │
│ Stdio (stdin/stdout) │
│ File Descriptors: 0 (in), 1 (out) │
├─────────────────────────────────────┤
│ IPC Mechanism │
│ Pipe (kernel ring buffer) │
├─────────────────────────────────────┤
│ Operating System │
│ Linux Kernel / macOS XNU │
└─────────────────────────────────────┘
为什么用 newline-delimited JSON?
js
// 错误示例:直接 JSON.parse 会失败
stdin.on('data', (chunk) => {
JSON.parse(chunk); // ❌ chunk 可能不完整!
});
// 正确示例:按行分割
let buffer = '';
stdin.on('data', (chunk) => {
buffer += chunk.toString();
const lines = buffer.split('\n');
buffer = lines.pop(); // 保留不完整的行
lines.forEach(line => {
if (line.trim()) {
const message = JSON.parse(line); // ✅ 保证完整性
handleMessage(message);
}
});
});
核心原因:
- Pipe 的数据传输是 流式 的,不保证一次
read()
能读到完整消息 \n
作为消息边界,简单高效(无需复杂的 frame 机制)- 兼容性好(所有语言都支持按行读取)
五、为什么各大 Agent 都选择 Stdio?
1. 从 Node.js 的 child_process
源码看实现成本
spawn 一个进程有多简单?
js
// Node.js 实现 MCP Client (仅 15 行核心代码)
const { spawn } = require('child_process');
const mcp = spawn('npx', ['your-mcp-server']);
let requestId = 1;
// 发送请求
function call(method, params) {
mcp.stdin.write(JSON.stringify({
jsonrpc: '2.0',
method,
id: requestId++,
params
}) + '\n');
}
// 接收响应
mcp.stdout.on('data', (data) => {
const response = JSON.parse(data.toString());
console.log(response.result);
});
// 初始化
call('initialize', { clientInfo: { name: 'MyClient' } });
对比 HTTP 实现:
js
// HTTP 实现需要 30+ 行
const express = require('express');
const fetch = require('node-fetch');
const app = express();
app.use(express.json());
let sessionId = null;
async function call(method, params) {
const response = await fetch('http://localhost:3000/mcp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...(sessionId && { 'mcp-session-id': sessionId })
},
body: JSON.stringify({
jsonrpc: '2.0',
method,
id: requestId++,
params
})
});
const result = await response.json();
sessionId = response.headers.get('mcp-session-id');
return result;
}
// 还需要启动服务器...
app.post('/mcp', (req, res) => { /* 处理逻辑 */ });
app.listen(3000);
实现成本对比:
- Stdio: 15 行核心代码,无需外部依赖
- HTTP: 30+ 行代码,需要 express/fetch 等依赖
- WebSocket: 50+ 行代码,需要处理连接管理、心跳
2. 从 Python 源码看跨语言兼容性
Python 实现 MCP Server(Stdio 版本):
js
# server.py (仅 20 行)
import sys
import json
def handle_request(request):
if request['method'] == 'initialize':
return {'result': {'protocolVersion': '2024-11-05'}}
elif request['method'] == 'tools/list':
return {'result': {'tools': [{'name': 'example'}]}}
# 主循环
while True:
line = sys.stdin.readline()
if not line:
break
request = json.loads(line)
response = {
'jsonrpc': '2.0',
'id': request['id'],
**handle_request(request)
}
sys.stdout.write(json.dumps(response) + '\n')
sys.stdout.flush() # 重要!立即发送
为什么需要 flush()
?
js
# 标准输出默认是行缓冲(line buffering)
# 但如果输出设备不是 TTY(如 pipe),会变成全缓冲(full buffering)
# 没有 flush():
sys.stdout.write('{"result":{}}\n')
# 数据停留在缓冲区,客户端收不到!
# 有 flush():
sys.stdout.write('{"result":{}}\n')
sys.stdout.flush() # 立即发送到 pipe
跨语言兼容性测试:
语言 | Stdio 支持 | HTTP 支持 | 额外依赖 |
---|---|---|---|
Node.js | ✅ (内置 child_process ) |
✅ | express/fetch |
Python | ✅ (内置 sys.stdin/stdout ) |
✅ | flask/requests |
Go | ✅ (内置 os.Stdin/Stdout ) |
✅ | net/http |
Rust | ✅ (内置 std::io ) |
✅ | tokio/axum |
Java | ✅ (内置 System.in/out ) |
✅ | spring-boot |
Shell | ✅ (内置 pipe) | ❌ | curl |
结论:Stdio 是唯一所有语言都原生支持且无需外部依赖的方式!
3. 从安全性角度看端口暴露风险
HTTP 服务的安全隐患:
js
# 启动一个 HTTP MCP Server
$ node http-mcp-server.js
Server listening on http://0.0.0.0:3000
# 问题 1: 端口扫描暴露
$ nmap localhost
PORT STATE SERVICE
3000/tcp open http
# 问题 2: 未授权访问
$ curl http://localhost:3000/mcp -d '{"method":"tools/list"}'
# 任何本机进程都能调用!
# 问题 3: SSRF 攻击
# 恶意网页可能通过 fetch() 访问本地服务
fetch('http://localhost:3000/mcp', {...});
Stdio 的天然隔离:
js
# Stdio 进程无法被外部访问
$ ps aux | grep mcp-server
user 12345 npx your-mcp-server # 仅父进程可通信
# 尝试从外部访问 → 失败
$ echo '{"method":"tools/list"}' | nc localhost 12345
Connection refused # 没有监听端口!
# 进程隔离
$ ls -la /proc/12345/fd/
lr-x------ 1 user user 0 stdin -> pipe:[123456]
l-wx------ 1 user user 1 stdout -> pipe:[123457]
# 只有父进程持有 pipe 的另一端!
安全性对比:
攻击向量 | Stdio | HTTP |
---|---|---|
端口扫描 | ❌ 无端口 | ✅ 可被扫描 |
未授权访问 | ❌ 仅父进程 | ✅ 本机所有进程 |
SSRF | ❌ 不可达 | ✅ 可通过浏览器 |
网络嗅探 | ❌ 内核内存 | ✅ 可抓包(即使 loopback) |
DDoS | ❌ 单进程隔离 | ✅ 可被滥用 |
4. 从资源管理角度看生命周期控制
Stdio 的精确控制:
js
const mcp = spawn('npx', ['mcp-server']);
// 1. 超时控制
setTimeout(() => {
if (!mcp.killed) {
mcp.kill('SIGTERM'); // 优雅关闭
setTimeout(() => mcp.kill('SIGKILL'), 5000); // 强制杀死
}
}, 30000);
// 2. 错误处理
mcp.on('error', (err) => {
console.error('Failed to start MCP:', err);
});
// 3. 退出清理
mcp.on('exit', (code, signal) => {
console.log(`MCP exited with code ${code}, signal ${signal}`);
// 自动清理资源
});
// 4. 内存限制(Linux)
spawn('npx', ['mcp-server'], {
cgroup: { memory: { limit_in_bytes: 512 * 1024 * 1024 } } // 限制 512MB
});
HTTP 服务的资源泄露风险:
js
// 问题:HTTP 服务器可能永久运行
const server = http.createServer((req, res) => {
// 处理 MCP 请求
});
server.listen(3000);
// 即使客户端断开,服务器仍在运行!
// 除非手动 server.close()
// 问题:并发连接管理
// 多个客户端同时连接 → 资源竞争
资源对比:
指标 | Stdio | HTTP |
---|---|---|
进程生命周期 | 跟随父进程 | 独立运行 |
内存隔离 | ✅ 独立进程空间 | ❌ 共享服务器内存 |
CPU 限制 | ✅ cgroup/nice | ❌ 需额外管理 |
并发控制 | ✅ 单连接(父子) | ❌ 需限流 |
自动清理 | ✅ 进程退出自动回收 | ❌ 需手动关闭 |
六、Stdio 的底层优化技巧
1. Pipe 缓冲区调优
Linux 默认 Pipe 大小:
js
# 查看默认大小
$ cat /proc/sys/fs/pipe-max-size
1048576 # 1MB
# 查看当前 pipe 大小
$ ulimit -p
512 # 默认 64KB (512 个 page,每个 page 4KB)
增大缓冲区(高吞吐场景):
c
// C 代码示例
#include <fcntl.h>
#include <unistd.h>
int pipefd[2];
pipe(pipefd);
// 设置为 1MB
fcntl(pipefd[1], F_SETPIPE_SZ, 1048576);
Node.js 实现:
js
const { spawn } = require('child_process');
const { promisify } = require('util');
const fs = require('fs');
const mcp = spawn('npx', ['mcp-server'], {
stdio: ['pipe', 'pipe', 'pipe'],
// 增大缓冲区
highWaterMark: 1024 * 1024 // 1MB
});
2. 零拷贝优化(Splice)
传统方式(2 次拷贝):
js
Pipe Buffer → User Space → Pipe Buffer
(MCP Server) (Node.js) (Client)
Splice 系统调用(0 次拷贝):
js
// Linux 特有:splice() 系统调用
ssize_t splice(int fd_in, loff_t *off_in,
int fd_out, loff_t *off_out,
size_t len, unsigned int flags);
// 直接在内核态传输数据
splice(mcp_stdout, NULL, client_stdin, NULL, len, SPLICE_F_MOVE);
性能提升:
- 传统方式:100-200 MB/s
- Splice 方式:1-5 GB/s(提升 10-50 倍)
3. 非阻塞 I/O + Event Loop
阻塞式读取(性能差):
js
// 同步读取 → 阻塞主线程
const line = fs.readFileSync(mcp.stdout.fd, 'utf8');
const response = JSON.parse(line);
非阻塞式读取(高性能):
js
// 异步读取 → 利用 Event Loop
mcp.stdout.on('data', (chunk) => {
// 立即返回,不阻塞
buffer += chunk.toString();
processLines(buffer);
});
Event Loop 机制:
js
┌───────────────────────────┐
│ Node.js Event Loop │
├───────────────────────────┤
│ 1. Timers (setTimeout) │
│ 2. Pending I/O callbacks │
│ 3. Idle, prepare │
│ 4. Poll (stdio events) ←──┤ ← 这里处理 pipe 数据
│ 5. Check (setImmediate) │
│ 6. Close callbacks │
└───────────────────────────┘
七、为什么不是所有场景都用 Stdio?
1. Stdio 的致命缺陷
问题 1:无法远程调用
js
# ❌ 无法跨机器
ssh remote-host "npx mcp-server" # 只能在远程执行,本地无法通信
# ✅ HTTP 可以
curl http://remote-host:3000/mcp
问题 2:每次调用启动进程开销
js
// 每次调用都 spawn 新进程
async function callMCP(method, params) {
const mcp = spawn('npx', ['mcp-server']); // 启动开销 100-500ms
// ...
mcp.kill();
}
// 高频调用 → 性能灾难
for (let i = 0; i < 1000; i++) {
await callMCP('tools/list', {}); // 总耗时 100 秒!
}
问题 3:无法多客户端共享
js
Client A → spawn MCP Server A (独立实例,内存 100MB)
Client B → spawn MCP Server B (独立实例,内存 100MB)
Client C → spawn MCP Server C (独立实例,内存 100MB)
总计:300MB 内存,无法共享缓存
HTTP 方式:
Client A ─┐
Client B ─┼→ HTTP MCP Server (单实例,内存 100MB,共享缓存)
Client C ─┘
2. HTTP 的优势场景
场景 1:云端 API 包装
js
// MCP Server 包装 OpenAI API
app.post('/mcp', async (req, res) => {
const { method, params } = req.body;
if (method === 'tools/call' && params.name === 'gpt4') {
const result = await fetch('https://api.openai.com/v1/chat/completions', {
headers: { 'Authorization': `Bearer ${OPENAI_KEY}` },
body: JSON.stringify({ model: 'gpt-4', ...params })
});
res.json({ result: await result.json() });
}
});
- 云端 API 本身就是 HTTP,Stdio 无意义
- 需要集中管理 API Key
场景 2:企业内部服务
js
// MCP Server 连接企业数据库
app.post('/mcp', async (req, res) => {
const { method, params } = req.body;
if (method === 'tools/call' && params.name === 'query_crm') {
const result = await pool.query('SELECT * FROM customers WHERE ...');
res.json({ result });
}
});
- 多个 Agent 共享同一数据库连接池
- 需要认证、授权、审计
场景 3:负载均衡
js
┌─→ MCP Server 1 (8 cores)
Load Balancer ────┼─→ MCP Server 2 (8 cores)
└─→ MCP Server 3 (8 cores)
Stdio 无法做到!每个进程独立运行。
3. 综合原因总结
维度 | Stdio 优势 | 占比权重 |
---|---|---|
性能 | 延迟 < 1μs,吞吐 5GB/s | 30% |
安全 | 无端口暴露,进程隔离 | 25% |
简单 | 15 行代码实现,无依赖 | 20% |
兼容 | 所有语言原生支持 | 15% |
资源 | 自动清理,精确控制 | 10% |
4. 决策矩阵
js
Agent 使用场景 推荐协议
├─ 本地工具(文件、代码) → stdio (100% 场景)
├─ 云端 API(天气、翻译) → http (80% 场景)
├─ 企业服务(数据库、ERP) → http (90% 场景)
├─ 实时交互(多轮对话) → websocket (60% 场景)
└─ 高性能计算(批量处理) → grpc (40% 场景)
5. 现状统计
根据 MCP 社区调研:
- Stdio : 占 85% 的 MCP 工具(如 npm 上的
@modelcontextprotocol/server-*
) - HTTP: 占 12%(主要是云端 API 包装)
- SSE/WebSocket: 占 3%(实验性)
为什么 Stdio 占绝对主导?
- MCP 最初设计就是本地优先(Claude Desktop 的设计哲学)
- npm/pypi 生态成熟(工具分发以 CLI 为主)
- 开发者习惯(命令行工具比 Web 服务更直观)
- 安全性要求(AI Agent 访问本地文件,不能暴露端口)
八、未来协议发展趋势
1. WebSocket 的必然性
为什么会普及:
- AI Agent 越来越需要 双向实时交互
- 多轮对话、工具链调用需要 低延迟
- WebSocket 是目前最成熟的双向协议
预测:
- 2025 年底,主流 Agent 会支持 WebSocket
- MCP 2.0 可能会正式加入 WebSocket 作为标准传输层
2. gRPC 在企业场景的崛起
为什么适合 Agent:
- 性能极高:Protocol Buffers 比 JSON 快 3-10 倍
- 强类型 :
.proto
定义避免 API 不一致 - 流式支持:天然支持双向流
应用场景:
- Agent 之间的内部通信(多 Agent 协作)
- 高性能场景(如实时翻译、语音识别)
- 微服务架构(K8s 环境)
3. 边缘计算与 P2P MCP
趋势:
- 隐私意识提升 → 数据不愿意上云
- 边缘设备算力提升(如 Apple M4、NVIDIA Jetson)
- P2P 技术成熟(libp2p、WebRTC)
愿景:
- Agent 直接在本地设备之间通信
- 去中心化的工具市场(类似 IPFS)
- 无需服务器的 Agent 协作网络
4. 协议自适应(Protocol Negotiation)
核心思想:
- 客户端和服务器协商最优协议(类似 HTTP/2 ALPN)
- 根据网络状况动态切换
- 自动降级策略
示例流程:
九、我的个人观点
1. 对协议演进的看法
-
stdio 永远不会消失
- 本地工具、命令行场景无可替代
- 开发者永远需要简单、快速的本地调用
- 类比:即使有了 HTTP,shell pipe 仍然是最高效的
-
HTTP 是过渡方案
- 当前主流是因为生态成熟
- 但对于实时 Agent 交互,延迟太高
- 未来会被 WebSocket/gRPC 替代(在需要实时性的场景)
-
SSE 很尴尬
- 介于 HTTP 和 WebSocket 之间
- 只适合"服务器单向推送"这个狭窄场景
- 未来可能被 WebSocket 完全取代
-
Streamable HTTP 是 AI 时代的产物
- 专为生成式 AI 设计(流式输出)
- 但实现复杂,采用率低
- 可能会被 WebSocket + Streaming 取代
2. 对 Agent 协议的预测
2026 年的 MCP 协议栈:
js
┌─────────────────────────────────────┐
│ Application Layer (MCP Protocol) │
├─────────────────────────────────────┤
│ Transport Layer (可插拔) │
│ ├─ stdio (本地工具) │
│ ├─ WebSocket (实时交互) │
│ ├─ gRPC (高性能/微服务) │
│ ├─ HTTP/3 (公网 API) │
│ └─ libp2p (P2P Agent) │
└─────────────────────────────────────┘
核心原则:
- 没有银弹:不同场景用不同协议
- 协议透明:开发者不关心底层用什么,框架自动选择
- 向后兼容:新协议不影响旧工具
关于作者:
如果你对 AI 应用开发和工程化实践感兴趣,欢迎关注我的掘金账号,一起探讨技术!