Skip to content

Tools

Applies to: CPersona 2.6.x. The authoritative description of every argument is the tool's own MCP description: your client reads it, and it ships with the version you are running. This page groups every tool by what you use it for, and links to the contract whenever a tool behaves in a way its name does not suggest.

Everyday memory

Tool What it does
store Write one memory. Since 2.6.6 the text goes in content; on a connection whose ACL grants write access to exactly one agent, agent_id may be omitted (the agent used comes back as resolved_agent_id); source defaults to the writing agent, and lock: true locks the memory in the same call. The message={content, id, source, timestamp, metadata} form of earlier versions is still accepted, with its own defaults. A [Memory from …] annotation, the stamp early versions put on recalled text, is removed wherever it appears. Branch on result — stored / skipped / rejected — not on ok (dedup contract)
recall Retrieve memories through the three-layer hybrid search. The last element is the best match (ordering contract). With trace: true it also returns a record of what each stage kept, dropped and reordered, with references and scores but no stored text (recall trace). With time_cue the caller says when the answer was stored, with a confidence; rows found in that period move up by a bounded number of places and up to three seats (3 / 2 / 1 by confidence) hold records that search found which the answer does not hold, without changing which rows pass the quality gate (time cue)
recall_with_context Recall and merge with conversation history you pass in, deduplicated. Returns a chronological merge, not a score ordering
get_contents Expand preview refs (mem:<id> / ep:<id>) returned by recall into full text (preview tier design). A ref can also name part of its record — overflow-tree nodes or a character span — so a reconstruct quote expands to its neighbours rather than the whole record
reconstruct Assemble recall items from the candidate rows a recall produces: select, order and assign roles, never compose. count is a ceiling, not a fill target and not a search depth; breadth (top_k, max_hops, max_evidence) is a separate set of bounds (the exit). Declared associations add alias cues to the keyword search, bundle related records and add walked evidence inside items (contract)
archive_episode Store a session summary. Also moves the episode boundary, which down-weights earlier records only when CPERSONA_EPISODE_PENALTY_ENABLED is on (it is off by default)
update_memory Correct the content of an existing memory. Use this, not a re-store with the same msg_id
declare_associations Declare associative memory after the fact — entities with aliases, and subject–predicate–object relations — anchored to a record you name; retract removes declarations. The same object rides on store as associations. Stored verbatim and read by reconstruct (associative memory design)
traverse The neighbourhood of a declared entity, as a graph: its aliases, the relations declared on it and on what they reach up to max_hops, and the refs of the records that mention each entity. No record text; limit bounds entities and refs per entity (associative memory design)

Profile and operator context

Tool What it does
get_profile Read the accumulated user/project profile for an agent
update_profile Replace the profile with a summary you computed. CPersona never writes it for you — see zero LLM dependency
get_operating_context Read the operator-owned instructions served to every connected client. Read-only over MCP; edited on the filesystem (design)

Profile rows are injected into recall responses but carry no score. That matters when you tighten limit.

Browsing

Tool What it does
list_memories Recent memories, newest first — no search, no scoring
list_episodes Archived episodes, newest first
get_queue_status Depth and retry state of the background task queue

Protection and deletion

Tool What it does
lock_memory Refuse edits and deletes on a memory. It is protection, not a ranking boost (contract)
unlock_memory Lift that protection
delete_memory Delete one memory. Ownership is enforced only when agent_id is passed — omit it and the delete is unscoped and can remove another agent's row (rejected while locked either way)
delete_episode Delete one episode. Same conditional ownership as delete_memory above
delete_agent_data Delete everything belonging to one agent. It is exposed over the network like any other tool, which is reason enough to set CPERSONA_AUTH_TOKEN on the HTTP transport

Retrieval quality

Tool What it does
set_recall_precision The main gate knob. Sets an agent's precision preference and recalibrates its post-fusion quality gate — reach for this before touching raw thresholds (tuning order)
get_recall_precision Read the effective precision for an agent
calibrate_threshold Re-derive the vector threshold from the corpus itself. The default method (separation) finds where a null distribution of random pairs separates from same-session positives; percentile and zscore are the alternatives. No labels needed. Run it after a re-embed or a large import

Portability and migration

