[BUG] Cloud routines / Claude Code on the web have no non-interactive way to trust a project-scoped `.mcp.json` MCP server - daily routine broke after the untrusted-workspace gate

Status Fixed / completed
Reported on v2.1.196
Maintainer reply None cached
Activity 4 comments · opened Jun 30, 2026 · closed Aug 28, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What happened

A scheduled Routine running on Claude Code on the web (cloud sandbox) calls tools from a project-scoped MCP server declared in the repo's .mcp.json, auto-approved via the repo's committed .claude/settings.json (permissions.allow: ["mcp__<server>__*"]).

This worked until ~2.1.196. Now every run, the MCP server sits at ⏸ Pending approval and/or its tools are denied, because the committed project config is treated as an untrusted workspace and ignored:

Ignoring N permissions.allow entries from .claude/settings.json: this workspace has not been trusted.
Run Claude Code interactively here once and accept the trust dialog, or set
projects["/path/to/repo"].hasTrustDialogAccepted: true in ~/.claude.json.

The relevant hardening:

2.1.196 — Security: claude mcp list/get no longer spawn .mcp.json servers that a repo self-approved via a committed .claude/settings.json; untrusted workspaces show ⏸ Pending approval

(The project-scoped ⏸ Pending approval gate itself landed earlier, ~2.1.154.)

Why this is unfixable for a routine

Every documented remedy is interactive, and a cloud routine has no human and no TUI:

  • "Accept the workspace trust dialog" — no dialog in a non-interactive cloud routine.
  • "Approve the server in the /mcp panel" — no /mcp panel in a routine.
  • claude mcp reset-project-choices — interactive re-prompt; nothing to re-prompt to.
  • hasTrustDialogAccepted: true in ~/.claude.json — the cloud sandbox is re-cloned per run; there is no persistent ~/.claude.json to set.

There is also no web-UI affordance to trust/approve a repo-scoped (.mcp.json) server — the connector UI only manages account-level connectors, so a server that exists only in the repo has nowhere to be approved from.

Net: the project-MCP approval model assumes an interactive session, but routines are non-interactive by definition. The two are mutually exclusive, with no escape hatch.

Repro

  1. Repo with .mcp.json declaring a project-scoped (e.g. HTTP) MCP server and .claude/settings.json with permissions.allow: ["mcp__<server>__*"].
  2. Configure a Routine on Claude Code web that calls a tool from that server.
  3. Run it (or wait for schedule).
  4. Server shows ⏸ Pending approval / tool calls are denied; routine fails. No way to approve from within the non-interactive run.

Confirming the rule syntax is NOT the problem

The same glob, supplied from a trusted source (CLI flag, which bypasses the untrusted-workspace gate), auto-approves with zero denials — proving the permission rule is valid and the issue is purely trust-source, not syntax:

claude -p "call <tool>" --permission-mode default --allowedTools 'mcp__<server>__*'
→ result returned, permission_denials: []

Whereas relying on the committed permissions.allow from .claude/settings.json in the same (untrusted) workspace → ignored.

Expected

A non-interactive way for a cloud routine / web session to trust a project-scoped .mcp.json server + its tools, e.g. any of:

  • A per-routine "trust this repo's MCP servers / approve these tools" setting in the web UI.
  • Honor enabledMcpjsonServers + permissions.allow from a committed .claude/settings.json when the routine owner is the repo owner (or behind an explicit opt-in flag).
  • A documented, supported headless approval (e.g. claude mcp approve <server> --scope project usable from a setup script).

Current workaround (for others hitting this)

Register the server from a trusted source the gate doesn't touch — user scope — at session start, e.g. in the cloud environment setup script (runs before the session) or a committed SessionStart hook:

claude mcp add -s user -t http <server> <url> -H "Authorization: Bearer $TOKEN"

with the secret in a cloud environment variable. Pair with a non-prompting permission mode. This sidesteps the repo-self-approval gate but defeats the point of repo-scoped config.

Related

  • #69960 — Cloud routines (CCR) cannot use Slack MCP write tools, "Always allow" unavailable (closed, same class, routine case unsolved)
  • #69055 — Routine inside Claude Code being skipped
  • #9189 — Project-scoped MCP servers don't trigger approval prompt
  • #63308 — docs omit claude mcp list/get pending-approval output for unapproved project servers
  • #12227 — Workspace trust not persisting
  • #67319 — Trust dialog never fires on a non-CLI surface → project .claude/settings.json silently skipped
  • #69953 — 3P mode: custom MCP servers blocked, allowedMcpServers hardcoded empty

Environment

  • Claude Code 2.1.196
  • Surface: Claude Code on the web (cloud routine / scheduled session)
  • MCP: project-scoped HTTP server in .mcp.json, bearer-auth

View original on GitHub ↗

3 Comments

Shocktrooper · 2 months ago

I too have ran into this with previously working projects

warmfire540 · 1 month ago

I believe I have this issue too. I have a local mcp and approvals in the settings, but this is all ignored during cloud routines and the routine sits waiting for approvals for hours

rpelevin · 1 month ago

This looks like the same authority boundary in a more concrete routine shape.

I would separate three records before the run starts:

  1. workspace trust: the routine owner has explicitly trusted this repository's project-scoped server definition;
  2. server definition: the .mcp.json server command or URL, package/source digest, headers/secret binding, and exposed tool set are the approved inputs;
  3. invocation authority: the scheduled run may execute this tool under a specific routine id, principal, policy version, and scope.

The critical test is not "does settings.json contain an allow rule?" It is whether that rule can be promoted into an effective non-interactive pre-grant for this cloud routine.

The fail-closed path should be equally explicit:

  • if project trust is missing, report untrusted_workspace before starting the server;
  • if the server definition changed, report approval_invalidated before any tool call;
  • if the tool/scope is outside the approved surface, report approval_required/no_effect;
  • if approval exists and all digests still match, run without a prompt and record the applied pre-grant.

That gives maintainers a clean regression boundary: a scheduled routine should either apply a typed pre-run authority record or fail before side effects. It should not park for hours on an approval surface that cannot be resolved inside the run.

Showing cached comments. Read the full discussion on GitHub ↗