April 22, 2026 • Versión: 2026.3.2

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ón
  • startupTimeoutMs: 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

  1. El servicio de plugins genera la conexión del cliente MCP
  2. El cliente MCP inicia el protocolo de enlace `initialize` con el servidor
  3. El servidor comienza la inicialización pesada (por ejemplo, cargando modelos de ML como sentence-transformers)
  4. Se alcanza la marca de 30 segundos antes de que el servidor complete la inicialización
  5. El cliente MCP rechaza con error de tiempo de espera
  6. El servicio de plugins marca el plugin como fallido y reintenta
  7. 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..config.timeout → Capa de solicitud MCP (post-init) ✓ plugins.entries..config.startupTimeoutMs → Capa del ciclo de vida del plugin ✓ plugins.entries..config.initTimeoutMs → NO IMPLEMENTADO ✗

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 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]);

} }

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": 90000

Verificació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 neuralmemory

Salida esperada:

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

El 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 MCP

Configuració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=90000

Error 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 ConfiguradoValor EfectivoRazón
5005000Mínimo aplicado: 5000ms
600000300000Máximo aplicado: 300000ms
NaN30000Valor 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:

  1. Configuración específica del plugin: plugins.entries.<id>.config.initTimeoutMs
  2. Variable de entorno: OPENCLAW_MCP_INIT_TIMEOUT_MS
  3. Configuración global: plugins.mcpInitTimeoutMs
  4. 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-transformers

Memoria 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: 120000 para el despliegue inicial
  • Reducir a initTimeoutMs: 30000 despué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 por plugins.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.

Evidencia y fuentes

Esta guía de solución de problemas fue sintetizada automáticamente por la tubería de inteligencia de FixClaw a partir de las discusiones de la comunidad.