DEV Community

RAXXO Studios
RAXXO Studios

Posted on Originally published at raxxo.shop

Claude Code 2.1.319 Adds MCP Task Backgrounding and a Deny Setting

  • Claude Code 2.1.319 shipped November 6 and moves MCP tool calls running as tasks to the background automatically

  • A new permissions.denyInsteadOfPrompting setting denies any call that would hang waiting on an unanswered prompt

  • The release also ships 90 bug fixes, including one where claude -p wrongly exited 0 after a refused action

  • For solo builders running unattended agents, the deny setting matters more than the backgrounding feature

Claude Code 2.1.319 landed on November 6 and quietly fixed the failure mode that makes unattended agents useless: a permission prompt nobody is there to answer. The same release teaches Claude Code to stop blocking on slow MCP tool calls, moving them to the background instead. Neither change is flashy, but both are the kind of fix a solo builder running scheduled jobs actually feels.

What Changed in Claude Code 2.1.319?

The headline additions are MCP task support in the terminal and a new permissions.denyInsteadOfPrompting setting. When an MCP server runs a tool call as a task, Claude Code now moves it to the background right away and tells Claude the result once it finishes, instead of freezing the whole turn until that one call returns. If you'd rather keep the old blocking behavior, the CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND environment variable brings it back, and CLAUDE_CODE_DISABLE_MCP_TASKS=1 turns off MCP tasks entirely.

The permission change is smaller to describe and bigger in practice. With permissions.denyInsteadOfPrompting set, a tool call that would normally wait on a permission prompt gets denied immediately instead, and the turn just continues. The changelog names three places it applies: terminal sessions, subagents, and teammates.

Alongside those two, the release adds /claude-api latency-optimize, a command that looks for where your Claude API code makes people wait and tests faster settings against your own eval. There's also a CLAUDE_CODE_DISABLE_FEATURE_FLAGS variable that stops feature-flag fetching without touching telemetry, so every flag just falls back to its built-in default. Teams running their own Claude apps gateway get a pile of smaller additions too: pooled budget priority rules, a custom sign-in notice, JSON-formatted operational logs. None of that is for a one-person studio, but it tells you where Anthropic is spending its maintenance budget this week, and it's not on flashy features.

I'm not going to pretend the 2.1.319 notes are thrilling reading. There's no new model, no new UI. What's actually in this release is 16 improvements and 90 bug fixes, most of them the unglamorous kind: a diff pane that stopped opening blank after 64 edits in one session, a slash command typed after a leading space finally running instead of being sent as plain text, Monitor's websocket watch no longer failing behind certain proxies. A couple land close to this piece's theme directly: scheduled tasks were silently dropping a connector named memory, which now stays mounted under a short suffix instead of vanishing, and background tasks that kept running past /clear were disappearing from the task list until something else started or finished.

That's the whole release in one sentence: a maintenance pass with two features bolted on, aimed at making jobs you don't watch tell you the truth.

How Does MCP Task Backgrounding Actually Work?

It works by letting a slow call stop blocking everything else. Before this release, if an MCP server took its time answering a tool call, say a search against a large index, or a request to an external API wrapped as an MCP tool, the whole Claude Code turn sat there waiting on it. Nothing else could happen until that one call returned.

Now, when the server marks that call as a task, Claude Code hands it off to the background the moment it starts. Claude gets told the result when the task finishes, but it isn't stuck watching the clock in the meantime. Picture three MCP servers doing three different jobs in one workflow: a file search, a short lookup, and one slow third-party call. Before 2.1.319, the slow one set the pace for the other two by definition. Now it doesn't.

Not every MCP server will make use of this on day one. Marking a call as a task is something the server has to do; Claude Code just reacts to it once it's marked that way. If none of the servers you use support it yet, you won't notice a thing changing today, only once they catch up.

The two opt-outs matter for different reasons. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND is for when you want the old wait-and-block behavior back, maybe because your workflow depends on strict ordering. CLAUDE_CODE_DISABLE_MCP_TASKS=1 is the bigger hammer: it turns off MCP tasks completely, which you'd reach for if a particular server's task reporting is buggy and you'd rather it just block than report a wrong result quietly. I haven't hit that case yet, but I'd want the switch available before I needed it, not after.

