mcpField
G
Gin-MCP: Zero-Config Gin to MCP Bridge

Gin-MCP: Zero-Config Gin to MCP Bridge

本地服务
github.com/ckanthony开发工具8511 周前更新

关于 Gin-MCP: Zero-Config Gin to MCP Bridge

Gin-MCP 是一个面向 Go Gin 框架的库,无需修改现有代码即可把 Gin 接口自动暴露为 MCP 工具。它面向希望让已有 Gin API 被 MCP 客户端调用的开发者,并支持通过注释和配置调整工具的生成与筛选。

主要功能

  1. 01自动发现已注册的 Gin 路由
  2. 02从路由参数与请求类型推断工具模式
  3. 03通过 @tags 与操作 ID 筛选暴露的接口
  4. 04转发客户端 Authorization 头
  5. 05支持 Streamable HTTP 传输

适用场景

  1. 01让现有 Gin API 被 Cursor 或 Claude Desktop 调用
  2. 02为受 JWT 保护的 API 提供 MCP 访问
  3. 03在代理环境中动态解析 BaseURL

MCP 相关

该项目是一个 MCP 服务端库,把 Gin 接口转换为 MCP 工具,并通过 /mcp 等路径提供 Streamable HTTP 或旧版 SSE 端点。它支持多个 MCP 协议版本的协商。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

Gin-MCP:Gin 到 MCP 的零配置桥接器

Go 参考 CI codecov MCP Dev

信任评分

只需一行代码,即可为任意 Gin API 启用 MCP 功能。

Gin-MCP 是一个主张鲜明、零配置的库,可自动将现有 Gin 端点公开为 Model Context Protocol (MCP) 工具,供 Cursor、Claude Desktop、Continue、Zed 等兼容 MCP 的客户端和其他支持 MCP 的工具立即使用。

我们的理念很简单:最少配置,最高效率。只需将 Gin-MCP 接入你的 Gin 应用,剩下的工作交给它处理。
Gin-MCP 标志

为什么选择 Gin-MCP?

  • 轻松集成: 无需编写繁琐的样板代码,即可将 Gin API 连接到 MCP 客户端。
  • 零配置(默认): 即刻上手。Gin-MCP 会自动发现路由并推断架构。
  • 提升开发效率: 少花时间配置工具,多花时间构建功能。
  • 灵活性: 默认采用零配置,需要时也可以自定义架构和端点公开方式。
  • 现有 API: 可与现有 Gin API 配合使用,无需更改任何代码。

演示

gin-mcp-example

功能

  • 自动发现: 智能查找所有已注册的 Gin 路由。
  • 架构推断: 根据路由参数和请求/响应类型(如可行)自动生成 MCP 工具架构。
  • 直接集成 Gin: 将 MCP 服务直接挂载到现有的 gin.Engine 上。
  • 保留参数: 在生成的 MCP 工具中准确反映 Gin 路由参数(路径、查询)。
  • 动态解析 BaseURL: 支持代理环境(Quicknode、RAGFlow),并提供按用户/部署区分的端点。
  • 可自定义架构: 使用 RegisterSchema 为特定路由手动注册架构,实现精细控制。
  • 选择性公开: 使用操作 ID 或标签筛选要公开的端点。
  • 灵活部署: 可将 MCP 服务挂载在同一个 Gin 应用中,也可单独部署。
  • 现代 MCP 传输: 默认使用 Streamable HTTP,并支持协议版本协商(2026-07-28 至 2025-03-26)、预先调用 server/discover,以及选择退出并改用旧版 HTTP+SSE。
  • 转发授权标头: 自动将客户端的 Authorization 标头转发给每次内部工具执行调用,使 MCP 能够访问受 JWT 保护的 API。

安装

go get github.com/ckanthony/gin-mcp

基本用法:即时创建 MCP 服务

只需编写少量代码,即可在几分钟内运行 MCP 服务:

package main

import (
	"net/http"

	server "github.com/ckanthony/gin-mcp/"
	"github.com/gin-gonic/gin"
)

