{"id":29114022,"url":"https://github.com/ckanthony/gin-mcp","last_synced_at":"2026-01-14T22:55:29.006Z","repository":{"id":288467131,"uuid":"968208783","full_name":"ckanthony/gin-mcp","owner":"ckanthony","description":"Enable MCP features for any Gin API with a line of code","archived":false,"fork":false,"pushed_at":"2025-08-14T11:15:08.000Z","size":839,"stargazers_count":46,"open_issues_count":2,"forks_count":9,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-14T13:12:26.307Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ckanthony.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-17T17:27:12.000Z","updated_at":"2025-08-14T11:15:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"00e6d2ac-9a56-425c-ab65-6e2c8737faf8","html_url":"https://github.com/ckanthony/gin-mcp","commit_stats":null,"previous_names":["ckanthony/gin-mcp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ckanthony/gin-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckanthony%2Fgin-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckanthony%2Fgin-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckanthony%2Fgin-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckanthony%2Fgin-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ckanthony","download_url":"https://codeload.github.com/ckanthony/gin-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ckanthony%2Fgin-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28437311,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-29T11:06:01.431Z","updated_at":"2026-01-14T22:55:28.983Z","avatar_url":"https://github.com/ckanthony.png","language":"Go","funding_links":[],"categories":["MCP Clients","Developer Tools","Api Integration Mcp Servers","پیاده‌سازی‌های سرور","⚙️ DevOps","Other Tools and Integrations","Server Implementations"],"sub_categories":["Weather","💻 \u003ca name=\"developer-tools\"\u003e\u003c/a\u003eابزارهای توسعه‌دهنده","How to Submit","💻 \u003ca name=\"developer-tools\"\u003e\u003c/a\u003eDeveloper Tools"],"readme":"# Gin-MCP: Zero-Config Gin to MCP Bridge\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/ckanthony/gin-mcp.svg)](https://pkg.go.dev/github.com/ckanthony/gin-mcp)\n[![CI](https://github.com/ckanthony/gin-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/ckanthony/gin-mcp/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/ckanthony/gin-mcp/branch/main/graph/badge.svg)](https://codecov.io/gh/ckanthony/gin-mcp)\n![](https://badge.mcpx.dev?type=dev 'MCP Dev')\n\n[![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/ckanthony/gin-mcp)](https://archestra.ai/mcp-catalog/ckanthony__gin-mcp)\n\n\u003ctable border=\"0\"\u003e\n  \u003ctr\u003e\n    \u003ctd valign=\"top\"\u003e\n      \u003cstrong\u003eEnable MCP features for any Gin API with a line of code.\u003c/strong\u003e\n      \u003cbr\u003e\u003cbr\u003e\n      Gin-MCP is an \u003cstrong\u003eopinionated, zero-configuration\u003c/strong\u003e library that automatically exposes your existing Gin endpoints as \u003ca href=\"https://modelcontextprotocol.io/introduction\"\u003eModel Context Protocol (MCP)\u003c/a\u003e tools, making them instantly usable by MCP-compatible clients like \u003ca href=\"https://cursor.sh/\"\u003eCursor\u003c/a\u003e, \u003ca href=\"https://claude.ai/desktop\"\u003eClaude Desktop\u003c/a\u003e, \u003ca href=\"https://continue.dev/\"\u003eContinue\u003c/a\u003e, \u003ca href=\"https://zed.dev/\"\u003eZed\u003c/a\u003e, and other MCP-enabled tools.\n      \u003cbr\u003e\u003cbr\u003e\n      Our philosophy is simple: \u003cstrong\u003eminimal setup, maximum productivity\u003c/strong\u003e. Just plug Gin-MCP into your Gin application, and it handles the rest.\n    \u003c/td\u003e\n    \u003ctd valign=\"top\" align=\"right\" width=\"200\"\u003e\n      \u003cimg src=\"gin-mcp.png\" alt=\"Gin-MCP Logo\" width=\"200\"/\u003e\n    \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Why Gin-MCP?\n\n-   **Effortless Integration:** Connect your Gin API to MCP clients without writing tedious boilerplate code.\n-   **Zero Configuration (by default):** Get started instantly. Gin-MCP automatically discovers routes and infers schemas.\n-   **Developer Productivity:** Spend less time configuring tools and more time building features.\n-   **Flexibility:** While zero-config is the default, customize schemas and endpoint exposure when needed.\n-   **Existing API:** Works with your existing Gin API - no need to change any code.\n\n## Demo\n\n![gin-mcp-example](https://github.com/user-attachments/assets/ad6948ce-ed11-400b-8e96-9b020e51df78)\n\n## Features\n\n-   **Automatic Discovery:** Intelligently finds all registered Gin routes.\n-   **Schema Inference:** Automatically generates MCP tool schemas from route parameters and request/response types (where possible).\n-   **Direct Gin Integration:** Mounts the MCP server directly onto your existing `gin.Engine`.\n-   **Parameter Preservation:** Accurately reflects your Gin route parameters (path, query) in the generated MCP tools.\n-   **Dynamic BaseURL Resolution:** Support for proxy environments (Quicknode, RAGFlow) with per-user/deployment endpoints.\n-   **Customizable Schemas:** Manually register schemas for specific routes using `RegisterSchema` for fine-grained control.\n-   **Selective Exposure:** Filter which endpoints are exposed using operation IDs or tags.\n-   **Flexible Deployment:** Mount the MCP server within the same Gin app or deploy it separately.\n\n## Installation\n\n```bash\ngo get github.com/ckanthony/gin-mcp\n```\n\n## Basic Usage: Instant MCP Server\n\nGet your MCP server running in minutes with minimal code:\n\n```go\npackage main\n\nimport (\n\t\"net/http\"\n\n\tserver \"github.com/ckanthony/gin-mcp/\"\n\t\"github.com/gin-gonic/gin\"\n)\n\nfunc main() {\n\t// 1. Create your Gin engine\n\tr := gin.Default()\n\n\t// 2. Define your API routes (Gin-MCP will discover these)\n\tr.GET(\"/ping\", func(c *gin.Context) {\n\t\tc.JSON(http.StatusOK, gin.H{\"message\": \"pong\"})\n\t})\n\n\tr.GET(\"/users/:id\", func(c *gin.Context) {\n\t\t// Example handler...\n\t\tuserID := c.Param(\"id\")\n\t\tc.JSON(http.StatusOK, gin.H{\"user_id\": userID, \"status\": \"fetched\"})\n\t})\n\n\t// 3. Create and configure the MCP server\n\t//    Provide essential details for the MCP client.\n\tmcp := server.New(r, \u0026server.Config{\n\t\tName:        \"My Simple API\",\n\t\tDescription: \"An example API automatically exposed via MCP.\",\n\t\t// BaseURL is crucial! It tells MCP clients where to send requests.\n\t\tBaseURL: \"http://localhost:8080\",\n\t})\n\n\t// 4. Mount the MCP server endpoint\n\tmcp.Mount(\"/mcp\") // MCP clients will connect here\n\n\t// 5. Run your Gin server\n\tr.Run(\":8080\") // Gin server runs as usual\n}\n\n```\n\nThat's it! Your MCP tools are now available at `http://localhost:8080/mcp`. Gin-MCP automatically created tools for `/ping` and `/users/:id`.\n\n\u003e **Note on `BaseURL`**: Always provide an explicit `BaseURL`. 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.\n\n## Advanced Usage\n\nWhile Gin-MCP strives for zero configuration, you can customize its behavior.\n\n### Annotating Handlers with Comments\n\nGin-MCP automatically extracts metadata from handler function comments to generate rich tool descriptions. Use these annotations to make your MCP tools more discoverable and easier to use:\n\n```go\n// listProducts retrieves a paginated list of products\n// @summary List all products\n// @description Returns a paginated list of products with optional filtering by price, tags, and availability\n// @param page Page number for pagination (default: 1)\n// @param limit Number of items per page (default: 10, max: 100)\n// @param minPrice Minimum price filter\n// @param tag Filter products by tag\n// @tags public catalog\nfunc listProducts(c *gin.Context) {\n    // Handler implementation...\n}\n```\n\n**Supported Annotations:**\n\n-   **`@summary`** - Brief one-line description that becomes the tool's primary description\n-   **`@description`** - Additional detailed explanation appended to the summary\n-   **`@param \u003cname\u003e \u003ctext\u003e`** - Attaches descriptive text to specific input parameters in the generated schema\n-   **`@tags`** - Space or comma-separated tags used for filtering tools (see \"Filtering Exposed Endpoints\" below)\n-   **`@operationId \u003cid\u003e`** - Custom operation ID for the tool (overrides the default `METHOD_path` naming scheme). Must be unique across all routes; duplicates will be skipped (first declaration wins) with a warning logged.\n\nAll annotations are optional, but using them makes your API tools much more user-friendly in MCP clients like Claude Desktop and Cursor.\n\n**Custom Operation IDs:**\n\nBy default, Gin-MCP generates operation IDs using the format `METHOD_path` (e.g., `GET_users_id`). For routes with very long paths, you can use `@operationId` to specify a shorter, more manageable name:\n\n```go\n// getUserProfile retrieves a user's profile with extended metadata\n// @summary Get user profile\n// @operationId getUserProfile\n// @param id User identifier\nfunc getUserProfile(c *gin.Context) {\n    // Instead of the default \"GET_api_v2_users_userId_profile_extended\"\n    // this tool will be named \"getUserProfile\"\n}\n```\n\n**Important:** Operation IDs must be unique. If two handlers use the same `@operationId`, the duplicate will be skipped entirely (first declaration wins), and a warning will always be logged. This ensures consistency between the tool list and operations map.\n\n### Fine-Grained Schema Control with `RegisterSchema`\n\nSometimes, 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:\n\n-   You use complex structs for query parameters (`ShouldBindQuery`).\n-   You want to define distinct schemas for request bodies (e.g., for POST/PUT).\n-   Automatic inference doesn't capture specific constraints (enums, descriptions, etc.) that you want exposed in the MCP tool definition.\n\n```go\npackage main\n\nimport (\n\t// ... other imports\n\t\"github.com/ckanthony/gin-mcp/pkg/server\"\n\t\"github.com/gin-gonic/gin\"\n)\n\n// Example struct for query parameters\ntype ListProductsParams struct {\n\tPage  int    `form:\"page,default=1\" json:\"page,omitempty\" jsonschema:\"description=Page number,minimum=1\"`\n\tLimit int    `form:\"limit,default=10\" json:\"limit,omitempty\" jsonschema:\"description=Items per page,maximum=100\"`\n\tTag   string `form:\"tag\" json:\"tag,omitempty\" jsonschema:\"description=Filter by tag\"`\n}\n\n// Example struct for POST request body\ntype CreateProductRequest struct {\n\tName  string  `json:\"name\" jsonschema:\"required,description=Product name\"`\n\tPrice float64 `json:\"price\" jsonschema:\"required,minimum=0,description=Product price\"`\n}\n\nfunc main() {\n\tr := gin.Default()\n\n\t// --- Define Routes ---\n\tr.GET(\"/products\", func(c *gin.Context) { /* ... handler ... */ })\n\tr.POST(\"/products\", func(c *gin.Context) { /* ... handler ... */ })\n\tr.PUT(\"/products/:id\", func(c *gin.Context) { /* ... handler ... */ })\n\n\n\t// --- Configure MCP Server ---\n\tmcp := server.New(r, \u0026server.Config{\n\t\tName:        \"Product API\",\n\t\tDescription: \"API for managing products.\",\n\t\tBaseURL:     \"http://localhost:8080\",\n\t})\n\n\t// --- Register Schemas ---\n\t// Register ListProductsParams as the query schema for GET /products\n\tmcp.RegisterSchema(\"GET\", \"/products\", ListProductsParams{}, nil)\n\n\t// Register CreateProductRequest as the request body schema for POST /products\n\tmcp.RegisterSchema(\"POST\", \"/products\", nil, CreateProductRequest{})\n\n\t// You can register schemas for other methods/routes as needed\n\t// e.g., mcp.RegisterSchema(\"PUT\", \"/products/:id\", nil, UpdateProductRequest{})\n\n\tmcp.Mount(\"/mcp\")\n\tr.Run(\":8080\")\n}\n```\n\n**Explanation:**\n\n-   `mcp.RegisterSchema(method, path, querySchema, bodySchema)`\n-   `method`: HTTP method (e.g., \"GET\", \"POST\").\n-   `path`: Gin route path (e.g., \"/products\", \"/products/:id\").\n-   `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.\n-   `bodySchema`: An instance of the struct used for the request body (or `nil` if none).\n\n### Filtering Exposed Endpoints\n\nControl which Gin endpoints become MCP tools using operation IDs or tags. Tags come from the `@tags` annotation in your handler comments (see \"Annotating Handlers\" above).\n\n#### Tag-Based Filtering\n\nTags are specified in handler function comments using the `@tags` annotation. You can specify tags separated by spaces, commas, or both:\n\n```go\n// listUsers handles user listing\n// @summary List all users\n// @tags public users\nfunc listUsers(c *gin.Context) {\n    // Implementation...\n}\n\n// deleteUser handles user deletion\n// @summary Delete a user\n// @tags admin, internal\nfunc deleteUser(c *gin.Context) {\n    // Implementation...\n}\n```\n\n#### Filtering Configuration\n\n```go\n// Only include specific operations by their Operation ID\nmcp := server.New(r, \u0026server.Config{\n    // ... other config ...\n    IncludeOperations: []string{\"GET_users\", \"POST_users\"},\n})\n\n// Exclude specific operations\nmcp := server.New(r, \u0026server.Config{\n    // ... other config ...\n    ExcludeOperations: []string{\"DELETE_users_id\"}, // Don't expose delete tool\n})\n\n// Only include operations tagged with \"public\" or \"users\"\n// A tool is included if it has ANY of the specified tags\nmcp := server.New(r, \u0026server.Config{\n    // ... other config ...\n    IncludeTags: []string{\"public\", \"users\"},\n})\n\n// Exclude operations tagged with \"admin\" or \"internal\"\n// A tool is excluded if it has ANY of the specified tags\nmcp := server.New(r, \u0026server.Config{\n    // ... other config ...\n    ExcludeTags: []string{\"admin\", \"internal\"},\n})\n```\n\n**Filtering Rules:**\n\n-   You can only use **one** inclusion filter (`IncludeOperations` **OR** `IncludeTags`).\n    - If both are set, `IncludeOperations` takes precedence and a warning is logged.\n-   You can only use **one** exclusion filter (`ExcludeOperations` **OR** `ExcludeTags`).\n    - If both are set, `ExcludeOperations` takes precedence and a warning is logged.\n-   You **can** combine an inclusion filter with an exclusion filter (e.g., include tag \"public\" but exclude operation \"legacyPublicOp\").\n-   **Exclusion always wins**: If a tool matches both inclusion and exclusion filters, it will be excluded.\n-   **Tag matching**: A tool is included/excluded if it has **any** of the specified tags (OR logic).\n\n**Examples:**\n\n```go\n// Include all \"public\" endpoints but exclude those also tagged \"internal\"\nmcp := server.New(r, \u0026server.Config{\n    IncludeTags: []string{\"public\"},\n    ExcludeTags: []string{\"internal\"},\n})\n\n// Include specific operations but exclude admin endpoints\nmcp := server.New(r, \u0026server.Config{\n    IncludeOperations: []string{\"GET_users\", \"GET_products\"},\n    ExcludeTags:       []string{\"admin\"},  // This will be ignored (precedence rule)\n})\n```\n\n### Customizing Schema Descriptions (Less Common)\n\nFor advanced control over how response schemas are described in the generated tools (often not needed):\n\n```go\nmcp := server.New(r, \u0026server.Config{\n    // ... other config ...\n    DescribeAllResponses:    true, // Include *all* possible response schemas (e.g., 200, 404) in tool descriptions\n    DescribeFullResponseSchema: true, // Include the full JSON schema object instead of just a reference\n})\n```\n\n## Examples\n\nSee the [`examples`](examples) directory for complete, runnable examples demonstrating various features:\n\n### Basic Usage Examples\n\n- **[`examples/simple/main.go`](examples/simple/main.go)** - Complete product store API with static BaseURL configuration\n- **[`examples/simple/quicknode.go`](examples/simple/quicknode.go)** - Dynamic BaseURL configuration for Quicknode proxy environments  \n- **[`examples/simple/ragflow.go`](examples/simple/ragflow.go)** - Dynamic BaseURL configuration for RAGFlow deployment scenarios\n\n### Dynamic BaseURL for Proxy Scenarios\n\nFor environments where each user/deployment has a different endpoint (like Quicknode or RAGFlow), you can configure dynamic BaseURL resolution:\n\n```go\n// Quicknode example - resolves user-specific endpoints\nmcp := server.New(r, \u0026server.Config{\n    Name: \"Your API\",\n    Description: \"API with dynamic Quicknode endpoints\",\n    // No static BaseURL needed!\n})\n\nresolver := server.NewQuicknodeResolver(\"http://localhost:8080\")\nmcp.SetExecuteToolFunc(func(operationID string, parameters map[string]interface{}) (interface{}, error) {\n    return mcp.ExecuteToolWithResolver(operationID, parameters, resolver)\n})\n```\n\n**Environment Variables Supported:**\n- **Quicknode**: `QUICKNODE_USER_ENDPOINT`, `USER_ENDPOINT`, `HOST`\n- **RAGFlow**: `RAGFLOW_ENDPOINT`, `RAGFLOW_WORKFLOW_URL`, `RAGFLOW_BASE_URL` + `WORKFLOW_ID`\n\nThis eliminates the need for static BaseURL configuration at startup, perfect for multi-tenant proxy environments!\n\n## Connecting MCP Clients\n\nOnce your Gin application with Gin-MCP is running:\n\n1.  Start your application.\n2.  In your MCP client, provide the URL where you mounted the MCP server (e.g., `http://localhost:8080/mcp`) as the SSE endpoint:\n    - **Cursor**: Settings → MCP → Add Server\n    - **Claude Desktop**: Add to MCP configuration file\n    - **Continue**: Configure in VS Code settings\n    - **Zed**: Add to MCP settings\n3.  The client will connect and automatically discover the available API tools.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit issues or Pull Requests. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckanthony%2Fgin-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fckanthony%2Fgin-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fckanthony%2Fgin-mcp/lists"}