A zero-configuration Go library to automatically expose existing Gin web framework APIs as MCP tools.
Enable MCP features for any Gin API with a line of code.
Gin-MCP is an opinionated, zero-configuration library that automatically exposes your existing Gin endpoints as Model Context Protocol (MCP) tools, making them instantly usable by MCP-compatible clients like Cursor. Our philosophy is simple: minimal setup, maximum productivity. Just plug Gin-MCP into your Gin application, and it handles the rest. |
![]() |
gin.Engine
.RegisterSchema
for fine-grained control.go get github.com/ckanthony/gin-mcp
Get your MCP server running in minutes with minimal code:
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
}
That's it! Your MCP tools are now available at http://localhost:8080/mcp
. Gin-MCP automatically created tools for /ping
and /users/:id
.
Note on
BaseURL
: Always provide an explicitBaseURL
. This tells the MCP server the correct address to forward API requests to when a tool is executed by the client. Without it, automatic detection might fail, especially in environments with proxies or different internal/external URLs.
While Gin-MCP strives for zero configuration, you can customize its behavior.
RegisterSchema
Sometimes, automatic schema inference isn't enough. RegisterSchema
allows you to explicitly define schemas for query parameters or request bodies for specific routes. This is useful when:
ShouldBindQuery
).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")
}
Explanation:
mcp.RegisterSchema(method, path, querySchema, bodySchema)
method
: HTTP method (e.g., "GET", "POST").path
: Gin route path (e.g., "/products", "/products/:id").querySchema
: An instance of the struct used for query parameters (or nil
if none). Gin-MCP uses reflection and jsonschema
tags to generate the schema.bodySchema
: An instance of the struct used for the request body (or nil
if none).Control which Gin endpoints become MCP tools using operation IDs or tags (if your routes define them).
// Only include specific operations by their Operation ID (if defined in your routes)
mcp := server.New(r, &server.Config{
// ... other config ...
IncludeOperations: []string{"getUser", "listUsers"},
})
// Exclude specific operations
mcp := server.New(r, &server.Config{
// ... other config ...
ExcludeOperations: []string{"deleteUser"}, // Don't expose deleteUser tool
})
// Only include operations tagged with "public" or "users"
mcp := server.New(r, &server.Config{
// ... other config ...
IncludeTags: []string{"public", "users"},
})
// Exclude operations tagged with "admin" or "internal"
mcp := server.New(r, &server.Config{
// ... other config ...
ExcludeTags: []string{"admin", "internal"},
})
Filtering Rules:
IncludeOperations
OR IncludeTags
).ExcludeOperations
OR ExcludeTags
).For advanced control over how response schemas are described in the generated tools (often not needed):
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
})
See the examples
directory for complete, runnable examples demonstrating various features.
Once your Gin application with Gin-MCP is running:
http://localhost:8080/mcp
) as the SSE endpoint.Contributions are welcome! Please feel free to submit issues or Pull Requests.