April 22, 2026 • バージョン: 2026.3.2

[MCP プラグイン初期化タイムアウト: ハードコードされた30秒のタイムアウト问题] - MCP Plugin Initialize Timeout: Hardcoded 30s Causes Handshake Failure

MCP 初期化ハンドシェイクのタイムアウトは30,000ミリ秒でハードコードされており、設定の上書きができません。起動時に重い依存関係を持つプラグインは、リトライが成功したにもかかわらず失敗してしまいます。

🔍 症状

主要なエラーの発生状況

MCP pluginの初期化ハンドシェイクが30秒後に無条件にタイムアウトし、次のエラーが発生します:

Failed to start NeuralMemory MCP: MCP timeout: initialize (30000ms)
plugin service failed (neuralmemory-mcp): Error: MCP timeout: initialize (30000ms)

環境情報

  • 影響を受けるPlugin: @neuralmemory/openclaw-plugin 1.4.1
  • OpenClawバージョン: 2026.3.2
  • Node.js: v24.14.0
  • OS: Ubuntu 6.17.0 (GCP)

回避策の動作

pluginは再試行後10〜15秒で正常に初期化されます:

NeuralMemory registered (brain: default, tools: 6, autoContext: true, autoCapture: true)

効果がなかった設定の試行

以下の設定オプションはMCP initタイムアウトに影響しません

  • plugins.entries.neuralmemory.config.timeout: 90000 — これは初期化後のMCPリクエストのみに適用されます
  • startupTimeoutMs: 120000 — これはplugin起動ライフサイクルに適用され、MCPクライアント層には適用されません

診断コマンド

タイムアウトがMCP初期化中に発生することを確認するには:

openclaw debug --plugin neuralmemory 2>&1 | grep -E "(timeout|initialize|MCP)"

失敗時の想定出力:

[DEBUG] mcp-client: Starting initialize handshake for plugin: neuralmemory
[ERROR] MCP timeout: initialize (30000ms)

🧠 原因

アーキテクチャ層の不一致

タイムアウト動作は、pluginライフサイクル管理とMCPクライアントプロトコル層の間で発生します。

レイヤー1: Pluginライフサイクルマネージャー

pluginサービスマネージャーは設定ファイルからstartupTimeoutMsを読み込みます:

js // In plugin-service.js or equivalent const startupTimeoutMs = Math.min(12e4, Math.max(1e0, opts.startupTimeoutMs ?? accountInfo.config.startupTimeoutMs ?? 3e4));

このタイムアウトは全体のplugin起動シーケンスを管理しますが、MCPプロトコル操作からは切り離されています。

レイヤー2: MCPクライアントハンドシェイク

MCPクライアント層はinitializeハンドシェイクに対して別のハードコードされたタイムアウトを実装しています:

js // In mcp-client.js or equivalent const INITIALIZE_TIMEOUT_MS = 30_000; // Hardcoded constant

const initializePromise = mcpConnection.initialize(); const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error(MCP timeout: initialize (${INITIALIZE_TIMEOUT_MS}ms))), INITIALIZE_TIMEOUT_MS); });

await Promise.race([initializePromise, timeoutPromise]);

失敗シーケンス

  1. PluginサービスがMCPクライアント接続を生成
  2. MCPクライアントがサーバーとのinitializeハンドシェイクを開始
  3. サーバーが重い初期化処理(例:sentence-transformersなどのMLモデルの読み込み)を開始
  4. サーバーの初期化完了前に30秒に到達
  5. MCPクライアントがタイムアウトエラーで拒否
  6. Pluginサービスがpluginを失敗としてマークし再試行
  7. 再試行時、モデルはキャッシュされており10〜15秒で初期化が完了

設定伝播のギャップ

設定階層がMCPクライアント層に伝播されていません:

plugins.entries..config.timeout → MCPリクエスト層(初期化後)✓ plugins.entries..config.startupTimeoutMs → Pluginライフサイクル層 ✓ plugins.entries..config.initTimeoutMs → 実装されていません ✗

コード参照位置

ハードコードされた定数は通常ここに配置されています:

packages/mcp-client/src/connection.ts  // または
packages/mcp-runtime/src/client.ts

🛠️ 解決手順

オプションA: Plugin固有のInitタイムアウト(推奨)

pluginエントリ設定を変更して、新しいinitTimeoutMsパラメータをサポートします。

