Local-first Personal Model Runtime for macOS
Persome exposes local capture context, durable personal memory, model structure, and explicit correction through the Model Context Protocol. MCP runs either in the daemon over streamable HTTP or as a per-client stdio process.
persome start
# http://127.0.0.1:8742/mcp
# or
persome mcp
The daemon endpoint requires Authorization: Bearer <PERSOME_LOCAL_API_TOKEN>.
The token is provisioned in the owner-only Runtime env file. Stdio does not
need or copy that bearer. Stdio also skips construction of the daemon-only
REST/Chat application and never runs database recovery, keeping per-client cold
starts bounded to MCP tools. Integrity recovery remains a daemon-start and
maintenance responsibility.
Stdio processes are shared-database clients: they can read and apply explicit
row-level memory writes, but they do not create or migrate schema and they
disable per-connection WAL auto-checkpoints. Onboarding normally initializes
the database already; for a brand-new or externally upgraded data root, run
persome start once before connecting stdio clients. While the daemon is live,
it pre-initializes every registered store schema, publishes an exact revision
and schema fingerprint, keeps the schema-owner connection, and performs WAL
maintenance. A stdio client rejects a missing, stale, future, or mismatched
receipt, and its SQLite authorizer rejects any schema-changing statement that
escapes the client-safe store helpers.
Example stdio client configuration:
{
"mcpServers": {
"persome": {
"command": "persome",
"args": ["mcp"]
}
}
}
| Tool | Purpose |
|---|---|
list_memories |
List durable Markdown memory files. |
read_memory |
Read one memory file with time, tag, and tail filters. |
search |
Search durable memory with BM25 and optional dense retrieval. |
read_receipt |
Resolve a memory entry to its provenance. |
related_events |
Retrieve time-adjacent context around one memory entry: overlapping timeline blocks plus nearest captures, anchored on parseable occurred_at else write time. Context is observed data, not evidence for the entry. |
resolve_evidence |
Resolve model, memory, activity, and capture references through one progressive evidence contract. |
recent_activity |
Read recent durable event entries. |
behavior_patterns |
Read modeled behavioral patterns plus evidence-backed observed workflow playbooks. |
get_model_snapshot |
Return a bounded model overview or one paged Point/Line/Face/Volume/Root/receipt section. |
entity_graph |
Read the entity/relation graph; retained as a compatibility model view. |
verify_fact |
Check a claim’s freshness and explain existing open contradiction ledger rows. |
remember |
Append an explicit, auditable memory. |
correct_memory |
Supersede or revoke memory through the correction workflow. |
process_pending_model_work |
Process a bounded number of pending sessions with the connected client’s model allowance through MCP Sampling. |
get_pending_model_work |
Inspect the semantic session backlog without invoking a model. |
| Tool | Purpose |
|---|---|
current_context |
Return recent capture headlines/full text and model-eligible timeline blocks; each block includes normalization_status. |
search_captures |
Search the local capture index. |
read_recent_capture |
Read an exact returned file_stem or nearest recent capture, with screenshot opt-in. |
attention_trajectory |
Read the derived attention path used by state formation. |
get_schema |
Return the Markdown memory schema. |
search_captures degrades explicitly: while the daemon’s index-health report
is degraded or stale, its JSON payload carries an index_health object
(status, index, capture_state, index_backlog, note), and a corrupt
capture index raises an actionable tool error rather than returning silently
partial results.
| Tool | Purpose |
|---|---|
query_health_metrics |
Query owner-authorized wearable observations by metric, provider, time range, and limit. |
Wearable results are raw consumer-device observations with source and import timestamps. Clients must not present them as medical diagnoses.
resolve_evidence returns explicit stored lineage in sources and
time-adjacent capture clues in context. Consumers must not present context
as direct proof. Display label as the human-readable card title and keep
reference as the stable technical handle. Point predecessor/successor links
are returned separately in history. Follow each returned reference to move
down one layer; a retained receipt whose payload is no longer available returns
status=missing.
behavior_patterns includes only active skill files with a current
evidence-backed observed-pattern entry. Later trigger echoes do not replace the
playbook. A playbook can guide personalization and imitation, but it never grants
a client permission to execute the observed actions.
verify_fact remains a deterministic read: it does not judge whether a claim is
true. When a recalled entry participates in an open contradiction ledger row,
the result includes the recorded reason and bounded competing claim. Resolved or
dismissed rows are not replayed.
The canonical model snapshot contains every non-archived historical Point,
evolution Line, and evidence receipt, so it grows with the audit history. MCP
does not put that complete object in one result. get_model_snapshot defaults
to an explicit overview envelope containing:
projection_schema_version, model_schema_version, section,
generated_at, build, model_stats, root, faces, volumes,
coverage, paging, full_export
Root, Face, and Volume objects retain their high-level meaning and evidence
counts, while unbounded member/receipt arrays are summarized. Points, Lines,
Faces, Volumes, Root, and receipt objects can be read with their section name, a
maximum limit of 100. Subsequent pages use the returned opaque cursor. Pass
up to 20 exact ids instead of a cursor for a focused selection. Set
include_evidence_refs=true only when the full aggregate references are
needed; the byte budget still applies.
Call a paged section without cursor for its first page, then pass that page’s
opaque next_cursor as cursor for the next page. The overview does not return
a page cursor. The JSON string in the MCP result’s content[0].text is capped
at 64 KiB. JSON-RPC framing and escaping add transport bytes outside this
payload budget. The server reduces the effective page before serialization and
returns a small explicit error if one object by itself cannot fit. When later
items remain, that error includes a resume_cursor that explicitly skips the
oversized object. One call is transactionally stable, but a page sequence is
not a frozen database revision; restart if a cursor is stale. Default redaction
applies before projection.
To avoid rebuilding a large canonical object for every page, one redaction variant is retained in process memory for at most 15 seconds; explicit MCP memory/model writes clear it, and it is never written to another file.
Use the CLI for the complete schema-v1 object:
persome model export --out ./model-snapshot.json
persome model export --out ./model-snapshot.json --raw # explicit local opt-out
section="full" returns a bounded export hint and never constructs an
unbounded MCP response. CLI export and owner-local /model/graph retain the
complete historical/audit contract.
The bounded default is a breaking MCP response-contract change scheduled for
the next minor release, v0.4.0, rather than a v0.3.x patch. In v0.3.x,
get_model_snapshot(redact=...) returned the complete canonical
schema_version: 1 snapshot. In v0.4.0, the same call returns the separately
versioned section="overview" envelope.
Client integrations must detect projection_schema_version, treat omitted
overview sections as omitted rather than empty, and request the required page
explicitly. Integrations that need one complete canonical object must use
persome model export; owner-local /model/graph and CLI export retain the
canonical schema-v1 shape.
[mcp]
auto_start = true
transport = "streamable-http"
host = "127.0.0.1"
port = 8742
streamable-http is the daemon default at /mcp.sse is a legacy transport.stdio is started explicitly with persome mcp. It exits on stdin EOF, and
a parent-death watchdog also exits it within seconds when the spawning
client dies without closing the pipe (no orphaned server accumulation).GET /health is public.process_pending_model_work tool sends modeling prompts and tool results back
to the originating trusted client through MCP Sampling; the client remains in
control of its model, authentication, approval policy, and allowance.get_model_snapshot projections redact detectable secrets and local paths by default and are byte-bounded.There are two credential-owner-preserving routes:
[agent_funding] invokes an authenticated Codex, Claude Code, or Cursor
Agent CLI for normal background stages. Enable it explicitly with
persome llm agent setup or an installer’s --fund-model flag. A durable
per-day invocation cap, per-call timeout, and concurrency limit bound spend.process_pending_model_work borrows the originating MCP session for one
explicit bounded batch and requires Sampling with tools.The CLI bridge passes prompts on stdin with a scrubbed environment. It never
opens ~/.codex/auth.json, Claude credentials, Cursor credentials, or another
OAuth store. Codex runs ephemeral in a read-only sandbox with user MCP/config
disabled; Claude disables built-in tools, MCP servers, settings, and session
persistence. Cursor runs without --force in an empty private temporary
directory because its current CLI does not expose equivalent isolation flags.
Only enable any route for a trusted client account.
process_pending_model_work(max_sessions=1) is the provider-neutral path for
using a model entitlement already available in Codex, Claude, or another MCP
client. Persome negotiates the client’s sampling and sampling.tools
capabilities. When supported, stage prompts run through
sampling/createMessage; no subscription credential or OAuth token is read,
copied, or persisted by Persome.
The operation must originate in a client tool call and is bounded to 1–10
sessions. Persome does not initiate MCP Sampling from its background daemon.
Cancelling the originating tool call cancels any in-flight Sampling request;
the per-call Sampling deadline does the same, and either path rejects further
Sampling calls so no additional client allowance is spent.
Clients that only implement MCP tools return
client_missing_sampling_with_tools; use another compatible client, a local
provider, a configured API provider, or the agent CLI bridge in that case.
Scheduled writers use [agent_funding] when it is enabled and otherwise retain
the configured provider route.
The same loopback ASGI app serves /model and the authenticated REST
routes. Use persome model open for a one-time browser bootstrap.