Long-running MCP calls (tasks)
Call Liyagent's own /mcp tools as MCP tasks, poll and cancel them, and answer the questions a task asks while it runs.
- Start a tool call as a task
- Poll, collect and cancel it
- Answer an input_required task
- Explain who can see a task
Liyagent serves its own tools at /mcp (Streamable HTTP), for MCP clients such as Claude Desktop, Cursor or your own agents. Some calls take minutes. The longest is ask_agent, which runs a whole agent. Liyagent supports the tasks utility from MCP 2025-11-25 for these calls: the client gets a task at once, then polls for it and collects the result when it is ready.
A call without a task is answered exactly as before. Clients that do not use tasks see no change.
Start a task
initialize advertises "tasks": {"list": {}, "cancel": {}, "requests": {"tools": {"call": {}}}}, and every tool in tools/list carries "execution": {"taskSupport": "optional"}. To run a call as a task, add task to its params:
{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": "ask_agent", "arguments": {"agent": "it-helpdesk", "message": "..."},
"task": {"ttl": 3600000}}}The answer is a CreateTaskResult: {"task": {"taskId", "status": "working", "createdAt", "lastUpdatedAt", "ttl", "pollInterval"}}. The call has already passed the same checks as any other call: kill switch, rate limits, Cedar, budget, data policies and guardrails. They apply to the work the task runs.
| Method | What it does |
|---|---|
tasks/get | The task's status: working, input_required, completed, failed or cancelled |
tasks/result | The tool's result once the task ends, tagged _meta["io.modelcontextprotocol/related-task"]. With Accept: text/event-stream it streams until then, including any question the task asks. Without a stream it waits up to mcp_task_result_wait_s (30 s) |
tasks/list | Your tasks, 50 at a time (nextCursor) |
tasks/cancel | Ends the task as cancelled and stops the agent run it wraps at its next step. A task that already ended answers -32602 |
A tool result with isError ends the task as failed.
Answer a question mid-task
When a server that the asked agent calls needs something from the user (an MCP elicitation/create), the task moves to input_required. Call tasks/result with Accept: text/event-stream. The stream carries the request:
{"jsonrpc": "2.0", "id": "tiq-task-<taskId>-1", "method": "elicitation/create",
"params": {"mode": "form", "message": "Which cost centre?", "requestedSchema": {...},
"_meta": {"io.modelcontextprotocol/related-task": {"taskId": "<taskId>"}}}}POST your answer back to /mcp as a JSON-RPC response with the same id: {"jsonrpc": "2.0", "id": "tiq-task-<taskId>-1", "result": {"action": "accept", "content": {...}}}. The task then continues and the stream ends with the result.
The same rules apply as when a person answers in the console. A form that asks for a password, token, key or card number is declined without being shown to you. A URL must be public HTTPS. Your answer is checked against the form before the server sees it, and an answer that does not fit is a decline. No answer within mcp_task_input_timeout_s (10 minutes) is also a decline.
Who can see a task
A task belongs to the caller that started it: the agent credential, or the app and the person signed in to it, in their tenant. Any other caller gets -32602 for that task id, as if it did not exist, and cannot answer its questions. tasks/list lists only your own.
Limits and durability
- Tasks are stored in the database, so any replica answers
tasks/get. The work runs in the process that accepted the call and reports that it is alive every 10 seconds. If that process stops, the task is reported asfailed("interrupted"), not leftworking. mcp_task_max_ttl_mscaps how long a task is kept (default 24 hours).mcp_task_max_opencaps a caller's open tasks (default 20). A call over the cap is refused withrefused_by: task_limit.mcp_tasks_enabledturns tasks off.- The audit log records
mcp.task.created,.completed,.failed,.cancelled,.input_requiredand.input_answeredunder the caller's name. Answers are never recorded.