Saltar al contenido principal
Avanzado9 min1590 palabras

MCP Tasks vs tool calls síncronos: cómo ejecutar operaciones largas

Una elección práctica entre MCP tools/call estándar y MCP Tasks experimentales para operaciones largas: capability negotiation, estados, polling, cancelación, seguridad, pruebas y rollout.

Contenido del artículo
  1. 01Respuesta corta: usa Tasks para ejecución durable, no para cada tool lento
  2. 02Dos niveles de negotiation evitan una compatibilidad imaginaria
  3. 03La state machine del Task no sustituye el estado de la operación de negocio
  4. 04Polling, progress y backoff necesitan un presupuesto acotado
  5. 05Authorization vincula el Task al contexto, no solo a un ID difícil de adivinar
  6. 06La matriz de pruebas valida transiciones, reintentos y resultados inciertos
  7. 07Rollout: adapter experimental, canary estrecho y fallback verificado

Respuesta corta: usa Tasks para ejecución durable, no para cada tool lento

Mantén un tools/call normal cuando la operación quepa en un timeout acotado, el resultado pueda devolverse de inmediato y una pérdida de conexión no requiera recuperación separada. Considera un MCP Task cuando el trabajo dure mucho, deba sobrevivir a una sola request o necesite polling, resultado diferido, cancelación o un estado intermedio input_required. Tasks forma parte de la especificación MCP 2025-11-25, pero está marcado como experimental; por eso debe aislarse detrás de un capability gate y no tratarse como baseline universal.

Un Task no es una cola, un workflow engine ni una garantía exactly-once. Estandariza la envoltura visible para el cliente de una operación larga: el receiver crea un task ID y comunica el estado, mientras el requestor consulta status y recupera el resultado. La operación de negocio sigue necesitando su propio operation ID, autorización, idempotencia, estado durable y reconciliación con el system of record. Si el proceso puede terminar de forma segura en una llamada corta, un Task solo añade estados y cleanup.

  • Lectura corta o compute acotado → tools/call normal.
  • Trabajo largo con resultado diferido → candidato a Task.
  • Se necesita una decisión adicional del usuario → Task con input_required.
  • Acción con consecuencias → ledger de operación de dominio independiente del wrapper de protocolo.
  • El peer no anunció la capability → no envíes task augmentation.

Dos niveles de negotiation evitan una compatibilidad imaginaria

El soporte de Tasks se negocia durante initialization. Para un tool call con Task, el server anuncia tasks.requests.tools.call; sin esa capability el client no debe ejecutar el tool como Task. Después, el tool concreto precisa el contrato mediante execution.taskSupport: forbidden es el valor por defecto, optional permite ambos modos y required exige un Task. Comprueba ambos niveles en cada sesión y no guardes la conclusión solo por el nombre del server o la versión del SDK.

Crea un capability manifest con la versión del protocolo, la versión de implementación del server, evidencia de sesión, operaciones list/get/result/cancel y el modo a nivel de tool. El router compara el manifest con los requisitos del workflow antes de la primera llamada. Si falta una capability necesaria, el fallback debe ser explícito: ruta síncrona corta, job API separado, human handoff o rechazo controlado. Convertir silenciosamente un Task required en una request HTTP larga crea otras semánticas de timeout y recovery.

La state machine del Task no sustituye el estado de la operación de negocio

Un MCP Task empieza en working y puede pasar a input_required, completed, failed o cancelled mediante las transiciones permitidas por la especificación. El receiver genera taskId; TTL determina cuándo puede borrarse el registro; pollInterval sugiere la frecuencia de consulta. El requestor obtiene el resultado real mediante tasks/result solo después de la finalización terminal. Guarda el último status observado, lastUpdatedAt, correlation ID y el próximo poll permitido para que un reconnect reanude la observación en vez de volver a iniciar el trabajo.

Mantén en paralelo una DomainOperation con idempotency key estable, actor, tenant, versión del objeto, efecto previsto, downstream receipt y outcome autoritativo. completed en el Task significa que el protocol result está listo; no demuestra que un sistema externo haya aceptado un pago, publicación o deployment. cancelled tampoco garantiza compensación por un efecto ya ejecutado. La UI debe separar transport/task state del domain outcome confirmado, y un unknown outcome debe ir a reconciliación antes de cualquier retry.

  • Task state → lo que el receiver informa sobre la ejecución de la request.
  • Domain state → lo que el system of record confirma sobre el efecto de negocio.
  • Cancellation → petición de detener trabajo posterior, no rollback automático.
  • TTL expiry → ciclo de vida del registro de protocolo, no permiso para olvidar evidencia de auditoría.

Polling, progress y backoff necesitan un presupuesto acotado

El client respeta pollInterval, añade jitter, limita la duración total y detiene el polling tras un estado terminal. Consultar con más frecuencia no acelera el job; solo aumenta la carga y el riesgo de rate limit. Las progress notifications pueden mejorar la UX, pero no deben reiniciar indefinidamente el deadline absoluto. Tras una pérdida de red, el client reanuda la observación del taskId conocido en lugar de repetir el originating tool call.

Define presupuestos separados para create, lecturas de status, result retrieval y business reconciliation. Guarda solo el response envelope mínimo: status, versión, timestamps, mensaje sanitizado y evidence handles. Un fallo de tasks/get puede significar expiry, fallo de autorización o pérdida del server; no convierte un unknown domain outcome en failed. Para artifacts grandes, devuelve metadata acotada y un handle autorizado en vez de un payload ilimitado en el contexto del modelo.

