Qilin MCP服务器框架
Qilin 是一个使用 Go 语言实现的 Model Context Protocol (MCP) 服务器框架。它提供了一套简洁的 API,帮助开发者快速构建符合 MCP 标准的应用后端,从而 enabling 语言模型 (LLM) 客户端与之交互,获取上下文信息和调用外部功能。
主要功能点
- MCP协议支持: 完全遵循 Model Context Protocol (MCP) 的规范,处理标准的 JSON-RPC 请求和响应。
- 工具注册与调用: 允许开发者定义、注册具有特定名称、描述和输入schema的工具。LLM客户端可以通过 'tools/call' 方法调用这些工具,并获取结构化或非结构化的结果。
- 资源托管与访问: 支持注册具有URI、名称、描述和MIME类型的资源。客户端可以通过 'resources/read' 方法读取资源内容。支持URI模板和路径参数。
- 资源列表与模板: 提供 'resources/list' 方法列出可访问的资源,以及 'resources/templates/list' 方法列出URI模板,帮助客户端理解可用的资源结构。
- 资源变更通知: 支持 'resources/subscribe' 和 'resources/unsubscribe' 方法,允许客户端订阅特定资源的更新通知 ('notifications/resources/updated')。
- 资源列表变更通知: 支持在资源列表发生变化时向客户端发送通知 ('notifications/resources/list_changed')。
- 中间件支持: 提供工具和资源的中间件机制,方便在请求处理前后添加自定义逻辑(如认证、日志记录等)。
- 多种内容类型: 工具和资源handler支持返回文本、JSON、图片、音频以及嵌入式资源等多种格式的内容。
- JSON-RPC over Stdio: 默认使用标准输入/输出作为传输通道,符合某些LLM客户端(如一些本地运行的客户端或开发工具)的连接方式。框架设计上也考虑了未来支持其他传输协议。
- 上下文管理: 提供丰富的上下文对象(如 'ToolContext', 'ResourceContext'),方便handler访问请求信息、路径参数,并向客户端发送响应。
安装步骤
Qilin 是一个 Go 语言库。要使用 Qilin 构建您的 MCP 服务器,首先需要安装 Go 环境。然后,可以通过 Go Modules 将 Qilin 库添加到您的项目依赖中:
go get github.com/miyamo2/qilin
接下来,您就可以在您的 Go 项目代码中导入 'github.com/miyamo2/qilin' 包来构建您的 MCP 服务器应用。
服务器配置 (供 MCP 客户端使用)
MCP 客户端(如一个大型语言模型应用)需要配置如何启动和连接到您的 MCP 服务器。典型的配置会包含服务器的名称、启动服务器可执行文件的命令及其参数。请注意,以下是一个通用的配置示例结构,具体的 'command' 和 'args' 取决于您使用 Qilin 框架编写并编译出的服务器应用程序。
{ // MCP 服务器的唯一名称,客户端用于识别和管理该服务器实例。 "name": "您的自定义服务器名称", // 启动您的 MCP 服务器应用程序的命令行命令。 // 这通常是您编译好的 Go 可执行文件的路径。 "command": "/path/to/your/compiled/qilin_server_executable", // 传递给您的服务器可执行文件的可选命令行参数列表。 // 根据您的服务器应用程序需要配置。 "args": ["--config", "/etc/your_server/config.yaml"], // 其他可能的MCP客户端特有配置... "protocol": "stdio" // 例如,指定传输协议为标准IO }
MCP 客户端会使用上述配置来启动您的 MCP 服务器进程,并通过标准输入/输出进行 JSON-RPC 通信。
基本使用方法 (构建 MCP 服务器)
以下是使用 Qilin 框架构建一个简单 MCP 服务器的基本步骤:
-
创建 Qilin 实例:
package main import "github.com/miyamo2/qilin" func main() { // 创建一个新的 Qilin 服务器实例,指定服务器名称 q := qilin.New("my_awesome_mcp_server") // ... 注册工具、资源等 ... // 启动服务器 if err := q.Start(); err != nil { // 处理启动错误 panic(err) } } -
注册工具 (Tool): 定义工具的输入结构体和处理函数。
// 定义工具的输入参数结构体,使用 jsonschema 标签描述字段 type AddParams struct { A float64 'json:"a" jsonschema:"title=First Number"' B float64 'json:"b" jsonschema:"title=Second Number"' } // 定义工具的处理函数 func AddToolHandler(c qilin.ToolContext) error { var params AddParams // 绑定客户端传入的参数到结构体 if err := c.Bind(¶ms); err != nil { return err } // 执行工具逻辑 result := params.A + params.B // 返回结果给客户端 (JSON 格式) return c.JSON(map[string]float64{"sum": result}) } func init() { // 在 Qilin 实例上注册工具 q.Tool("add", (*AddParams)(nil), AddToolHandler, qilin.ToolWithDescription("Add two numbers together")) // 可选添加描述 } -
注册资源 (Resource): 定义资源的URI模式和处理函数。
// 定义资源内容结构体 type UserInfo struct { ID string 'json:"id"' Name string 'json:"name"' } // 定义资源的处理函数 func GetUserInfoHandler(c qilin.ResourceContext) error { // 从URI路径中获取参数 userID := c.Param("userId") if userID == "" { return fmt.Errorf("userId is required") } // 模拟数据查询 userInfo := UserInfo{ ID: userID, Name: fmt.Sprintf("User %s", userID), } // 返回资源内容给客户端 (JSON 格式) return c.JSON(userInfo) } func init() { // 在 Qilin 实例上注册资源,支持路径参数 {userId} q.Resource("User Profile", "myapp://users/{userId}", GetUserInfoHandler, qilin.ResourceWithDescription("Get user information by ID"), // 可选添加描述 qilin.ResourceWithMimeType("application/json")) // 可选指定MIME类型 } -
注册资源列表处理器 (可选): 如果您希望自定义 'resources/list' 的行为,可以注册资源列表处理器。
func CustomResourceListHandler(c qilin.ResourceListContext) error { // c.Resources() 包含所有注册的资源(包括模板) // 您可以在这里动态生成或过滤资源列表 dynamicResourceURI, _ := url.Parse("myapp://dynamic/resource") c.SetResource(dynamicResourceURI.String(), qilin.Resource{ URI: (*qilin.ResourceURI)(dynamicResourceURI), Name: "Dynamic Resource", Description: "This resource is generated dynamically", MimeType: "text/plain", }) // 不要清除 c.Resources() 中框架已注册的静态资源,除非您想完全替换列表 return nil } func init() { q.ResourceList(CustomResourceListHandler) } -
注册资源/列表变更观察者 (可选): 注册函数以便在资源或资源列表发生变化时通知客户端。这些函数会在服务器启动后在新goroutine中运行。
func UserStatusChangeObserver(c qilin.ResourceChangeContext) { // 这是一个运行很长时间的观察者函数 // 监听用户状态变化,并在变化时调用 c.Publish for { select { case <-c.Context().Done(): // 服务器关闭时退出 return case <-time.After(5 * time.Minute): // 假设每5分钟检查一次 // 模拟某个用户状态改变,并发布通知 changedUserURI, _ := url.Parse("myapp://users/user123") c.Publish(changedUserURI, time.Now()) } } } func init() { // 为URI模式 myapp://users/{userId} 注册观察者 q.ResourceChangeObserver("myapp://users/{userId}", UserStatusChangeObserver) } -
编译并运行: 将您的 Go 代码编译成可执行文件,然后按照服务器配置中的 'command' 和 'args' 启动它。MCP 客户端即可连接并与之交互。
进阶用法
- 中间件: 使用 'q.UseInTools()' 和 'q.UseInResources()' 添加全局中间件。
- 自定义 JSON 库: 使用 'qilin.WithJSONMarshalFunc()' 和 'qilin.WithJSONUnmarshalFunc()' 选项替换默认的 JSON 库。
- 错误处理: 在 Tool 或 Resource handler 中返回 'error' 会自动转换为 JSON-RPC 错误响应。
通过上述步骤,您可以利用 Qilin 框架快速构建符合 MCP 规范的应用后端,为您的 LLM 应用提供强大的上下文感知和外部功能调用能力。
信息
分类
AI与计算