// MCP 传输层核心抽象. // // 本文件定义了三个核心接口: // - Transport:字节级 JSON-RPC 消息传输(Send/Recv/Close) // - AuthProvider:按请求提供 HTTP 鉴权头(支持 token 动态刷新) // // 以及两个开箱即用的 AuthProvider 实现: // - StaticTokenAuth:静态 Bearer token // - NoopAuth:无认证 // // 设计精妙(CLEVER): Transport 操作粒度选在「raw JSON 字节层」-- // 不是 io.Reader/Writer(太低层),也不是 JSON-RPC 方法调用(太高层). // 原因: // 1. stdio 传输:字节层契合 newline-framed JSON over pipes. // 2. SSE 传输:Send 走独立 HTTP POST(完整 JSON body), // Recv 从 SSE event 流读完整 JSON 事件--两条连接,无法建模为单个 io.ReadWriter. // 3. HTTP Streamable:POST 响应本身可以是 SSE 流,同样无法用 io.ReadWriter 表达. // // 如果选 io.Reader/Writer 层:无法建模 SSE / HTTP Streamable 的双连接模型. // 如果选 JSON-RPC 方法层:请求/响应关联(pending map)被埋进 Transport, // Client 无法统一管理,重连时 pending 会丢失. package mcp import "context" // Transport 是 MCP 传输层的核心接口. // // 实现: // - StdioTransport:子进程 stdin/stdout(MCP 2024-11-05 规范必须支持) // - SSETransport:HTTP GET SSE + POST(远程服务器,2024-11-05 规范) // - HTTPTransport:HTTP Streamable(2025-03-26 规范,新服务器优先) type Transport interface { // Send 向服务器发送一条 JSON-encoded 消息(JSON-RPC 请求或通知). // msg 不含换行符;传输实现自行决定帧格式(stdio 追加 '\n',HTTP 用 body). Send(ctx context.Context, msg []byte) error // Recv 阻塞等待来自服务器的一条 JSON-encoded 消息. // 正常关闭时返回 (nil, io.EOF),ctx 超时时返回 ctx.Err(). Recv(ctx context.Context) ([]byte, error) // Close 终止连接并释放资源.可安全地重复调用. Close() error } // AuthProvider 为每条出站 HTTP 请求提供鉴权头部. // // 升华改进(ELEVATED): 按请求调用(而非建连时一次性注入)-- // 早期实现 MCP client 的认证是建连时静态注入,不支持 token 过期后透明刷新. // 我们将 Headers() 设计为 per-request 调用,消费层(CLI / SaaS 后端)可以在此: // - 检查 token 是否即将过期,必要时发起 OAuth2 token refresh // - 从 secret manager 动态读取最新凭证 // - 实现请求级签名(AWS SigV4 等) // // Engine 核心不感知任何 OAuth 协议细节,符合「零硬编码」原则. // OAuth 实现由 CLI 消费层自行注入;engine 只定义扩展点. type AuthProvider interface { // Headers 返回要追加到出站 HTTP 请求的 header 键值对. // 返回 nil 表示无需额外头部. Headers(ctx context.Context) (map[string]string, error) } // StaticTokenAuth 提供静态 Bearer token 认证. // // 适用场景:API key,服务账号令牌等不过期的长效凭证. // 对于需要 token 刷新的场景,消费层应自行实现 AuthProvider 接口. type StaticTokenAuth struct { // Token 是 Bearer token 值,不含 "Bearer " 前缀. Token string } // Headers 返回 Authorization: Bearer 头部. func (s *StaticTokenAuth) Headers(_ context.Context) (map[string]string, error) { return map[string]string{ "Authorization": "Bearer " + s.Token, }, nil } // NoopAuth 不提供任何认证信息. // // 适用场景:匿名访问的 MCP 服务器,或凭证已内嵌于 URL(如 ?token=...)的场景. type NoopAuth struct{} // Headers 返回 nil(无额外头部). func (n *NoopAuth) Headers(_ context.Context) (map[string]string, error) { return nil, nil }