Authorization vincula el Task al contexto, no solo a un ID difícil de adivinar

La especificación exige vincular Tasks al authorization context cuando está disponible. tasks/get, list, result y cancel deben volver a comprobar actor, tenant y operación permitida; conocer taskId no es permission por sí mismo. Si un peer no puede identificar al requestor, usa IDs criptográficamente impredecibles, un TTL más corto y discovery restringido. Un server sin context binding fiable no debería exponer task listing.

No escribas tokens, datos sensibles de elicitation ni el downstream result completo en statusMessage o logs. La elicitation en URL mode sirve para un flujo externo de credenciales o pago, pero accept solo significa consentimiento para visitar la URL, no finalización de la acción externa. Para input_required registra la clase del campo solicitado, expiry y la regla de redaction; tras un cambio de identity o revocación de scope, continuar el Task debe volver a pasar autorización.

La matriz de pruebas valida transiciones, reintentos y resultados inciertos

La contract suite cubre initialize, capability ausente, cada valor de taskSupport, create, get, list, result, cancel, transición inválida, TTL expirado y pagination. La fault injection corta el transporte antes y después de CreateTaskResult, entre completed y result retrieval, durante input_required y después de una petición de cancel. Las assertions comprueban que el originating call no se repite automáticamente, el status solo cambia por transiciones permitidas y una duplicate delivery no crea un segundo domain effect.

Los security cases intentan leer o cancelar el Task de otro tenant, adivinar un ID, obtener result tras perder scope, manipular related-task metadata e insertar prompt injection en status o result. Los load tests miden jobs concurrentes acotados, polling amplification, cleanup y backpressure en downstream. La evaluación model-in-the-loop solo es necesaria donde el modelo decide invocar el tool o interpreta el result; protocol conformance y authorization siguen siendo gates deterministas.

  • Hard gate → acceso cross-tenant, transición inválida, efecto duplicado o fuga de secretos.
  • Recovery gate → reconnect continúa el Task conocido sin un segundo start.
  • Cancellation gate → terminal semantics y domain reconciliation se verifican por separado.
  • Compatibility gate → el fallback funciona con un peer sin capability de Tasks.

Rollout: adapter experimental, canary estrecho y fallback verificado

Empieza con un workflow read-only o reversible donde un Task aporte valor operativo medible: sobrevive a un request timeout, reduce recuperación manual o hace observable una operación larga. Fija versiones de protocolo y SDK, capability manifest, tools permitidos, TTL máximo, concurrencia, retención de status, owners y kill switch. El shadow mode puede comparar la proyección de estado con un job API existente, pero no debe ejecutar dos veces la operación de negocio.

Promueve el canary solo después de superar gates de contract, security, load y recovery. Rollback bloquea nuevos inicios con Task, mantiene un watcher para Tasks ya creados, reconcilia operaciones de dominio in-flight y restaura la ruta síncrona o job-API verificada. Repite las pruebas tras cambios en la especificación MCP, el estado experimental de Tasks, SDK, transition schema, authorization context, transport o downstream idempotency. Es un veredicto local de compatibilidad, no una afirmación de que Tasks sean mejores para todos los MCP servers.

Ejemplos prácticos

Export largo con recuperación segura

Un tool crea un export read-only y devuelve un Task. El client guarda taskId y el exportId de dominio, hace polling con el intervalo recomendado y, tras completed, obtiene un manifest con checksum y un download handle de corta duración. Una caída de red reanuda el polling; no crea un segundo export.

Deployment donde cancelled no significa rolled back

Un Task envuelve un deployment job. Cancel detiene los pasos siguientes, pero el controller comprueba por separado si parte del cambio ya se aplicó. La UI muestra un Task cancelled y un domain outcome reconciliation_required hasta que el system of record confirme rollback o un release estable.

FAQ

¿MCP Tasks ya es estable para production?

Tasks está definido en MCP 2025-11-25, pero la especificación lo marca como experimental. Usa capability negotiation explícita, compatibilidad fijada, canary y fallback; vuelve a comprobar el estado actual antes del rollout.

¿Un Task vuelve tools/call asíncrono automáticamente?

No. El server y el tool concreto deben anunciar soporte, y el receiver debe implementar durable execution, status, recuperación de result, cancellation, authorization y cleanup.

¿Cuándo conviene mantener un job API propio?

Cuando los clients no soportan Tasks, el workflow necesita semánticas de orchestration más ricas o el job API existente ya ofrece los SLA, audit y recovery necesarios. Un MCP Task puede ser un adapter sobre ese API en lugar de sustituirlo.

¿Se puede repetir tools/call si se pierde la create response?

No a ciegas. Primero reconcilia mediante un client operation ID o idempotency key. De lo contrario, una respuesta perdida después de un start correcto puede crear una operación duplicada.

Materiales relacionados

Fuentes

  1. Tasks — MCP specification 2025-11-25primaria
  2. Lifecycle — MCP specification 2025-11-25primaria
  3. Tools — MCP specification 2025-11-25primaria
  4. Authorization — MCP specification 2025-11-25primaria
  5. Elicitation — MCP specification 2025-11-25primaria