Skip to main content
Read the response’s WWW-Authenticate header:An OAuth client reads resource_metadata and signs in again by itself. If it keeps getting 401, its access was disconnected in Settings > API & MCP > Connected apps: connect it again.With a pc_… token, the first case almost always means the client configuration does not pass the header. The exact form is Authorization: Bearer pc_…, with the space.An OAuth pcat_… token only works on the MCP server: a REST route refuses it with 401.
The client asked for a token for another address than the one the server issues tokens for. That address is exactly https://app.doers.sh/mcp. A client configured with any other address, https://api.doers.sh/mcp included, fails here: change the URL in the client and connect again.
It did not find the authorization server. Check that discovery answers:
Both must return JSON.
An authorization code lasts 60 seconds and works once. A consent page left open, or a client that replays its request, hits this. Connect again.The same error on a refresh means that refresh token was already used. Reusing one is treated as a theft: the whole connection is revoked, and the client has to sign in again.
The return address is not one the client registered, or is neither https nor http on the loopback address. A client whose configuration changed must register again: remove it and add it back.
A web client sent an Origin that is not on the server’s list. Native clients (Claude Code, Cursor, VS Code) send none and cannot trigger this. See Protocol for the list.
The client sent an MCP-Protocol-Version the server does not know. The response lists the accepted versions in error.data.supported.
Expected. The server offers no event stream, and the specification allows a 405 here. A conforming client carries on with POST. A client that insists on a stream can use the mcp-remote bridge (see Connecting a client).
tools/list needs a credential like every other method. A client connecting without one gets a 401, and some show an empty list instead of an error. Check by hand:
when and deadline are two fields. The server’s instructions explain it at connection, but not every client passes them to the model. If it persists, add a line to your system prompt: “in Doers, when is when I plan to do a task and deadline is when it is due; they are different fields.” See Data model.
The server works in UTC and does not know your time zone. Pass the day argument, computed in your time zone, to the tools that take it (get_context, get_day_plan, suggest_day_plan, plan_today, plan_round), or send the X-Doers-Today: YYYY-MM-DD header. whoami returns serverDay, the day the server is using for your request: your header’s day, or the UTC day.quick_add_task always reads relative dates such as “tomorrow” against the server’s UTC clock: send an explicit date when it matters.
Check its kind. A kind: "event" entry is a calendar block: it is left out of task lists, the context counters and the ranking. For a real task, create it without kind (the default is task).
On purpose. update_tasks, create_tasks, complete_tasks, archive_tasks, schedule_tasks and reorder_hierarchy are all or nothing: if one task is out of reach, nothing changes. The message names the cause; remove that identifier and try again.