Daily Study
更新: 8/7/2025 字数: 0 字 时长: 0 分钟
Daily Plan
#todo
- [ ]
tRPC MCP
MCP
架构
- MCP主机:像Claude桌面端、集成开发环境(IDE)或希望通过MCP访问数据的人工智能工具等程序。
- MCP客户端:维护与服务器一对一连接的协议客户端。
- MCP服务器:轻量级程序,每个程序都通过标准化的模型上下文协议(Model Context Protocol)暴露特定功能。
- 本地数据源:你的计算机上的文件、数据库和服务,MCP服务器可以安全地访问这些资源。
- 远程服务:通过互联网(例如通过API)可用的外部系统,MCP服务器可以连接到这些系统
核心组件
- Prompt:用于引导模型生成特点类型的内容
- Resource:是模型可以访问的外部资源,如文件、数据库或API服务
- Tool:模型可以调用的外部工具或服务
通信机制
- STDIO(标准输入/输出)是最简单的通信方式,适用于命令行工具和本地应用程序。在这种模式下,MCP 服务器通过标准输入接收请求,并通过标准输出发送响应。优点是简单易用、无需网络配置;缺点是只适用于本地交互,且不支持复杂的会话管理。
- SEE (Server-Sent Events)是一种基于 HTTP 的单向通信机制,适用于网络应用程序和分布式系统。在这种模式下,客户端通过 HTTP 连接接收来自服务器的实时更新,而服务器则通过另一个 HTTP 端点接收客户端的请求。SSE 特别适合需要实时更新的应用场景。优点是支持实时通信、适合分布式环境;缺点是实现相对复杂,需要处理连接管理和状态同步。
工作模式
MCP 协议基于 JSON-RPC 2.0 通信协议,支持两种标准传输方式:stdio 和 Streamable HTTP。新版 MCP 协议(2025-03-26)更新了传输机制,引入了 Streamable HTTP 机制,用以替代旧版(2024-11-05)中的 HTTP+SSE 模式。
Streamable HTTP 代替旧版 HTTP+SSE 模式
旧版 MCP 协议(2024-11-05)中的 HTTP+SSE 模式存在以下问题:
分散的端点设计:根据协议要求,服务器"必须(MUST)提供两个端点"——一个 SSE 端点用于客户端接收消息,另一个 HTTP POST 端点用于客户端发送消息。
复杂的连接流程:客户端首先必须连接 SSE 端点,等待服务器发送一个
endpoint
事件,告知客户端应该向哪个 URI 发送 HTTP POST 请求。会话管理受限:没有标准化的会话管理和身份验证机制。
单向通信限制:服务器和客户端之间的通信路径被严格区分,增加了实现复杂性。
强制有状态连接:SSE 连接必须持续维护,限制了水平扩展能力。
鉴于上述这些局限性,新版 MCP 协议(2025-03-26)引入了 Streamable HTTP 传输机制,旨在提供一个更灵活、高效和健壮的通信方案,以替代原有的 HTTP+SSE 模式。后续章节将详细解析这一新的机制。
Streamable HTTP 核心机制解析
统一接入与明确分工:单一端点与 HTTP 方法语义
单一 MCP 端点
服务器必须(MUST)提供一个单一的 HTTP 端点路径(MCP 端点),该端点同时支持 POST 和 GET 方法。这解决了旧版模式中端点分散(SSE 端点和 POST 端点分离)的问题。HTTP 方法规范
POST:客户端发送所有 JSON-RPC 消息的唯一方式。客户端必须(MUST)在请求中包含
Accept
头部,列出application/json
和text/event-stream
。对于仅包含响应或通知的 POST,服务器接受时必须(MUST)返回 202 Accepted。GET:客户端发起,用于建立 SSE 连接以接收服务器主动推送。协议指出"客户端可以(MAY)向 MCP 端点发出 HTTP GET,这可用于打开 SSE 流,允许服务器与客户端通信,而无需客户端首先通过 HTTP POST 发送数据"。此时,客户端必须(MUST)包含一个
Accept
头部,列出text/event-stream
作为支持的内容类型。DELETE:客户端可选,用于主动终止会话。协议规定"不再需要特定会话的客户端应该(SHOULD)发送带有
Mcp-Session-Id
头的 HTTP DELETE 到 MCP 端点,以显式终止会话"。
按需流式与双向通信
POST 请求处理
客户端通过 POST 发送所有类型的 JSON-RPC 消息。对于包含请求的 POST,协议明确规定服务器有两种响应选择:"服务器必须(MUST)返回
Content-Type: text/event-stream
以启动 SSE 流,或返回Content-Type: application/json
以返回一个 JSON 对象"。对于简单、快速的操作,可选择普通 JSON 返回,接近传统 RPC 模式,避免 SSE 开销;对于需长时间处理、分批返回或持续更新的操作,则选择 SSE 流式响应。体现了"可流式(Streamable)"的设计理念。在 SSE 流中,服务器可以(MAY)在发送响应前发送请求和通知。
这些消息应该(SHOULD)与原始客户端请求相关。
SSE 通信模式
POST 响应:服务器可选择 SSE 流发送中间更新。
GET 长连接:用于推送独立消息,这些消息应该(SHOULD)与并发请求无关。
多连接管理
客户端可以(MAY)同时连接多个 SSE 流。
服务器必须(MUST)在单一流上发送每个消息。
服务器不能(MUST NOT)跨流广播相同消息。
mcp-go && 使用 http 接入 mcp
文章链接:https://cloud.tencent.com/developer/article/2514815 mcp-go:https://github.com/mark3labs/mcp-go
- HTTP 暴露 MCP 服务,主要通过两个接口来实现:
- sse:负责给 MCP Client 下发临时凭证,
base path + /sse
- message:负责主要的数据交互
base path + /message
- sse:负责给 MCP Client 下发临时凭证,
// serveHTTP 启动HTTP服务
func serveHTTP(svc *trpcserver.Server, mcpSvr *server.MCPServer) {
// 创建SSE服务器
// SSE端点会自动变为 /mcp/sse
// 消息端点会自动变为 /mcp/message
sseServer := server.NewSSEServer(mcpSvr, server.WithBasePath("/mcp"))
wrappedHTTP := &wrappedHTTP{Handler: sseServer}
thttp.HandleFunc("/mcp/sse", wrappedHTTP.ServeHTTP)
thttp.HandleFunc("/mcp/message", wrappedHTTP.ServeHTTP)
http.RegisterNoProtocolService(svc.Service("trpc.amc.demo.mcp"))
if err := svc.Serve(); err != nil { log.Errorf("TRPC server error: '%v'", err)
}
}
- 定义了一个
wrappedHTTP
实例,用来包装一层 mcp-go 的 HTTP 函数。这主要是为了适配标准net/http
的 handler 和 tRPG 的 handler 格式(加一个 error 返回)。这个类型的 实现,除了加 error 这一点之外,还拦截了一下 http 收包和回包的过程,便于我们观察 MCP 的交互过程。 thttp.RegisterNoProtocolService(svc.Service("trpc.amc.demo.mcp"))
。在net/http
中,启动 HTTP 服务的时候,监听在哪一个网卡、什么端口,是需要在代码中传入的。而 tRPC 框架则将这些参数转移到了trpc_go.yaml
配置文件中。可以看看 示例配置。因此,这一句主要就是将 HTTP 服务与 yaml 配置文件中的具体项目绑定起来。