func main() {
	// 1. Create your Gin engine
	r := gin.Default()

	// 2. Define your API routes (Gin-MCP will discover these)
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "pong"})
	})

	r.GET("/users/:id", func(c *gin.Context) {
		// Example handler...
		userID := c.Param("id")
		c.JSON(http.StatusOK, gin.H{"user_id": userID, "status": "fetched"})
	})

	// 3. Create and configure the MCP server
	//    Provide essential details for the MCP client.
	mcp := server.New(r, &server.Config{
		Name:        "My Simple API",
		Description: "An example API automatically exposed via MCP.",
		// BaseURL is crucial! It tells MCP clients where to send requests.
		BaseURL: "http://localhost:8080",
	})

	// 4. Mount the MCP server endpoint
	mcp.Mount("/mcp") // MCP clients will connect here

	// 5. Run your Gin server
	r.Run(":8080") // Gin server runs as usual
}

就这么简单!现在,你的 MCP 工具已可通过 http://localhost:8080/mcp 使用。Gin-MCP 已自动为 /ping 和 /users/:id 创建工具。

关于 BaseURL 的说明:请始终提供明确的 BaseURL。这样,当客户端执行工具时,MCP 服务就能知道应将 API 请求转发到哪个地址。如果不提供,在某些环境中自动检测可能会失败,尤其是使用代理或内外部 URL 不同的环境。

高级用法

Gin-MCP 力求实现零配置,但你也可以自定义其行为。

使用注释为处理函数添加注解

Gin-MCP 会自动从处理函数注释中提取元数据,生成详尽的工具描述。使用这些注解可以让其他人更容易发现和使用你的 MCP 工具:

// listProducts retrieves a paginated list of products
// @summary List all products
// @description Returns a paginated list of products with optional filtering by price, tags, and availability
// @param page Page number for pagination (default: 1)
// @param limit Number of items per page (default: 10, max: 100)
// @param minPrice Minimum price filter
// @param tag Filter products by tag
// @tags public catalog
func listProducts(c *gin.Context) {
    // Handler implementation...
}

支持的注解:

  • @summary - 简短的一行描述,将作为工具的主要说明
  • @description - 补充的详细说明,将附加在摘要之后
  • @param <name> <text> - 为生成的架构中的特定输入参数添加描述文本
  • @tags - 用于筛选工具的标签,以空格或逗号分隔(请参阅下文的“筛选公开的端点”)
  • @operationId <id> - 工具的自定义操作 ID(覆盖默认的 METHOD_path 命名方案)。所有路由中的 ID 必须唯一;重复项将被跳过(以首次声明为准),并记录警告。

所有注解都是可选的,但使用它们可以让 API 工具在 Claude Desktop 和 Cursor 等 MCP 客户端中更易于使用。

自定义操作 ID:

默认情况下,Gin-MCP 使用 METHOD_path 格式生成操作 ID(例如 GET_users_id)。对于路径特别长的路由,可以使用 @operationId 指定更短、更易管理的名称:

// getUserProfile retrieves a user's profile with extended metadata
// @summary Get user profile
// @operationId getUserProfile
// @param id User identifier
func getUserProfile(c *gin.Context) {
    // Instead of the default "GET_api_v2_users_userId_profile_extended"
    // this tool will be named "getUserProfile"
}

**重要提示:**操作 ID 必须唯一。如果两个处理函数使用相同的 @operationId,重复项将被完全跳过(以首次声明为准),并始终记录警告。这可以确保工具列表与操作映射保持一致。

使用 RegisterSchema 精细控制架构

有时,自动推断架构并不足够。RegisterSchema 允许你为特定路由显式定义查询参数或请求正文的架构。适用于以下情况:

  • 使用复杂结构体作为查询参数(ShouldBindQuery)。
  • 希望为请求正文定义不同的架构(例如 POST/PUT)。
  • 自动推断无法捕获你希望在 MCP 工具定义中公开的特定约束(枚举、描述等)。
package main

import (
	// ... other imports
	"github.com/ckanthony/gin-mcp/pkg/server"
	"github.com/gin-gonic/gin"
)

