Troubleshooting
Ordered roughly by how often each one happens.
The MCP tools don't appear at all
The client never completed a handshake. Work through it in order:
- Restart the client. MCP configs are read at startup. This is the fix surprisingly often.
- Check the URL ends in
/mcp.https://api.witwiki.app/mcp, nothttps://api.witwiki.app. A bare host returns 404 and the client reports it as a generic connection failure. - Check the transport is HTTP.
"type": "http", or--transport httpon the CLI. Clients default to stdio, which will try to execute your URL as a command. - Check the server is reachable:
curl -i https://api.witwiki.app/mcp \
-H "Authorization: Bearer YOUR_API_KEY"
Anything other than a connection error means the network path is fine and the problem is in your client config.
In Claude Code, /mcp lists servers and their state — a server stuck in
connecting or failed is a config problem, not an auth problem.
401 Unauthorized
The credential wasn't accepted.
- The key was revoked or mistyped. Keys are shown once and stored as bcrypt hashes, so there's nothing to look up — if in doubt, mint a fresh one at /keys.
- The header is malformed. It must be
Authorization: Bearer <key>. A missingBearerprefix, or a stray newline from a copy-paste, produces a 401. - You pasted a truncated key. Copy from the reveal panel with the copy button rather than by selection.
A 401 from an OAuth-aware client is often not an error at all — the server
returns WWW-Authenticate with its metadata URL, which is how the client
discovers where to send you to sign in.
403 Forbidden
Authenticated fine, not allowed to do that. There are two separate systems that produce a 403, and knowing which one fired tells you the fix.
Missing scope — the message names the scope, e.g.
missing scope: wiki:write. Your API key doesn't carry it. Mint a key with the
scope, or with no scopes at all (which means unrestricted).
Insufficient role — the message is insufficient role. Your account's role
in the org is too low. Roles rank owner 50, admin 40, member 30,
viewer 20, agent 10, and each endpoint requires a minimum.
The most common surprises:
| Operation | Needs | Catches out |
|---|---|---|
DELETE /api/pages/{path} | admin | Members can create pages but not delete them |
| Deleting a page over MCP | wiki:write scope | Same action, different gate — MCP never checks role |
GET /api/org/members | viewer | An agent-role API key cannot list the org's members |
POST /api/graph/rebuild | member | It rewrites derived state, so it is an editor action |
PATCH/DELETE /api/org/members/{userID} | admin | And only for members below your own rank — see below |
GET /api/audit | owner | Admins cannot read the audit log |
| Billing | owner | Not delegable; promote a second owner instead |
Role changes and removals that get refused
Roles are editable in /settings, and removal follows the same rules — deleting a member is the same privilege as demoting them. Four messages produce a 403 or 409 rather than a saved change:
- "You cannot assign a role at or above your own level." An admin can move
someone between
memberandviewer; making another admin, or touching an owner, is an owner's job. - "You cannot change the role of / remove a member at or above your own level." Admins cannot demote or delete owners and fellow admins.
- "You cannot change your own role." Nobody can, owner included, and nobody removes themselves. Promote a second owner and have them demote you.
- "Org must retain at least one owner." The last owner can be neither demoted nor removed — billing, the audit log, and org settings would have nobody who could reach them.
Why MCP and REST disagree
The REST API enforces roles. MCP enforces scopes. They are independent, so the same credential can succeed over one surface and fail over the other.
The clearest case is page deletion. Over MCP, an agent-role key with
wiki:write deletes pages without complaint. Over REST, the identical key hits
DELETE /api/pages/{path} — which demands rank 40 — and agent ranks 10. It
gets a 403.
This is deliberate. MCP is the agent surface and scopes are the agent control; REST is the human surface and roles are the human control. When a permission result surprises you, first work out which surface you were on.
My wiki is empty, but I know I wrote pages
Almost always identity or project, not data loss. Ask which credential am I using, and which project does it resolve to?
- API keys are bound to one project. A key issued for project A will never see project B's pages, no matter which project the web UI is showing.
- OAuth resolves to your user account, not to a project. Connecting the same wiki over a bearer key and over OAuth can very easily land you in two different projects — and each will look correct and empty from the other's point of view.
- The web app shows the active project, chosen in the top-nav selector. It is not necessarily the project your key writes to.
Confirm it directly:
project_list({}) → which projects can this credential see?
wiki_listPages({}) → what does it actually hold?
If wiki_listPages returns content you don't recognise, you're authenticated as
something other than you assumed. Mint a key for the project you actually want.
wiki_getIndex returns "not found"
Every project is seeded with an index page at creation, so this should not
happen on a new project — if it does, you are almost certainly pointed at a
different project than you think (see above), or the index was deleted at some
point. wiki_updateIndex recreates it.
My agent has the tools but never uses them
Not a bug — a prompting gap. A connected agent has no reason to believe the wiki contains anything useful and no instruction to write to it.
Paste the CLAUDE.md or AGENTS.md snippet from Integration into your repo. That's the piece that turns a connection into a habit.
My agent overwrote a page
wiki_updatePage replaces the whole page — there is no merge. An agent that
writes without reading first will destroy content it never saw.
The fix is the prompt: the snippets in Integration state the
read-before-write rule explicitly. Page history is available at
GET /api/page-versions/{path}, and a version can be restored with
POST /api/page-restore/{path}.
Everything works, but writes fail with a scope error
You created the key with scopes ticked and wiki:write isn't among them.
Worth knowing which direction the default runs: an empty scope list means unrestricted, not read-only. A key created with no boxes ticked can do everything. Restricting a key requires ticking scopes deliberately — and once you tick any, only what you ticked is permitted.
Still stuck
Check /log for what your agent actually did, and /audit (owner-only) for authentication and permission events. Between them they usually show which identity made the call and what the server thought of it.