Перейти к основному содержимому
Продвинутый8 мин1273 слов

MCP Tasks vs синхронные tool calls: как выполнять долгие операции

Практический выбор между обычным MCP tools/call и экспериментальными MCP Tasks для долгих операций: capability negotiation, состояния, polling, cancellation, безопасность, тесты и rollout.

Содержание статьи
  1. 01Короткий ответ: Tasks нужны для durable execution, а не для каждого медленного tool
  2. 02Два уровня negotiation защищают от мнимой совместимости
  3. 03Task state machine не заменяет состояние бизнес-операции
  4. 04Polling, progress и backoff требуют bounded budget
  5. 05Authorization привязывает Task к контексту, а не только к сложному ID
  6. 06Тестовая матрица проверяет переходы, повторы и неопределённый результат
  7. 07Rollout: experimental adapter, узкий canary и проверенный fallback

Короткий ответ: Tasks нужны для durable execution, а не для каждого медленного tool

Оставляйте обычный tools/call, когда операция укладывается в ограниченный request timeout, результат можно вернуть сразу, а потеря соединения не требует отдельного восстановления. Рассматривайте MCP Task, когда работа длится долго, должна пережить один request или требует polling, deferred result, cancellation либо промежуточного состояния input_required. Tasks входят в спецификацию MCP 2025-11-25, но помечены как experimental, поэтому функцию следует изолировать capability gate, а не считать универсальным baseline.

Task не является очередью, workflow engine или гарантией exactly-once. Он стандартизирует видимую клиенту оболочку долгой операции: receiver создаёт task ID и сообщает состояние, а requestor проверяет status и получает результат. Бизнес-операции всё равно нужны собственный operation ID, authorization, idempotency, durable state и reconciliation с system of record. Если процесс можно безопасно завершить одним коротким call, Task только добавляет состояния и cleanup.

  • Короткое чтение или bounded compute → обычный tools/call.
  • Долгая работа с deferred result → кандидат на Task.
  • Нужно дополнительное решение пользователя → Task со статусом input_required.
  • Действие с последствиями → domain operation ledger независимо от protocol wrapper.
  • Peer не объявил capability → не отправляйте task augmentation.

Два уровня negotiation защищают от мнимой совместимости

Поддержка Tasks согласуется при initialization. Для task-augmented tool call server объявляет tasks.requests.tools.call; без этой capability client не должен запускать tool как Task. Затем конкретный tool уточняет контракт через execution.taskSupport: forbidden является default, optional разрешает оба режима, required требует Task. Проверяйте оба уровня в каждой сессии и не кешируйте вывод только по имени server или версии SDK.

Создайте capability manifest с protocol version, server implementation version, session evidence, операциями Task list/get/result/cancel и режимом на уровне tool. Router сравнивает manifest с требованиями workflow до первого вызова. Если нужной возможности нет, fallback должен быть явным: короткий synchronous path, отдельный job API, human handoff или контролируемый отказ. Тихая замена required Task на долгий HTTP request создаёт другие timeout и recovery semantics.

Task state machine не заменяет состояние бизнес-операции

MCP Task начинается в working и может перейти в input_required, completed, failed или cancelled по разрешённым спецификацией переходам. taskId генерирует receiver; TTL определяет, когда запись можно удалить; pollInterval подсказывает частоту проверок. requestor получает фактический результат через tasks/result только после terminal completion. Сохраняйте last observed status, lastUpdatedAt, correlation ID и следующий разрешённый poll, чтобы reconnect продолжал наблюдение, а не запускал работу заново.

Параллельно ведите DomainOperation со стабильным idempotency key, actor, tenant, object version, intended effect, downstream receipt и authoritative outcome. completed в Task означает, что protocol result готов, но не доказывает, что внешняя система приняла платёж, publish или deployment. cancelled также не гарантирует компенсацию уже выполненного effect. UI должен отдельно показывать transport/task state и подтверждённый domain outcome, а unknown outcome направлять на reconciliation до retry.

  • Task state → что receiver сообщает о выполнении request.
  • Domain state → что system of record подтверждает о бизнес-последствии.
  • Cancellation → запрос остановить дальнейшую работу, не автоматический rollback.
  • TTL expiry → lifecycle protocol record, а не право забыть audit evidence.

Polling, progress и backoff требуют bounded budget

Client соблюдает pollInterval, добавляет jitter, ограничивает общую длительность и прекращает polling после terminal state. Более частый poll не ускоряет job, но повышает нагрузку и риск rate limit. Progress notification может улучшать UX, однако не должна бесконечно сдвигать абсолютный deadline. После network loss client возобновляет наблюдение за известным taskId, а не повторяет исходный tool call.

Задайте отдельные бюджеты для create, status reads, result retrieval и business reconciliation. Храните только минимально необходимый response envelope: status, version, timestamps, очищенное сообщение и evidence handles. Ошибка tasks/get может означать expiry, authorization failure или server loss; она не превращает unknown domain outcome в failed. Для крупных artifacts лучше возвращать bounded metadata и авторизованный handle, а не неограниченный payload в model context.

