如何让现有应用支持 MCP 协议:迁移路线、适配模式与实践要点
一、为什么要给旧系统加上 MCP?
- 让 LLM 直接调用既有功能,而无需开发专用插件
- 统一上下文管理,避免多套 API 集成逻辑
- 通过流式传输(SSE / Streamable HTTP)提升响应时效与用户体验
二、三种主流适配模式
- 轻量包装(Wrapper):在原接口外层写一个「Remote MCP Server」,把每个业务端点暴露为 MCP 工具;适合已有 REST/GraphQL 服务
- 边车代理(Sidecar / Proxy):把现有服务编译或容器化后,旁挂 mcp-proxy 或 mcp-access-point,自动转换 HTTP↔MCP
- 代码内嵌(In-Process SDK):在应用代码中直接引入 mcp-sdk(Python/Go/TS),以 Stdio 或 Streamable HTTP 模式启动 MCP 服务器;适合微服务或脚本型工具
三、迁移流程(无代码版)
- Step 1 梳理接口:列出现有服务中可对外暴露的功能与参数
- Step 2 生成工具元数据:每个接口需要
name
、description
、parameters
(JSON Schema) - Step 3 选择传输层:
- 浏览器场景:SSE
- 高并发 & 双向流:Streamable HTTP
- 本地脚本:Stdio
- Step 4 实现 OAuth 2.1:为每个工具配置最小 scope,保护敏感资源
- Step 5 部署 & 灰度:使用 mcp-proxy 蓝绿发布,兼容旧 SSE 客户端
- Step 6 监控 & 优化:关注帧速率、上下文字节数、RTT;必要时压缩或拆分大响应
四、常见坑与最佳实践
- 连接缓冲:Nginx 需
proxy_buffering off;
,否则流式分块被积压 - 安全:对
metadata.signature
做 RSA 验签,防止伪造工具 - 大文件:调用方将二进制上传对象存储,返回预签名 URL,而非 Base64
- 版本碎片:2024 版默认 SSE,2025-03-26 版默认 Streamable HTTP,注意客户端升级
#### 示例代码(可直接复制运行)
> **Python — 现有 Flask API 包装成 Streamable HTTP MCP 服务器**
```python
# server.py
from flask import Flask, request, jsonify
from mcp import MCPServer, Tool
# ① 原有 Flask 业务
app = Flask(__name__)
@app.route("/sum")
def sum_api():
a, b = int(request.args["a"]), int(request.args["b"])
return jsonify({"result": a + b})
# ② 用 SDK 包装成 MCP Server
srv = MCPServer("LegacyTools", transport="streamable_http", listen="0.0.0.0:8080")
@Tool(name="sum", description="两数求和", parameters={"a": "int", "b": "int"})
def sum_tool(a: int, b: int) -> int:
# 复用现有逻辑
return a + b
if __name__ == "__main__":
srv.run() # Streamable HTTP server on /message
Node/TypeScript — mcp-proxy 将现有 REST 服务转换为 MCP
// proxy.ts
import { RESTAdapter } from "mcp-proxy";
const adapter = new RESTAdapter({
baseUrl: "https://legacy.example.com",
routes: [
{
mcpName: "getUser",
description: "根据 ID 获取用户信息",
path: "/user/{id}",
method: "GET",
params: { id: "string" }
}
]
});
adapter.listen(8080); // 开启 /message (Streamable HTTP) 端口
Go — 在单体应用内嵌 Stdio MCP 服务器
// main.go
package main
import (
"github.com/mark3labs/mcp-go"
"log"
)
func add(a, b int) int { return a + b }
func main() {
server := mcpgo.NewStdioServer("CLI-Tools")
server.Tool("add", "两数求和", mcpgo.Args{"a": "int", "b": "int"}, add)
if err := server.Run(); err != nil {
log.Fatal(err)
}
}