MCP Errors and Retries
This page explains how AutoCISO MCP reports failures, how the SDKs turn them into typed exceptions, and how retries and rate limits work.
The error envelope
Most failures are not transport errors. The server returns HTTP 200 with a tool result flagged isError, and the result body is an envelope keyed on error:
{ "error": "SCOPE_FORBIDDEN", "scope": "mcp:read" }
The key is error — there is no message field. Extra fields are code-specific (scope, reason, detail, tool). The SDKs read error, synthesize a human-readable message from the code plus the passthrough fields, and raise a mapped exception. Never write code that reads a message key from this envelope — it doesn’t exist.
Two error planes
AutoCISO MCP failures arrive on one of two planes:
1. Tool-result codes (HTTP 200, inside the {"error": CODE, ...} envelope):
SCOPE_FORBIDDEN, NOT_PERMITTED, INVALID_ARGUMENTS, INTERNAL_ERROR, ORG_SUSPENDED, UNKNOWN_TOOL.
2. HTTP statuses the MCP app itself emits:
401, 404, and 429 — and only those. The MCP app never emits 403 or any 5xx. If you ever see a 403 or a 5xx, it came from infrastructure (ingress / load balancer), not the MCP application.
Code → exception → cause → fix
Tool-result codes (HTTP 200)
| Code | SDK exception | Cause | Fix |
|---|---|---|---|
SCOPE_FORBIDDEN | AutocisoScopeError | Token lacks the required scope | Recreate the token with mcp:read (or mcp:write) |
NOT_PERMITTED | AutocisoPermissionError | Write tool called but write disabled for org | Expected on read-only orgs — not a bug |
INVALID_ARGUMENTS | AutocisoValidationError | Bad or missing tool argument | Check the argument against the Tool Catalog |
INTERNAL_ERROR | AutocisoServerError | Server-side failure | Retry; if persistent, contact support |
ORG_SUSPENDED | AutocisoUnavailableError | Org is suspended | Resolve the account status |
UNKNOWN_TOOL | AutocisoUnknownToolError | Tool name not recognized | Check the spelling against the catalog |
HTTP statuses
| Status | SDK exception | Cause | Fix |
|---|---|---|---|
401 | AutocisoAuthError | Token missing, malformed, or revoked | Re-copy or recreate the token |
404 | ServerUnavailableError | MCP disabled for your org (beta gate) | Expected in beta — see Troubleshooting |
429 | AutocisoRateLimitError | Rate limit exceeded | Back off and retry (the SDK does this for you) |
Retries
- On by default for reads. Idempotent read tools retry automatically on
429and transient errors, using exponential backoff with jitter, capped at ~3 attempts. - Writes are never auto-retried.
risk_create_draftis not retried because the server has no idempotency key — a blind retry could create a duplicate draft. Handle write failures yourself.
Rate limits
Handling errors in code
import {
AutocisoScopeError,
AutocisoPermissionError,
AutocisoRateLimitError,
} from '@autociso/mcp-client';
try {
const risks = await client.risk.registerList();
} catch (err) {
if (err instanceof AutocisoScopeError) {
console.error('Token is missing a required scope');
} else if (err instanceof AutocisoPermissionError) {
console.error('Write not permitted for this org');
} else if (err instanceof AutocisoRateLimitError) {
console.error('Rate limited — the SDK already backed off and gave up');
} else {
throw err;
}
} from autociso_mcp import (
AutocisoScopeError,
AutocisoPermissionError,
AutocisoRateLimitError,
)
try:
risks = client.risk.register_list()
except AutocisoScopeError:
print("Token is missing a required scope")
except AutocisoPermissionError:
print("Write not permitted for this org")
except AutocisoRateLimitError:
print("Rate limited — the SDK already backed off and gave up") Was this page helpful?