Troubleshooting
Common issues, their causes, and how to resolve them. Start with the table, then read the matching section.
| Symptom | Likely cause | Fix |
|---|---|---|
| HTTP 401 on every call | Missing, revoked, or malformed credential | Recreate the token, or re-run the OAuth flow |
Tools missing from tools/list | No write scope, or alpha not opted in | Re-consent with write; send the alpha header |
HTTP 200 with isError: true | Workspace not resolved, bad arguments, or throttled | Read the message; call getWorkspaces first |
| Empty result set | Conflicting or lowercase enum values | Use UPPERCASE; drop the conflicting filter |
| Write “succeeded”, nothing changed | Non-empty userErrors | Fix the named field and retry |
Every call returns 401
Authentication failures are uniform by design: the same message whether the token is missing, malformed, revoked, or disabled. Don’t parse it for a cause — recreate the bearer token in the Integration tab, or delete and re-add the OAuth connection so the client re-registers.
Documented tools are missing
tools/list advertises only what your credential can call. An OAuth connection without the write
scope sees no write tools; alpha-gated tools are omitted unless the request sends
X-Archive-Alpha-Features. Calling a hidden tool returns the same response as calling one that
doesn’t exist. See Alpha features.
Workspace can’t be resolved
A valid credential that can’t resolve the requested workspace gets HTTP 200 with isError: true and
a uniform message — identical for an unknown UUID, a workspace you’re not a member of, and one
outside your grant. Call getWorkspaces and pass one of the returned IDs as workspaceId.
Searches return nothing
Every enum value is UPPERCASE. A lowercase value, or a pair of filters that can’t both be true,
returns an empty page rather than an error. The filter enum also differs from the enum an item’s
type field reads back as — Core concepts
explains why a value you read is not always a value you can filter by.
A write returned success but changed nothing
A non-empty userErrors array is a successful tool result reporting a domain rejection. Read each
entry’s field and message, correct the input, then retry.
{
"collection": null,
"userErrors": [
{ "field": ["input", "name"], "message": "has already been taken" }
]
} Requests are rate limited
MCP calls spend from the same weighted per-workspace bucket as /api/v2. Read your ceiling from the
RateLimit-Policy header, prefer responseFormat: "concise" while narrowing a result set, and back
off on throttles. See Rate limits & plans.
A write timed out
When you can’t tell whether the write landed, read first with the verify tool named in the write’s
description — a delete is confirmed when the read returns null. Never blind-retry create*,
uploadItemFromUrl, or refetchEngagementBulk.
Client-specific issues
- Claude.ai / Claude Desktop — a stale or wrongly-scoped authorization is fixed by removing the connector and re-adding it. Scopes are chosen only at consent time, so re-consenting is how you gain (or drop) write access.
- Claude Code — run
/mcpand re-authenticate; check the server is registered withclaude mcp list. - Clients via
mcp-remote— clear the cached auth state in~/.mcp-authand reconnect.
If none of this resolves the issue, contact us with the details listed in Support & contact.