mcpField
M
MCP Gateway

MCP Gateway

ローカル
github.com/lucky-aeon開発ツール3421 週間前に更新

MCP Gateway について

MCP Gateway は、クライアントからのリクエストを個別の MCP サーバーへ転送するか、ゲートウェイ配下のすべての MCP サーバーを単一のポータルから利用できるようにするリバースプロキシです。SSE と Streamable HTTP の両方のトランスポートに対応し、OAuth 2.1 によるリソースサーバー認証も備えています。

主な機能

  1. 01複数の MCP サーバーのツールと SSE ストリームを集約する統一エンドポイント
  2. 02SSE と Streamable HTTP の切り替え可能なトランスポート
  3. 03Mcp-Session-Id ヘッダーによるセッション管理
  4. 04Bearer トークン認証と OAuth 2.1 メタデータの検出
  5. 05config.json によるプロトコル、認証、セッションの設定

活用シーン

  1. 01複数の MCP サーバーを一つのエンドポイントの背後にデプロイする
  2. 02MCP サーバーに Bearer トークンや OAuth による保護を追加する
  3. 03ローカル開発で認証なしの MCP アクセスを行う

MCP 対応

本ゲートウェイは MCP サーバーのリバースプロキシとして動作し、集約されたツールを SSE または Streamable HTTP のエンドポイントでクライアントに公開し、下流の各 MCP サーバーへリクエストを転送します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"gateway-lucky-aeon": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"pull"
]
}
}
}
起動コマンドdocker run -i --rm pull

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
ocipull

ツール

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

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

詳細

MCP Gateway

説明

MCP ゲートウェイは、クライアントからのリクエストを MCP サーバーに転送するリバースプロキシサーバーです。または、統合ポータルを通じて、ゲートウェイ配下のすべての MCP サーバーを利用できます。

起動時に切り替え可能な 2 つのトランスポートプロトコルをサポートしています。

  • SSE(デフォルト、従来の MCP トランスポート)
  • Streamable HTTP(MCP 仕様 2025-03-26)

機能

  • 複数の MCP サーバーをデプロイする
  • MCP サーバーに接続する
  • ゲートウェイを使って MCP サーバーを呼び出す
  • すべての MCP サーバーの SSE ストリームを取得する
  • すべての MCP サーバーのツールを取得する
  • Mcp-Session-Id ヘッダーによるセッション管理に対応した、Streamable HTTP の集約エンドポイント
  • 動的な機能集約(少なくとも 1 つの下流 MCP がサポートする機能のみをゲートウェイが通知します)
  • 保護されたリソースメタデータの検出に対応した、MCP OAuth 2.1 リソースサーバー認証

インストール

  1. GitHub パッケージをプルする
docker pull ghcr.io/lucky-aeon/mcp-gateway:latest
  1. Docker イメージを自分でビルドする
docker build -t mcp-gateway .

使い方

GitHub の Docker コンテナを実行する

docker run -d --name mcp-gateway -p 8080:8080 ghcr.io/lucky-aeon/mcp-gateway

自分でビルドした Docker コンテナを実行する

docker run -d --name mcp-gateway -p 8080:8080 mcp-gateway

設定

ゲートウェイは設定ディレクトリから config.json を読み込みます(./vm が存在する場合はそこをデフォルトとし、存在しない場合は . を使用します)。最小限の例:

{
    "LogLevel": 0,
    "Bind": "[::]:8080",
    "Auth": {
        "Enabled": true,
        "AuthorizationServers": ["https://auth.example.com"],
        "TokenIssuer": "https://auth.example.com",
        "TokenJWKSURI": "https://auth.example.com/.well-known/jwks.json",
        "TokenAudience": "http://localhost:8080/stream",
        "RequiredScopes": ["mcp:read"],
        "ScopesSupported": ["mcp:read"]
    },
    "GatewayProtocol": "all",
    "McpServiceMgrConfig": {
        "McpServiceRetryCount": 3
    }
}

主なフィールド:

