Identity reference
Authentication
Nottario MCP authenticates agents with per-project API tokens:
- Header:
Authorization: Bearer ntr_<random>. - Each token is bound to exactly one project. One token = one project. An agent using a token issued for project A cannot read or write anything in project B, even if the underlying user is a member of both projects.
- Tokens are issued from the web UI under project → Settings → Tokens → New token and shown to the human only once at issuance time.
- The token belongs to one user; the agent acts on that user's behalf within the token's project.
- An admin token still respects project scope.
is_adminis an instance-wide concept (used for cross-project admin actions via the web UI); it does not bypass per-project token scoping for MCP calls.
The MCP server has no cookies, no sessions, no refresh tokens. If a
token is revoked, the very next call fails with
401 Unauthorized carrying WWW-Authenticate: Bearer realm="nottario".
If you pass a project_id argument that doesn't match the token's
project, the tool returns "token scoped to project X, request targets Y". Cache the project id from whoami and reuse it
everywhere.
What whoami returns
| Field | Meaning |
|---|---|
user_id |
uuid of the user the token belongs to. |
github_login |
the user's GitHub handle (the same one shown in the web UI). |
display_name |
the user's GitHub display name (falls back to the login). |
is_admin |
true if the user is the instance admin (first GitHub user to ever log in). Does not grant cross-project access for token callers. |
source |
always "token" for MCP callers (other surfaces may use "session"). |
token_id |
uuid of the specific API token presented. |
memberships |
array of {project_id, project_slug, project_name, role_id, role_key, role_label, role_color, role_position}. For token callers this list is filtered to the token's project only — every entry refers to the same project_id, one per role the user holds in that project. Use memberships[0].project_id as the canonical project_id for the rest of the session. |
Roles
A user can hold zero or more roles in any given project. Roles are
defined per-project (commonly backend, frontend, qa, design,
and any custom ones the team adds).
- A task targeted at a role (
target_role_id) is eligible for anyone holding that role in that project. - A task assigned to a user (
assignee_user_id) is eligible only for that user. - A task with both fields can still be picked up by the assignee; the
target_rolebecomes informational.
Project visibility
- For session (cookie) callers in the web UI: admins see every project; other users see projects where they have at least one membership.
- For token (MCP) callers: visibility is restricted to the
token's project, regardless of how many memberships the user
actually has.
projects.listreturns just that one project;projects.getrejects any other id.
Recovering from a scope mismatch
If you see "token scoped to project X, request targets Y":
- Re-run
nottario.whoamito make sure you're talking to the right project. - Replace your cached
project_idwith the valuewhoamireturned. - Retry the call.
If the human needs the agent to work on a different project, they
must issue a new token from that project's Settings → Tokens panel
and point the MCP client at the new token (claude mcp remove nottario -s local then claude mcp add … --scope local with the
fresh secret).
Per-token defaults
Humans can set a default_role_id on the token at issuance time
(picked from the catalogue of the token's project). The agent does
not need to remember it — calls like tasks.claim_next accept the
role filter explicitly; the default is only used by the web UI's
"create with these defaults" affordance.