One detail worth knowing if you're on Bedrock, Vertex, Foundry, or behind an LLM gateway with telemetry or feature flags off: MCP tasks are built to keep working there too, since the backgrounding logic doesn't depend on flag fetching.

If a background task comes back with something clearly wrong, check the MCP server's own logs before Claude Code's. Backgrounding changes when you're told the result, not what the server actually computed, so a bad answer is still the server's problem, not a new one this release introduced.

That's the backgrounding story, in full.

Is permissions.denyInsteadOfPrompting Worth Turning On?

Yes, for anything that runs without a person watching it. This is the setting I'd flip on today for every scheduled or CI job. Before it existed, a tool call that needed approval and got no answer in a terminal session, a subagent, or a teammate would just sit there. On a scheduled run, that's not a pause, it's a dead session that burns its time budget doing nothing.

Any job you kick off and walk away from, a nightly sync, a scheduled report, a cron-triggered agent, is exactly the kind of work this setting is aimed at, whether or not your particular session type is one of the three the changelog names.

With permissions.denyInsteadOfPrompting on, that same call gets refused on the spot and the turn moves forward. The agent doesn't get what it asked for, but it also doesn't hang, and whatever comes next in the script still runs. For an unattended job, a clean denial you can see in the log beats a silent hang every time.

A hang helps nobody. A denial at least tells you something.

This release pairs well with a fix from the same changelog: claude -p in auto mode used to exit 0 even when its actions were refused because no safety check was available, so a script checking only the exit code would think everything worked when nothing had happened. Text and JSON output now exit 1 in that case. Put the two together and you get an unattended agent that fails loudly instead of succeeding quietly at doing nothing, which is exactly what I want from anything I'm not watching.

I'd leave the setting off for interactive sessions, where I actually want to see the prompt and decide. It's a tool for the sessions nobody is reading, not a blanket default.

What Solo Builders Should Actually Do With This

I'd update to 2.1.319 or later this week, mainly for the exit-code and permission fixes rather than the new features, and I'd check the version with claude --version before assuming I already have it. Point releases land fast enough that it's easy to be two or three behind without noticing.

If you run anything on a schedule, whether that's a nightly content job, a backup script, or a monitoring check, add permissions.denyInsteadOfPrompting to that session's settings today. Turning it on is one line in settings.json, scoped to the session or project that runs unattended rather than set globally, since the whole point is picking which jobs should fail safely on their own, not making every session impossible to approve by hand. It costs you nothing when everything goes right, and it saves a wasted run when a permission you didn't anticipate comes up. Leave your interactive terminal sessions as they are; you still want the prompt there.

If you lean on MCP servers for anything slow, a vector search, a scrape, a third-party API call, you'll likely feel the backgrounding change once those servers support it, without doing anything at all on your end. Keep CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND in your back pocket in case one server's task reporting turns out to be unreliable. I'd rather know the escape hatch exists than discover it mid-incident.

None of this replaces reading your own logs. A denied call still means the step didn't happen, and the fix for that is still you, not the setting. What changed is that you'll know it didn't happen, which is most of the battle with anything unattended.

This release follows a run of similar ones. 2.1.318 fixed a related false-success bug in claude -p, 2.1.317 added a warning when a new scheduled task picks up connectors you never asked for, and 2.1.316 shipped the subagent effort dial the same week Opus 4.8 fast mode got its deprecation notice. Read together, the last month of releases is about one thing: making unattended Claude Code sessions tell the truth about what they actually did.

Bottom Line

2.1.319 won't show up in a highlight reel. There's no new model and no feature you'll screenshot. What it does is close a gap that only shows up once you're running Claude Code without watching it: a permission prompt that used to hang forever now gets denied and logged, and a slow MCP call no longer freezes the session around it.

If you run any scheduled or unattended job, turn on permissions.denyInsteadOfPrompting this week and update past 2.1.319 for the exit-code fix that comes with it. If you only ever use Claude Code interactively at your own keyboard, this release changes less for you, and that's fine too. Not every update is for every workflow. The question worth asking is simpler: if a prompt came up in your last unattended run and nobody answered it, do you actually know what happened next, or did the script just assume the best?

Top comments (0)