MCP
Connect an MCP client: the endpoint, the twelve tools, sessions, anchor handles and budgets.
Connecting
https://mcp.fastpad.aiJSON-RPC over a single POST. Authenticate with Authorization: Bearer fpk_live_…. An unauthenticated call answers 401 with a WWW-Authenticate challenge and a link to the protected-resource metadata, so a client can discover how to authenticate without being told.
fp login # device flow; approve in a browser
fp mcp --check # verifies the brokered credentialFor a local stdio client, fp mcp is the command the client launches — it speaks the stdio transport and refuses at a prompt. Configure the client with command: "fp" and args: ["mcp"].
The tools
Twelve composite tools rather than thirty narrow ones, in a fixed order, sized to fit in about 5,000 tokens of schema. Three MCP servers together have been measured consuming 143,000 tokens of a 200,000-token window before doing any work.
| Tool | Scope | Returns |
|---|---|---|
fastpad_capabilities | any | identity, scopes, your writable note set, limits — and the session token everything else needs |
fastpad_search | search:read | ids, titles, path, score, block anchors, a short snippet. Never bodies |
fastpad_fetch | notes:read | up to 20 notes as Markdown, or a structural digest with no prose |
fastpad_context | notes:read | a packed context bundle: retrieve, expand, dedupe, rerank, fit a budget |
fastpad_query | notes:read | structured metadata query over typed properties |
fastpad_graph | graph:read | one-hop typed traversal, every edge with its evidence |
fastpad_propose | notes:propose | a durable proposal and its review URL. The only write |
fastpad_turn | notes:read | status, diff or abandon on your own proposals; accept too, only under turns:accept |
fastpad_changes | notes:read | the change feed since a cursor |
fastpad_history | notes:read | one block as it stands, with authorship and review state. Not a version log |
fastpad_memory | notes:read | the memory index, or one topic |
fastpad_calendar | notes:read | events in a time window; busy/free only for a note-scoped token. Never writes |
Call fastpad_capabilities first. It is not a courtesy: MCP is stateless, so the session every other tool takes is minted there.
Anchor handles
Proposed edits address blocks by handle, obtained from fastpad_fetch with with_handles: true. Never by text offset: a concurrent human edit relocates an anchor, where an offset silently targets the wrong text.
A handle is a signed capability bound to your session, your token, one note, one block and the note’s state at the moment you read it, valid for five minutes. So a handle leaked into a shared transcript is inert for anyone else; revoking the token kills every handle it minted; a handle can only ever address the note it came from; and if a person edited the note since you read it, the write is refused rather than applied blind.
Proposing an edit
fastpad_capabilities— session, scopes, writable notesfastpad_searchorfastpad_context— find the notefastpad_fetchwithwith_handles: true— body, handles, frontierfastpad_propose— ops,expected_frontier,idempotency_key- Hand the returned review URL to a person
Seven op kinds: insert_after, insert_before, replace_block, delete for prose, add_edge for a typed connection, and add_event and move_event for the calendar. The last three always wait for a person, whatever the token was granted. dry_run validates and diffs and writes nothing. idempotency_key is required — there is no stream resumability, so a dropped response must be retried under the same key or one proposal becomes two review queues.
Declare source_block_ids. They become real citations when a human accepts, and without them a later retraction cannot reach content that was accepted from a source found to be wrong.
Budgets, limits and errors
Every result is capped at 25,000 tokens, cut at a block boundary, with a cursor and a one-line instruction on how to narrow — because truncation without guidance makes a model either hallucinate over the gap or re-issue the same call.
| Error | What to do |
|---|---|
stale-frontier | re-read the note, recompute, propose again |
handle-expired | re-fetch with with_handles: true |
out-of-scope | ask for a new token. Tagging cannot widen a resolved scope |
insufficient-scope | re-authorize once for the full set named in the challenge |
cross-note-copy-denied | you are proposing text you read from a different note |
approve-not-permitted | your token lacks turns:accept; hand the review URL to a person |
rate-limited | honor retry_after_ms |
Every error is an RFC 9457 problem document whose type is a URL you can open. The full catalog is at fastpad.ai/errors.