Reference

MCP tools

All 13 tools the Personify MCP server exposes — signatures, parameters, examples.

The Personify MCP server exposes 13 read-only tools. They cluster into four groups:

  • Searchsearch, semantic_search
  • Browsetimeline, get_item, recent_items, recent_runs
  • Cataloglist_sources, list_accounts, stats
  • Graphgraph_search_entities, get_entity, entity_neighborhood, entity_context

All tools return JSON. All tools are safe to call repeatedly — there are no side effects.


Postgres full-text search across item_text.body. Returns the most relevant items as {id, source, kind, ts, title, snippet, score}. Best for keyword and phrase queries.

Signature

python
search(query: str, limit: int = 25, source: str | None = None) -> list[hit]

Parameters

NameTypeDefaultDescription
querystringrequiredSearch expression.
limitint25Max hits returned.
sourcestringnullRestrict to a source slug.

Example

vault
$ search(query="rust borrow checker", limit=3)
[{"id": 4127, "source": "github", "kind": "code",
"ts": "2025-11-04T12:14:00Z", "title": "src/borrow.rs",
"snippet": "fn check_borrow(...)", "score": 0.41}, ...]

pgvector cosine similarity over embedded chunks. Best for "find items semantically similar to this idea" rather than exact matches. Requires the optional embeddings extra and a vault embed pass.

Signature

python
semantic_search(query: str, limit: int = 25, source: str | None = None) -> list[hit]

Parameters

NameTypeDefaultDescription
querystringrequiredNatural-language query — embedded with the same model used for items.
limitint25Max hits returned.
sourcestringnullRestrict to a source slug.

Example

vault
$ semantic_search(query="library metaphor for ownership")
[{"id": 7710, "source": "chatgpt", "kind": "message",
"ts": "2025-09-12T22:01:00Z",
"title": "Rust ownership analogies", "score": 0.81}, ...]

timeline

Items with non-null timestamps in a date range, most recent first.

Signature

python
timeline(start: str | None = None,
        end: str | None = None,
        source: str | None = None,
        limit: int = 200) -> list[item]

Parameters

NameTypeDefaultDescription
startISO 8601nullInclusive lower bound.
endISO 8601nullExclusive upper bound.
sourcestringnullRestrict to a source slug.
limitint200Max items returned.

Example

vault
$ timeline(start="2026-01-01", end="2026-02-01", source="gmail", limit=2)
[{"id": 91201, "source": "gmail", "ts": "2026-01-29T16:42:00Z",
"title": "Re: Q1 plan"}, ...]

get_item

Retrieve a single item by id. The body is truncated to 4096 chars by default — pass include_body=True for the full text.

Signature

python
get_item(item_id: int, include_body: bool = False) -> item

Parameters

NameTypeDefaultDescription
item_idintrequiredItem id.
include_bodyboolfalseIf true, return full untruncated body.

Example

vault
$ get_item(item_id=4127)
{"id": 4127, "source": "github", "ts": "2025-11-04T12:14:00Z",
"title": "src/borrow.rs", "body": "fn check_borrow(...) { ...
[body truncated at 4096 chars]"}

recent_items

Paginated browse over items with stable ordering: ts DESC NULLS LAST, id DESC.

Signature

python
recent_items(source: str | None = None,
            account: str | None = None,
            kind: str | None = None,
            limit: int = 50,
            offset: int = 0) -> page

Parameters

NameTypeDefaultDescription
sourcestringnullFilter by source slug.
accountstringnullFilter by account handle.
kindstringnullFilter by item kind.
limitint50Page size.
offsetint0Skip this many.

Example

vault
$ recent_items(source="discord", limit=2)
{"items": [{"id": 12, "kind": "message", ...}],
"limit": 2, "offset": 0, "has_more": true}

recent_runs

Most recent ingestion runs with status, parser, and item counts.

Signature

python
recent_runs(limit: int = 10) -> list[run_summary]

Parameters

NameTypeDefaultDescription
limitint10Max runs returned.

Example

vault
$ recent_runs(limit=2)
[{"id": 14, "source": "github", "status": "completed",
"items_added": 8201, "started_at": "2026-05-03T09:11:00Z"}, ...]

list_sources

Active source registry — {slug, label, created_at} for every source with at least one ingested item.

Signature

python
list_sources() -> list[source]

Example

vault
$ list_sources()
[{"slug": "gmail", "label": "Gmail", "created_at": "..."},
{"slug": "github", "label": "GitHub", "created_at": "..."}, ...]

list_accounts

All account handles that have data ingested.

Signature

python
list_accounts() -> list[account]

Example

vault
$ list_accounts()
[{"handle": "myname@example.com", "source": "gmail"},
{"handle": "my-org", "source": "github"}, ...]

stats

Vault summary — item / export / run totals plus per-source and per-account breakdowns. Same data as the /stats HTTP endpoint and the vault://stats resource.

Signature

python
stats() -> vault_summary

Example

vault
$ stats()
{"items": 128402, "exports": 12, "runs": 14,
"items_per_source": {"gmail": 82140},
"items_per_account": {...}}

graph_search_entities

Find entities by name or alias substring. type is validated against the live entity-type registry — invalid types return an error rather than an empty list.

Signature

python
graph_search_entities(query: str,
                     type: str | None = None,
                     limit: int = 20) -> list[entity_summary]

Parameters

NameTypeDefaultDescription
querystringrequiredSubstring matched against canonical name and aliases.
typestringnullOne of the 22 entity types (e.g. Project, Person).
limitint20Max entities returned.

Example

vault
$ graph_search_entities(query="personify", type="Project")
[{"id": 81, "type": "Project", "name": "Personify",
"canonical_name": "personify", "origin": "extractor"}]

get_entity

Entity with aliases and item-backed evidence. Every entity in the graph is grounded in itemsevidence lists the items the extractor saw.

Signature

python
get_entity(entity_id: int) -> entity_full

Example

vault
$ get_entity(entity_id=81)
{"entity": {"id": 81, "type": "Project", "name": "Personify"},
"aliases": [{"alias": "the vault"}], "evidence": [{"source_id": 4127, ...}]}

entity_neighborhood

Walk the graph outward from an entity. Depth is capped at 2 — depth-3 graphs explode quickly and aren't useful as LLM context.

Signature

python
entity_neighborhood(entity_id: int, depth: int = 1) -> graph_subgraph

Parameters

NameTypeDefaultDescription
entity_idintrequiredCenter of the walk.
depthint11 or 2.

Example

vault
$ entity_neighborhood(entity_id=81, depth=1)
{"nodes": [{"id": 81, ...}, {"id": 14, ...}],
"edges": [{"source_id": 81, "target_id": 14, "type": "USES"}]}

entity_context

LLM-friendly grounding payload combining entity, neighborhood, evidence snippets, and suggested follow-up queries. Designed to be dropped straight into a prompt.

Signature

python
entity_context(entity_id: int) -> context_payload

Example

vault
$ entity_context(entity_id=81)
{"entity": {...}, "neighborhood": {"nodes": [...], "edges": [...]},
"evidence": [{"item_id": 4127, "snippet": "..."}],
"suggested_queries": ["how does Personify ingest GitHub repos?"]}