DEV Community

Cover image for Solucionar Timeouts de MCP: Patrón HandleId Asíncrono
Elizabeth Fuentes L for AWS Español

Posted on

Solucionar Timeouts de MCP: Patrón HandleId Asíncrono

Las herramientas MCP congelan a los agentes de IA cuando las APIs externas son lentas, causando errores 424. El patrón handleId asíncrono devuelve inmediatamente un ID de trabajo y consulta los resultados sin bloquear.

El timeout de herramienta MCP ocurre cuando un agente de IA llama a una herramienta del Protocolo de Contexto de Modelo (MCP) que depende de una API externa lenta. La herramienta bloquea al agente indefinidamente en lugar de devolver un error. El resultado es un error 424 (Failed Dependency) o un flujo de trabajo congelado sin retroalimentación al usuario. Este post muestra el problema con escenarios reales y cómo el patrón handleId asíncrono proporciona respuestas inmediatas.

Esta demo usa Strands Agents con MCP (Model Context Protocol). El patrón asíncrono es independiente del framework y aplica a cualquier agente que llame APIs externas a través de MCP.

Código funcional: github.com/aws-samples/sample-why-agents-fail

Serie: Por Qué Fallan los Agentes de IA

  1. Desbordamiento de Ventana de Contexto — Patrón de Puntero de Memoria para datos grandes
  2. Herramientas MCP Que Nunca Responden (este post) — Patrón asíncrono para APIs externas lentas
  3. Loops de Razonamiento en Agentes de IA — Detectar y bloquear llamadas repetidas a herramientas

El Problema: Herramientas MCP Que Nunca Responden

El Protocolo de Contexto de Modelo (MCP) permite a los agentes de IA llamar herramientas externas. Pero cuando esas herramientas dependen de APIs lentas, todo el flujo de trabajo del agente se congela. El agente espera. El usuario espera. No pasa nada.

Una observación comunitaria de Octopus (Resilient AI Agents With MCP, 2025) identifica el problema central: a medida que aumentan las integraciones de sistemas externos, también aumenta la probabilidad de fallo. Los sistemas dejan de estar disponibles, responden lentamente o devuelven errores. Los agentes no tienen una estrategia incorporada para manejar esto.

Los reportes de OpenAI Community confirman el impacto del mundo real:

  • Errores 424 cuando las herramientas MCP tardan demasiado
  • Estados sin respuesta donde las solicitudes ni tienen éxito ni fallan
  • Herramientas que pasan la validación de handshake pero hacen timeout durante la ejecución

Por Qué Sucede Esto

MCP espera que las herramientas respondan rápidamente. Cuando una herramienta llama a una API externa lenta.

El protocolo MCP tiene expectativas de timeout implícitas. Si la herramienta no responde dentro de ~7-10 segundos, la conexión puede caerse con un error 424 (Failed Dependency). El agente recibe un error en lugar de datos, y el usuario no obtiene una respuesta útil.

Tres modos de fallo:

  1. API lenta — La herramienta espera 15+ segundos, UX pobre pero eventualmente responde
  2. API fallida — Servicio externo no disponible, error 424 después del timeout
  3. Estado sin respuesta — Solicitud aceptada pero nunca devuelve, requiere reinicio de sesión

La Demo: Simulando Escenarios Reales de Timeout

Construimos un servidor MCP que simula estos escenarios del mundo real:

from mcp.server import FastMCP
import asyncio

# FastMCP es un framework ligero de servidor MCP — las herramientas se registran con @mcp.tool()
mcp = FastMCP("Timeout Demo Server")

# Línea base: responde en 1s, bien dentro del umbral de timeout implícito de MCP (~7-10s)
@mcp.tool(description="Fast API - responds in 1 second")
async def fast_api(query: str) -> str:
    await asyncio.sleep(1)
    return f"Fast result for: {query}"

# Caso problema: retraso de 15s excede timeout de MCP — el agente se congela esperando esto
@mcp.tool(description="Slow API - responds in 15 seconds")
async def slow_api(query: str) -> str:
    await asyncio.sleep(15)  # Simula un servicio externo lento (pipeline de datos, trabajo por lotes)
    return f"Slow result for: {query}"

# Caso de fallo: retraso de 7s activa el timeout, luego lanza Failed Dependency (424)
@mcp.tool(description="Failing API - returns 424 after delay")
async def failing_api(query: str) -> str:
    await asyncio.sleep(7)
    raise Exception("Failed Dependency: External service unavailable")
Enter fullscreen mode Exit fullscreen mode

La Solución Async HandleId

Comparación de llamada a herramienta MCP síncrona bloqueada por 17.2 segundos versus patrón handleId asíncrono completando en 1.7 segundos

En lugar de esperar operaciones lentas, devuelve inmediatamente con un ID de seguimiento:

import uuid

# Almacén de trabajos en memoria: mapea job_id → {status, query, result}
# Para producción, reemplazar con un almacén persistente (Redis, DynamoDB) para durabilidad entre reinicios
JOBS = {}

# El patrón handleId: devuelve un ID de seguimiento inmediatamente en lugar de bloquear
@mcp.tool(description="Start a long-running job, returns immediately with job ID")
async def start_async_job(query: str) -> str:
    job_id = str(uuid.uuid4())[:8]  # ID corto que el LLM puede pasar en llamadas de seguimiento
    JOBS[job_id] = {"status": "processing", "query": query}

    # Fire-and-forget: el trabajo lento se ejecuta en segundo plano, la herramienta devuelve antes de que termine
    asyncio.create_task(do_work(job_id, query))

    # El agente recibe esto en < 1s — sin timeout, sin UI congelada
    return f"Job started: {job_id}. Use check_job_status to poll for results."

