mcp-go
这一节我们来学习 mcp go 语言实现的框架 mcp-go
1. 说明
为了快速对 mcp 有个整体的了解,我结合 ABcoder 向 mcp 提了几个问题,后面的内容基于这些问题回答的整理。
|
|
1. 核心包结构
根据对代码库的分析,MCP-Go 是一个实现了 Model Context Protocol (MCP) 的 Go 语言库,它提供了客户端和服务端之间进行通信的框架。以下是 MCP-Go 中的核心对象:
MCP-Go 主要由三个核心包组成:
- mcp: 定义了协议的基本类型和接口
- client: 实现了 MCP 客户端
- server: 实现了 MCP 服务端
1.1 MCP 包中的核心对象
基础类型
- Content: 表示内容的接口,有多种实现如 TextContent、ImageContent、AudioContent 等
- Resource: 表示资源,包含 URI、名称、描述等信息
- ResourceTemplate: 资源模板,用于构造资源 URI
- Tool: 表示可以被调用的工具,包含名称、描述、输入模式等
- Meta: 元数据对象,用于存储额外信息
- RequestId: 请求 ID,用于标识请求
请求求和响应类型
- Request: 基础请求类型
- Result: 基础结果类型
- JSONRPCMessage: 表示 JSON-RPC 消息,可以是请求、通知、响应或错误
- CallToolRequest/CallToolResult: 工具调用请求和结果
- InitializeRequest/InitializeResult: 初始化请求和结果
工具相关
- ToolInputSchema: 工具输入模式
- ToolAnnotation: 工具注解,包含工具的各种提示信息
- PropertyOption: 用于配置属性的函数选项
- ToolOption: 用于配置工具的函数选项
1.2 客户端核心对象
Client
Client
是 MCP 客户端的主要实现,它提供了与服务端通信的方法:
|
|
主要方法包括:
- Initialize: 初始化客户端与服务端的连接
- ListTools/ListPrompts/ListResources: 列出可用的工具、提示和资源
- CallTool: 调用服务端提供的工具
- ReadResource: 读取资源内容
- Subscribe/Unsubscribe: 订阅/取消订阅资源变更通知
Transport
transport.Interface
是客户端与服务端通信的传输层接口,有多种实现:
- HTTP 传输
- SSE (Server-Sent Events) 传输
- 标准输入/输出传输
- 进程内传输
1.3 服务端核心对象
MCPServer
MCPServer
是 MCP 服务端的主要实现,它处理来自客户端的请求:
|
|
主要方法包括:
- AddTool/AddTools: 添加工具
- AddResource/AddResources: 添加资源
- AddPrompt/AddPrompts: 添加提示
- AddResourceTemplate/AddResourceTemplates: 添加资源模板
处理函数类型
- ToolHandlerFunc: 处理工具调用的函数
- ResourceHandlerFunc: 处理资源请求的函数
- PromptHandlerFunc: 处理提示请求的函数
- NotificationHandlerFunc: 处理通知的函数
1.4 通信流程
- 客户端通过
Initialize
方法与服务端建立连接 - 客户端可以列出服务端提供的工具、资源和提示
- 客户端可以调用服务端的工具,读取资源,或获取提示
- 服务端处理请求并返回结果
- 客户端可以订阅资源变更通知
2. mcp-go 底层实现机制分析
2.1 底层传输协议
mcp-go 底层确实使用了 HTTP 作为主要的传输协议,但它并不是一个传统意义上的 HTTP 服务器,而是实现了基于 HTTP 的 JSON-RPC 通信机制。具体来说:
-
传输层实现:在
client/transport
包中,有多种传输实现:StreamableHTTP
:基于 HTTP 的传输实现,支持 JSON-RPC 消息通过单独的 HTTP 请求传输SSE
:基于 Server-Sent Events 的实现Stdio
:基于标准输入输出的实现InProcessTransport
:进程内通信实现
-
HTTP 传输细节:
StreamableHTTP
结构体实现了Interface
和BidirectionalInterface
接口- 它通过单独的 HTTP 请求传输 JSON-RPC 消息,每个请求一条消息
- HTTP 响应体可以是单个 JSON-RPC 响应,也可以是升级为 SSE 流的响应
- 支持 OAuth 认证
- 支持持续监听(通过
WithContinuousListening
选项)
-
框架使用:
- mcp-go 并没有使用任何第三方 HTTP 框架(如 Gin、Echo 等)
- 它直接使用了 Go 标准库中的
net/http
包来实现 HTTP 客户端和服务端功能 - 在
NewStreamableHTTP
函数中可以看到,它创建了标准的http.Client
实例
2.2 通信模式
mcp-go 实现了 Model Context Protocol (MCP),这是一个用于 AI 模型与外部工具通信的协议:
-
JSON-RPC 通信:
- 使用 JSON-RPC 2.0 协议格式进行通信
- 支持请求-响应模式和通知模式
- 支持双向通信(客户端到服务端和服务端到客户端)
-
流式通信:
- 支持通过 SSE(Server-Sent Events)实现服务端到客户端的流式通信
- 支持长连接和断线重连
3. MCP-Go 中添加工具/资源与 HTTP 接口的关系
MCP (Model Context Protocol) 是一个用于 AI 模型与外部工具通信的协议。当你调用 AddTool
、AddResource
等方法时,你是在向 MCP 服务器注册这些功能,然后 MCP 服务器会通过 JSON-RPC 协议将这些功能暴露为 API 接口。
3.1 添加工具 (AddTool/AddTools)
当你调用 s.AddTool(tool, helloHandler)
时:
- 你向 MCP 服务器注册了一个名为
tool
的工具及其处理函数helloHandler
- MCP 服务器会创建一个 JSON-RPC 方法
mcp/tool/call
- 客户端可以通过发送 POST 请求到服务器的
/
路径,请求体为 JSON-RPC 格式的消息来调用这个工具
|
|
3.2 添加资源 (AddResource/AddResources)
当你调用 s.AddResource(resource)
时:
- 你向 MCP 服务器注册了一个资源
- MCP 服务器会创建以下 JSON-RPC 方法:
mcp/resource/read
:读取资源内容mcp/resource/list
:列出所有可用资源
|
|
3.3 添加提示 (AddPrompt/AddPrompts)
当你调用 s.AddPrompt(prompt)
时:
- 你向 MCP 服务器注册了一个提示
- MCP 服务器会创建以下 JSON-RPC 方法:
mcp/prompt/get
:获取特定提示mcp/prompt/list
:列出所有可用提示
|
|
3.4 添加资源模板 (AddResourceTemplate/AddResourceTemplates)
当你调用 s.AddResourceTemplate(template)
时:
- 你向 MCP 服务器注册了一个资源模板
- MCP 服务器会创建 JSON-RPC 方法
mcp/resource_template/list
|
|
3.5 HTTP 传输机制
MCP 服务器使用 HTTP 作为传输层,但它不是传统的 REST API:
- 所有请求都发送到同一个端点(通常是根路径
/
) - 使用 JSON-RPC 协议:所有请求和响应都遵循 JSON-RPC 2.0 格式
- 支持双向通信:
- 客户端到服务器:通过 HTTP POST 请求
- 服务器到客户端:通过 SSE(Server-Sent Events)或 WebSocket
3.6 实际例子
假设你有以下代码:
|
|
客户端可以通过以下 HTTP 请求调用这个工具:
|
|
服务器会响应:
|
|
4. 请求路由
以 tool call 为例说明请求的路由过程。
4.1 生成 JSON RPC call 的位置
在 server/request_handler.go
文件中的 HandleMessage
方法(第 17-339 行)负责处理接收到的 JSON-RPC 消息。当接收到 MethodToolsCall
类型的请求时(第 306-327 行),系统会:
- 解析接收到的 JSON 消息到
mcp.CallToolRequest
结构体 - 调用
s.handleToolCall(ctx, baseMessage.ID, request)
方法处理工具调用 - 生成 JSON-RPC 响应并返回
相关代码片段(第 306-327 行):
|
|
4.2 路由找到对应的 tool handle 的位置
在 server/server.go
文件中的 handleToolCall
方法(第 1056-1114 行)负责查找并执行对应的工具处理函数:
- 首先检查会话特定的工具(session-specific tools)
- 如果在会话中未找到,则检查全局工具(global tools)
- 应用中间件(middlewares)
- 执行工具处理函数并返回结果
|
|
可以看到 mcp-go 请求路由处理的核心是 HandleMessage 方法。
5. HandleMessage
|
|