Skip to content

McpHub:MCP サーバーライフサイクル管理

源码版本v4.0.10

役割

McpHub は Cline が外部 MCP (Model Context Protocol) サーバーを接続するための中央ハブ (McpHub) である。cline_mcp_settings.json に設定されたすべてのサーバーを読み込み、各サーバーに対して独立した client + transport 接続を確立し、公開されたツール (tool)、リソース (resource)、プロンプト (prompt) をメモリにキャッシュして主 agent が呼べるようにする。MCP ツールチェーン全体——設定変更、ファイル監視、接続/再接続、能力発見、tools/call 呼び出しまで——をこの 1 つのクラスに集約し、主 Task は MCP SDK を直接触る必要がない。

位置としては「主 agent loop」と「具体的 MCP プロトコル」の中間にある。Task が MCP ツールを呼ぶ時、McpHub.callTool (callTool:1233) を経由する。UI が現在のサーバーリストを見たい時は getServers() でソート済みスナップショットを取る (getServers:112)。Extension インスタンス内に McpHub は 1 つだけだが、connections: McpConnection[] 配列内の各エントリは独立 transport で、1 つ落ちても他へ影響しない。

設計動機

  • サーバーごとに 1 つの client:異なる MCP サーバーは異なる capabilities、異なる設定、異なるエラー処理を持つ。独立 client により再接続とスコープ分離がシンプルになる (per-server client:363)。
  • 3 種 transport の統一:stdio はローカルプロセス、sse は Server-Sent Events、streamableHttp は新版 HTTP ストリーム。connectToServerswitch で振り分ける (transport switch:382)。
  • ファイル監視 + 内部更新のデュアルチャネル:watchMcpSettingsFile は外部エディタによる設定変更を監視し、isUpdatingClineSettings は内部自身が書き込む際に発火をスキップ (isUpdatingClineSettings:76)。ループを防ぐため。
  • OAuth は遅延ロード:sse/streamableHttp のみ McpOAuthManager に authProvider を要求し、stdio は対象外 (authProvider setup:377)。
  • 企業ポリシーを接続前に前置:企業デプロイでは marketplace を無効化したりホワイトリストを設定したりでき、stdio 接続前に弾く (enterprise allowlist:310)。
  • UID でツール名を短縮:各サーバーに c + nanoid(5) の短い uid を割り当て、MCP ツール名が長文字列になるのを回避 (getMcpServerKey:130)。

主要ファイル

  • McpHub class:51 — シングルトンクラス。connections、ファイル監視、OAuth manager、通知コールバックを保持。
  • constructor:108 — 起動時に即座に watchMcpSettingsFile + initializeMcpServers を実行。
  • watchMcpSettingsFile:213 — chokidar で設定ファイル変更を監視し、diff から追加/削除/変更を検出して再接続。
  • connectToServer:286 — 中核接続メソッド。検証、transport 選択、client 構築、能力発見。
  • transport switch:382 — stdio / sse / streamableHttp の 3 分岐。
  • stdio stderr pipe:415 — stdio サーバーは stderr を引き出して info/error ログストリームにする。
  • fetchToolsList:677tools/list を送信し、各 tool に autoApprove マークを付ける。
  • fetchResourcesList:713resources/list を送信。disabled サーバーは空を返す。
  • notification handler:611notifications/message コールバックを登録し、サーバーログを現在の Task または一時保留に流す。
  • deleteConnection:784 — transport と client を閉じ、connections からフィルタ除去。
  • restartConnection:1047 — サーバーを再接続。500ms の意図的遅延で UI が「connecting」状態を表示できるようにする。
  • callTool:1233tools/call を送信。サーバー設定からタイムアウトを取り、全程に telemetry を埋め込む。

データフロー

connectToServer に入ったらまず 3 つを行う。企業ポリシーの検証、disabled プレースホルダーまたは実 client の構築、transport 選択である。transport 選択後 McpConnection を作って配列に追加し、client.connect(transport) で実際にハンドシェイクする。ハンドシェイク成功後に通知コールバックを登録し、4 つの能力リストを取得する:

typescript
// apps/vscode/src/services/mcp/McpHub.ts
connection.server.status = "connected"
connection.server.error = ""

// Register notification handler for real-time messages
try {
  // ...
  connection.client.setNotificationHandler(NotificationMessageSchema as any, async (notification: any) => {
    // ...
    if (this.notificationCallback) {
      this.notificationCallback(name, level, message)
    } else {
      this.pendingNotifications.push({ serverName: name, level, message, timestamp: Date.now() })
    }
  })
} catch (error) {
  Logger.error(`[MCP Debug] Error setting notification handlers for ${name}:`, error)
}

// Initial fetch of tools, resources, and prompts
connection.server.tools = await this.fetchToolsList(name)
connection.server.resources = await this.fetchResourcesList(name)
connection.server.resourceTemplates = await this.fetchResourceTemplatesList(name)
connection.server.prompts = await this.fetchPromptsList(name)

この処理は post-connect setup:584 付近にある。接続確立後、外部からのツール呼び出しはすべて callTool を経由する——接続を探し、config.timeout でタイムアウトを算出し、tools/call を送信 (tools/call request:1270)。リソース読み取りも同様で、resources/read を経由する (resources/read:1183)。

境界と失敗

  • OAuth 未設定時は即フォールバック:client.connectUnauthorizedError を投げた時、エラーにせず connection を oauthRequired: true とマークし、ユーザーがフロントエンドで認可するのを待つ (UnauthorizedError branch:556)。
  • disabled サーバーはプレースホルダーのみで接続しない:disabled 設定は UI 表示のため connections 配列に入るが、client/transport はどちらも null (disabled placeholder:339)。
  • stdio stderr の分類:stderr に error という文字が現れたら error、それ以外は info log として扱う (stderr classification:420)。
  • streamableHttp 404 は 405 扱い:多くのサーバーが SSE 非サポート時に返すべき 405 を誤って 404 で返す。fetch 層で 404 を 405 に正規化し SDK に受け入れさせる (404 to 405:499)。
  • SSE token の動的リフレッシュ:sse 分岐はカスタム fetch で毎回 authProvider.tokens() を取り直す。さもなくば token 期限切れ後に再接続でずっと 401 になる (dynamic token fetch:459)。
  • streamableHttp の再接続は handler に委譲:StreamableHttpReconnectHandlerconnectToServer クロージャを受け取り、自前で再接続タイミングを決める (reconnect handler:519)。
  • 通知の一時保留:アクティブな Task がない時、サーバーからの notification は一旦 pendingNotifications に貯め、次の Task が立った時に取り出す (pendingNotifications:631)。

まとめ

McpHub は MCP プロトコルの詳細をすべて内部に収め、主 agent には callTool/readResource/getServers の 3 つの口を露出する。これがどうツールレイヤーに包まれて use_mcp_tool になるかは cap-tools/use-mcp-tool、subagent がどう独自のコンテキストウィンドウを隔離するかは subagent、主 Task がどう MCP サーバーリストをシステムプロンプトに詰め込むかは agent-loop/task-class を参照のこと。

公式資料: Cline 文档 · README