[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

Open 💬 3 comments Opened Jun 30, 2026 by PrashamTrivedi

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 ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