Connecting agents
This is the reference for wiring a coding agent — Claude Code and any other MCP
client — to a logbook project. It covers minting API keys, the per-project
connection URLs, the exact .mcp.json and claude mcp add shapes, the monorepo
pattern, legacy tokens, every authentication error you can hit, and the security
model that guarantees an agent can never write into the wrong backlog.
For the human side — signing up, the onboarding wizard, inviting teammates — see Getting started.
The model in one sentence
The key decides WHO, the URL decides WHERE. An org API key authenticates the
connection as a member of your organization; the project slug in the connection
URL fixes which project that connection reads and writes. Scope is static per
connection, so misfiling into another project is structurally impossible — there
is no per-call project parameter to get wrong.
API keys
Keys are lgbk_… bearer tokens minted at the organization level. One key
authenticates an agent as you for every project in the org; which project a
given connection touches is decided entirely by the URL it connects to, never by
the key.
Minting a key
- Open Settings → API tokens.
- Enter a label (defaults to
claude-code) and click Generate key. - The full token is shown once, under a "Copy now — shown only once"
notice. Copy it immediately. Only a SHA-256 hash and a short prefix
(
lgbk_plus the next several characters, displayed aslgbk_xxxxxxxx…) are stored; the raw token is never retrievable again. If you lose it, revoke it and mint a new one.
The Settings list shows each key's prefix, label, and last-used time (stamped on every authenticated MCP request). Creating a project or running the one-paste setup prompt also mints a fresh org key as a convenience, so you rarely generate one by hand.
Connection URLs
Under the keys, Settings lists a connection URL per project:
https://logbook.gvy.ai/api/mcp/<project-slug>
One URL per project, each with a copy button. Pair any org key with a project's URL to connect an agent to that project. Same key, different URLs, different projects. The slug is the project's globally unique, URL-safe identifier derived from its name.
Connecting Claude Code
The one-command path
From inside the repository you want to track:
claude mcp add --transport http logbook \
https://logbook.gvy.ai/api/mcp/<project-slug> \
--header "Authorization: Bearer lgbk_your_token_here"
This is exactly the command logbook generates for you in Settings → Connect
Claude Code and in the setup prompt shown when you create a project. The server
is named logbook; the transport is http; the token rides in an
Authorization: Bearer header. Add --scope user to register the server for
every repository on your machine instead of just the current one.
The .mcp.json path
To check the connection into a repository (so every agent working there picks it
up), write a .mcp.json at the repo root:
{
"mcpServers": {
"logbook": {
"type": "http",
"url": "https://logbook.gvy.ai/api/mcp/<project-slug>",
"headers": {
"Authorization": "Bearer lgbk_your_token_here"
}
}
}
}
This is the file form of the claude mcp add command above: type: "http"
matches --transport http, url is the project connection URL, and the
Authorization header carries the org token. Name the server entry after the
project it points at (see the monorepo pattern below for why this matters).
Both forms are equivalent. Use the command for a quick local connection; use
.mcp.json when the connection should live with the code.
What ships with the connection
Once connected, the agent gains the logbook toolset — reading, creating, updating, and crossing off backlog items — plus two planning prompts that Claude Code surfaces as slash commands:
/mcp__logbook__plan-work— an intake interview that turns a rough idea into well-formed items, checks prior art, decides log vs epic, and files the plan in one call only after you approve it./mcp__logbook__enrich-log— a gap audit that pulls an existing item, checks it against the quality bar, asks only about the gaps, and applies fixes on approval.
The slash-command prefix follows the server name you chose. If you name the
server logbook, the commands are /mcp__logbook__plan-work and
/mcp__logbook__enrich-log; if you name it after a project (for example
billing), they become /mcp__billing__plan-work and so on. These prompts
travel with the token — no installation, versioned server-side, always in sync
with the tools.
Hearing about assignments
To have an agent pick up new assignments and notes at the start of every
session, add a Claude Code SessionStart hook in the consuming repo that
prompts a check_inbox (or briefing) call. Notes, status changes, and
assignments addressed to you land there.
The monorepo pattern
In a monorepo where different directories map to different logbook projects, use
directory-scoped .mcp.json files so an agent only ever sees the backlog for
the project it is working in.
my-monorepo/
├── apps/
│ ├── billing/
│ │ └── .mcp.json # url: …/api/mcp/billing, server name: "billing"
│ └── web/
│ └── .mcp.json # url: …/api/mcp/web, server name: "web"
Each .mcp.json carries that project's connection URL and one server entry named
after the project:
{
"mcpServers": {
"billing": {
"type": "http",
"url": "https://logbook.gvy.ai/api/mcp/billing",
"headers": { "Authorization": "Bearer lgbk_your_token_here" }
}
}
}
An agent invoked inside apps/billing/ connects only to the billing project
and sees only its items, labels, and team; an agent in apps/web/ sees only
web. The same org key appears in both files — the URL is what separates
them. Naming each server entry after its project keeps the slash commands and
tool namespaces unambiguous when an agent's working directory spans more than
one config.
Because scope is fixed by config rather than by runtime arguments, the risk of writing into the wrong backlog moves entirely to config-review time, where it is visible and reviewable.
Legacy project-bound tokens
Before org keys, every token was hard-bound to a single project
(project_id set, no org). These legacy tokens still work but are no longer
minted by any current UI path — mint org keys instead. They differ from org keys
in where they are valid:
| Org key | Legacy project token | |
|---|---|---|
| Bound to | an organization | one project |
Valid on /api/mcp/<slug> | any project in the org (slug picks it) | only when the slug is its own project |
Valid on bare /api/mcp | no — returns a 400 with the slug list | yes — resolves to its bound project |
| Minted by | Settings, project setup | pre-migration only |
Legacy tokens appear in Settings → Legacy tokens, labeled
legacy — bound to <project>, and remain revocable. They keep working on the
bare /api/mcp endpoint (no slug), where scope equals their bound project.
There is no forced migration; revoke them once nothing uses them.
Note that the codebase retains the internal createApiToken function that mints
legacy project tokens, but no Settings action, onboarding step, or project-setup
flow calls it — all of those now issue org keys via createOrgApiToken. In
practice, the only legacy tokens in existence are ones created before the
org-key migration.
Authentication errors
Every error is a self-describing JSON body with an error field, meant to be
read by the agent that hit it so it can self-correct. The important ones:
Org key on the bare /api/mcp path — 400
An org key has no default project, so the bare path cannot resolve one. The response lists the org's project slugs so the agent knows exactly where to reconnect:
This is an org key — it has no default project. Connect to
/api/mcp/<project-slug>; this org has: billing, web.
The JSON body also includes a machine-readable projects array of the slugs.
The fix is always to append the intended slug to the URL.
Legacy token, wrong slug — 403
A legacy project token used on a slug that is not its own:
This token is bound to the "billing" project and cannot act on "web".
Use /api/mcp/billing or the bare /api/mcp endpoint.
Org key, slug not in this org — 404
No project with slug "web" in this token's organization.
The same 404 is returned whether the slug does not exist at all or belongs to
a different organization — a slug in another tenant is not probeable with your
key.
Missing or unrecognized token — 401
No bearer header:
Unauthorized. Pass a logbook API token: Authorization: Bearer lgbk_…
(generate one in Settings).
Token not found (revoked, mistyped, or from another instance):
Unauthorized. This logbook API token is not recognized — generate a fresh one
in Settings.
Revoking a key
Revoke any key — org or legacy — from Settings → API tokens with the ×
button beside it. Revocation is scoped to your active organization: the delete
only touches keys the org owns (org keys) or legacy keys bound to one of the
org's projects, so a stray id from another tenant is a no-op. Any connection
still using a revoked key immediately begins failing authentication with the
401 "not recognized" error above. To rotate a key, mint a new one, update your
.mcp.json or re-run claude mcp add, then revoke the old one.
Security model
Three properties hold by construction:
- The URL decides WHERE. The project a connection acts on is fixed by the
slug in its URL and cannot change mid-session. There is no per-tool
projectargument, so there is nothing an agent can pass to reach across projects. - The key decides WHO. An org key proves organization membership; that is the entire authorization it grants. It carries no per-project or per-role permissions beyond "a member of this org."
- Writes never cross projects. An org key on
/api/mcp/<slug>is honored only if that slug's project belongs to the key's organization; otherwise it is a404. A legacy token is honored only on its own project. The org-ownership check is the tenant boundary, and it is enforced on every request before any tool runs.
Two deliberate consequences: there is intentionally no cross-project write surface on a single connection (the ambiguity logbook refuses), and slugs live in the URL path — visible in every config file, greppable, and reviewable — rather than hidden in a header or query string.
Every write an agent makes is attributed in the activity feed as
claude (<your name>), using the name on the logbook user the key belongs to, so
agent edits are always distinguishable from human ones.
The toolset at a glance
An agent connected to a project can:
- Survey —
backlog_stats(call first for any audit),list_backlog,get_my_work,briefing(session-start: inbox, your items, scoreboard),team_summary,list_team,list_labels,history_for_files. - Read one or many items —
pull_item(preferred, optionalclaim),pull_items(batch),get_item,get_document. - Create —
create_item,create_items(batch, all-or-nothing validation),create_label. - Update —
update_item,update_items(batch),add_task,complete_task,add_note,link_items,attach_document,archive_done_items. - Set up —
link_repo(register a GitHub repo with the project).
Item creation is subject to the org's plan limits (the free plan caps logs); a
capped org receives a structured upgrade_required error from create_item /
create_items with the usage numbers and an upgrade URL. Reads and updates are
never gated. Tool names, parameters, and calibrations are documented in each
tool's own MCP description, which the agent sees on connection.
Where to go next
- Getting started — the human path: accounts, orgs, the onboarding wizard, projects, and teams.