auto_recover
Automatically recover npm-dev-mcp server by performing health checks, executing recovery steps, and verifying restoration.
Instructions
MCPサーバーの自動復旧を実行(ヘルスチェック→復旧→再検証)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| maxRetries | No | 最大復旧試行回数(デフォルト: 3) | |
| forceRecover | No | 強制復旧モード(デフォルト: false) | |
| restartMcp | No | MCPサーバー自体の再起動を含むか(デフォルト: false) |
Implementation Reference
- src/tools/autoRecover.ts:51-227 (handler)Main handler function for the auto_recover tool. Orchestrates multi-step recovery: health check, process recovery, state recovery, post-recovery verification with retries.export async function autoRecover(args: { maxRetries?: number; forceRecover?: boolean; restartMcp?: boolean; } = {}): Promise<string> { const logger = Logger.getInstance(); const healthChecker = HealthChecker.getInstance(); const processManager = ProcessManager.getInstance(); const stateManager = StateManager.getInstance(); const maxRetries = args.maxRetries || 3; const forceRecover = args.forceRecover || false; const restartMcp = args.restartMcp || false; let attempts = 0; const warnings: string[] = []; const steps = { healthCheck: false, processRecovery: false, stateRecovery: false, mcpRestart: false }; try { logger.info('Starting auto recovery process', { maxRetries, forceRecover, restartMcp }); while (attempts < maxRetries) { attempts++; logger.info(`Recovery attempt ${attempts}/${maxRetries}`); // Step 1: ヘルスチェック try { const healthStatus = await healthChecker.performHealthCheck(); steps.healthCheck = true; if (healthStatus.isHealthy) { logger.info('System is healthy, no recovery needed'); return JSON.stringify({ success: true, message: 'システムは正常状態です。復旧は不要でした。', steps, attempts, finalHealth: healthStatus, warnings, timestamp: new Date().toISOString() } as AutoRecoveryResult); } logger.warn('System unhealthy, proceeding with recovery', { devServerStatus: healthStatus.devServerStatus, checks: healthStatus.checks }); } catch (error) { logger.error('Health check failed', { error }); warnings.push(`ヘルスチェック失敗: ${error}`); } // Step 2: プロセス復旧 try { const activeProcesses = await processManager.getStatus(); const noRunningProcesses = activeProcesses.every(p => p.status !== 'running'); if (noRunningProcesses) { logger.info('Attempting process recovery'); // 状態から復旧を試行 const recoveryResult = await recoverFromState({ force: forceRecover }); const result = JSON.parse(recoveryResult); if (result.success) { steps.processRecovery = true; logger.info('Process recovery successful'); } else { warnings.push(`プロセス復旧失敗: ${result.message}`); // 復旧に失敗した場合は新しいプロセスを開始 try { // Start a default one if none exist? Or just skip? // Maybe start in CWD as fallback await processManager.startDevServer(); steps.processRecovery = true; logger.info('Started new dev server process'); } catch (startError) { warnings.push(`新プロセス開始失敗: ${startError}`); } } } else { steps.processRecovery = true; logger.info('At least one process is already running'); } } catch (error) { logger.error('Process recovery failed', { error }); warnings.push(`プロセス復旧エラー: ${error}`); } // Step 3: 状態復旧 try { await stateManager.ensureStateConsistency(); steps.stateRecovery = true; logger.info('State recovery completed'); } catch (error) { logger.error('State recovery failed', { error }); warnings.push(`状態復旧エラー: ${error}`); } // Step 4: MCPサーバー再起動(要求された場合) if (restartMcp && attempts === maxRetries) { try { logger.warn('Attempting MCP server restart as last resort'); // 注意: 実際のMCPサーバー再起動は外部プロセス管理が必要 // PM2やsystemdなどでの管理が前提 warnings.push('MCPサーバー再起動が要求されましたが、外部管理ツールでの実行が必要です'); steps.mcpRestart = true; } catch (error) { logger.error('MCP restart failed', { error }); warnings.push(`MCP再起動エラー: ${error}`); } } // 復旧後のヘルスチェック try { await new Promise(resolve => setTimeout(resolve, 2000)); // 2秒待機 const postRecoveryHealth = await healthChecker.performHealthCheck(); if (postRecoveryHealth.isHealthy) { logger.info('Recovery successful, system is now healthy'); return JSON.stringify({ success: true, message: `自動復旧が成功しました(${attempts}回目の試行)`, steps, attempts, finalHealth: postRecoveryHealth, warnings, timestamp: new Date().toISOString() } as AutoRecoveryResult); } else { logger.warn('System still unhealthy after recovery attempt', { attempt: attempts, devServerStatus: postRecoveryHealth.devServerStatus }); if (attempts < maxRetries) { await new Promise(resolve => setTimeout(resolve, 5000)); // 5秒待機してリトライ } } } catch (error) { logger.error('Post-recovery health check failed', { error }); warnings.push(`復旧後ヘルスチェック失敗: ${error}`); } } // 最大試行回数に達した場合 logger.error('Auto recovery failed after maximum attempts', { attempts: maxRetries }); return JSON.stringify({ success: false, message: `自動復旧が失敗しました(${maxRetries}回試行)`, steps, attempts, warnings, timestamp: new Date().toISOString() } as AutoRecoveryResult); } catch (error) { logger.error('Auto recovery process failed', { error }); return JSON.stringify({ success: false, message: `自動復旧プロセスでエラーが発生しました: ${error}`, steps, attempts, warnings: [...warnings, String(error)], timestamp: new Date().toISOString() } as AutoRecoveryResult); } }
- src/tools/autoRecover.ts:8-33 (schema)JSON Schema definition for the auto_recover tool inputs.export const autoRecoverSchema: Tool = { name: 'auto_recover', description: 'MCPサーバーの自動復旧を実行(ヘルスチェック→復旧→再検証)', inputSchema: { type: 'object', properties: { maxRetries: { type: 'number', description: '最大復旧試行回数(デフォルト: 3)', default: 3, minimum: 1, maximum: 10 }, forceRecover: { type: 'boolean', description: '強制復旧モード(デフォルト: false)', default: false }, restartMcp: { type: 'boolean', description: 'MCPサーバー自体の再起動を含むか(デフォルト: false)', default: false } }, additionalProperties: false }
- src/index.ts:55-65 (registration)Registration of the auto_recover schema in the MCP server's tools list, used for listTools responses.const tools = [ scanProjectDirsSchema, startDevServerSchema, getDevStatusSchema, getDevLogsSchema, stopDevServerSchema, restartDevServerSchema, getHealthStatusSchema, recoverFromStateSchema, autoRecoverSchema, ];
- src/index.ts:207-215 (registration)Dispatch handler in MCP server CallToolRequest that invokes the autoRecover function.case 'auto_recover': return { content: [ { type: 'text', text: await autoRecover(args as { maxRetries?: number; forceRecover?: boolean; restartMcp?: boolean }), }, ], };
- Dependency mapping for auto_recover tool, requiring stateManager and healthChecker services to be initialized.export const SERVICE_DEPENDENCIES = { 'scan_project_dirs': ['projectContext'], 'start_dev_server': ['stateManager'], 'get_dev_status': ['stateManager'], 'get_dev_logs': ['stateManager'], 'stop_dev_server': ['stateManager'], 'restart_dev_server': ['stateManager'], 'get_health_status': ['healthChecker'], 'recover_from_state': ['stateManager'], 'auto_recover': ['stateManager', 'healthChecker'] } as const;