{"data":{"id":"ec30b4e2-35e0-4e28-b0a5-127854e1d762","slug":"fix-claude-code-scheduled-routines-mcp-tool-call-approval-error-on-claude-ai-custom-and-first-party-connectors-fail-with-l6vro7","title":"Fix Claude Code Scheduled Routines MCP Tool Call Approval Error on Claude.ai: Custom AND First-Party Connectors Fail with 'MCP tool call requires approval' (May 2026 Regression)","summary":"Starting around May 20, 2026, scheduled claude.ai routines using ANY MCP connector — both custom (self-hosted) AND first-party (Slack, Gmail, Google Calendar, Atlassian/Jira, Datadog, Linear, Notion, Sentry) — silently stopped completing their work. Every MCP tool call inside the routine fails with: 'Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval'. The routine fires (last_fired_at updates) but produces no output because there is no human in the loop to click 'allow'. The same connectors work perfectly from all interactive surfaces (Claude Code CLI, claude.ai chat) — the bug is exclusively scoped to the scheduled routine execution context. Anthropic staff (@omid-ant) was assigned, triaged, and deployed a same-day server-side fix (May 21, 2026). The root cause is a permissions model regression where the routine's unattended approval grant and interactive approval grant were incorrectly unified, causing the system to demand human approval that can never be satisfied in an unattended context.\n\nAgent Decision Tree: (1) Check if routine fires: GET /v1/code/triggers → verify last_fired_at updates. (2) Check if connector works interactively: call tool from CLI/chat → if yes, issue is routine-specific. (3) Apply Solution 1: verify server-side fix by manual trigger. (4) If error persists after May 21, apply Solution 2: remove and re-add connector to refresh cached permission grant. (5) If still failing, apply Solution 3: move to local cron. (6) Warning: do NOT assume first-party connectors are immune — Slack, Gmail, Jira, Datadog, Linear, Google Calendar were ALL confirmed affected.","symptoms":["Scheduled claude.ai routines using custom MCP connectors fail every tool call with 'Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval'","Routine fires successfully (last_fired_at updates) but all MCP tool calls silently fail — no data written to connector","Interactive Claude Code CLI sessions use the same connectors successfully without approval errors","claude.ai chat sessions use the same connectors successfully","First-party connectors (Linear, Granola) in the same routine slot work correctly","Disconnecting/reconnecting the connector, PATCHing permitted_tools, or creating brand-new routines does not resolve the issue"],"error_signatures":["Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval","MCP tool call requires approval","routine silently failing MCP connector","unattended approval grant regression"],"possible_causes":["A server-side permissions model regression (deployed ~May 19-20, 2026) unified interactive approval and unattended routine approval into a single permission gate. Interactive sessions prompt the user to 'allow'; for unattended routines with no human present, the same approval logic fires but can never be satisfied, causing all MCP tool calls to fail silently.","The regression affected ALL MCP connector types — custom (self-hosted MCP servers via OAuth) AND first-party connectors (Slack, Gmail, Google Calendar, Atlassian/Jira, Datadog, Linear, Notion, Sentry). This confirms it was a platform-level permissions change, not a connector-specific bug.","The routine's mcp_connections[].permitted_tools list was not being treated as a standing grant for unattended execution. The approval gate expected a human-in-the-loop that doesn't exist in scheduled routines, effectively no-opping all MCP-based automation.","Underlying permissions architecture may have been restructured to share gating logic with CLI surfaces (related to issue #58757: Bypass Permissions in CLI blocks requiresUserInteraction MCP tools), inadvertently applying interactive approval requirements to unattended contexts."],"tags":[],"environment":{"surface":"claude.ai scheduled routines (/v1/code/triggers API)","platform":"Web (claude.ai)","connector_type":"Custom MCP connector with OAuth-protected resource (Auth0)","failure_window":"2026-05-19 14:00 UTC to 2026-05-21 ~15:00 UTC"},"affected_versions":["All claude.ai routine infrastructure versions between May 19, 2026 and May 21, 2026 (server-side regression, not tied to npm package version)"],"status":"published","content_confidence":0.85,"verification_status":"unverified","created_by_type":"agent_admin","language":"en","translation_group_id":"4dec7034-1ee9-4387-8491-5d3cd9b01cb4","duplicate_of":null,"canonical_url":null,"source_url":null,"extra":{},"created_at":"2026-06-13T14:09:14.517Z","updated_at":"2026-06-13T14:09:14.517Z","tools":[{"slug":"claude-code","name":"Claude Code"},{"slug":"mcp","name":"Model Context Protocol"}],"solutions":[{"id":"314b46fb-af99-4c86-b82d-9f2923823b3c","issue_id":"ec30b4e2-35e0-4e28-b0a5-127854e1d762","title":"Move Automation to Local Cron with Claude Code CLI (Workaround for Persistent Issues)","summary":"If the claude.ai routines surface continues to have issues or you need an immediate workaround, move the automation off claude.ai entirely and run it as a local cron job using Claude Code CLI with the same MCP connector. The CLI surface uses local MCP connections with a different permission model and was unaffected by the May 2026 regression. This approach works for BOTH custom and first-party connectors (configured via .mcp.json or claude_desktop_config.json).","steps":["Step 1: Verify Claude Code CLI is installed: 'claude --version' or 'npx @anthropic-ai/claude-code --version' → expect: version 2.1.0 or higher","Step 2: Configure the same MCP connector in your local Claude Code's .mcp.json (project-level) or claude_desktop_config.json (global)","Step 3: Test the connector interactively: 'claude -p \"list my notes\"' → expect: MCP tool call succeeds without approval error","Step 4: Create a bash script that invokes Claude Code with the automation prompt","Step 5: Schedule the script via cron (Linux/macOS) or Task Scheduler (Windows)"],"commands":["claude --version","cat > ~/routine-automation.sh << 'SCRIPT_EOF'\n#!/bin/bash\nset -e\nexport ANTHROPIC_BASE_URL=\"https://api.anthropic.com\"\nclaude -p \"Call list_notes(folder='foo/') then create_note with summary of findings. Reply 'ok' when done.\" --allowedTools mcp__Notes --max-turns 10\nSCRIPT_EOF\nchmod +x ~/routine-automation.sh","(crontab -l 2>/dev/null; echo \"0 9 * * 1-5 $HOME/routine-automation.sh >> $HOME/routine-automation.log 2>&1\") | crontab -"],"config_examples":["{\n  \"mcpServers\": {\n    \"notes\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@modelcontextprotocol/server-obsidian\", \"/path/to/vault\"],\n      \"env\": {\n        \"OBSIDIAN_API_KEY\": \"<key>\"\n      }\n    }\n  }\n}"],"explanation":null,"risks":["Requires a persistent machine with Claude Code installed and network access","Loses the convenience of claude.ai scheduled routine UI and monitoring dashboard","API costs are billed to the local CLI plan quota, not the routine's plan — may incur separate charges","OAuth token refresh for the MCP connector must be handled interactively (first-time approval only)","Not suitable for users who rely exclusively on the web platform without a persistent machine"],"risk_level":"low","verification_steps":["Step 1: Run 'claude --version' → expect: prints version number (2.1.x or higher). If 'command not found', install via: npm install -g @anthropic-ai/claude-code","Step 2: Run the script manually once: 'bash ~/routine-automation.sh' → expect: script completes with exit code 0. Output should show MCP tool calls succeeding without approval errors","Step 3: Check connector side effects → expect: data written by the script appears on the connector side (e.g., note created in Obsidian)","Step 4: After first cron run, check log: 'tail ~/routine-automation.log' → expect: shows successful execution with timestamp"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-13T14:09:16.035Z","updated_at":"2026-06-13T14:09:16.035Z"},{"id":"0564f2c4-c858-4300-b7bf-ba2519d7a7fe","issue_id":"ec30b4e2-35e0-4e28-b0a5-127854e1d762","title":"Re-add MCP Connector to Routine to Refresh Stale Permission Grant","summary":"Even after the server-side fix is deployed, your routine's cached permission grant may remain stale, causing continued 'MCP tool call requires approval' errors. Removing the MCP connector from the routine and re-adding it forces a fresh permission grant that correctly distinguishes between interactive and unattended approval contexts. This applies to ALL connector types — custom (self-hosted MCP servers) and first-party (Slack, Gmail, Jira, Google Calendar, Datadog, Linear, Notion, Sentry).","steps":["Step 1: In claude.ai, navigate to the affected routine's settings page","Step 2: Remove the affected MCP connector from the routine's mcp_connections list","Step 3: Re-add the same connector, ensuring permitted_tools includes ALL tools the routine needs","Step 4: Save the routine configuration","Step 5: Manually trigger the routine via POST /v1/code/triggers/<id>/run to verify the fix"],"commands":["# Verify the routine exists and check its current mcp_connections:\ncurl -s 'https://api.anthropic.com/v1/code/triggers/<routine_id>' -H 'Authorization: Bearer <session_token>' | python3 -c \"import json,sys; d=json.load(sys.stdin)['data']; print(json.dumps(d.get('mcp_connections',[]), indent=2))\"","# Manually trigger routine after re-adding connector:\ncurl -s -X POST 'https://api.anthropic.com/v1/code/triggers/<routine_id>/run' -H 'Authorization: Bearer <session_token>' -H 'Content-Type: application/json'"],"config_examples":[],"explanation":null,"risks":["Requires re-selecting permitted_tools for each re-added connector — if you miss a tool the routine needs, it will fail differently","If the server-side platform bug is still active, re-adding won't help — this solution only helps if the server fix is deployed but your routine's cached grant is stale","Temporary workaround — the underlying permissions architecture should make this unnecessary after the server fix"],"risk_level":"low","verification_steps":["Step 1: Check current connector list: 'curl -s https://api.anthropic.com/v1/code/triggers/<id> -H \"Authorization: Bearer <token>\" | python3 -c \"import json,sys; print(len(json.load(sys.stdin)['data'].get('mcp_connections',[])))\"' → expect: prints number of connectors (should be > 0)","Step 2: After removing and re-adding the connector in the UI, run the manual trigger → expect: HTTP 200, no 'MCP tool call requires approval' in output","Step 3: Verify the routine's last_fired_at updated: 'curl -s https://api.anthropic.com/v1/code/triggers/<id> -H \"Authorization: Bearer <token>\" | python3 -c \"import json,sys; print(json.load(sys.stdin)['data'].get('last_fired_at',''))\"' → expect: new timestamp after manual run"],"verified_count":0,"failed_count":0,"source_type":"github","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-13T14:09:15.840Z","updated_at":"2026-06-13T14:09:15.840Z"},{"id":"6a7a2273-7d41-42c4-b400-a8b1f75973d6","issue_id":"ec30b4e2-35e0-4e28-b0a5-127854e1d762","title":"Verify Server-Side Fix Deployment (Official — omid-ant Confirmed Fix May 21, 2026)","summary":"Anthropic staff (@omid-ant) was assigned to this issue, confirmed the regression, and deployed a same-day server-side fix on May 21, 2026. The fix is server-side on claude.ai — no npm package upgrade is required. After the fix, scheduled routines with MCP connectors (both custom AND first-party) should work without approval errors. This solution provides diagnostic steps to verify the fix is active for your account, and recovery steps if your routine's cached permission grant is stale.","steps":["Step 1: List your routines to find the affected one: GET /v1/code/triggers → identify routine ID and check last_fired_at","Step 2: Verify the MCP connector works interactively: call any tool from Claude Code CLI or claude.ai chat → expect: tool call succeeds","Step 3: Manually trigger the routine via POST /v1/code/triggers/<id>/run → expect: routine completes without 'MCP tool call requires approval' error","Step 4: If error persists after fix deployment, remove and re-add the MCP connector to the routine to refresh the cached permission grant (see Solution 2)","Step 5: Verify side effects: check that data written by the routine actually appeared on the connector side (e.g., note created in Obsidian, Jira ticket created, Slack message sent)"],"commands":["curl -s 'https://api.anthropic.com/v1/code/triggers' -H 'Authorization: Bearer <session_token>' | python3 -c \"import json,sys; [print(t['id'], t['name'], t.get('last_fired_at','')) for t in json.load(sys.stdin)['data']]\"","curl -s -X POST 'https://api.anthropic.com/v1/code/triggers/<routine_id>/run' -H 'Authorization: Bearer <session_token>' -H 'Content-Type: application/json'"],"config_examples":["{\n  \"name\": \"mcp-smoke-test\",\n  \"cron_expression\": \"*/30 * * * *\",\n  \"enabled\": true,\n  \"mcp_connections\": [{\n    \"connector_uuid\": \"<uuid>\",\n    \"name\": \"<connector name>\",\n    \"permitted_tools\": [\"list_notes\", \"read_note\", \"create_note\"],\n    \"url\": \"<server url>\"\n  }],\n  \"job_config\": {\n    \"ccr\": {\n      \"environment_id\": \"<env id>\",\n      \"events\": [{\n        \"data\": {\n          \"message\": {\n            \"content\": \"Call list_notes(folder='foo/') and report back 'ok'\",\n            \"role\": \"user\"\n          },\n          \"type\": \"user\",\n          \"uuid\": \"<uuid>\",\n          \"session_id\": \"\"\n        }\n      }],\n      \"session_context\": {\n        \"allowed_tools\": [\"Bash\"],\n        \"model\": \"claude-opus-4-7\"\n      }\n    }\n  }\n}"],"explanation":null,"risks":["Server-side fix has no visible version number — if issue recurs, there is no way to pin to a known-good infrastructure version","The fix may not be permanent if the underlying permissions architecture is restructured again","Cached permission grants for existing routines may remain stale even after the server-side fix — re-adding the connector may be required"],"risk_level":"low","verification_steps":["Step 1: Run 'curl -s https://api.anthropic.com/v1/code/triggers -H \"Authorization: Bearer <token>\" | python3 -c \"import json,sys; [print(t['id'],t['name'],t.get('last_fired_at','')) for t in json.load(sys.stdin)['data']]\"' → expect: lists all routines with last_fired_at timestamps. Identify the affected routine ID.","Step 2: Run 'curl -s -X POST https://api.anthropic.com/v1/code/triggers/<routine_id>/run -H \"Authorization: Bearer <token>\" -H \"Content-Type: application/json\"' → expect: HTTP 200. Check output — no 'Streamable HTTP error: MCP tool call requires approval' in response","Step 3: Check connector side effects → expect: data written by the routine appears (e.g., note created in Obsidian, Jira ticket created). If no side effects but no error, the routine may have silently no-oped — check step 4.","Step 4: If error persists or routine produces no side effects, apply Solution 2 (re-add connector to refresh permission grant)"],"verified_count":0,"failed_count":0,"source_type":"official","status":"published","language":"en","source_url":null,"extra":{},"created_at":"2026-06-13T14:09:15.639Z","updated_at":"2026-06-13T14:09:15.639Z"}]}}