Skip to main content
Glama

gpu-broker-mcp

AIエージェント向けにGPUコンピュートアクセスを仲介するステートレスMCPサーバー。エージェントは4つのMCPツールを通じて、ノードの検出、容量の予約、推論のディスパッチ、結果のポーリングを行います。SSHキー、ノードIP、プロバイダーAPIを直接管理する必要はありません。

SDK: mcp==2.0.0(Python SDK v2、mcp.server.MCPServer) 対象仕様: MCP仕様リビジョン2026-07-28 トランスポート: Streamable HTTP、ステートレスモード(stateless_http=True、json_response=True)。セッションなし、Mcp-Session-Idなし、スティッキールーティングなし。

アーキテクチャ

┌─────────────────────────────────────────────────────────────┐
│  Agent (MCP client)                                         │
│  Calls: list_nodes → reserve_node → dispatch_inference      │
│         → get_result (poll)                                 │
└────────────────────────┬────────────────────────────────────┘
                         │ JSON-RPC over Streamable HTTP
                         │ (stateless, any replica)
┌────────────────────────▼────────────────────────────────────┐
│  gpu-broker-mcp server                                      │
│                                                             │
│  ┌──────────────────┐  ┌──────────────────┐                 │
│  │ HMAC-SHA256       │  │ NodePool ABC     │                 │
│  │ Handle signing    │  │  ├ FakeNodePool   │                │
│  │ & validation      │  │  └ VastNodePool   │                │
│  └──────────────────┘  └──────────────────┘                 │
│                                                             │
│  ┌──────────────────┐  ┌──────────────────┐                 │
│  │ Error taxonomy    │  │ JobStore ABC     │                 │
│  │ (single enum,     │  │  └ InMemoryStore  │                │
│  │  structured JSON) │  │    (per-replica)  │                │
│  └──────────────────┘  └──────────────────┘                 │
└────────────────────────┬────────────────────────────────────┘
                         │ SSH (VastNodePool only)
┌────────────────────────▼────────────────────────────────────┐
│  GPU node (e.g. Vast.ai RTX 3090)                           │
│  Runs inference workload, returns stdout                    │
└─────────────────────────────────────────────────────────────┘

ブローカーはローカルで実行されます。GPUノードのクライアントであり、ノード上に常駐するわけではありません。CPUバウンドのHMAC署名とJSONシリアライゼーションを行うだけで、GPUの恩恵を受ける処理はありません。

Related MCP server: vibedonate

セッションではなく署名付きハンドルを採用する理由

予約状態はハンドル自体の中に格納されます。base64エンコードされたJSONペイロード(ノードID、有効期限、スコープ)と、そのHMAC-SHA256署名を連結したものです。シークレットはGPU_BROKER_SECRETから取得され、未設定の場合はサーバーは起動を拒否します。

つまり、シークレットを共有する任意のレプリカが、自分が発行していないハンドルを検証できます。セッションテーブルはなく、Mcp-Session-Idヘッダーもなく、スティッキールーティングの要件もありません。ロードバランサーは任意のリクエストを任意のレプリカにルーティングできます。ハンドルにはスコープ(reserveとtask)があるため、予約ハンドルをタスクIDとして再生することはできず、その逆も同様です。誤用するとHANDLE_SCOPE_INVALIDが返されます。

インメモリのJobStoreがレプリカ間で失うのはジョブステータスの参照のみです。レプリカBは、レプリカAにディスパッチされたジョブのステータスを伝えることはできません。これはステートレス設計の欠陥ではなく、共有バックエンド(Redis、Postgres)の要件です。署名検証(セキュリティ上重要な部分)は完全に移植可能です。

ツール

ツール

パラメータ

戻り値

list_nodes

—

利用可能なノードのJSON配列(id、model、vram、price、load)

reserve_node

node_id、ttl_seconds

署名付き予約ハンドル

dispatch_inference

handle、payload

{"task_id": "...", "status": "pending"}

get_result

task_id

{"status": "pending|completed|failed", "output": ..., "error": ...}

ツールのシグネチャはバックエンド間で安定しています。FakeNodePoolをVastNodePoolに交換しても、クライアントから見えるインターフェースは変わりません。

キャッシュに関する注意

list_nodesはツール結果にmeta.ttlMsとmeta.cacheScopeを返します。これはローカルな規約です。SEP-2549はtools/listとresources/listのレスポンスを規定するものであり、個々のtools/callの結果を規定するものではありません。これを認識するクライアントはキャッシュでき、認識しないクライアントは単に再呼び出しします。

ルーティングヘッダー

サーバーはゲートウェイルーティング用にMcp-MethodおよびMcp-Nameヘッダーを出力しますが、サーバー側では強制しません。強制ポイントはエッジ(APIゲートウェイ、リバースプロキシ)であり、ブローカー自体ではありません。

エラー分類