// Example struct for query parameters
type ListProductsParams struct {
	Page  int    `form:"page,default=1" json:"page,omitempty" jsonschema:"description=Page number,minimum=1"`
	Limit int    `form:"limit,default=10" json:"limit,omitempty" jsonschema:"description=Items per page,maximum=100"`
	Tag   string `form:"tag" json:"tag,omitempty" jsonschema:"description=Filter by tag"`
}

// Example struct for POST request body
type CreateProductRequest struct {
	Name  string  `json:"name" jsonschema:"required,description=Product name"`
	Price float64 `json:"price" jsonschema:"required,minimum=0,description=Product price"`
}

func main() {
	r := gin.Default()

	// --- Define Routes ---
	r.GET("/products", func(c *gin.Context) { /* ... handler ... */ })
	r.POST("/products", func(c *gin.Context) { /* ... handler ... */ })
	r.PUT("/products/:id", func(c *gin.Context) { /* ... handler ... */ })


	// --- Configure MCP Server ---
	mcp := server.New(r, &server.Config{
		Name:        "Product API",
		Description: "API for managing products.",
		BaseURL:     "http://localhost:8080",
	})

	// --- Register Schemas ---
	// Register ListProductsParams as the query schema for GET /products
	mcp.RegisterSchema("GET", "/products", ListProductsParams{}, nil)

	// Register CreateProductRequest as the request body schema for POST /products
	mcp.RegisterSchema("POST", "/products", nil, CreateProductRequest{})

	// You can register schemas for other methods/routes as needed
	// e.g., mcp.RegisterSchema("PUT", "/products/:id", nil, UpdateProductRequest{})

	mcp.Mount("/mcp")
	r.Run(":8080")
}

说明:

  • mcp.RegisterSchema(method, path, querySchema, bodySchema)
  • method:HTTP 方法(例如 “GET”、“POST”)。
  • path:Gin 路由路径(例如 “/products”、“/products/:id”)。
  • querySchema:用于查询参数的结构体实例(如果没有,则为 nil)。Gin-MCP 会使用反射和 jsonschema 标签生成架构。
  • bodySchema:用于请求正文的结构体实例(如果没有,则为 nil)。
筛选公开的端点

使用操作 ID 或标签来控制哪些 Gin 端点会成为 MCP 工具。标签来自处理函数注释中的 @tags 注解(请参阅上文的“使用注释为处理函数添加注解”)。

基于标签筛选

在处理函数注释中使用 @tags 注解指定标签。标签可以用空格、逗号或两者分隔:

// listUsers handles user listing
// @summary List all users
// @tags public users
func listUsers(c *gin.Context) {
    // Implementation...
}

// deleteUser handles user deletion
// @summary Delete a user
// @tags admin, internal
func deleteUser(c *gin.Context) {
    // Implementation...
}
过滤配置
// Only include specific operations by their Operation ID
mcp := server.New(r, &server.Config{
    // ... other config ...
    IncludeOperations: []string{"GET_users", "POST_users"},
})

// Exclude specific operations
mcp := server.New(r, &server.Config{
    // ... other config ...
    ExcludeOperations: []string{"DELETE_users_id"}, // Don't expose delete tool
})

// Only include operations tagged with "public" or "users"
// A tool is included if it has ANY of the specified tags
mcp := server.New(r, &server.Config{
    // ... other config ...
    IncludeTags: []string{"public", "users"},
})

// Exclude operations tagged with "admin" or "internal"
// A tool is excluded if it has ANY of the specified tags
mcp := server.New(r, &server.Config{
    // ... other config ...
    ExcludeTags: []string{"admin", "internal"},
})

过滤规则:

  • 只能使用一个包含过滤器(IncludeOperations 或 IncludeTags)。
    • 如果两者都设置,则 IncludeOperations 优先,并会记录警告。
  • 只能使用一个排除过滤器(ExcludeOperations 或 ExcludeTags)。
    • 如果两者都设置,则 ExcludeOperations 优先,并会记录警告。
  • 可以组合使用包含过滤器和排除过滤器(例如,包含标签 "public",但排除操作 "legacyPublicOp")。
  • 排除始终优先:如果某个工具同时匹配包含过滤器和排除过滤器,则会被排除。
  • 标签匹配:工具只要具有任意一个指定标签,就会被包含或排除(OR 逻辑)。

