← Docs

MCP tools

Every tool and resource the L6 server exposes, with signatures and behaviour, generated from the server source at each release.

Generated from the server source by tools/gen_mcp_reference.py in the bourdon repository. Do not edit the page; regenerate it.

16 tools and 3 resources, read from the server source.

Recognition (turn-start)#

Call these when a turn begins. They are bounded in time by contract and never wait on retrieval.

prepare_recognition_context#

prepare_recognition_context(prompt: str, access_level: str = 'team', include_private: bool = False, federation_hop: int = 0) -> dict

Return immediate recognition and a bounded prompt-context fragment.

This is the MCP-facing timing layer: agents can call it at turn start, prepend the returned prompt_context to their own model prompt, and continue with deeper retrieval in parallel.

When peers are configured (--peer flag, Phase 1.6+), the local recognition fires first (~1.2 ms substrate) then peers are queried in parallel under a tight per-peer timeout. Peer-matched entities are merged into matched_entities with agents tagged peer:<peer-name>:<agent>. Slow / dead peers are dropped and reported in peer_latencies_us so the response is bounded.

federation_hop is an internal depth guard: peer L6 servers pass 1 so the query answers from the local store only (depth-1 federation, #139). End clients leave it at 0.

When one or more local participant surfaces have a persisted drift verdict (the export watermark says a store that used to yield has stopped, P1-11), the response additionally carries drifting_surfaces: [{agent, checked_at, reason}]. The key is PRESENT only when non-empty -- a healthy machine says nothing -- and it degrades to absent when the watermark state is unreadable.

get_deeper_context#

get_deeper_context(prompt: str, access_level: str = 'team', include_private: bool = False) -> dict

Return post-recognition deeper context for the prompt.

This companion tool is intentionally separate from prepare_recognition_context so immediate recognition never waits on retrieval. Context is assembled from the local store -- free, no model call -- and an enabled L2 backend is appended when one is configured.

The response carries its own provenance: source, entities, doors (which retrieval door matched), l1_documents, truncated, and reason when the context is empty. Callers that want prose synthesize it with their own model; see hydration_hint.

compile_codex_turn#

compile_codex_turn(prompt: str, cwd: str | None = None, access_level: str = 'team', max_items: int = 6, max_chars: int = 1800) -> dict

Compile a turn-scoped Codex recognition brief.

This is the active recognition-orchestration surface for Codex: it ranks prompt, cwd/repo identity, local Codex thread metadata, and L6 federation context into a compact prompt fragment without depending on native Stage 1 summarization.

Read#

Query the federation library. Every read re-applies visibility at query time through access_level.

find_entity#

find_entity(name: str, access_level: str = 'public', include_private: bool = False, federation_hop: int = 0) -> dict

Find an entity by name across all agents.

include_private defaults to False. Callers that genuinely need unredacted output must pass True explicitly -- this is a second line of defense on top of per-manifest visibility policy.

When the server has peer L6 servers configured (--peer flag), the result also merges matches from each peer's library, tagging peer-sourced agents as peer:<peer-name>:<agent>.

federation_hop is an internal depth guard: peer L6 servers pass 1 so the query answers from the local store only (depth-1 federation, #139). End clients leave it at 0.

query_agent_memory#

query_agent_memory(agent: str, topic: str, access_level: str = 'public', include_private: bool = False) -> dict

Find entries in one agent's L5 that match a topic.

Parameters

  • agent : str Agent ID (e.g. "claude-code", "codex", "alpha-agent").
  • topic : str The entity name or topic to look for. Case-insensitive.

Returns

  • dict {"agent": str, "matches": list[EntityMatch-as-dict]}

get_cross_agent_summary#

get_cross_agent_summary(project: str, access_level: str = 'public', include_private: bool = False, federation_hop: int = 0) -> dict

Aggregate everything the federation knows about a project.

Returns agents that touched it, recent sessions whose project_focus references it, and entity matches. When peers are configured (--peer flag), peer libraries are merged in with agents tagged as peer:<peer-name>:<agent>.

federation_hop is an internal depth guard: peer L6 servers pass 1 so the query answers from the local store only (depth-1 federation, #139). End clients leave it at 0.

list_recent_work#

list_recent_work(since: str | None = None, agent: str | None = None, access_level: str = 'public', include_private: bool = False, limit: int | None = None, cursor: str | None = None, summary: bool = False, federation_hop: int = 0) -> dict

Return a page of sessions across agents (or a single agent).

Parameters

  • since : str, optional ISO 8601 date (YYYY-MM-DD) or datetime. When omitted AND cursor is omitted, the store applies a 14-day default window so the first call from a naive caller doesn't pull the entire history.
  • agent : str, optional Filter to one agent's sessions.
  • limit : int, optional Page size. Defaults to 20, capped at 100.
  • cursor : str, optional Opaque token from a previous response's next_cursor. Pagination loop: call once, then keep passing the most recent next_cursor until has_more is false. Re-pass any since / agent filters on each page.
  • summary : bool, optional When true, omit key_actions and files_touched from each session row. Useful for timeline/dashboard callers that only need date + agent + project focus.
  • federation_hop : int, optional Internal depth guard. Peer L6 servers pass 1 so a federated query answers from the local store only, federation is depth-1 by contract (#139). End clients leave this at 0.

list_workstreams#

list_workstreams(status: str | None = None, agent: str | None = None, access_level: str = 'public', include_private: bool = False) -> dict

List workstreams -- ongoing multi-session initiatives, distinct from a single dated Session and from a named glossary Entity.

Parameters

  • status : str, optional Filter to one lifecycle state: active / paused / done / archived. Omit to return all statuses.
  • agent : str, optional Filter to one agent's workstreams.

Unlike list_recent_work, this is not paginated -- workstreams are a small, named, bounded set (capped at 200/agent per the L5 schema). Dedupes by name across agents, same as find_entity.

Federation note: this queries the LOCAL store only. Cross-peer workstream federation is not yet wired (tracked as a follow-up to the entity/session federated query paths).

list_notes#

list_notes(since: str | None = None, agent: str | None = None, access_level: str = 'public', include_private: bool = False, limit: int | None = None, cursor: str | None = None) -> dict

Return a page of freestanding notes across agents (or a single agent) -- unstructured journal entries, not tied to a specific named entity or a single session's action log.

Pagination and default-since-window behavior mirror list_recent_work exactly.

Federation note: this queries the LOCAL store only. Cross-peer note federation is not yet wired (tracked as a follow-up to the entity/session federated query paths).

list_agents#

list_agents(federation_hop: int = 0) -> dict

List agent IDs known to this L6 server, plus any peers' agents.

Peer-sourced agents are NOT prefix-tagged here, call sites that need provenance use the more detailed find_entity / get_cross_agent_summary tools where each agent is tagged peer:<peer-name>:<agent>.

federation_hop is an internal depth guard: peer L6 servers pass 1 so the query answers from the local store only (depth-1 federation, #139). End clients leave it at 0.

export_agents#

export_agents() -> dict

Export THIS server's LOCAL agents only, source-attributed for the tray.

Returns the bourdon.agents/v1 envelope for this machine's own *.l5.yaml manifests -- each agent redacted and tagged source=<this machine> / source_kind="local".

Critically, this tool does NOT fan out to peers. The federated merge (local + every peer's export_agents) happens caller-side in core.l6_store.L6Store.export_agents_federated, which re-tags each peer's agents with that peer's name. Keeping this tool local-only is what prevents the bidirectional-federation echo: when peer A calls peer B's export_agents, B returns only B's agents, never A's agents bounced back.

describe_caller#

Annotations: openWorldHint=false, readOnlyHint=true

describe_caller() -> dict[str, object]

Describe this authenticated member and current meetings authority.

Requires explicit library enrollment and member-bound credentials. A descriptor is a policy observation, not a reusable write permit.

Write#

The single write path. Quarantined members are staged, never live.

commit_to_federation#

commit_to_federation(agent_id: str, agent_type: str | None = None, instance: str | None = None, role_narrative: str | None = None, entities: list[dict] | None = None, sessions: list[dict] | None = None, workstreams: list[dict] | None = None, notes: list[dict] | None = None, mode: str = 'merge', session_id: str | None = None, transcript_ref: str | None = None, expected_digest: str | None = None) -> dict

Write a contribution to the federation under agent_id.

The write-side companion to the read tools. Lets MCP-aware cloud agents (Claude Desktop, ChatGPT desktop, other webview/cloud-only agents that have no readable on-disk store for Bourdon to scrape) push their own L5 contributions into the federation by calling this tool when they decide a piece of context is worth sharing.

Parameters

  • agent_id : str Agent slug, e.g. claude-desktop. Must match ^[a-z0-9][a-z0-9_-]*$.
  • agent_type : str, optional Required when creating a NEW manifest for this agent_id; one of the L5 schema enum values (code-assistant, note-capture, other, etc.). Ignored when merging into an existing manifest that already has agent.type set.
  • instance : str, optional Optional machine/deployment identifier.
  • role_narrative : str, optional Free-text description of the agent's role within a fleet.
  • entities : list of dict, optional Each entity dict needs at minimum a non-empty name (other L5 entity fields -- type, summary, tags, visibility, aliases, valid_from, valid_to -- pass through as-is).
  • sessions : list of dict, optional Each session dict needs at minimum a date: an ISO 8601 calendar date (YYYY-MM-DD), or exactly "" when the source carried no recognisable timestamp (the schema's empty-date provision -- never substitute the current date). Other L5 session fields -- cwd, project_focus, key_actions, files_touched, visibility -- pass through.
  • workstreams : list of dict, optional Each workstream dict needs at minimum a non-empty name. A status (one of active/paused/done/archived) defaults to active if omitted. Other fields -- summary, started, last_touched, related_entities, tags, visibility -- pass through.
  • notes : list of dict, optional Each note dict needs at minimum a date and non-empty text. Other fields -- related_entities, tags, visibility -- pass through.
  • mode : "merge" or "replace" merge (default) unions new rows with the existing manifest. Entities dedupe by name.lower(); sessions dedupe by (date, cwd). List fields (tags, aliases, key_actions, files_touched, project_focus) are unioned on dupe; non-list fields are overwritten. replace wipes the manifest and writes only the provided content.

Returns

  • dict with the write summary (counts added/updated/total, path,
  • agent identity, last_updated). On invalid input, returns a
  • structured error response with an error key. When the merged
  • result is semantically identical to the current manifest, nothing
  • is written (no version snapshot, no timestamp bump) and the
  • summary carries no_op: true with the unchanged digest; the
  • no_op key is absent on a real write (B3-P2-01).

Quarantined callers (v0.9.0): the write is STAGED under <library>/staging/<caller>/ instead of touching the live store, and only the caller's own agent_id namespace is writable. Staged content is invisible to every read until the operator runs bourdon staging promote <agent>.

DURABILITY (issue #134): commits are durable only on commit-only slugs (claude-desktop-chat, alpha-agent, other self-authoring agents). Reader-backed manifests (claude-code, codex, cursor, ...) are REGENERATED from their native stores by bourdon export-all / the per-agent export hooks, which discards rows previously merged in via this tool. Commit under your own self-authoring agent_id, not a reader's.

History and rollback#

Every commit archives the manifest it replaced, so memory has an undo history with provenance.

list_memory_versions#

list_memory_versions(agent_id: str, limit: int | None = None) -> dict

Prior states of one agent's memory, newest first.

Every commit archives the manifest it replaced, so this is the undo history. Each row carries an opaque version_id to pass to rollback_agent_memory, and a digest8 that joins to the provenance entry explaining which session produced that state.

Read access follows the same rules as any other read: quarantined callers may only list history for namespaces they were granted (or org-readable namespaces), and only because this tool is on the quarantined allowlist -- the central check is applied here like everywhere else (B3-P1-18).

explain_memory_change#

explain_memory_change(agent_id: str, digest: str) -> dict

Which session produced a given state of an agent's memory.

Hand it a manifest digest (or a version's digest8) and it returns the write that created it -- caller, session, transcript, and what changed. This is the join that turns "this row looks wrong" into "this run put it there, here is its transcript."

session_id and transcript_ref are caller-asserted and unverified. The recorded caller identity is not.

Access follows the same rules as any other read: the quarantined allowlist gates the tool, and read grants (or org-readability) gate the namespace (B3-P1-18).

rollback_agent_memory#

rollback_agent_memory(agent_id: str, version_id: str, expected_digest: str | None = None, session_id: str | None = None) -> dict

Restore an archived version of an agent's memory. TRUSTED ONLY.

⚠ This is the most destructive operation the server exposes. It discards every contribution made after the chosen version -- including contributions from OTHER agents, which had no part in the bad update and were never consulted about undoing it. Quarantined callers cannot reach it at all, and they cannot reach it by staging either: staging is for adding content, and a rollback is a deletion wearing a restore's clothes.

Pass expected_digest when the decision took a while. Choosing a version is a human-length window, and a commit that lands meanwhile would otherwise be erased by the restore without anyone seeing it.

The restore is itself snapshotted first, so a rollback is undoable.

Resources#

MCP resources are read-only URIs a client can list and fetch without a tool call.

agent-library://agents#

list_agents_resource() -> list[str] | dict

List of all agent IDs known to the federation.

agent-library://agents/{agent_id}/memory#

get_agent_memory_resource(agent_id: str) -> dict

Full visibility-filtered L5 manifest for one agent.

Returns an empty dict with an error key when the agent is unknown (MCP resources can't signal 404 cleanly, so we surface it in the payload).

agent-library://entities/{name}#

get_entity_resource(name: str) -> list[dict] | dict

Cross-agent view of one entity by name.