すべてのツールエラーは、code、message、retryable、およびオプションのretry_after_secondsを含む構造化JSONを返します。エージェントはmessageではなくcodeで分岐すべきです。messageは人間が読むための診断情報であり、変更される可能性があります。

コード

再試行可能

発生条件

NVML_VERSION_MISMATCH

いいえ

NVIDIA管理ライブラリのバージョンがGPUホストのドライバと一致しない

DRIVER_LIBRARY_MISMATCH

いいえ

GPUホスト上のCUDAドライバ/ライブラリのバージョン競合

DPKG_LOCK_CONTENTION

はい

GPUホスト上で別のプロセスがパッケージマネージャのロックを保持している(例: unattended-upgrades)

DOCKER_SOCKET_PERMISSION_DENIED

いいえ

GPUホスト上でコンテナランタイムソケットにアクセスできない

INSUFFICIENT_VRAM

いいえ

要求されたワークロードに対してGPUメモリが不足している

NODE_UNREACHABLE

はい

GPUノードに接続できない(SSHタイムアウト、接続拒否、DNS失敗)

RESERVATION_EXPIRED

いいえ

署名付きハンドルのTTLが経過した

HANDLE_SIGNATURE_INVALID

いいえ

HMAC署名が一致しない — 改ざん、誤ったシークレット、または不正なハンドル

HANDLE_SCOPE_INVALID

いいえ

ハンドルのスコープ不一致(例: 予約ハンドルが期待される場所にタスクハンドルを渡した)

TLS_PROXY_FAILURE

はい

ブローカーとノード間のTLS終端またはプロキシ層の障害

JOB_NOT_FOUND

いいえ

署名は有効だが、このレプリカのストアにジョブが存在しない(レプリカ間でのインメモリストアで想定される)

ホストレベルのエラー(NVML_VERSION_MISMATCHからDOCKER_SOCKET_PERMISSION_DENIEDまで)は、vast.py:_raise_from_stderr内のSSH stderr文字列からマッピングされます。パターンはVast.ai GPUホストの既知の障害モードに基づいていますが、実際に取得した本番環境の文字列に対してはまだ検証されていません。タスク3では、エラー出力をそのまま取得し、マッチングパターンを改良します。

クイックスタート

フェイクモード(GPUなし、APIキーなし)

export GPU_BROKER_SECRET="any-secret-string"
python src/gpu_broker/server.py
# Server at http://127.0.0.1:8000/mcp

Vast.aiモード(実GPU)

export GPU_BROKER_SECRET="any-secret-string"
export VASTAI_API_KEY="your-vast-api-key"

# Find and rent a node
python vast_manage.py search --gpu "RTX 3090" --max-price 0.30
python vast_manage.py rent <offer_id>
python vast_manage.py wait <instance_id>

# Start the broker (auto-detects VASTAI_API_KEY)
python src/gpu_broker/server.py

# When done
python vast_manage.py destroy <instance_id>

テストの実行

uv run pytest tests/ -v

テストには以下が含まれます:

  • ハンドルのラウンドトリップ(reserve → dispatch → get_result)

  • 改ざんされた署名の拒否

  • 期限切れハンドルの拒否

  • スコープ不一致の拒否

  • レプリカ間参照でのJOB_NOT_FOUND

  • サブプロセスのステートレス性テスト: 3つの実HTTPサーバーを起動し(AとBはシークレットを共有、Cは別のシークレット)、Aからタスクを発行し、Aがpendingを返し、BがJOB_NOT_FOUNDを返し、CがHANDLE_SIGNATURE_INVALIDを返すことを確認

  • シークレット未設定時の起動拒否

  • すべてのエラーバリアントのシリアライゼーションラウンドトリップ

現在のスコープと制限事項

これは実動プロトタイプであり、本番システムではありません。

  • FakeNodePoolは3つのノードの静的リストを返し、実際の推論はディスパッチしません。ツールの相互作用とハンドルの仕組みをテストするのに役立ちます。

  • VastNodePoolはVast.ai APIにクエリして実行中のインスタンスを取得し、SSH経由で推論をディスパッチします。実際の処理を行いますが、コネクションプーリング、再試行ロジック、システムデフォルト以外のSSHキー管理はありません。

  • InMemoryJobStoreは再起動時にすべての状態を失い、レプリカ間でジョブステータスを共有できません。本番デプロイには共有バックエンド(Redis、Postgres)が必要です。

  • ホストレベルの障害に対するエラー分類パターンは、既知の障害モードに基づく推定です。GPUホストから実際に取得したstderrに対して検証する必要があります。

  • MCPエンドポイント自体に認証はありません。HTTPポートに到達できるクライアントは誰でもツールを呼び出せます。本番環境では前面に認証レイヤーが必要です。

  • レート制限、リクエストサイズ制限、監査ログはありません。

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers