Errors and limits
Every failure arrives in the same envelope with a code from a closed set, so an agent can branch on it instead of matching on prose.
{"error":{"code":"provider_not_connected","message":"github is not connected",
"provider":"github","request_id":"cb6e68fe-542d-4284-9a0f-25018bae6f90"}}provider, retry_after and reauth_url appear only when they mean something. request_id is always there and is the thing to quote when you ask us about a call.
Over MCP the same envelope comes back as a tool result with isError set, not as a transport error, so the model reads the code and reacts rather than seeing the call vanish.
The codes
invalid_credentialThe bearer is missing, unknown or revoked. Not retryable.credential_scope_deniedThe credential is scoped to other providers, or is read only.tool_not_foundNo such tool or provider in this workspace.invalid_argumentsThe arguments do not match the tool input schema.provider_not_connectedNobody has connected that provider yet. Connect it and retry.reauth_requiredThe grant died. Carries reauth_url. A human has to reconnect.quota_exceededThe monthly call quota is spent. Carries retry_after.rate_limitedToo many calls in a minute. Carries retry_after. Retryable.plan_blockedThe plan does not include this tool.upstream_errorThe vendor refused the call. Their reason is in the message.upstream_timeoutThe vendor did not answer in time. Retryable.internal_errorOurs. Quote the request_id.
Limits
A workspace serves at most 60 tools to a client. Past that the list is capped, catalog_truncated says so rather than the list quietly shortening, and selat__search_tools reaches everything the cap left out. The cap exists because agents pick worse tools as the list grows, so a large catalog is a product hazard as much as it is a feature.
Calls are rate limited per workspace and counted against the monthly quota on your plan. Discovery is not counted: listing tools and searching them are free.