Fix Scheduled Routines MCP 'Tool Call Requires Approval' Error on Claude.ai with Custom and First-Party Connectors (May 2026 Regression)
A regression introduced around 2026-05-20 caused every MCP tool call inside claude.ai scheduled routines to fail with 'Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval', silently no-oping all connector-dependent automations. The bug affected 18+ first-party connectors (Slack, Atlassian/Jira, Gmail, Google Calendar, Google Drive, Datadog, Sentry, Notion, Linear, Figma, Amplitude, Guru, Ramp, Zapier, monday.com, Todoist, Snowflake, Microsoft 365) and all custom OAuth MCP connectors. Root cause: the platform's permission model treated interactive approval (call-time 'ask the user') and unattended approval (bind-time grant from routine config) as a single gate, so routines with no human present silently failed. The permitted_tools field on mcp_connections was not being honored as a standing grant for the non-interactive routine surface. Anthropic deployed a platform-side fix within ~10 hours of acknowledgment. Local CLI cron jobs using the same connectors worked throughout as a temporary workaround.
Symptoms
- Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval on every MCP tool call inside scheduled routines
- Scheduled routines fire (last_fired_at updates) but produce no output — all MCP-dependent work silently no-ops
- Same MCP connector works perfectly from interactive surfaces: local Claude Code CLI, remote CLI, and claude.ai chat
- No approval UI surfaces during routine execution because the routine context is non-interactive by design
- Both first-party connectors (Slack, Notion, Datadog, Google Calendar) and custom OAuth MCP connectors affected
- Regression onset around 2026-05-20 — routines that had been working for days/weeks suddenly started failing
Error signatures
Streamable HTTP error: Error POSTing to endpoint: MCP tool call requires approval
MCP tool call requires approval
Possible causes
- Platform-side regression in the claude.ai routine execution layer introduced around 2026-05-20 that changed how MCP connector permissions are evaluated for non-interactive surfaces
- Permission model conflating interactive approval (call-time 'ask the user now') with unattended approval (bind-time grant from routine config) — routines have no human to click 'allow', so the approval gate degrades to a hard no when no interactive UI is available
- The permitted_tools field on mcp_connections was designed to act as a standing bind-time grant scoped to the routine surface but was not being honored, causing the system to fall through to the interactive approval gate which cannot succeed in a non-interactive context
- The permission logic was built for the interactive case first (where a user can click 'Allow') and bolted onto scheduled runs, where the same prompt silently becomes an infinite wait — the fix required splitting approval-at-bind-time (for unattended surfaces) from approval-at-call-time (for interactive surfaces)
Solutions
Verify and Reset Routine Connector Permissions
If routines continue to fail after the platform fix, the issue may be stale permission state from the regression window. Remove and re-add the MCP connector to the routine to force a fresh permission grant with proper bind-time approval. This resolves lingering state from the period when permitted_tools was not being honored as a standing grant.
- In claude.ai/code, navigate to the affected routine's settings
- Remove the MCP connector from the routine and save
- Re-add the same MCP connector to the routine
- Confirm the 'no approval needed' banner appears for the connector's permitted tools
- Manually trigger the routine via 'Run now' to verify the fix
Commands
# If using the API to manage routines, GET then PATCH to force re-grant:
# First, GET the current configuration:
curl -s -H "Authorization: Bearer $CLAUDE_API_KEY" "https://api.claude.ai/v1/code/triggers/<routine_id>" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps(d.get('mcp_connections',[]), indent=2))"# Then PATCH with modified mcp_connections to force re-grant:
# curl -s -X PATCH -H "Authorization: Bearer $CLAUDE_API_KEY" -H "Content-Type: application/json" \
# -d '{"mcp_connections":[...]}' "https://api.claude.ai/v1/code/triggers/<routine_id>"Config examples
{
"mcp_connections": [{
"connector_uuid": "<uuid>",
"name": "Slack",
"permitted_tools": ["slack-post-message", "slack-list-channels"],
"url": "https://mcp.claude.ai/connectors/slack"
}]
}Risks
- Removing and re-adding the connector may require re-authorizing OAuth if the token expired during the regression window
- Custom connector URLs must be re-entered if they aren't auto-populated
Verification
- Step 1: Remove connector from routine → save → re-add connector → save → expect: 'no approval needed' banner appears in the routine settings UI (below the connector name)
- Step 2: Click 'Run now' on the routine → expect: routine completes without 'MCP tool call requires approval' error (open DevTools → Console tab before clicking to catch Streamable HTTP errors)
- Step 3: Check destination connector for expected output → expect: output from the test run is present (e.g., Slack message posted, Jira comment added, Google Calendar event created with timestamp within last 2 minutes of clicking 'Run now')
Use Local CLI Cron as Workaround During Platform Outages
While the routine surface was broken, the same MCP connectors worked perfectly from local Claude Code CLI sessions against identical OAuth grants. For production-critical MCP automations, maintain a local CLI-based cron fallback that can be activated when platform-side routine issues are detected. This pattern also provides resilience against future platform regressions.
- Set up a local cron job or launchd/systemd timer that invokes Claude Code CLI with the same MCP connector and task prompt
- Use the --print flag for non-interactive execution: claude --print 'Call mcp__connector__tool with parameters X and reply ok'
- Monitor both the platform routine and the local cron via a health check that verifies output landed in the destination connector
- When platform routine fails (output missing), the local cron continues to provide coverage
Commands
# Example: local CLI cron invocation with MCP connector (test interactively first):
claude --print 'Using the Slack MCP connector, post "Daily health check passed" to #alerts channel' 2>&1
# Check that local CLI has the same MCP connector configured:
claude mcp list 2>/dev/null || python3 -c "import json; d=json.load(open('$HOME/.claude/mcp.json')); print(list(d.get('mcpServers',{}).keys()))"# Verify the specific tool is callable (replace placeholders):
claude --print 'Call mcp__<connector>__<tool> with {{"param": "value"}} and reply with the result' 2>&1 | head -20Config examples
{
"mcpServers": {
"claude_ai_slack": {
"type": "remote",
"url": "https://mcp.claude.ai/connectors/slack"
}
}
}Risks
- Local CLI requires the machine to be running when the cron fires (unlike claude.ai routines which run on platform infrastructure)
- May consume local API quota/tokens instead of platform routine allocation
- Requires maintaining OAuth tokens on the local machine separately from claude.ai
Verification
- Step 1: Run 'claude mcp list' → expect: the same connector shown in claude.ai routine settings appears in the list (at least one entry)
- Step 2: Run 'claude --print "Call mcp__<connector>__<list_tool> with no params and reply ok"' → expect: tool executes successfully, output contains expected data (e.g., list of Slack channels, list of Jira issues)
- Step 3: Add a cron entry (e.g., '0 */6 * * * cd /path && claude --print "..."') and wait for it to fire → expect: output from the cron-invoked Claude Code session lands in destination connector
Diagnose: Confirm This Is the Routine-Surface Approval Bug (Not Interactive Approval)
An AI agent or developer encountering 'MCP tool call requires approval' needs to determine whether this is the routine-surface regression (platform bug, server-side fix) or a different MCP permission issue. This diagnostic solution provides the checks to isolate the root cause before applying workarounds. The decision tree: (a) If error occurs ONLY in scheduled routines AND MCP works from CLI → this is the routine-surface bug; (b) If error occurs in BOTH routines and interactive CLI → different issue (likely OAuth/permission config).
- Check the execution surface: is this error occurring in a scheduled routine (claude.ai/code → Routines) or during interactive use (CLI, chat, Desktop)?
- If in a routine: check last_fired_at — did the routine fire but produce no output? This confirms the bug pattern (routine executes, MCP calls silently fail)
- If interactive: this is NOT the routine-surface bug — the error here indicates a genuine permission/approval configuration issue that requires user interaction
- Cross-check: run the same MCP connector from local CLI. If CLI works but routine doesn't, this confirms the routine-surface regression
Commands
# AI AGENT DECISION TREE — run these checks in order to identify the root cause:
# Step A: Determine execution context
# If you can run this echo command, you are in an interactive context (CLI/chat), not a routine:
echo 'INTERACTIVE_CONTEXT' 2>/dev/null && echo '→ This is interactive. If MCP works here but not in routines, proceed to Step B.'
# Step B: Verify MCP works from CLI
claude mcp list 2>/dev/null || python3 -c "import json; d=json.load(open('$HOME/.claude/mcp.json')); print(list(d.get('mcpServers',{}).keys()))"# Step C: Test a tool call from CLI
claude --print 'Call mcp__<connector>__<tool> with minimal params and reply with the result' 2>&1 | grep -v 'Streamable HTTP error' | head -5
# Step D: If Steps B-C succeed but routine fails → confirmed routine-surface regression
Risks
- This diagnostic only confirms the bug — it does not fix it. The fix is server-side (see Solution 1).
- If MCP tools fail in BOTH routine and interactive contexts, the issue is different (likely OAuth token expiry or connector misconfiguration)
Verification
- Step 1: Run 'echo $CLAUDE_API_KEY' to confirm API access → expect: non-empty key string
- Step 2: Run 'claude mcp list' from local CLI → expect: list of configured MCP connectors appears (at least one connector should match what's configured in the failing routine)
- Step 3: From CLI, call the failing MCP tool: 'claude --print "Call mcp__<connector>__<tool> with minimal params and reply ok"' → expect: tool executes successfully, output contains expected data (no 'MCP tool call requires approval' error)
- Step 4: Compare with routine output — if Step 3 succeeds but routine doesn't produce output → expect: THIS CONFIRMS the routine-surface regression (proceed to Solution 1 or 3)
Wait for Platform Fix (Automatic Resolution)
Anthropic deployed a server-side fix within ~10 hours of acknowledging the issue on May 21, 2026 (first wave ~15:14 UTC, full resolution ~19:57 UTC). No client-side update is required — the fix is applied at the claude.ai platform level. Routines should resume working automatically. Staff member omid-ant confirmed resolution. If issues persist after the fix window, restart Claude Desktop and re-test.
- Confirm your routines are now executing: check claude.ai/code → Routines → last_fired_at shows recent timestamps post-2026-05-21T20:00Z
- Verify tool execution: check the destination connector (e.g., Slack channel, Google Calendar) for expected output from the most recent routine run
- If routines still fail post-fix: try removing and re-adding the MCP connector to the routine to force a fresh permission grant (see Solution 4)
- If the issue persists: file a new bug report referencing #61015 and the specific connector/error observed
Commands
# Diagnostic: check if the routine ran recently and what connectors are attached
# This helps an AI agent distinguish this bug from other MCP failures
curl -s -H "Authorization: Bearer $CLAUDE_API_KEY" "https://api.claude.ai/v1/code/triggers" 2>/dev/null | python3 -c "
import json, sys
triggers = json.load(sys.stdin).get('data', [])
for t in triggers:
name = t.get('name', 'unnamed')
last = t.get('last_fired_at', 'never')
conns = [c.get('name','?') for c in t.get('mcp_connections', [])]
print(f'{name}: last_fired={last}, connectors={conns}')
"# Check latest Claude Code version (informational — fix is platform-side, not client):
npm view @anthropic-ai/claude-code version 2>/dev/null
Risks
- None — the fix is automatic and server-side. No configuration change needed.
- If routines still fail after 2026-05-21T20:00Z, the cause may be a different issue (stale OAuth token, connector-specific bug)
Verification
- Step 1: Navigate to claude.ai/code → Routines and check last_fired_at timestamps → expect: timestamps show execution after 2026-05-21T20:00Z (post-fix window)
- Step 2: Check destination connector for expected output — e.g., Slack channel should have a new message, Google Calendar should have the event → expect: output from the most recent routine run is present in the destination
- Step 3: Click 'Run now' on the routine in claude.ai UI → expect: routine completes without 'MCP tool call requires approval' error (check browser DevTools → Console for Streamable HTTP errors if UI doesn't show detail)
- Step 4: From interactive Claude Code CLI, run 'claude mcp list' to confirm connector is configured, then call the same tool → expect: tool executes successfully, confirming the OAuth grant is intact and the bug is scoped to routine surface only
Agent JSON
Canonical machine-readable representation of this issue:
{
"issue_id": "352f0577-a4fe-4b32-9eb8-e5c0706526aa",
"slug": "fix-scheduled-routines-mcp-tool-call-requires-approval-error-on-claude-ai-with-custom-and-first-party-connectors-may-202-8w8s7b",
"verification_status": "unverified",
"canonical_json": "https://codekb.dev/v1/issues/fix-scheduled-routines-mcp-tool-call-requires-approval-error-on-claude-ai-with-custom-and-first-party-connectors-may-202-8w8s7b"
}