Skip to content

Long-running waits and tasks

Alcarta supports three delivery styles for waits. Polling remains available in every case and is the safest compatibility baseline.

With email_await delivery poll (the default), the tool call blocks until a predicate matches or the deadline passes. Message waits allow up to 300 seconds; request waits allow up to 14,400 seconds. Values over the configured limit are rejected rather than clamped.

A timeout is a normal success with timed_out: true. During graceful shutdown, a wait instead returns shutdown: true and timed_out: false; reconnect immediately without backoff.

Set delivery to websocket or any. The call returns immediately with:

  • a single-use websocket_url;
  • the deadline for opening that URL;
  • an unconditional wait_id fallback.

The websocket token is consumed by the connection and is never renewed. Its connect TTL is not the duration of the monitor; the requested timeout_seconds still bounds the watch.

Every proxy hop must forward the websocket Upgrade and Connection headers, preserve the 101 response, and disable response buffering. If Upgrade is stripped, Alcarta answers 400 invalid_request with reason upgrade_required.

Tasks are available only on MCP revision 2025-11-25. The initialize result declares the tasks capability, and email_await, monitor_inbox, and monitor_approval advertise execution.taskSupport: "optional".

To start a task, add the protocol-level task member to tools/call; do not put it inside the tool’s arguments:

{
"jsonrpc": "2.0",
"id": 20,
"method": "tools/call",
"params": {
"name": "email_await",
"arguments": {
"event": {"type": "request_state_changed", "request_ids": ["chk_…"]},
"timeout_seconds": 14400
},
"task": {}
}
}

The call returns a task handle immediately. Use tasks/get, tasks/result, tasks/list, and tasks/cancel. Tasks are bound to the token ID that created them; another token cannot inspect them. Polling task state is the protocol default. Status notifications are an optimization and must not be required for correctness.

For message waits, always persist next_cursor before processing the payload and return it as since_cursor on the next wait. Events are doorbells; provider state and the database remain the source of truth.