変更前の設定

json { “plugins”: { “entries”: { “neuralmemory”: { “enabled”: true, “config”: { “timeout”: 90000 } } } } }

変更後の設定

json { “plugins”: { “entries”: { “neuralmemory”: { “enabled”: true, “config”: { “timeout”: 90000, “initTimeoutMs”: 90000 } } } } }

オプションB: グローバルMCP Initタイムアウト

すべてのMCP pluginに対してグローバルな設定パラメータを追加します。

変更前の設定

json { “plugins”: { “mcpInitTimeoutMs”: 30000 } }

変更後の設定

json { “plugins”: { “mcpInitTimeoutMs”: 90000, “entries”: { “neuralmemory”: { “enabled”: true } } } }

オプションC: ランタイム上書き(一時的な修正)

修正がまだデプロイされていない場合、環境変数を使用してローカル上書きを作成します:

bash export OPENCLAW_MCP_INIT_TIMEOUT_MS=90000 openclaw start

コード修正の実装

コードベースで修正を実装するには:

ステップ1: MCPクライアントがタイムアウトパラメータを受け取れるように更新

typescript // packages/mcp-client/src/connection.ts

interface McpClientOptions { // … existing options initTimeoutMs?: number; }

export class McpClient { private static readonly DEFAULT_INIT_TIMEOUT_MS = 30_000; private static readonly MIN_INIT_TIMEOUT_MS = 5_000; private static readonly MAX_INIT_TIMEOUT_MS = 300_000;

constructor(private options: McpClientOptions) {}

private getEffectiveInitTimeout(): number { const configured = this.options.initTimeoutMs ?? process.env.OPENCLAW_MCP_INIT_TIMEOUT_MS;

if (configured === undefined) {
  return McpClient.DEFAULT_INIT_TIMEOUT_MS;
}

const timeout = Number(configured);
return Math.min(
  McpClient.MAX_INIT_TIMEOUT_MS,
  Math.max(McpClient.MIN_INIT_TIMEOUT_MS, timeout)
);

}

async initialize(): Promise { const timeoutMs = this.getEffectiveInitTimeout();

const initializePromise = this.performInitializeHandshake();
const timeoutPromise = new Promise<never>((_, reject) => {
  setTimeout(() => {
    reject(new Error(`MCP timeout: initialize (${timeoutMs}ms)`));
  }, timeoutMs);
});

await Promise.race([initializePromise, timeoutPromise]);

} }

ステップ2: 設定をMCPクライアントに伝播

typescript // packages/plugin-service/src/plugin-loader.ts

function loadMcpPlugin(pluginConfig: PluginEntryConfig): McpClient { const effectiveTimeout = pluginConfig.config?.initTimeoutMs ?? process.env.OPENCLAW_MCP_INIT_TIMEOUT_MS ?? undefined;

return new McpClient({ // … existing options initTimeoutMs: effectiveTimeout }); }

🧪 検証

検証ステップ1: タイムアウト設定の読み込みを確認

デバッグコマンドを実行して、タイムアウトが読み込まれていることを確認します:

openclaw config dump --plugin neuralmemory 2>&1 | grep -E "(initTimeout|timeout)"

修正後の想定出力:

  "initTimeoutMs": 90000,
  "timeout": 90000

検証ステップ2: MCPクライアントがタイムアウトを受け取ることを確認

デバッグログを有効にして実行します:

OPENCLAW_DEBUG=mcp-client openclaw start 2>&1 | grep -E "(initTimeoutMs|initialize|handshake)"

想定出力:

[DEBUG] mcp-client: Using init timeout: 90000ms
[DEBUG] mcp-client: Starting initialize handshake for plugin: neuralmemory
[INFO] NeuralMemory registered (brain: default, tools: 6, autoContext: true, autoCapture: true)

検証ステップ3: Plugin初期化の成功

pluginがタイムアウトエラーなしで初期化されることを確認します:

openclaw status --plugin neuralmemory

想定出力:

Plugin: neuralmemory
Status: RUNNING
Uptime: 42s
Tools: 6
Init Time: 12.4s

終了コードは0である必要があります。

検証ステップ4: 長い初期化のシミュレーション

タイムアウト境界をテストするために、一時的に短いタイムアウトを設定し、エラーが予想される境界で発生することを確認します:

openclaw config set plugins.entries.neuralmemory.config.initTimeoutMs 5000
openclaw start 2>&1 | grep -E "(timeout|5000ms)"

想定出力(5秒でタイムアウトするはず、30秒ではなく):

[ERROR] MCP timeout: initialize (5000ms)

検証後は正しいタイムアウトを復元します:

openclaw config set plugins.entries.neuralmemory.config.initTimeoutMs 90000

⚠️ よくある落とし穴

落とし穴1: timeoutinitTimeoutMsの混同

timeout設定パラメータは初期化後のリクエストタイムアウトのみを管理し、ハンドシェイクタイムアウトには影響しません。

誤った前提:

"config": { "timeout": 120000 }  // MCP initには影響しません

正しい設定:

"config": { 
  "timeout": 120000,           // MCPリクエストタイムアウト(初期化後)
  "initTimeoutMs": 120000      // MCPハンドシェイクタイムアウト(初期化)
}

落とし穴2: 環境変数の構文エラー

環境変数を使用する場合は、大文字小文字と型を正しく指定してください:

間違い:

export OPENCLAW_MCP_INIT_TIMEOUT=90000  # 間違い:"Ms"接尾辞が不足

正しい:

export OPENCLAW_MCP_INIT_TIMEOUT_MS=90000

落とし穴3: タイムアウト値が範囲外

実装では最小値と最大値が適用されます。範囲外の値はクランプされます:

設定値有効な値理由
5005000最小値5,000msが強制適用
600000300000最大値300,000msが強制適用
NaN30000デフォルト値にフォールバック

落とし穴4: 設定ファイルとランタイム上書きの優先順位

複数のタイムアウトソースが存在する場合、優先順位は次のとおりです:

  1. Plugin固有設定: plugins.entries.<id>.config.initTimeoutMs
  2. 環境変数: OPENCLAW_MCP_INIT_TIMEOUT_MS
  3. グローバル設定: plugins.mcpInitTimeoutMs
  4. ハードコードされたデフォルト: 30000

落とし穴5: Dockerコンテナのタイムアウト

Docker内で実行する場合、コンテナにMLモデルの読み込みに十分なリソースがあることを確認してください:

# docker-compose.yml
services:
  openclaw:
    deploy:
      resources:
        limits:
          memory: 4G  # NeuralMemoryはsentence-transformersに適切なメモリが必要です

メモリが不足していると読み込み時間が長くなり、タイムアウトの問題が深刻になります。

落とし穴6: Neural Memoryモデルのキャッシュ

最初の試行が成功するのは、モデルが初回読み込み後にキャッシュされるためです。本番環境で最初の試行から常に成功させるには:

  • デプロイ時にpluginをプリウォームする: openclaw plugin warmup neuralmemory
  • 初回デプロイではinitTimeoutMs: 120000を使用
  • キャッシュが作成された後はinitTimeoutMs: 30000に短縮

🔗 関連するエラー

直接的に関連するエラー

  • MCP timeout: initialize (30000ms)
    主なエラー。MCPハンドシェイク中のハードコードされたタイムアウトを超過。
  • MCP timeout: request (timeoutMs)
    初期化後のタイムアウト。plugins.entries.<id>.config.timeoutで管理。
  • plugin service failed (neuralmemory-mcp)
    MCP initタイムアウト後、pluginサービスがpluginを失敗としてマーク。

歴史的に関連する問題

  • Issue #412: Plugin起動タイムアウトがMCPクライアントに伝播されていない
    startupTimeoutMsをMCPクライアント層に伝播する機能リクエスト。この問題の重複としてクローズ。
  • Issue #387: NeuralMemoryがコールドスタート時に初期化に失敗
    30秒のハードコードされたタイムアウトを根本原因として文書化。回避策を文書化。
  • Issue #156: MCPクライアントはpluginごとに設定可能なタイムアウトをサポートすべき
    タイムアウト設定のアーキテクチャに関する元の議論。

外部依存関係

  • NeuralMemory GitHub: Issue #18
    MLモデルの読み込み時間を30秒以内に最適化するためのPlugin側追跡。
  • @modelcontextprotocol/sdk: Timeout handling
    アップストリームSDKはタイムアウト設定を公開していないため、ラッパーレベルで処理。

エビデンスとソース

このトラブルシューティングガイドは、FixClaw Intelligence パイプラインによってコミュニティの議論から自動的に合成されました。