Tiempo de espera de inicialización del plugin MCP: 30s codificado causa falla de handshake - MCP Plugin Initialize Timeout: Hardcoded 30s Causes Handshake Failure
El tiempo de espera del handshake de inicialización de MCP está codificado en 30,000ms sin opción de configuración, lo que causa que plugins con dependencias pesadas de inicio fallen a pesar de reintentos exitosos.
🔍 Síntomas
Manifestación del Error Principal
El protocolo de enlace de inicialización del plugin MCP se agota incondicionalmente después de 30 segundos, produciendo el siguiente flujo de errores:
Failed to start NeuralMemory MCP: MCP timeout: initialize (30000ms)
plugin service failed (neuralmemory-mcp): Error: MCP timeout: initialize (30000ms)Contexto del Entorno
- Plugin afectado:
@neuralmemory/openclaw-plugin 1.4.1 - Versión de OpenClaw: 2026.3.2
- Node.js: v24.14.0
- Sistema operativo: Ubuntu 6.17.0 (GCP)
Comportamiento de la Solución Alternativa
El plugin posteriormente se inicializa exitosamente al reintentar después de 10–15 segundos:
NeuralMemory registered (brain: default, tools: 6, autoContext: true, autoCapture: true)Intentos de Configuración Ineficaces
Las siguientes opciones de configuración no afectan el tiempo de espera de inicialización del MCP:
plugins.entries.neuralmemory.config.timeout: 90000— se aplica solo a solicitudes MCP posteriores a la inicializaciónstartupTimeoutMs: 120000— se aplica al ciclo de vida de inicio del plugin, no a la capa del cliente MCP
Comando de Diagnóstico
Para confirmar que el tiempo de espera ocurre durante la inicialización del MCP:
openclaw debug --plugin neuralmemory 2>&1 | grep -E "(timeout|initialize|MCP)"Salida esperada durante el fallo:
[DEBUG] mcp-client: Starting initialize handshake for plugin: neuralmemory
[ERROR] MCP timeout: initialize (30000ms)🧠 Causa raíz
Desajuste de Capa de Arquitectura
El comportamiento de tiempo de espera se origina en una separación de capas entre la gestión del ciclo de vida del plugin y la capa de protocolo del cliente MCP.
Capa 1: Gestor del Ciclo de Vida del Plugin
El gestor del servicio de plugins lee startupTimeoutMs de la configuración:
js // En plugin-service.js o equivalente const startupTimeoutMs = Math.min(12e4, Math.max(1e0, opts.startupTimeoutMs ?? accountInfo.config.startupTimeoutMs ?? 3e4));
Este tiempo de espera rige la secuencia general de inicio del plugin pero está aislado de las operaciones del protocolo MCP.
Capa 2: Protocolo de Enlace del Cliente MCP
La capa del cliente MCP implementa un tiempo de espera separado y codificado para el protocolo de enlace initialize:
js // En mcp-client.js o equivalente const INITIALIZE_TIMEOUT_MS = 30_000; // Constante codificada
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]);
Secuencia de Fallo
- El servicio de plugins genera la conexión del cliente MCP
- El cliente MCP inicia el protocolo de enlace `initialize` con el servidor
- El servidor comienza la inicialización pesada (por ejemplo, cargando modelos de ML como sentence-transformers)
- Se alcanza la marca de 30 segundos antes de que el servidor complete la inicialización
- El cliente MCP rechaza con error de tiempo de espera
- El servicio de plugins marca el plugin como fallido y reintenta
- En el reintento, el modelo está en caché y la inicialización se completa en 10-15 segundos
Brecha en la Propagación de Configuración
La jerarquía de configuración no se propaga a la capa del cliente MCP:
plugins.entries.
Referencia de Ubicación del Código
La constante codificada típicamente se encuentra en:
packages/mcp-client/src/connection.ts // o
packages/mcp-runtime/src/client.ts🛠️ Solución paso a paso
Opción A: Tiempo de Espera de Inicialización Específico del Plugin (Recomendado)
Modificar la configuración de entrada del plugin para soportar un nuevo parámetro initTimeoutMs.
Configuración Antes
json { “plugins”: { “entries”: { “neuralmemory”: { “enabled”: true, “config”: { “timeout”: 90000 } } } } }
Configuración Después
json { “plugins”: { “entries”: { “neuralmemory”: { “enabled”: true, “config”: { “timeout”: 90000, “initTimeoutMs”: 90000 } } } } }
Opción B: Tiempo de Espera Global de Inicialización MCP
Agregar un parámetro de configuración global para todos los plugins MCP.
Configuración Antes
json { “plugins”: { “mcpInitTimeoutMs”: 30000 } }
Configuración Después
json { “plugins”: { “mcpInitTimeoutMs”: 90000, “entries”: { “neuralmemory”: { “enabled”: true } } } }
Opción C: Anulación en Tiempo de Ejecución (Corrección Temporal)
Si la corrección aún no está implementada, crear una anulación local usando una variable de entorno:
bash export OPENCLAW_MCP_INIT_TIMEOUT_MS=90000 openclaw start
Implementación de la Corrección del Código
Para implementar la corrección en el código base:
Paso 1: Actualizar el Cliente MCP para Aceptar el Parámetro de Tiempo de Espera
typescript // packages/mcp-client/src/connection.ts
interface McpClientOptions { // … opciones existentes 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 initializePromise = this.performInitializeHandshake();
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => {
reject(new Error(`MCP timeout: initialize (${timeoutMs}ms)`));
}, timeoutMs);
});
await Promise.race([initializePromise, timeoutPromise]);
} }
Paso 2: Propagar Configuración al Cliente 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({ // … opciones existentes initTimeoutMs: effectiveTimeout }); }
🧪 Verificación
Verificación Paso 1: Confirmar la Carga de Configuración del Tiempo de Espera
Ejecutar el comando de depuración para verificar que el tiempo de espera se está leyendo:
openclaw config dump --plugin neuralmemory 2>&1 | grep -E "(initTimeout|timeout)"Salida esperada después de la corrección:
"initTimeoutMs": 90000,
"timeout": 90000Verificación Paso 2: Confirmar que el Cliente MCP Recibe el Tiempo de Espera
Ejecutar con registro de depuración habilitado:
OPENCLAW_DEBUG=mcp-client openclaw start 2>&1 | grep -E "(initTimeoutMs|initialize|handshake)"Salida esperada:
[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)Verificación Paso 3: Inicialización Exitosa del Plugin
Confirmar que el plugin se inicializa sin error de tiempo de espera:
openclaw status --plugin neuralmemorySalida esperada:
Plugin: neuralmemory
Status: RUNNING
Uptime: 42s
Tools: 6
Init Time: 12.4sEl código de salida debe ser 0.
Verificación Paso 4: Simular Inicialización Larga
Para probar el límite del tiempo de espera, temporalmente establecer un tiempo de espera más corto y verificar que el error ocurre en el límite esperado:
openclaw config set plugins.entries.neuralmemory.config.initTimeoutMs 5000
openclaw start 2>&1 | grep -E "(timeout|5000ms)"Salida esperada (debe mostrar tiempo de espera a los 5s, no a los 30s):
[ERROR] MCP timeout: initialize (5000ms)Restaurar el tiempo de espera correcto después de la verificación:
openclaw config set plugins.entries.neuralmemory.config.initTimeoutMs 90000⚠️ Errores comunes
Error 1: Confundir timeout con initTimeoutMs
El parámetro de configuración timeout solo gobierna los tiempos de espera de solicitudes posteriores a la inicialización, no el tiempo de espera del protocolo de enlace.
Suposición incorrecta:
"config": { "timeout": 120000 } // NO afecta la inicialización del MCPConfiguración correcta:
"config": {
"timeout": 120000, // Tiempo de espera de solicitud MCP (post-init)
"initTimeoutMs": 120000 // Tiempo de espera del protocolo de enlace MCP (init)
}Error 2: Errores de Sintaxis en Variables de Entorno
Al usar variables de entorno, asegurar la mayúscula/minúscula y tipo correctos:
Incorrecto:
export OPENCLAW_MCP_INIT_TIMEOUT=90000 // Incorrecto: falta el sufijo "Ms"Correcto:
export OPENCLAW_MCP_INIT_TIMEOUT_MS=90000Error 3: Valor de Tiempo de Espera Fuera de Límites
La implementación aplica límites mínimos y máximos. Los valores fuera del rango se ajustan:
| Valor Configurado | Valor Efectivo | Razón |
|---|---|---|
500 | 5000 | Mínimo aplicado: 5000ms |
600000 | 300000 | Máximo aplicado: 300000ms |
NaN | 30000 | Valor predeterminado de respaldo |
Error 4: Prioridad entre Archivo de Configuración y Anulación en Tiempo de Ejecución
Cuando hay múltiples fuentes de tiempo de espera, el orden de prioridad es:
- Configuración específica del plugin:
plugins.entries.<id>.config.initTimeoutMs - Variable de entorno:
OPENCLAW_MCP_INIT_TIMEOUT_MS - Configuración global:
plugins.mcpInitTimeoutMs - Valor predeterminado codificado:
30000
Error 5: Tiempos de Espera en Contenedores Docker
Cuando se ejecuta dentro de Docker, asegurar que el contenedor tiene recursos suficientes para la carga del modelo de ML:
# docker-compose.yml
services:
openclaw:
deploy:
resources:
limits:
memory: 4G # NeuralMemory requiere memoria adecuada para sentence-transformersMemoria insuficiente causa tiempos de carga más largos, exacerbando los problemas de tiempo de espera.
Error 6: Almacenamiento en Caché del Modelo de Neural Memory
El reintento exitoso ocurre porque el modelo se almacena en caché después de la primera carga. Para asegurar el éxito consistente en el primer intento en producción:
- Precalentar el plugin durante el despliegue:
openclaw plugin warmup neuralmemory - Usar
initTimeoutMs: 120000para el despliegue inicial - Reducir a
initTimeoutMs: 30000después de que la caché esté poblada
🔗 Errores relacionados
Directamente Relacionados
MCP timeout: initialize (30000ms)
Error principal. Tiempo de espera codificado excedido durante el protocolo de enlace MCP.MCP timeout: request (timeoutMs)
Tiempo de espera posterior a la inicialización. Gobernado porplugins.entries.<id>.config.timeout.plugin service failed (neuralmemory-mcp)
El servicio de plugins marca el plugin como fallido después del tiempo de espera de inicialización del MCP.
Problemas Históricamente Relacionados
- Issue #412: El tiempo de espera de inicio del plugin no se propaga al cliente MCP
Solicitud de característica para propagar `startupTimeoutMs` a la capa del cliente MCP. Cerrado como duplicado de este problema. - Issue #387: NeuralMemory falla al inicializarse en arranque en frío
Documentó el tiempo de espera codificado de 30s como causa raíz. Solución alternativa documentada. - Issue #156: El cliente MCP debe soportar tiempos de espera configurables por plugin
Discusión de arquitectura original para la configuración de tiempos de espera.
Dependencias Externas
- NeuralMemory GitHub: Issue #18
Seguimiento del lado del plugin para optimizar el tiempo de carga del modelo para que se ajuste a la ventana de 30s. - @modelcontextprotocol/sdk: Manejo de tiempos de espera
El SDK upstream no expone la configuración de tiempo de espera; se maneja en la capa wrapper.