Claude Code MCP Tasks: Background Jobs and Elicitation
Run long MCP tools without blocking Claude Code. Check version, protocol and feature-flag requirements, return a valid task handle and final result, audit elicitation hooks, and understand what survives cancellation, exit or session changes.
Contents

For Claude Code MCP Tasks, use a task-capable MCP server and invoke its tool from the main conversation in the terminal CLI on v2.1.304 or later. The server accepts the job, Claude continues working, and the result returns when the job finishes. Check the eligibility conditions before changing your server: an ordinary tool call moved into the background after two minutes uses a different mechanism.
As of 2026-10-24, Claude Code documents MCP Tasks as a public beta. This guide covers the current 2026-07-28 protocol and the conditions that determine whether your call qualifies.
What Tasks and Elicitation do
Use Tasks for long work that the server can accept and track independently, such as builds, test runs, exports, or research. Use Elicitation when the server needs a decision or missing information from you before proceeding.
Three behaviors can otherwise look similar:
| Mechanism | What happens | What the server must implement |
|---|---|---|
| Ordinary MCP call | Claude waits for the tool’s result. | A normal tool implementation. |
| Automatic backgrounding | A main-conversation call still running after two minutes moves into the background. Its result arrives later, but the background call does not survive exiting the session. | No Tasks support is required. |
| MCP Task | The server returns a task handle when it accepts the job. Claude Code follows that handle and retrieves the outcome. Remote server jobs can continue after the CLI exits. | The Tasks extension and persistent task handling. |
Elicitation is a separate capability. A report tool might ask which environment to query, then run the export as a Task. A quick tool can request the same clarification without creating a Task.
Elicitation also predates this rollout: the Claude Code v2.1.76 release introduced elicitation dialogs and the Elicitation and ElicitationResult hooks. The newer capability here is server-managed Tasks.
Check whether your call can become an MCP Task
Every condition in the official eligibility checklist must hold. Installing a newer CLI only satisfies the first row.
| Check | Required condition |
|---|---|
| Claude Code version | v2.1.304 or later. |
| Server implementation | The server supports the Tasks extension. An MCP connection alone does not establish support. |
| Transport and protocol | An HTTP, stdio, or claude.ai connector server connected on protocol revision 2026-07-28. |
| Legacy overrides | Neither MCP_SDK_GENERATION=v1 nor MCP_PROTOCOL_NEGOTIATION=legacy can force the connection onto the older protocol. |
| Feature availability | The session fetches feature flags, and Anthropic enables Tasks for that session type. |
| Supported surface | Terminal CLI, Agent SDK, or GitHub Actions. The VS Code extension and desktop app do not currently support MCP Tasks. |
| Caller | The call originates in the main conversation. Calls made by subagents do not become MCP Tasks. |
| Input mode | An interactive session, or a qualifying Agent SDK or streaming-input session as described below. |
For noninteractive operation, an Agent SDK session or a claude -p run using --input-format stream-json additionally requires:
CLAUDE_AUTO_BACKGROUND_TASKS=1CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUNDnot set to1CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSnot set to0
Keep its input open: the run does not wait for MCP Tasks after input closes. A one-shot claude -p "..." invocation does not get Tasks. GitHub Actions being a supported surface does not remove these input-mode requirements.
The environment-variable reference identifies several flag-fetching blockers:
DISABLE_GROWTHBOOK=1ortrueDO_NOT_TRACK=1- Any nonempty
DISABLE_TELEMETRY - Any nonempty
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
For the last two variables, even 0 or false disables the relevant behavior. Ordinary third-party-provider sessions, including Amazon Bedrock, also skip flag fetching; the reference documents an exception for host-managed embeddings.
Inspect the launching environment and effective settings. The usual settings files are ~/.claude/settings.json, .claude/settings.json, and .claude/settings.local.json, with managed settings also relevant. The settings reference explains their scopes.
Removing a legacy override cannot upgrade a server that lacks the newer protocol. Likewise, API compatibility through a gateway does not establish feature-flag eligibility. If your deployment must retain a blocking setting, use ordinary tool calls.
For interactive sessions, CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS=0 makes Claude wait. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND=1 also makes it wait for Tasks, although ordinary automatic backgrounding can subsequently move a long call. CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 alone does not force MCP Tasks to stay in the foreground.
Run one job and verify the result
Start with an authenticated server whose documentation or implementation establishes Tasks support, then try one non-destructive job. In Bash, check the installation and configured servers before opening the interactive CLI:
claude --version
claude mcp list
claude
For a self-updating installation below the minimum version, run claude update and recheck. These commands are covered by the CLI reference.
Inside Claude Code, use /mcp to confirm the server is connected and complete any required authentication. For a connected test-runner tool, a useful request is:
Run this repository’s test suite through its MCP tool from the main conversation. While it runs, explain the test layout from the README. When the job finishes, report the result and any failures.
Verify the behavior at two levels:
- In Claude Code: look for the MCP task count and inspect
/tasks. An entry in/tasksby itself is insufficient because ordinary background calls appear there too. - In your server’s trace: confirm that
tools/callreturnedresultType: "task"and that subsequenttasks/getrequests refer to the sametaskId.
At completion, Claude Code receives the result; ask Claude to report it. If Claude is idle, it can pick up the result automatically. If the call remains ordinary, inspect the actual request’s capabilities and the eligibility checklist before rewriting the tool.
Server authors: return a handle and deliver the outcome
Implement the current Tasks extension rather than copying an older experimental example. The MCP 2026-07-28 changes replaced tasks/result with polling through tasks/get, added tasks/update, and removed tasks/list.
Return a task only when the request permits it
Check the capability on each request at:
params._meta["io.modelcontextprotocol/clientCapabilities"].extensions["io.modelcontextprotocol/tasks"]
Its value is {}. Your server advertises the corresponding extension under capabilities.extensions in its server/discover response. The Tasks extension overview documents both locations.
When the client declares support, the server decides whether that particular operation should become a Task. Without the capability, return an ordinary result when possible. If the operation requires Tasks, the extension defines the missing-capability error -32021; do not return a task handle to an incapable caller.
Persist the task before replying, so its ID already resolves through tasks/get. Keep it answerable across connections, and check authentication and task access on follow-up requests.
This illustrative JSON-RPC response accepts a build. Its ID, timestamps, and eventual result are examples, not an execution record:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "task",
"taskId": "6f17bfa2-4c5e-4d21-b563-2f7e83a902bc",
"status": "working",
"createdAt": "2026-10-24T08:00:00Z",
"lastUpdatedAt": "2026-10-24T08:00:00Z",
"ttlMs": 3600000,
"pollIntervalMs": 5000
}
}
The task fields sit directly inside JSON-RPC result. There is no additional task wrapper, and the initial handle needs no content array.
| Field | Requirement |
|---|---|
resultType | "task" for the initial task response. |
taskId | Required, server-generated, and difficult to guess. Claude Code additionally limits it to 128 printable ASCII characters with no spaces. |
status | Required: working, input_required, completed, failed, or cancelled. |
createdAt, lastUpdatedAt | Required ISO 8601 timestamp strings. |
ttlMs | Required integer milliseconds measured from creation, or null for unlimited retention. It is not a job-duration estimate. |
pollIntervalMs | Optional integer polling interval in milliseconds; do not send null. |
statusMessage | Optional progress or status text. |
The released extension schema defines the structure. Claude-specific validation is documented in the server-author reference.
If Claude reports Unsupported result type 'task' for tools/call, check whether the incoming request included the extension, then verify that none of taskId, status, createdAt, lastUpdatedAt, or ttlMs is missing. An unsupported status value produces the same error. An invalid task ID instead produces a malformed-task-handle error.
Put the completed tool result in tasks/get
Answer each poll with the task’s current state. A successful tasks/get response uses resultType: "complete" even while the job’s status remains working: the polling request has completed, not necessarily the job.
For the illustrative build above, a completed response is:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"taskId": "6f17bfa2-4c5e-4d21-b563-2f7e83a902bc",
"status": "completed",
"createdAt": "2026-10-24T08:00:00Z",
"lastUpdatedAt": "2026-10-24T08:03:00Z",
"ttlMs": 3600000,
"result": {
"resultType": "complete",
"content": [
{
"type": "text",
"text": "Build completed successfully."
}
]
}
}
}
The nested result contains the normal tool result. A tool-level error using isError: true still belongs in a completed task; failed is reserved for a JSON-RPC execution error carried in error.
Implement tasks/cancel as well, but treat cancellation as cooperative. The extension specification does not guarantee that cancellation stops work already underway. Claude Code currently retrieves outcomes through polling, so do not rely on notifications/tasks to deliver the result.
Use Elicitation for decisions the tool cannot make
Ask for the missing environment, destination, or approval before performing the action that depends on it. Form-mode elicitation collects structured fields; URL mode offers a browser flow, such as external sign-in.
During a Task, expose a question through tasks/get with status: "input_required" and an inputRequests map. Each entry uses a unique key and contains the requested method, such as elicitation/create, plus its params. Claude Code sends the answer through tasks/update, using matching keys in inputResponses.
In the interactive CLI, close /tasks if the question is hidden behind it. Declining or pressing Esc answers the elicitation; the server decides whether its job continues.
For a Task requesting user input in a noninteractive session, Claude Code asks the server to cancel it without running Elicitation hooks or the Agent SDK’s onElicitation callback. Supply required choices before starting unattended work, or use an interactive session. This restriction is specific to input requested through MCP Tasks.
Also audit hooks before treating an elicitation as human approval. The hooks reference documents that:
Elicitationcan answer automatically and suppress the dialog.ElicitationResultcan change the user’s response, including replacing a refusal with acceptance if written incorrectly.ElicitationResultdoes not run when anElicitationhook already answered.
Review effective hooks from user, project, local, managed, and plugin configuration. Checking only the repository’s settings file can miss the hook that supplies an answer.
What happens on stop, exit, clear, and resume?
Stop a remote Task explicitly if you want to request cancellation; exiting the CLI does not do that. The documented lifecycle distinguishes server execution from Claude Code’s tracking.
| Action | Result and next step |
|---|---|
Select the Task in /tasks and press x, or ask Claude to stop it | Claude Code stops following it and requests cancellation. The server may still finish. |
Press Esc during ordinary interaction | This does not stop a background Task. |
| Exit while a remote Task runs | The server job continues. Resume its original session to follow it again. |
| Exit with a stdio Task | The local server process stops. Do not assume its work survives unless the server explicitly supports execution beyond that process. |
Use /clear, /branch, or switch sessions with /resume while Claude Code stays open | The result can arrive in the current conversation. After exiting, resume the session where the Task originally started. |
| Resume the original session interactively | Tracking resumes after the server reconnects, provided it still knows the Task. Keep its name and connection settings unchanged. |
Start a new session or use --fork-session | The new session does not inherit tracking of the Task. |
Resume through one-shot claude -p | That run does not follow the Task; use interactive resume or qualifying streaming input. |
If the server is disconnected, reconnect it through /mcp before stopping the Task. Otherwise no cancellation request reaches it, and Claude Code forgets the Task.
Use claude --resume to select the original conversation. The server’s retention policy still matters: a resumable conversation cannot recover a result the server has discarded.
A prompt to audit your MCP setup
Use a read-only audit to identify the smallest useful change before modifying servers or settings. This prompt adapts @Voxyz_ai’s MCP audit suggestion, adding checks for the current response format and streaming-session behavior.
Goal: Audit my Claude Code MCP setup for Tasks and Elicitation.
Read the current official documentation:
https://code.claude.com/docs/en/mcp
https://code.claude.com/docs/en/env-vars
https://code.claude.com/docs/en/hooks
https://modelcontextprotocol.io/extensions/tasks/overview
Scope: Inspect connected MCP servers, their configuration, effective settings, and any MCP server implementation in this repository. Say explicitly if no server implementation is present. Keep credential values out of the report.
Check:
1. Long-running tools: identify builds, test runs, exports, or research that could benefit from Tasks. For my server code, recommend the smallest change to return a valid task handle, persist it across connections, and deliver the final result through tasks/get. For third-party servers, cite evidence for the deployed version's support; otherwise mark support unknown.
2. Eligibility: check the CLI version, transport, actual protocol revision, per-request Tasks capability, feature-flag fetching, provider, supported surface, main conversation versus subagents, and input mode. Include MCP_SDK_GENERATION, MCP_PROTOCOL_NEGOTIATION, privacy/flag-fetching variables, CLAUDE_AUTO_BACKGROUND_TASKS, CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND, and CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS. Distinguish one-shot claude -p from stream-json input.
3. Elicitation: find tools that guess missing parameters or perform irreversible actions without obtaining the necessary decision. Inspect Elicitation and ElicitationResult hooks for automatic acceptance or changes to a user's refusal, including hooks outside this repository.
4. Lifecycle: check cancellation, remote versus stdio execution, retention, and resume. Identify unattended Tasks that might request user input.
Output: For each finding, name the tool or setting, cite the evidence, describe current behavior, recommend the smallest change, and give one verification step. Mark conditions you cannot observe as unknown.
Do not edit files, change settings, or invoke operational jobs during this audit. Show recommendations first.