Tool What it does
export_memories Write memories, episodes, profiles and the declared associations (entities, aliases, mentions, relations) to JSONL. It is schema-version independent, so it doubles as a logical backup (backup runbook). A source or metadata value that is not JSON is carried as its own text and restored as it was
import_memories Read that JSONL back, with the declared associations pointed at the restored records. Idempotent, though not by one key: memories dedup on msg_id and on identical content within the project/channel scope, while episodes dedup on an identical summary (they carry no msg_id). A line with a value it cannot store is refused and reported in errors; the rest of the file is restored. An export written by 2.4.37 or earlier carries no project or channel axis, so its rows are restored into the global pool, and errors says how many
merge_memories Move or copy one agent's data into another, declared associations included, atomically and with deduplication
migrate_channel_axis Re-channel bridge-type memories onto their concrete channel, together with the associations declared about them. A one-time repair, not a routine operation

Health and maintenance

Tool What it does
check_health Registry-driven check with severity-tagged issues and, with fix=true, auto-repair: contamination, duplicates, FTS integrity, embedding-dimension drift, schema objects, stale tasks, invalid data. Some checks are report-only by design, isolation-axis hygiene among them: which spelling of an axis is canonical is an operator's call, not a repair
deep_check Semantic data-quality pass: anonymous sources, too-short content, stale profiles, orphaned episodes
get_session_findings The same findings, pulled on demand. This is the SuperAuditor pull contract (standard). Whole-database by design (no agent or project filter), read-only, with capped_kinds naming every kind that had more than per_kind_limit rows. A probe that raised shows up as a finding of kind check_crashed rather than failing the call

check_health and deep_check are also reachable outside MCP, as python -m cpersona.checkup. That is the form to use in CI. Cadence guidance is in the operations runbook.

Server version

Tool What it does
check_update Whether a newer release of the server itself exists, or whether the release you are running has been withdrawn (PyPI yank) — something an installed server can otherwise never learn. The check runs once per process start and is cached for 24h; this tool reads that verdict, refresh=true re-fetches, and apply=true runs the update (pip and source-checkout installs only)

The same verdict rides on recall as an update key, once per session and absent when there is nothing to say. It also appears in check_health as an update_available (info) or version_yanked (warn) issue.

recall carries one more notice of the same kind: suggestion, once per session, when a recall that searches vectors locally has a scope (source filter included) holding 1,000 or more records with a stored vector past the scan window, and no coarse index exists for a time cue to search the rest of its period (binary coarse search). It holds a message to relay and the fix call that builds the index. Building it needs write access to every agent, so it is the user's decision.

Nothing is ever installed as a side effect. apply=true is the only thing that installs anything, and a restart is always required afterwards, because the process that ran the install is still running the old code.

Two setups are declined, each with a reason. Under uvx, the environment is a cache entry keyed by the launch arguments, so the change belongs in your MCP client's config (uvx cpersona@latest). A source checkout that is not on a branch — a clone parked at a release tag, which is a normal way to deploy one — is declined too: git pull has nothing to fast-forward from a detached HEAD. The tool refuses before running anything and answers with the git fetch --tags && git checkout <tag> form to use instead. The command shown on recall, in check_health and by check_update is already that form for such a checkout.

One apply runs at a time. A second is refused while the first is still installing, including one whose call was cancelled: a cancelled call stops waiting, but the installer step it started runs to the end.

A refresh=true whose fetch fails keeps the verdict already known (its checked_at does not move). Being offline does not make a withdrawn release any less withdrawn.

CPERSONA_UPDATE_CHECK=false disables the feature entirely, including the one outbound request (what it sends).

Session controls

Tool What it does
pause_persistence Turn writes into no-ops for a TTL window. Responses carry persisted: false; branch on that, not on an id
resume_persistence Re-enable writes immediately
persistence_status Whether writes are paused, and how much TTL remains

Use these for benchmarking, or for throwaway exploration you do not want in the corpus.

The blast radius follows session_key, which each of the three tools reports back as scope. Declare a key on the pause and on the write calls it should cover, and the pause covers that key alone (scope: "session"). A session sending a different key is neither silenced by it nor able to clear it. The key is compared, never verified, so it partitions keys rather than callers: anyone sending the same string shares the pause.

Omit the key and you arm the bucket that every keyless caller shares (scope: "process"). Under stdio, where the client owns its own process, that bucket is the session. On a streamable-HTTP deployment one process serves every client, so a keyless pause silences writes for every other keyless session — and those sessions are not told.

Two paths do not fit the persisted: false shape. check_health and deep_check are not blocked, but downgrade to fix=false. migrate_channel_axis is forced into dry-run and reports repairs_skipped, with no persisted key at all.

Isolation arguments

The three isolation axes are not offered uniformly. agent_id is accepted by most tools (25), project_id by nine, and channel by exactly seven: store, declare_associations, recall, recall_with_context, reconstruct, traverse and archive_episode.

They are independent axes rather than one nested hierarchy, and reads treat an empty value differently from an omitted one. See isolation axes.