示例:

// Include all "public" endpoints but exclude those also tagged "internal"
mcp := server.New(r, &server.Config{
    IncludeTags: []string{"public"},
    ExcludeTags: []string{"internal"},
})

// Include specific operations but exclude admin endpoints
mcp := server.New(r, &server.Config{
    IncludeOperations: []string{"GET_users", "GET_products"},
    ExcludeTags:       []string{"admin"},  // This will be ignored (precedence rule)
})
自定义架构描述(较少使用)

如需高级控制生成的工具中响应架构的描述方式(通常不需要):

mcp := server.New(r, &server.Config{
    // ... other config ...
    DescribeAllResponses:    true, // Include *all* possible response schemas (e.g., 200, 404) in tool descriptions
    DescribeFullResponseSchema: true, // Include the full JSON schema object instead of just a reference
})

示例

请参阅 examples 目录,查看演示各种功能的完整可运行示例:

基本用法示例
代理场景的动态 BaseURL

对于每个用户或部署使用不同端点的环境(如 Quicknode 或 RAGFlow),可以配置动态 BaseURL 解析:

// Quicknode example - resolves user-specific endpoints
mcp := server.New(r, &server.Config{
    Name: "Your API",
    Description: "API with dynamic Quicknode endpoints",
    // No static BaseURL needed!
})

resolver := server.NewQuicknodeResolver("http://localhost:8080")
mcp.SetExecuteToolFunc(func(operationID string, parameters map[string]interface{}) (interface{}, error) {
    return mcp.ExecuteToolWithResolver(operationID, parameters, resolver)
})

支持的环境变量:

  • Quicknode:QUICKNODE_USER_ENDPOINT、USER_ENDPOINT、HOST
  • RAGFlow:RAGFLOW_ENDPOINT、RAGFLOW_WORKFLOW_URL、RAGFLOW_BASE_URL + WORKFLOW_ID

这样就无需在启动时配置静态 BaseURL,非常适合多租户代理环境!

MCP 传输方式与协议版本

破坏性变更: 默认传输方式现为 Streamable HTTP。旧版 HTTP+SSE 传输(协议版本 2024-11-05,已被 MCP 规范弃用)仍可通过选择退出启用:TransportType: server.TransportTypeSSE。

Gin-MCP 默认使用现代的无状态 MCP Streamable HTTP 传输:每次向挂载路径发送 POST 请求,都会直接在 HTTP 请求体中返回 JSON-RPC 响应,无需持久 GET 连接或 Pod 亲和性,因此兼容水平自动扩缩容和无法实现会话亲和性的托管负载均衡器(例如 GCP、AWS ALB)。可选的 GET 端点会为服务器发起的通知(例如 tools/listChanged)提供 SSE 会话;基本的请求-响应操作不需要此功能。

旧版 SSE 传输(MCP 规范 2024-11-05)要求持久 GET 连接与后续 POST 请求路由到同一个 Pod,因此必须使用粘性会话——只有在客户端不支持 Streamable HTTP 时才选择退出并使用该传输方式。

支持的协议版本(Streamable HTTP,按从新到旧排列):

版本说明
2026-07-28当前版本。无状态:无需 initialize 握手。每个请求的 _meta 都包含 io.modelcontextprotocol/protocolVersion 和 clientCapabilities;Mcp-Method/Mcp-Name 标头会经过验证(见下文)。
2025-11-25最后一个包含 initialize 握手的版本。
2025-06-18支持。
2025-03-26支持;也是请求完全未携带版本时使用的回退版本。
2024-11-05仅用于旧版 HTTP+SSE(已弃用)。
mcp := server.New(r, &server.Config{
    Name:        "My API",
    Description: "An example API exposed via MCP.",
    BaseURL:     "https://api.example.com",

    // Transport selection (default: Streamable HTTP).
    TransportType: server.TransportTypeStreamableHTTP, // or server.TransportTypeSSE

    // DNS-rebinding protection: requests with an Origin header not in this list
    // get HTTP 403. Empty = allow all. Requests without an Origin header
    // (server-to-server) are always allowed.
    AllowedOrigins: []string{"https://app.example.com"},

    // Pin a single protocol version. Empty = all versions supported by the transport.
    ProtocolVersion: "",

    // Advertised in serverInfo (default "0.1.0").
    ServerVersion: "1.0.0",

    // Cache hints advertised on tools/list for 2026-07-28 clients
    // (defaults: 60000 ms, "public").
    CacheTTLMs: 60000,
    CacheScope: "public",
})
mcp.Mount("/mcp")