フィールドデフォルト説明
Bind[::]:8080サーバーのリッスンアドレスです。
GatewayProtocolall公開するゲートウェイプロトコルです。all、sse、または streamhttp を指定します。--protocol フラグでも上書きできます。
Auth.Enabledtrue認証を必須にするかどうかです。ローカルで認証なしの MCP 利用を許可するには、false に設定します。
Auth.ApiKey123456従来の単一キー管理 API ログイン用トークンです。MCP 認証には使用されません。
Auth.Modesingle-keysingle-key または saas です。SaaS モードでは、MCP Gateway アカウントとパスワードログインを使用します。
Auth.AuthorizationServersempty任意の外部 OAuth 発行者 URL です。SaaS モードでは、空にするとゲートウェイ自身を認可サーバーとして通知します。
Auth.TokenIssuerfirst authorization serverMCP OAuth アクセストークンに想定される iss クレームです。
Auth.TokenJWKSURIdiscovered from issuerJWT アクセストークンの検証に使用する JWKS URL です。
Auth.TokenIntrospectionURLempty不透明なアクセストークン用の RFC 7662 イントロスペクションエンドポイントです。設定すると、JWKS の代わりにイントロスペクションを使用します。
Auth.TokenAudiencerequest resource URL想定される aud クレームです。認可サーバーで使用する MCP リソースインジケーターを設定します。
Auth.RequiredScopesemptyMCP リクエストに必要なスコープで、WWW-Authenticate に通知されます。
Auth.ScopesSupportedempty保護されたリソースメタデータで通知されるスコープです。
SessionGCInterval10sアイドル状態のプロキシセッションをガベージコレクションする間隔です。
ProxySessionTimeout1mアイドル状態のプロキシセッションがガベージコレクションされるまでのタイムアウトです。
McpServiceMgrConfig.McpServiceRetryCount3MCP サービスが failed と判定されるまでの最大再試行回数です。
ゲートウェイプロトコルの選択

config.json で GatewayProtocol を設定します。

{ "GatewayProtocol": "all" }

または、CLI フラグを渡します(こちらが優先されます)。

./mcp-gateway --protocol=streamhttp

有効な値:all(デフォルト)、sse、または streamhttp。

認証

Auth.Enabled が true の場合、すべての MCP プロトコルリクエストで Bearer トークンを提示する必要があります。

Authorization: Bearer <access-token>

ゲートウェイは、api_key、sessionId、Mcp-Session-Id、X-Session-Id を認証情報として扱わなくなりました。Mcp-Session-Id は引き続きトランスポートのセッション識別子であり、認証が必要な Streamable HTTP リクエストでは Bearer トークンと一緒に送信する必要があります。

MCP OAuth のディスカバリーでは、ゲートウェイは OAuth Protected Resource Metadata を公開します。

GET /.well-known/oauth-protected-resource
GET /.well-known/oauth-protected-resource/stream

OAuth ディスカバリーが利用可能な場合、認証されていない MCP リクエストは、WWW-Authenticate: Bearer ... resource_metadata="..." チャレンジとともに 401 を返します。認証なしでローカル開発を行う場合は、Auth.Enabled を false に設定してください。

Auth.Mode = "saas" で外部の Auth.AuthorizationServers を設定していない場合、ゲートウェイは MCP ログインに独自のアカウントシステムを使用します。ディスカバリーでは、ゲートウェイのオリジンが認可サーバーとして通知され、次のエンドポイントが公開されます。

GET /.well-known/oauth-authorization-server
POST /oauth/token
POST /oauth/register

/oauth/token は、フォームエンコードされた grant_type=password と username/password を受け付け、/api/v1/auth/login が使用するものと同じゲートウェイ JWT を返します。Keycloak、Auth0、またはその他の外部 OAuth プロバイダーを使用する場合にのみ、Auth.AuthorizationServers を設定してください。

ブラウザベースの MCP クライアントも、通知された認可エンドポイントを使用できます。

GET /oauth/authorize

組み込みの認可エンドポイントは、Gateway アカウントのログインフォームを表示し、PKCE を含む OAuth 認可コードフローを完了します。 /oauth/register は、MCP Inspector などのクライアント向けに、最小限の動的クライアント登録を実装しています。

API

デプロイ

対応:uvx、npx、または SSE URL

POST /deploy HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
    "mcpServers": {
        "time": {
            "url": "http://mcp-server:8080",  // url 和 command 二选一
            "command": "uvx",  // url 和 command 二选一
            "args": ["mcp-server-time", "--local-timezone=America/New_York"],  // 可选,command 的参数
            "env": {  // 可选,环境变量
                "KEY1": "VALUE1",
                "KEY2": "VALUE2"
            }
        }
    }
}
MCP を使用する(SSE モード)

GatewayProtocol が all(デフォルト)または sse の場合に利用できます。

GET SSE
GET /{mcp-server-name}/sse HTTP/1.1
Host: localhost:8080
POST メッセージ
POST /{mcp-server-name}/message HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
    "method": "tools/call",
    "params": {
        "name": "get_current_time",
        "arguments": {
            "timezone": "Asia/Seoul"
        }
    },
    "jsonrpc": "2.0",
    "id": 2
}
Gateway を使用する(SSE モード)

GatewayProtocol が all(デフォルト)または sse の場合に利用できます。

ゲートウェイと MCP への直接接続の違いは、ゲートウェイとのやり取りだけで済み、リクエストはゲートウェイによって対応する MCP サーバーに自動的に転送される点です。call 時には、リクエストがどの MCP サーバーからのものかを示すため、method の前に mcpServerName の内容を追加する必要があります。

GET SSE
GET /sse HTTP/1.1
Host: localhost:8080

ここでの SSE は、ゲートウェイ配下にあるすべての MCP サーバーの SSE ストリームです。

