[Intuition-Lab/personal-model] MCP interface
Universal
API Leak/Open
7,407 characters
# MCP interface
Persome exposes local capture context, durable personal memory, model geometry,
provenance, and explicit correction through the Model Context Protocol.
## Start
Streamable HTTP is hosted by the daemon:
```bash
persome start
# http://127.0.0.1:8742/mcp
```
HTTP requires the owner bearer token stored in `<PERSOME_ROOT>/env`. Prefer
the stdio installer commands below; they do not duplicate the credential.
Stdio runs one server process for the client:
```bash
persome mcp
```
## Official MCP Registry
The committed [`server.json`](server.json) publishes the stdio server as
`io.github.Intuition-Lab/personal-model` and points Registry clients to the
public `personal-model` PyPI package. A successful GitHub `Release` workflow
automatically publishes the matching version through GitHub Actions OIDC; the
`Publish MCP Registry` workflow can also be dispatched manually for recovery.
The stdio server lives exactly as long as its client: it exits on stdin EOF,
and a parent-death watchdog also exits it within seconds if the spawning
client dies without closing the pipe, so orphaned servers never accumulate.
Example client configuration:
```json
{
"mcpServers": {
"persome": {
"command": "persome",
"args": ["mcp"]
}
}
}
```
## Model and memory tools
| Tool | Purpose |
|---|---|
| `list_memories` | List durable Markdown memory files. |
| `read_memory` | Read a memory file with time, tag, and tail filters. |
| `search` | Search durable memory with lexical and optional dense retrieval; latency-sensitive ranked-hit consumers may pass `include_chains=false` to skip relation-chain narration. |
| `read_receipt` | Resolve an entry ID to local 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 any model ID or receipt one layer down with human labels; separates direct sources, nearby context, and Point history. |
| `recent_activity` | Read recent durable event entries. |
| `behavior_patterns` | Read modeled patterns and supporting evidence. |
| `get_model_snapshot` | Return a bounded model overview or one paged Point/Line/Face/Volume/Root/receipt section. |
| `entity_graph` | Compatibility graph view backed by the same model stores. |
| `verify_fact` | Check a claim against current and superseded memory. |
| `get_schema` | Return the Markdown memory schema. |
## Capture and state tools
| Tool | Purpose |
|---|---|
| `current_context` | Read recent capture headlines/text and model-eligible timeline blocks; each block includes `normalization_status`. |
| `search_captures` | Search the local capture index. |
| `read_recent_capture` | Read an exact `file_stem` or nearby capture; screenshot inclusion is opt-in. |
| `attention_trajectory` | Read the attention path used during state formation. |
When the evidence layer is degraded (index corruption, failing capture
indexing, or an unindexed capture backlog), `search_captures` adds an
in-band `index_health` object (`status`, `index`, `capture_state`,
`index_backlog`, `note`) so a thin result set is never mistaken for "nothing
happened on screen". A corrupt index raises an actionable tool error instead
of returning partial results.
## Explicit write tools
| Tool | Purpose |
|---|---|
| `remember` | Append a user-requested, auditable memory. |
| `correct_memory` | Supersede or revoke memory while preserving provenance. |
The server exposes no computer-use, meeting, notification, product dashboard,
or task-lifecycle tools.
`resolve_evidence` returns a human-readable `label` for display, keeps the
stable technical handle in `reference`, and separates `sources`, `context`, and
Point predecessor/successor `history`. Consumers must not present nearby
`context` as direct proof.
## Bounded model projection
`get_model_snapshot` defaults to `section="overview"`: build metadata and full
model counts plus compact Root, Face, and Volume objects. The response has its
own `projection_schema_version` and explicitly reports coverage; omitted
Points, Lines, and receipts are not represented as empty canonical arrays.
Call `section="points"`, `"lines"`, `"faces"`, `"volumes"`, `"root"`, or
`"receipts"` without a cursor for the first page, then pass that page's opaque
`next_cursor` as `cursor` for the next page. The overview itself does not return
a page cursor. `limit` is capped at 100, or pass up to 20 exact `ids`.
Aggregate receipt arrays require `include_evidence_refs=true`.
The JSON string in the MCP result's `content[0].text` is capped at 64 KiB and
may contain a smaller effective page to stay within that bound. JSON-RPC
framing and escaping add transport bytes outside this payload budget. An
individually oversized item returns a `resume_cursor` when later items remain.
Each page is stable for its own call; restart pagination if a cursor becomes
stale while the model changes.
The complete schema-v1 snapshot, including historical Points and receipts,
stays available as an owner-local file:
```bash
persome model export --out ./model-snapshot.json
```
`section="full"` returns this instruction without serializing the full model
over MCP.
### Compatibility and migration
This bounded default is a breaking response-contract migration targeted for
the next minor release, v0.4.0; it must not ship as a v0.3.x patch. In v0.3.x,
`get_model_snapshot(redact=...)` returned the complete canonical
`schema_version: 1` object. Starting with v0.4.0, the same call returns the
separately versioned `section="overview"` envelope.
Consumers must branch on `projection_schema_version`, page only the sections
they need, and use `persome model export` when they require the complete
canonical object. Missing Point, Line, or receipt arrays in an overview mean
“omitted,” not “empty.” CLI export and owner-local `/model/graph` retain the
complete canonical schema-v1 contract.
## Transport configuration
```toml
[mcp]
auto_start = true
transport = "streamable-http"
host = "127.0.0.1"
port = 8742
```
`sse` remains a deprecated transport compatibility option. New clients should
use streamable HTTP or stdio.
## Security boundary
- The HTTP server accepts loopback bind addresses only; browser Host/Origin
guards also reject non-loopback access.
- HTTP MCP requires the dedicated `PERSOME_LOCAL_API_TOKEN` bearer. Canonical
`GET /health` is the only unauthenticated liveness route.
- `persome install claude-code`, `codex`, `claude-desktop`, and `opencode`
register owner-local stdio subprocesses by default.
- MCP results contain personal data and must be treated as untrusted content by
consuming agents; captured text may contain prompt injection.
- Screenshots are excluded unless explicitly requested.
- `get_model_snapshot` projections redact by default and are byte-bounded.
- `remember` and `correct_memory` are deliberate writes with audit history.
The daemon HTTP endpoint also serves `/model`. Open the
viewer with `persome model open`; it uses a short-lived, one-time browser
capability rather than placing the long-lived token in a URL.
See [SECURITY_PRIVACY.md](SECURITY_PRIVACY.md) for the full data and egress
model. The implementation-oriented reference remains
[`docs/mcp.md`](docs/mcp.md).