MCP 客户端只需发送单个 POST /mcp 即可连接,无需事先发送 GET 请求。

版本协商。 协议版本由 MCP-Protocol-Version 标头和 params._meta["io.modelcontextprotocol/protocolVersion"] 确定。如果两者都存在,则必须一致(否则返回 HTTP 400、-32020)。如果两者都不存在,则默认使用 2025-03-26。不支持的版本会被拒绝,并返回 HTTP 400 和 -32022;error.data.supported 列表会告知客户端此服务支持的版本。客户端也可以预先调用 server/discover RPC,在无需握手的情况下获取 supportedVersions、capabilities 和服务器信息。旧版 initialize 握手永远不会协商到 2026-07-28,而会回退到最后一个支持握手的版本 2025-11-25。

2026-07-28 标头验证。 协商使用 2026-07-28 的请求还必须发送 Mcp-Method 标头(纯 ASCII),其值必须与 JSON-RPC method 匹配;对于 tools/call,还必须发送与 params.name 匹配的 Mcp-Name 标头。对于不符合标头安全要求的 Mcp-Name 值,可使用 =?base64?...?= 标记进行 Base64 编码后发送,服务器端会对其解码。任何缺失、无效或不匹配的标头都会被拒绝,并返回 HTTP 400 和 -32020。

Origin 验证(DNS 重绑定防护)

根据 MCP 规范 2025-03-26 §Security,服务器应验证 Origin 标头。使用 AllowedOrigins 限制源自浏览器的请求(参见上文配置示例):

  • 请求携带的 Origin 标头不在列表中 → 403 Forbidden。
  • 请求不携带 Origin 标头(服务器到服务器:curl、Node.js 等)→ 始终允许。
  • AllowedOrigins 为空或为 nil → 允许所有源(适用于要求 Bearer 令牌的场景)。
Authorization 标头转发

当 Gin 端点受到 JWT Bearer 令牌保护时,可以将客户端的 Authorization 标头转发到每次内部工具执行的 HTTP 调用:

mcp := server.New(r, &server.Config{
    Name:               "My API",
    BaseURL:            "https://api.example.com",
    ForwardAuthHeaders: true,
})
mcp.Mount("/mcp")
  • SSE 传输: 在建立 SSE 连接时捕获一次该标头,并在该连接上的所有后续工具调用中重复使用。
  • Streamable HTTP 传输: 每个 POST 请求都会单独捕获该标头(每次调用相互独立)。
  • 默认值:false(禁用,以保持向后兼容)。

连接 MCP 客户端

运行集成了 Gin-MCP 的 Gin 应用后:

  1. 启动应用。
  2. 在 MCP 客户端中,提供挂载 MCP 服务的 URL(例如,http://localhost:8080/mcp):
    • Streamable HTTP 传输(默认):作为普通 HTTP 端点连接(仅 POST)。
    • SSE 传输(仅在通过 TransportType: server.TransportTypeSSE 明确配置时):作为 SSE 端点连接(先 GET,再向同一路径发送 POST)。
    • Cursor:设置 → MCP → 添加服务
    • Claude Desktop:添加到 MCP 配置文件
    • Continue:在 VS Code 设置中配置
    • Zed:添加到 MCP 设置
  3. 客户端将连接并自动发现可用的 API 工具。

贡献

欢迎贡献!欢迎提交问题或 Pull Request。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。