クライアントが SSE を購読すると、ゲートウェイは各 MCP サーバーへの SSE 接続を作成し、すべての MCP サーバーの SSE ストリームを統合します。

すべての tools/call の結果では、結果がどの MCP サーバーからのものかを示すため、method の前に mcpServerName の内容が追加されます。

POST メッセージ
POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
    "method": "tools/call",
    "params": {
        "name": "{mcp-server-name}-get_current_time",
        "arguments": {
            "timezone": "Asia/Seoul"
        }
    },
    "jsonrpc": "2.0",
    "id": 2
}

ゲートウェイ配下のすべてのツールを取得

POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json

{
    "method": "tools/list",
    "jsonrpc": "2.0",
    "id": 1
}

# SSE 响应 message event

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "{mcpServerName}-get_current_time",
        "description": "Get current time in a specific timezones",
        "inputSchema": {
          "type": "object",
          "properties": {
            "timezone": {
              "type": "string",
              "description": "IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no timezone provided by the user."
            }
          },
          "required": [
            "timezone"
          ]
        }
      },
      {
        "name": "{mcpServerName}-convert_time",
        "description": "Convert time between timezones",
        "inputSchema": {
          "type": "object",
          "properties": {
            "source_timezone": {
              "type": "string",
              "description": "Source IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no source timezone provided by the user."
            },
            "time": {
              "type": "string",
              "description": "Time to convert in 24-hour format (HH:MM)"
            },
            "target_timezone": {
              "type": "string",
              "description": "Target IANA timezone name (e.g., 'Asia/Tokyo', 'America/San_Francisco'). Use 'America/New_York' as local timezone if no target timezone provided by the user."
            }
          },
          "required": [
            "source_timezone",
            "time",
            "target_timezone"
          ]
        }
      }
    ]
  }
}
Gateway を使用する(Streamable HTTP モード)

GatewayProtocol が all(デフォルト)または streamhttp の場合に利用できます。

spec 2025-03-26 で定義されている MCP Streamable HTTP トランスポートを実装しています。ゲートウェイは、POST、GET、DELETE を受け付ける単一の集約エンドポイント /stream を公開します。セッション識別子は、HTTP ヘッダー Mcp-Session-Id で受け渡されます。

1. セッションを確立する(initialize)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "protocolVersion": "2025-03-26",
        "capabilities": {},
        "clientInfo": {"name": "my-client", "version": "1.0.0"}
    }
}

レスポンス:

HTTP/1.1 200 OK
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "protocolVersion": "2025-03-26",
        "serverInfo": {"name": "mcp-gateway", "version": "1.0.0"},
        "capabilities": { /* OR-merged from all downstream MCP servers */ },
        "instructions": "MCP Gateway aggregates multiple MCP servers. Tools are namespaced as <serverName>_<toolName>."
    }
}

返された Mcp-Session-Id を保持し、以降のすべてのリクエストで送信してください。

2. ハンドシェイクを完了する(通知)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0

{"jsonrpc": "2.0", "method": "notifications/initialized"}

レスポンス:202 Accepted(本文なし)。

3. ツールを呼び出す、またはリソースを一覧表示する
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0

{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
        "name": "{mcp-server-name}_get_current_time",
        "arguments": {"timezone": "Asia/Seoul"}
    }
}

集約されたツール名は <serverName>_<toolName> の形式です。SSE ゲートウェイモードと同じルールです。

レスポンスは HTTP レスポンス本文で同期的に返されます。

{"jsonrpc": "2.0", "id": 2, "result": { /* ... */ }}

通知(id のない JSON-RPC メッセージ)は 202 Accepted で応答され、非同期で転送されます。

4. サーバー起点のイベントを購読する(任意)
GET /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: text/event-stream
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0

ゲートウェイは接続を開いたままにし、サーバーからクライアントへの JSON-RPC リクエストおよび通知(進捗の更新やログメッセージなど)に対して event: message フレームを送信します。JSON-RPC レスポンスがここでプッシュされることはありません。これらは、元の POST /stream リクエストに対する HTTP レスポンスで返されます。

: で始まる行は SSE のキープアライブコメントであり、無視できます。

5. セッションを終了する
DELETE /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0

レスポンス:200 OK。

単一サーバーへのパススルー

Streamable HTTP モードでは、個々の MCP サーバーに直接アクセスすることもできます。

POST /{mcp-server-name} HTTP/1.1
GET  /{mcp-server-name} HTTP/1.1

ゲートウェイはリクエストを対象の MCP の message エンドポイントに転送します。このモードでのセッション管理は、下流サーバーの責任です。

MCP Inspector での接続
  1. Inspector で トランスポートタイプ に Streamable HTTP を選択します。
  2. URL:http://localhost:8080/stream。
  3. 認可サーバーで OAuth フローを完了し、Authorization: Bearer <access-token> を指定します。
  4. Connect をクリックします。Inspector が Mcp-Session-Id の交換を自動的に処理します。

コメント

MCP は初めてですか?

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

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