キーワードを入力して検索

📝

MCPサーバーにHTTPモードを追加してVPSから使えるようにした実装記録

齊木祐介 齊木祐介 994 views

背景

⚠️ 本記事のコードはサンプルです。実際の認証情報・設定値は含まれていません。

自作のMCPサーバー @claudecodenavi/mcp はClaude Code向けにstdio専用で動いていた。しかしVPS上のAIシステム(AI社長)からも同じツールを使いたくなった。

選択肢は2つあった:

  • VPS側に独自のツール実装を作る(重複管理が発生)
  • npm版にHTTPモードを追加して、VPSにインストールして使う

2を選択。 コードが一箇所で管理され、一般ユーザーもHTTPモードが使える。

実装内容

server.jsのリファクタリング

Before(v1.0.2):

  • グローバルなserver変数にツール定義とハンドラーを直接設定
  • StdioServerTransportのみ

After(v1.1.0):

  • ツール定義をTOOLS配列に分離
  • ハンドラーをhandleToolCall()関数に分離
  • createMcpServer()ファクトリーで複数インスタンス生成可能に
  • --httpフラグでHTTPモード起動
// 起動モード
const HTTP_MODE = process.argv.includes('--http');

// メイン
if (HTTP_MODE) {
  startHttpMode().catch(console.error);
} else {
  startStdioMode().catch(console.error);
}

HTTPモードのエンドポイント

| エンドポイント | 用途 |
|---|---|
| POST /mcp | StreamableHTTP(MCP公式プロトコル) |
| POST /api/tool | REST API直接呼び出し |
| GET /api/tools | ツール一覧取得 |
| GET /health | ヘルスチェック |

Bearer token認証はMCP_AUTH_TOKEN環境変数で設定。

package.jsonの変更

{
  "version": "1.1.0",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.9.0",
    "express": "^4.21.0",
    "cors": "^2.8.5"
  }
}

SDK ^0.5.0 → ^1.9.0(StreamableHTTPServerTransport対応のため)。express/corsはHTTPモード時のみ動的importされるので、stdioモードでは読み込まれない。

VPS側の構成

複数MCPサーバーのルーティング

AI社長(ai-router.php)は複数のMCPサーバーからツールを集約して使う。

config/mcp-tools.phpを改修して、複数サーバーからツール定義を取得し、ツール名→サーバーのルーティングマップを自動構築するようにした。

$servers = [
    'mothership' => [
        'endpoint' => 'http://127.0.0.1:3002/api/tool',
        'tools_url' => 'http://127.0.0.1:3002/api/tools',
    ],
    'claudecodenavi' => [
        'endpoint' => 'http://127.0.0.1:3003/api/tool',
        'tools_url' => 'http://127.0.0.1:3003/api/tools',
    ],
];

ai-router.phpのcallMcpTool()がツール名からルーティング先を自動解決:

private function callMcpTool(string $toolName, array $args): mixed {
    $routing = $this->mcpConfig['tool_routing'] ?? [];
    $serverKey = $routing[$toolName] ?? 'mothership';
    $server = $this->mcpConfig['servers'][$serverKey] ?? null;
    $endpoint = $server['endpoint'] ?? ...;
    // ...
}

これによりcreate_postはclaudecodenavi(3003)へ、pod_listはmothership(3002)へ自動ルーティングされる。

結果

| サーバー | ポート | ツール数 |
|---|---|---|
| mcp-mothership | 3002 | 69 |
| @claudecodenavi/mcp | 3003 | 33 |
| 合計 | | 102 |

後方互換の確認

SDK v0.5.0 → v1.9.0でstdioのプロトコル(JSON-RPC改行区切り)は変わっていない。実際にパイプでメッセージを流して確認:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize",...}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | node server.js

→ initialize正常応答 + 33ツール全て返却。一般ユーザーのstdioモードに影響なし、ダウンタイム0秒。

まとめ

  • npm版MCPサーバーにHTTPモードを追加するパターンは汎用的に使える
  • --httpフラグで切り替えるだけなので、一般ユーザーのstdioモードに一切影響しない
  • PHP側のルーティング基盤を作ったことで、今後新しいMCPサーバーを追加する際も$servers配列に1エントリ追加するだけ
  • express/corsはHTTPモード時のみ動的importなので、stdioモードのメモリフットプリントは増えない
齊木祐介

Discussion

0
または

8文字以上で入力してください

または

パスワードをリセット

登録したメールアドレスを入力してください。パスワードリセット用のリンクをお送りします。