different-ai/openwork · warning
MCP_HTTP_429
MCP_HTTP_429
Error message
MCP_HTTP_429
What it means
MCP_HTTP_429 is raised when the external MCP provider responds with HTTP 429 Too Many Requests. The classifier marks it provider_throttled, retryable, and owned by the provider admin: the request is valid but the provider's rate limit has been exhausted. The phase is preserved from the failing request so operators can see which lifecycle stage was throttled.
Solutions
- Wait for the provider rate-limit window to reset, then retry with bounded exponential backoff.
- Respect the Retry-After response header if the provider supplies one.
- Throttle or queue MCP tool calls in the caller, and consider requesting a higher quota from the provider admin.
Example fix
// before: immediate retry loop
for (;;) await callTool('search', args)
// after: bounded backoff honoring Retry-After
const delay = Number(res.headers.get('Retry-After') ?? 30) * 1000
await sleep(delay)
await callTool('search', args) Defensive patterns
Strategy: retry
Validate before calling
// simple client-side rate limiter to stay under provider limits
const limiter = new TokenBucket({ ratePerMin: 50 })
await limiter.take(1) // before each MCP call Type guard
function isThrottled(d: { code: string }): boolean {
return d.code === 'MCP_HTTP_429'
} Try / catch
for (let attempt = 0; attempt < 5; attempt++) {
try {
return await client.callTool(req)
} catch (e) {
if (!isThrottled(e.diagnostic)) throw e
const retryAfter = Number(e.headers?.['retry-after'] ?? 2 ** attempt)
await sleep(Math.min(retryAfter * 1000, 60_000)) // bounded backoff
}
}
throw new Error('rate limit persisted after retries') Prevention
- Instrument call volume per provider and keep it under documented quota.
- Use jittered exponential backoff with a max attempt count instead of tight loops.
- Batch or queue scheduled automations rather than polling in parallel.
When it happens
Trigger: Any MCP-phase HTTP request (tool discovery, tool execution, initialize) that the provider answers with status 429. Typically triggered by high tool-call frequency, large parallel batches, or shared per-tenant provider quotas being consumed by other workloads.
Common situations: Automations or scheduled agents hammering a tool in a tight loop; several agents in the same org sharing one provider API quota; bursty catalog pagination during tool discovery tripping per-minute limits.
Related errors
- MCP_PROVIDER_HTTP_429
- MCP_LIFECYCLE_DEADLINE
- MCP_OAUTH_TOO_MANY_REQUESTS
- MCP_PROVIDER_INVALID_PARAMS|MCP_PROVIDER_HTTP_403|MCP_PROVIDER_HTTP_429
- MCP_SESSION_NOT_FOUND
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/ffbad726541ee0fa.
Report an issue: GitHub.
Appendix: source
Thrown at ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts:929
actionOwner: "organization_admin",
operatorAction: "Verify the complete MCP endpoint path, including any provider tenant or instance prefix.",
}
}
if ((status === 406 || status === 415) && phase.startsWith("MCP_")) {
return {
phase: "MCP_TRANSPORT",
category: "mcp_transport_negotiation",
code: `MCP_HTTP_${status}`,
retryable: false,
actionOwner: "provider_admin",
operatorAction: "Verify Streamable HTTP content negotiation and the provider's supported MCP transport.",
}
}
if (status === 429) {
return {
phase,
category: "provider_throttled",
code: "MCP_HTTP_429",
retryable: true,
actionOwner: "provider_admin",
operatorAction: "Wait for the provider rate limit to reset, then retry with bounded backoff.",
}
}
if (status >= 500) {
return {
phase,
category: "provider_unavailable",
code: `MCP_HTTP_${status}`,
retryable: true,
actionOwner: "provider_admin",
operatorAction: "Check provider availability and reverse-proxy logs using the diagnostic reference, then retry.",
}
}
if ((status === 401 || status === 403) && phase.startsWith("MCP_") && input.hasAuthorization) {
// A 401 is itself an authentication challenge. A 403 is ambiguous for
// enterprise providers: only a Bearer/insufficient_scope challenge meansView on GitHub (pinned to 2b7df46e8a)