DEV Community

Piekwerk
Piekwerk

Posted on

MCP tasks landed in Claude Code: a tool call can now outlive your session, and 6 config decisions come with it

Claude Code's MCP documentation now carries a full section on server-side MCP tasks, and coverage on October 25 flagged what it means: the feature is live as a public beta, starting with the CLI. The short version is that a long tool call is no longer a request you wait on. The tool call returns as soon as the server accepts the job, the job keeps running on the server, and Claude Code follows it by polling status in the background. The footer shows a count like 1 MCP task while that happens.

It requires Claude Code v2.1.304 or later, which shipped October 19. I read the whole docs section, because it moves several defaults that agent config people care about. Here are the six decisions it forces, and where each one lands in your settings.

Decision 1: wait, or let it run in the background

By default a task in the background has no Claude Code time limit. The normal tool call limits, the wall-clock limit and the idle timeout, only apply until the server answers the call with the task. After that, Claude Code polls, and answered status checks count as activity for the idle timeout.

The subtle part is the default path. Automatic backgrounding moves a long call after two minutes, and the moved call is a plain background call, not an MCP task. It does not survive exiting the session. So the default behavior hands you the weaker of the two mechanisms exactly when calls run long. Two environment variables change that, both settable in the env block of settings.json:

{
  "env": {
    "CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS": "0"
  }
}
Enter fullscreen mode Exit fullscreen mode

CLAUDE_CODE_MCP_AUTO_BACKGROUND_MS set to 0 makes Claude wait for every MCP tool call until the call ends. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND set to 1 waits for a task's result specifically. One trap from the docs worth repeating: setting CLAUDE_CODE_DISABLE_BACKGROUND_TASKS to 1 or starting in bare mode does not, by itself, make Claude wait for MCP tasks.

Decision 2: what happens when a task asks a question nobody can answer

A running task can open an elicitation dialog to ask you for input. Declining, or pressing Esc, is an answer, and the server then decides whether the task goes on. One UI detail that will confuse somebody on your team: while the /tasks panel is open, the dialog stays hidden, so close the panel to answer.

Elicitation itself has two modes. Form mode shows fields the server defines. URL mode hands a link to your system browser, for flows that finish outside the terminal. URL mode has a length cap with odd arithmetic: every character that needs escaping counts four times toward the cap, so a clean URL reaches it around 8,000 characters and a heavily percent-escaped one around 4,000. Over the cap, the only option is to decline.

The part your config actually owns is the headless case. In a non-interactive session, Claude Code asks the server to cancel a task that requests input, and it does this without running your Elicitation hooks and without calling the Agent SDK's onElicitation callback. Your auto-respond hook is an interactive-session tool. If a pipeline goes through -p, a task that asks a question dies instead. Release 2.1.310 also changed the timeout error for exactly this case, so Claude now gets told that no answer came and does not repeat the call. If you run unattended sessions against servers that elicit, that failure mode belongs in your runbook, not in your hopes.

Decision 3: what you let survive an exit

A task on a remote server keeps running after you exit Claude Code. A stdio server's process stops when Claude Code exits. The docs put it plainly: unless the server's documentation says the work outlives the process, let those tasks finish or stop them first.

The resume rules have edges worth memorizing now rather than during an incident:

  • /clear or /branch: the result still arrives in your current conversation.
  • claude --resume or --continue: Claude Code follows the task again once the server connects, and picks up the result if it finished meanwhile.
  • A one-shot claude -p "<prompt>" run does not follow the task. Resume interactively, or with --input-format stream-json.
  • A new session, or --fork-session, does not follow it either.

Stopping is its own skill. Esc does not stop a background task. You select it in /tasks and press x, and if the server got disconnected you reconnect from /mcp first, because otherwise no cancel request goes out and Claude Code forgets the task. The status messages have a 300-second family, "did not reconnect within 300s", "no sign-in accepted within 300s", five minutes of error answers, and a "rejected this task's id" case where Claude Code keeps asking for up to five minutes.

Decision 4: what an idle agent may do with a finished result

The result goes to Claude, not into the transcript, so you ask Claude for it. And if Claude is idle when the result arrives, Claude starts on it unprompted. Read that again with your permissions hat on. A job you may have forgotten about, started by a server, hands its output to an agent sitting idle, and the agent acts.

This is fine when your guardrails are real and mostly noise when they are decorative. It renews the argument for deny rules that actually cover the tools a result might trigger, and for watching what got blocked. The safety_event telemetry from 2.1.307 is the right instrument here, I wrote it up when it landed.

Decision 5: which of your servers get tasks at all

A tool call becomes an MCP task only when all of these hold. The server supports tasks. It is an HTTP, stdio, or claude.ai connector server connected on protocol revision 2026-07-28, so setting MCP_SDK_GENERATION=v1 or MCP_PROTOCOL_NEGOTIATION=legacy rules it out. The session fetches feature flags, which rules out third-party providers like Bedrock and any setup with telemetry or flag fetching turned off. And Anthropic has to have turned tasks on for your kind of session: on v2.1.304 or later that covers terminal CLI sessions, Agent SDK sessions, and GitHub Actions runs. The VS Code extension and the desktop app do not have MCP tasks yet.

If you probed your servers when 2.1.292 started asking for the 2026-07-28 revision, that probe list is your shortlist. Servers stuck on 2025-11-25 keep their old behaviors, including the URL-prompt path that needs "bareElicitationCapability": true in the server's MCP config entry.

Decision 6: what you promise the server side

If you build MCP servers, the contract is explicit. On a 2026-07-28 connection, each request carries Claude Code's client capabilities at params._meta["io.modelcontextprotocol/clientCapabilities"], with "io.modelcontextprotocol/tasks": {} under extensions. A tools/call request that cannot become a task omits that extension, so you can detect support per call rather than per server. Claude Code also declares elicitation: {form: {}, url: {}} in its capabilities on those connections.

The server-side story across ecosystems is bigger than this client release. The C# SDK made mid-call input a first-class round trip in its 2.0 line, I covered that stabilization today, and the two pieces are the same protocol revision showing up on both ends. A server that answers a long call with a task, and a client that follows it across sessions, is a different operational model from a two-minute tool call that times out.

The config answer, compressed

My answers, for a start: decide the wait behavior explicitly instead of inheriting the two-minute default, audit any unattended -p pipeline against servers that elicit, and treat "idle Claude starts on results unprompted" as a permission question rather than a convenience. Everything else, resume semantics, stop keys, status timeouts, is muscle memory you build the first time a build task outlives its terminal. The docs page is the source of truth and this is a beta, so expect the edges to move.

Top comments (1)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.