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 は、既存の Gin エンドポイントをハンドラーのコードを変更せずに MCP ツールとして公開する Go ライブラリです。Gin API を MCP クライアントから利用したい開発者向けです。アノテーションと設定により、生成されるツールを調整できます。

主な機能

  1. 01登録済み Gin ルートの自動検出
  2. 02ルートパラメーターからのツールスキーマ推論
  3. 03オペレーション ID やタグによるエンドポイントの絞り込み
  4. 04クライアントの Authorization ヘッダーの転送
  5. 05デフォルトの Streamable HTTP トランスポート

活用シーン

  1. 01既存の Gin API を Cursor や Claude Desktop から呼び出す
  2. 02JWT で保護された API への MCP アクセスの提供
  3. 03プロキシ環境での BaseURL の動的解決

MCP 対応

本プロジェクトは、Gin エンドポイントを MCP ツールに変換する MCP サーバーのライブラリです。/mcp などのマウントパスで Streamable HTTP を提供し、旧版の SSE はオプトアウトで利用できます。複数の MCP プロトコルバージョンをネゴシエーションします。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

Gin-MCP:設定不要の Gin から MCP へのブリッジ

Go Reference CI codecov MCP Dev

Trust Score

1 行のコードで、あらゆる Gin API に MCP 機能を追加できます。

Gin-MCP は、既存の Gin エンドポイントをModel Context Protocol(MCP)のツールとして自動的に公開する、独自の方針に基づいた設定不要のライブラリです。これにより、Cursor、Claude Desktop、Continue、Zedなど、MCP 対応クライアントですぐに利用できるようになります。

私たちの考え方はシンプルです。最小限のセットアップで最大限の生産性を実現します。Gin-MCP を Gin アプリケーションに組み込むだけで、あとはすべて Gin-MCP が処理します。
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 トランスポート: プロトコルバージョンのネゴシエーション(2026-07-28 から 2025-03-26 まで)、事前の server/discover、および従来の HTTP+SSE を無効化するオプションに対応した、ストリーミング可能な HTTP(デフォルト)。
  • 認証ヘッダーの転送: クライアントの 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 を指定してください。これにより、クライアントがツールを実行したときに、API リクエストを転送する正しいアドレスを MCP サーバーに伝えられます。指定しない場合、自動検出に失敗することがあります。特に、プロキシを使用する環境や、内部 URL と外部 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 - @summary に追加される、詳しい説明です。
  • @param <name> <text> - 生成されたスキーマ内の特定の入力パラメーターに、説明文を追加します。
  • @tags - ツールのフィルタリングに使う、スペースまたはカンマ区切りのタグです(下記の「公開するエンドポイントのフィルタリング」を参照)。
  • @operationId <id> - ツール用のカスタム operation ID です(デフォルトの METHOD_path 命名規則を上書きします)。すべてのルートで一意である必要があります。重複がある場合は警告がログに記録され、後から宣言されたものはスキップされます(最初の宣言が優先されます)。

すべてのアノテーションは省略可能ですが、使用すると Claude Desktop や Cursor などの MCP クライアントで、API ツールをより使いやすくできます。

カスタム operation ID:

デフォルトでは、Gin-MCP は METHOD_path 形式で operation 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"
}

重要: operation ID は一意である必要があります。2 つのハンドラーで同じ @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)。
公開するエンドポイントのフィルタリング

operation 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"},
})

フィルタリングルール:

  • 使用できる包含フィルターは1つだけです(IncludeOperations または IncludeTags)。
    • 両方が設定されている場合は、IncludeOperations が優先され、警告がログに記録されます。
  • 使用できる除外フィルターは1つだけです(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 は、JSON-RPC レスポンスを HTTP ボディに直接返します。永続的な GET 接続もポッドアフィニティも不要なため、水平オートスケーリングや、セッションアフィニティに対応できないマネージドロードバランサー(GCP、AWS ALB など)と互換性があります。サーバー起点の通知(例:tools/listChanged)用に、オプションの GET エンドポイントで SSE セッションを提供できます。基本的なリクエスト/レスポンスの処理には必要ありません。

旧来の SSE トランスポート(MCP 仕様 2024-11-05)では、後続の POST リクエストを同じポッドにルーティングする永続的な GET 接続が必要となるため、スティッキーセッションが必要です。クライアントが Streamable HTTP に対応していない場合に限り、こちらを選択してください。

サポート対象のプロトコルバージョン(Streamable HTTP、新しい順):

バージョン備考
2026-07-28現行バージョン。ステートレスで、initialize ハンドシェイクはありません。リクエストごとの _meta に io.modelcontextprotocol/protocolVersion と clientCapabilities が含まれます。Mcp-Method/Mcp-Name ヘッダーが検証されます(以下を参照)。
2025-11-25initialize ハンドシェイクがある最後のバージョンです。
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 クライアントは、事前の GET なしで単一の POST /mcp を使って接続できます。

バージョンネゴシエーション。 プロトコルバージョンは、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 としてネゴシエートされたリクエストでは、JSON-RPC の method と一致する Mcp-Method ヘッダー(プレーンな ASCII)も送信する必要があります。また、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:Settings → MCP → Add Server
    • Claude Desktop:MCP 設定ファイルに追加します
    • Continue:VS Code の設定で構成します
    • Zed:MCP 設定に追加します
  3. クライアントが接続し、利用可能な API ツールを自動的に検出します。

コントリビューション

コントリビューションを歓迎します。お気軽に Issue や Pull Request をお送りください。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。