# Endpoint de consulta: el agente llama a esto repetidamente hasta que el estado es "completed"
@mcp.tool(description="Check status of a running job")
async def check_job_status(job_id: str) -> str:
    job = JOBS.get(job_id)
    if not job:
        return f"Job {job_id} not found"
    if job["status"] == "completed":
        return f"COMPLETED: {job['result']}"  # Devuelve el resultado real al agente
    return f"PROCESSING: Job {job_id} still running"  # El agente consulta de nuevo después de una breve espera
Enter fullscreen mode Exit fullscreen mode

Resultados de la Demo

Probamos los cuatro escenarios con un Strands Agent conectado al servidor MCP:

Escenario Tiempo de Respuesta Experiencia de Usuario Hallazgo de Investigación
Fast API (retraso 1s) 3.2s total ✅ Buen UX Línea base
Slow API (retraso 15s) 17.8s total ❌ UX pobre — agente espera Octopus: "el agente espera indefinidamente"
Failing API (424) 7.7s total ❌ Error después de esperar OpenAI Community: errores 424
Patrón asíncrono (handleId) 3.7s total ✅ Respuesta inmediata Solución: "responder ASAP con handleId"

Gráfico de barras comparando tiempos de respuesta de herramientas MCP en escenarios de fast API, slow API, failing API y async handleId

El patrón asíncrono transforma una espera de 17.8s en una respuesta inmediata de 3.7s. El agente le dice al usuario "trabajo iniciado" y puede verificar el estado más tarde, sin UI congelada y sin errores de timeout.

¿Por Qué Strands Agents para Integración MCP?

El MCPClient se conecta a cualquier servidor MCP en dos líneas. El agente descubre herramientas disponibles en tiempo de ejecución a través de list_tools_sync(), así que no mantienes una lista de herramientas codificada. Cuando el servidor MCP implementa el patrón handleId asíncrono, el agente consulta automáticamente sin código de orquestación adicional.

Strands soporta múltiples proveedores de modelos (OpenAI, Amazon Bedrock, Anthropic, Ollama). Los patrones de timeout de MCP mostrados aquí funcionan idénticamente en todos los proveedores.

Cuándo Usar Cada Patrón

Llamada directa (herramientas rápidas < 5s):

  • Búsquedas, cálculos, llamadas pequeñas a API
  • Sin riesgo de timeout

HandleId asíncrono (herramientas lentas > 5s):

  • Llamadas a API externas con latencia impredecible
  • Procesamiento de datos, generación de reportes
  • Cualquier operación que pueda exceder el timeout de MCP

Reintento con backoff (fallos intermitentes):

  • Servicios que ocasionalmente fallan pero se recuperan
  • Operaciones dependientes de red

Pruébalo Tú Mismo

Necesitas Python 3.9+, uv, y una clave API de OpenAI. El servidor MCP se ejecuta localmente como un subproceso, así que no se necesitan servicios externos.

git clone https://github.com/aws-samples/sample-why-agents-fail
cd sample-why-agents-fail/stop-ai-agents-wasting-tokens/02-mcp-timeout-demo
uv venv && uv pip install -r requirements.txt
export OPENAI_API_KEY="tu-clave-aquí"

uv run python test_mcp_timeout.py   # Ejecuta los 4 escenarios
Enter fullscreen mode Exit fullscreen mode

O abre test_mcp_timeout.ipynb en Jupyter, JupyterLab, VS Code, o tu entorno de notebook preferido.

Conclusiones Clave

  1. Las herramientas MCP hacen timeout silenciosamente — errores 424 sin recuperación
  2. Las APIs lentas congelan todo el agente — espera de 17.8s sin retroalimentación
  3. El patrón handleId asíncrono lo soluciona — respuesta inmediata, consultar por resultados
  4. Diseña para el fallo — cada llamada externa puede hacer timeout, planifica en consecuencia

Preguntas Frecuentes

¿Qué causa errores 424 en llamadas a herramientas MCP?

Un error 424 (Failed Dependency) ocurre cuando una herramienta MCP tarda más que el umbral de timeout implícito (típicamente 7-10 segundos) en responder. El protocolo MCP espera que las herramientas devuelvan resultados rápidamente. Cuando una API externa bloquea la herramienta más allá de este umbral, la conexión se cae y el agente recibe un error 424 en lugar de datos.

¿Cuándo debo usar el patrón handleId asíncrono en lugar de una llamada directa a herramienta MCP?

Usa el patrón handleId asíncrono para cualquier herramienta que llame a una API externa con latencia impredecible: procesamiento de datos, generación de reportes, llamadas a servicios de terceros, o cualquier operación que pueda exceder 5 segundos. Para búsquedas rápidas, cálculos y llamadas pequeñas a API por debajo de 5 segundos, las llamadas directas funcionan bien.

¿El patrón handleId asíncrono funciona con cualquier servidor MCP, no solo Strands?

Sí. El patrón handleId asíncrono es un patrón de diseño de servidor MCP, no una característica de framework. Cualquier agente compatible con MCP puede llamar herramientas start_long_job y check_job_status. El patrón funciona con OpenAI Agents, integraciones MCP de LangChain, y cualquier cliente que soporte el Protocolo de Contexto de Modelo.

Referencias

Investigación

Implementación


Gracias!

🇻🇪🇨🇱 Dev.to Linkedin GitHub Twitter Instagram Youtube

Top comments (0)