Authorization привязывает Task к контексту, а не только к сложному ID

Спецификация требует привязывать Tasks к authorization context, когда он доступен. tasks/get, list, result и cancel должны повторно проверять actor, tenant и разрешённую operation; знание taskId само по себе не является permission. Если peer не может идентифицировать requestor, нужны криптографически непредсказуемые IDs, более короткий TTL и ограниченный discovery. Server без надёжного context binding не должен открывать task listing.

Не записывайте token, sensitive elicitation data или полный downstream result в statusMessage и logs. URL-mode elicitation полезна для внешнего credential или payment flow, но accept означает только согласие перейти по URL, а не завершение внешнего действия. Для input_required фиксируйте requested field class, expiry и redaction rule; после смены identity или отзыва scope продолжение Task должно заново пройти authorization.

Тестовая матрица проверяет переходы, повторы и неопределённый результат

Contract suite покрывает initialize, отсутствие capability, каждое значение taskSupport, create, get, list, result, cancel, invalid transition, expired TTL и pagination. Fault injection разрывает transport до и после CreateTaskResult, между completed и result retrieval, во время input_required и после cancel request. Assertions проверяют, что originating call не повторяется автоматически, status меняется только по разрешённым переходам, а duplicate delivery не создаёт второй domain effect.

Security cases пытаются прочитать или отменить Task другого tenant, угадать ID, получить result после потери scope, подменить related-task metadata и вставить prompt injection в status или result. Load test измеряет bounded concurrent jobs, polling amplification, cleanup и backpressure на downstream. Model-in-the-loop eval нужен только там, где модель решает вызвать tool или интерпретирует result; protocol conformance и authorization остаются deterministic gates.

  • Hard gate → cross-tenant access, invalid transition, duplicate effect или secret leakage.
  • Recovery gate → reconnect продолжает известный Task без повторного start.
  • Cancellation gate → terminal semantics и domain reconciliation проверяются отдельно.
  • Compatibility gate → fallback работает с peer без Tasks capability.

Rollout: experimental adapter, узкий canary и проверенный fallback

Начните с одного read-only или reversible workflow, где Task даёт измеримую operational benefit: переживает request timeout, уменьшает ручное восстановление или делает долгую операцию наблюдаемой. Зафиксируйте protocol и SDK versions, capability manifest, allowed tools, max TTL, concurrency, status retention, owners и kill switch. Shadow mode может сравнивать state projection с действующим job API, но не должен запускать бизнес-операцию дважды.

Продвигайте canary только после прохождения contract, security, load и recovery gates. Rollback блокирует новые task-augmented starts, оставляет watcher для уже созданных Tasks, reconcile-ит in-flight domain operations и возвращает проверенный synchronous или job-API path. Retest запускайте после изменения MCP specification, experimental status Tasks, SDK, transition schema, authorization context, transport или downstream idempotency. Это локальный verdict для конкретной совместимости, а не утверждение, что Tasks лучше для всех MCP servers.

Практические примеры

Долгий export с безопасным восстановлением

Tool создаёт read-only export и возвращает Task. Client сохраняет taskId и domain exportId, делает polling по рекомендованному интервалу, а после completed получает manifest с checksum и короткоживущим download handle. Разрыв сети возобновляет polling; он не создаёт второй export.

Deployment, где cancelled не означает rolled back

Task оборачивает deployment job. Cancel останавливает последующие шаги, но controller отдельно проверяет, была ли применена часть изменений. UI показывает cancelled Task и reconciliation_required domain outcome, пока system of record не подтвердит rollback или стабильный release.

FAQ

MCP Tasks уже стабильны для production?

Tasks описаны в MCP 2025-11-25, но спецификация помечает их experimental. Используйте явную capability negotiation, закреплённую совместимость, canary и fallback и проверяйте текущий статус перед rollout.

Task делает tools/call асинхронным автоматически?

Нет. Server и конкретный tool должны объявить поддержку, а receiver должен реализовать durable execution, status, получение result, cancellation, authorization и cleanup.

Когда лучше оставить собственный job API?

Когда clients не поддерживают Tasks, workflow требует более богатых orchestration semantics или существующий job API уже имеет нужные SLA, audit и recovery. MCP Task может быть adapter поверх него, а не заменой.

Можно ли повторить tools/call, если create response потерялась?

Не вслепую. Сначала выполните reconciliation по client operation ID или idempotency key. Иначе потерянная после успешного start response может создать дублирующую операцию.

Связанные материалы

Источники

  1. Tasks — MCP specification 2025-11-25первичный
  2. Lifecycle — MCP specification 2025-11-25первичный
  3. Tools — MCP specification 2025-11-25первичный
  4. Authorization — MCP specification 2025-11-25первичный
  5. Elicitation — MCP specification 2025-11-25первичный