precis-mcp
by retospect
README.md
# precis-mcp
[](https://github.com/retospect/precis-mcp/actions/workflows/check.yml)
[](https://pypi.org/project/precis-mcp/)
[](https://pypi.org/project/precis-mcp/)
[](LICENSE)
[](https://doi.org/10.5281/zenodo.22863181)
Untiring, token-efficient research collaborator: reads papers and
patents, cites the paragraph, writes the paper, designs and simulates
what it proposes. A [Model Context Protocol](https://modelcontextprotocol.io/)
server for language-model agents:
- **Research** — papers, patents and reviews with paragraph-level
citations; findings, argument graphs and a term taxonomy.
- **Writing** — paper, patent and report drafts with figures and
diagrams; export to LaTeX, PDF and Word; audio narration.
- **Science and design** — atomistic structures, proteins, reactions and
catalytic pathways, sourced material properties, CAD assemblies, PCBs
and flow simulation, all built from code you can read.
- **Work** — todos, quests, jobs, agent fleets and long-term memory,
plus cached web, Wolfram, YouTube and Perplexity calls.
Agents use seven verbs (`get`, `search`, `put`, `edit`, `delete`, `tag`,
`link`) over every kind; content lives in PostgreSQL with `pgvector`,
with a web interface ([see how it works](guide/README.md)).
| The tagline | Where to see it |
|---|---|
| **Untiring** | [Quests](src/precis/data/skills/precis-quest-help.md): open problems worked tick after tick, reading, proposing, simulating, ranking · [The loop](guide/README.md#the-loop) |
| **Token-efficient** | [Fisheye](src/precis/data/skills/precis-fisheye-help.md): one view across every domain (papers, DFT cells, 3-D designs, boards, memory), the focus in full and its neighbours in summary |
| **Reads papers and patents** | [Drive](guide/README.md#drive): one search over everything · [Reading papers](guide/README.md#reading-papers) |
| **Cites the paragraph** | [Claims & nanopubs](guide/README.md#claims-and-nanopubs): every claim tied to a passage, signable |
| **Writes the paper** | [Writing a paper](guide/README.md#writing-a-paper) · [Figures & diagrams](guide/README.md#figures-and-diagrams) |
| **Designs and simulates** | [Structures & CAD](guide/README.md#structures-and-cad) · [Molecular machines](guide/molecular-machines.md) · [structure editor](src/precis/data/skills/precis-se-help.md) · [PCBs](src/precis/data/skills/precis-pcb-help.md) |
| **Web** | [Drive](guide/README.md#drive) is the front door; every kind has a page |
| **Podcasts** | Daily morning brief and evening meditation, plus any draft narrated to audio: [audio](src/precis/data/skills/precis-audio-help.md) · [feed and ops](docs/runbooks/audio-ops.md) |
## See it
<a href="guide/README.md">
<img src="guide/assets/drive/tour.svg" alt="precis Drive — search everything you've collected, animated tour" width="720">
</a>
A two-minute tour, section by section, lives right here in the repo at
**[guide/README.md](guide/README.md)**. A narrated version (audio) lives at
**[retospect.github.io/precis-mcp](https://retospect.github.io/precis-mcp/)**
once Pages is enabled. Video: coming.
**Set it up:** single machine —
[`docs/setup-single-machine.md`](docs/setup-single-machine.md) ·
cluster (multi-host, ansible) — [`deploy/README.md`](deploy/README.md).
> **Status.** Actively developed on the v8 line. There is no
> CHANGELOG — `git log` is the change story. The kinds catalogue
> below is a *living* set: the authoritative, build-specific
> enumeration is always `get(kind='skill', id='precis-help')`
> against a running server (it introspects the live registry),
> paired with `get(kind='skill', id='precis-overview')` for the
> guided tour. Agents should start at `precis-toolpath-help`
> ("I want to X — what do I call?").
## What it does
One tool surface — **eight verbs** discriminated by a single `kind=`
argument — over three categories of content. Ref kinds are addressed
by slug or integer id (output hands you a compact `<2-char><id>`
handle, e.g. `pa5` a paper, `me42` a memory); tool kinds take `q=`
or `id=` and hand back text.
- **Reading & reference** — `paper` (ingested research PDF),
`patent` (EPO OPS record), `cfp` (call-for-proposal / spec doc),
`oracle` (curated wisdom entry), `conv` (past conversation),
`pres` (slide deck), `skill` (agent how-to — you're reading one).
- **Files under `PRECIS_ROOT` / code** — `markdown`, `plaintext`,
`tex`, and `python` (symbol- and callgraph-aware repo navigator).
- **Authored artifacts** — `draft` (chunk-native document that
exports to LaTeX/PDF/Word), `cad` (analytic-SDF solid modeling —
designs are probed, not meshed; unit-required DSL), `se`
(structural-envelope designs: blocks/ports/joints with DRC,
stability + prestress analysis, a fastener engine, STL/3MF/STEP
export), `nm` (molecular-machine designs on the same block
surface — envelopes bound to atomistic structures, mechanics
ceilings), `structure` (atomistic cell + bond graph for
DFT/molecular work), `pcb` (netlist + placement graph, built-in
vector place-and-route → BOM/CPL/DSN), and `folder` (organizational
container for the above).
- **Autonomous work** — `quest` (an open problem worked on without
being asked: each tick reads, proposes, simulates and ranks, with a
logbook and a tree of sub-quests), `todo` (task tree; a todo can recur
on a schedule and spawn work each tick), `job` (one unit of execution
on the cluster: an LLM or agent run, a relaxation or DFT step, a
sandboxed coding task), `gripe` (a defect report that fixer agents
pick up), `plan` (a working plan on a draft's chunk tree).
- **Memory & evidence** — `memory` (agent memory graph), `citation`
(verified claim → source quote), `finding` (chain-of-evidence over a
citation chase), `anki` (spaced-repetition cloze cards → AnkiWeb).
- **Identity, comms & audit** — `orcid` (researcher-identity hub),
`message` (proactive outbound), `alert` (machine-detected ops
condition), `agentlog` (per-run attribution trail), `provenance`
(derivation audit).
- **Tool kinds** (stateless or cache-backed) — `calc` (local SymPy),
`math` (Wolfram), `youtube` (transcript), `web` (fetch + extract),
`wikipedia` (on-demand article), `websearch` /
`perplexity-reasoning` / `perplexity-research` (Perplexity Sonar
tiers).
- **Discovery** — `random`: pick a random indexed block to stumble
into content when you don't know what to ask for.
The active set depends on which optional extras and env vars are
configured (see [Install](#install)) — a kind whose dependency or
env var is missing simply drops off the surface. This list is a
snapshot; `get(kind='skill', id='precis-help')` enumerates the kinds
wired in *your* build, and `get(kind='skill', id='precis-overview')`
gives the design-rationale tour with an example handle per kind.
## Eight verbs
| Verb | Use when |
|----------|-----------------------------------------------------|
| `get` | You know the **name** (slug, id, file path) — or you're calling a tool. |
| `search` | You're looking for **content** by topic or phrase. Hybrid lexical (tsvector) + semantic (pgvector) with RRF fusion. |
| `put` | Create a new ref. Optionally tag and link on creation. |
| `edit` | Rewrite a region of a file-kind ref by content anchors (`find-replace`, `append`, `insert`, `replace`). |
| `delete` | Soft-delete a numeric ref, or delete a region from a file kind by selector. |
| `tag` | Add and/or remove tags. Three namespaces: closed (`STATUS:done`), flag (`pinned`), open (`topic-foo`). |
| `link` | Add or remove a cross-link to another ref. Vocabulary: `related-to`, `blocks`, `contradicts`, `cites`, `derived-from`, `supports`, … |
| `more` | Fetch the next page of a truncated response (`more(cursor='…')` — every truncation footer hands you the cursor). |
Address by `id=` for names, `q=` for content. No URI selector strings
for ids; region selectors inside files use the compact `slug~SELECTOR`
shape (e.g. `notes--meeting~L42-58`).
## Install
Use [uv](https://docs.astral.sh/uv/) and Python 3.13, the version CI tests
on every run (uv fetches 3.13 itself if it is missing):
```bash
uv tool install --python 3.13 'precis-mcp[all]'
```
This puts the `precis` command in its own isolated environment; upgrade
with `uv tool upgrade precis-mcp`.
**Disk space.** Measured 2026-10-20 on macOS arm64, Python 3.13:
| Install | Environment size |
|---|---|
| `precis-mcp` (core only) | ~650 MB |
| `precis-mcp[all]` | ~1.6 GB (CPU torch is ~530 MB of that) |
Linux installs that pull CUDA builds of torch are several GB larger. Models
download on first use, on top of the environment: the bge-m3 embedder
(`embed`, ~2.3 GB) and Marker's PDF layout/OCR models (`paper`, roughly
1–2 GB). Plan for about 5 GB free for a full single-machine install, plus
your Postgres data.
Plain pip also works on Python 3.12–3.13:
```bash
pip install 'precis-mcp[all]'
```
**Deterministic, no-API tool kinds ship in core** — no extra needed: `calc`
(sympy + pint), `plot` / `figure` (matplotlib), `mermaid` (`mermaidx`, no
Node/Chromium), `docx` + `tex` export (python-docx / latex2mathml / lxml /
resvg), `cad` STL/3MF export (manifold3d CSG kernel), `structure` CIF
I/O + symmetry (ASE + spglib), and `pcb` footprint resolution. So do the
light network/API-client kinds — `math` (Wolfram), `youtube`, `web`,
`wikipedia`, `news`, `edgar`, the Perplexity trio, and `patent` (EPO OPS):
their real gate is an API key, which fails loudly at call time, so they
ship with every install and appear once their credential resolves
(env var or the DB secrets vault). Only genuinely heavy packs
(torch-bound ML, ~200 MB binaries, daemon-shaped bridges) stay behind
extras — each enables its kinds; omit any you don't want:
| Extra | Enables | Heavy? |
|----------------|----------------------------------------------------|--------|
| `embed` | In-process bge-m3 embedder (sentence-transformers + torch) — needed for `search` unless you point at a remote embedder | yes (~2 GB model on first load) |
| `paper` | `paper` ingest — Marker PDF → chunks + CrossRef/S2 metadata | yes (pulls torch via Marker) |
| `web` | `precis web` browser UI (FastAPI + Jinja + HTMX) | no |
| `all` | `embed` + `paper` + `web` — the single-machine set. Excludes every tier below — install those explicitly. | yes |
| `asa` | `asa-bot` Discord bridge (discord.py) | no |
| `asa-slack` | `asa-slack` Slack bridge (slack_bolt) | no |
| `tts` | Audio export — local TTS for voice drafts + the morning brief (Kokoro) | yes (host-specific) |
| `cad-step` | `cad` exact STEP export (OpenCASCADE B-rep) | yes (~200 MB OCCT libs) |
| `dft-ml` | `structure` ML-potential relax (ASE + MACE-torch) | yes (pulls torch) |
| `chem` | Kept as a no-op alias: RDKit (the `route` retrosynthesis kind) moved into core on 2026-10-15 | no |
| `catalyst` | `pathway` kind surface (autocatpath engine — release-gated dep, not on PyPI; resolves via `[tool.uv.sources]` in this repo) | no |
| `catalyst-gpu` | `pathway` compute — in-process NEB/relax (autocatpath[mace] + cuequivariance; same dep caveat) | yes (pulls torch) |
| `struct-search`| Global structure search (AGOX GOFEE/basin-hopping) | yes (ray, dscribe, …) |
| `estimate` | `estimate` kind — chemistry-workup descriptors (mendeleev + pymatgen + tblite) | moderate |
| `chain` | `se` chain fold checks (ViennaRNA) | no |
| `pourbaix` | `pourbaix_bulk` job (pymatgen + Materials Project) | moderate |
| `guide` | User-guide capture/annotate pipeline (Pillow) — repo tooling, not a kind | no |
A bare `pip install precis-mcp` gives you the state kinds (`todo`,
`memory`, `gripe`, `anki`, `conv`, `oracle`, `skill`, `random`), the
core deterministic and network tool kinds listed above (key-gated ones
appear when their credential resolves), and the `markdown` /
`plaintext` / `python` / `tex` file kinds (the file kinds ride on
`PRECIS_ROOT` / `PRECIS_PYTHON_ROOTS`).
Optional deps surface as `InitError` at boot: the kind silently drops
off the tool surface with a WARNING, the server stays up.
### Database
`precis-mcp` requires PostgreSQL with the `pgvector` extension (SQL
extension name: `vector`). The CLI `precis migrate` applies the
forward-only numbered SQL migrations in `src/precis/migrations/`. See
`0001_initial.sql` for the schema.
```bash
createdb precis
psql precis -c 'CREATE EXTENSION vector;'
export PRECIS_DATABASE_URL=postgresql://localhost/precis
export PRECIS_EMBEDDER=bge-m3 # or "mock" for tests
precis migrate
```
Step-by-step single-machine runbook (worker, web UI, secrets):
[`docs/setup-single-machine.md`](docs/setup-single-machine.md). Cluster
(multi-host, ansible): [`deploy/README.md`](deploy/README.md).
### Upgrading
```bash
pip install -U 'precis-mcp[all]' # or: uv tool upgrade precis-mcp
precis migrate # then restart serve / worker / web
```
Daemons check the migration ledger at startup and **refuse to boot while
migrations are pending** (`PRECIS_SCHEMA_GATE=refuse`, the default) — a
new package can never silently run on an old schema. A DB *ahead* of the
package (a newer peer migrated it mid-deploy) warns and still boots.
Alternatives to running `precis migrate` by hand:
- `PRECIS_AUTO_MIGRATE=1` — or `--migrate` on `precis serve` /
`precis web` / `precis worker` — each daemon migrates itself at
startup, serialized under a Postgres advisory lock. The docker image
defaults this on for `precis …` commands, so a container restart
self-migrates.
- `PRECIS_SCHEMA_GATE=warn` — log one loud warning and boot anyway; for
read-mostly clients of a DB another host migrates (e.g. a session MCP
server) that must stay up through a deploy window. `precis-status`
reports the pending count as `schema_state`.
- `PRECIS_SCHEMA_GATE=off` — bypass the check entirely (same as the
legacy `PRECIS_SKIP_SCHEMA_CHECK=1`): loud warning, diagnosis only,
not for running services.
## Run
`precis serve` speaks MCP over stdio. Wire it into your agent's MCP
config:
```json
{
"mcpServers": {
"precis": {
"command": "precis",
"args": ["serve"],
"env": {
"PRECIS_DATABASE_URL": "postgresql://localhost/precis",
"PRECIS_EMBEDDER": "bge-m3",
"PRECIS_ROOT": "/absolute/path/to/notes",
"PRECIS_PYTHON_ROOTS": "myrepo:/absolute/path/to/myrepo"
}
}
}
}
```
### One-tool profile
Setting `PRECIS_MCP_PROFILE=command` in the server env collapses the
eight-tool surface into a single `precis(command=..., text=None)`
tool. `command` takes the same one-string call syntax the docs
already teach — e.g. `get(kind='skill', id='toc')` — parsed by
`src/precis/tools/command_parser.py`: one call, keyword args only,
`ast.literal_eval`-safe literal values; a bad call gets an
actionable `[error:BadInput]`, not a crash. `text=` is the escape
hatch for large bodies, so a caller doesn't have to quote-escape
them inside `command`. The frozen schema is ~850 bytes vs ~22 KB for
the typed per-verb schemas — cheaper cold-start, and a `tools/list`
block that never changes, so prompt caches keyed on it never
invalidate. Default profile is `typed` (unset = the per-verb tools
above).
`precis eval '<call>'` is the CLI twin: it evaluates one call string
against the same parser (`--text` / `--text-file` for the large-body
escape hatch) without building the multi-flag `precis tools <verb>
--flag value` form.
### Environment variables
| Var | Purpose |
|-------------------------------|--------------------------------------------------|
| `PRECIS_DATABASE_URL` | Postgres DSN (required for all ref kinds). |
| `PRECIS_OWNER` | Canonical username for the human running this instance — the author stamped on a web "ask a follow-up" and the `user:<owner>` addressee of an `ask-user` pause. Defaults to `reto`. |
| `PRECIS_EMBEDDER` | `"mock"` (dev/tests), `"bge-m3"` (in-process), or `"remote"` (HTTP client to `precis serve-embeddings`). |
| `PRECIS_EMBEDDER_URL` | Required for `remote`: ordered, comma-separated base URL(s), e.g. `http://127.0.0.1:8181`. First healthy endpoint wins; rest are fallback. |
| `PRECIS_ROOT` | Single root dir for `markdown` / `plaintext` / `tex` kinds. The trio is hidden when unset; every read/write is normalised against this path (`Path.resolve()` + `relative_to`). |
| `PRECIS_PYTHON_ROOTS` | `alias:/path,alias2:/path2` — exposed Python repos. |
| `PRECIS_PYTHON_ALLOW_EXEC=1` | Gate for `python` runtrace (spawns subprocess). |
| `EPO_OPS_CLIENT_KEY` + `_SECRET` | Enables `patent` kind (env or DB vault; `PRECIS_PATENT_RAW_ROOT` is just a cache path with a config default). |
| `ORCID_CLIENT_ID` + `_SECRET` | Enables the `orcid` researcher-identity kind. |
| `PRECIS_DIGIKEY_CLIENT_ID` + `_SECRET` | Live supplier stock for `component` `view='stock'` (paste on `/secrets`). |
| `WOLFRAM_APP_ID` | Enables `math` kind. |
| `PERPLEXITY_API_KEY` | Enables `websearch` / `perplexity-reasoning` / `perplexity-research`. |
| `PRECIS_WEB_AUTH` | `off` disables the `precis web` HTTP Basic gate (local dev only). Anything else — including unset — keeps it **on**: every route requires an account from `precis users`. |
| `PRECIS_WEB_PASSWORD_PEPPER` | Vault-resident pepper HMAC'd into web passwords before scrypt, so a shareable *logical* `pg_dump` carries no crackable hashes. `precis users add` mints one on first use; you rarely set this by hand. |
| `PRECIS_CORPUS_DIR` | Corpus root(s) for the `precis web` paper viewer. An `os.pathsep`-separated list is allowed (e.g. `/opt/a/corpus:/opt/b/corpus`); the web tries each `<root>/<letter>/<cite_key>.pdf` in order and serves the first that exists. Point it at the same path the ingest watcher writes to. |
| `LOG_LEVEL` | `DEBUG` / `INFO` / `WARNING` / `ERROR`. |
| `PRECIS_MCP_PROFILE` | `typed` (default, per-verb tools) or `command` (single `precis(command)` tool — see [One-tool profile](#one-tool-profile)). |
| `PRECIS_MCP_TOKEN` | Bearer token `precis serve --transport sse\|streamable-http` requires (stdio ignores it). |
| `PRECIS_AUTO_MIGRATE` | `=1` lets each daemon apply pending migrations at startup — see [Upgrading](#upgrading). |
| `PRECIS_SCHEMA_GATE` | `refuse` (default) / `warn` / `off` — startup migration-ledger check; `off` ≡ legacy `PRECIS_SKIP_SCHEMA_CHECK=1`. See [Upgrading](#upgrading). |
This table is the getting-started subset. precis reads ~150 `PRECIS_*`
variables in all — feature toggles, autonomy modes, budgets, model ids,
compute-routing, paths, and secrets. For the **exhaustive catalog** —
every var, its code default, the value deployed to each cluster service,
and an assessment of whether that state is right — see
[`docs/reference/config-variables.md`](docs/reference/config-variables.md).
The policy for *adding* a var (the three-tier scheme) is
[`docs/conventions/env-vars.md`](docs/conventions/env-vars.md).
## Design system
The `cad` / `se` / `nm` kinds form one design surface, macro to
molecular, built for LLM authoring:
- **Explicit units everywhere.** Every dimensioned input states its
unit (`3mm`, `1.4Å`, `12 N`, `90deg` — pint-backed, hogsheads
included); internals are SI (metres, radians, float64); display is
a neat SI-prefix formatter (`2.3 nm`, `1.2 kN`). A bare number
where a unit is required is *rejected with a hint* echoing the
plausible readings — the zero-counting / exponent-slip failure
modes of LLM-authored geometry die at the parser. Two declared
enclaves keep ecosystem conventions honest (`pcb` is mm like its
gerber/IPC world; `structure` is Å/eV like its ASE/CIF world),
self-named and converted at every API boundary.
- **Structural analysis** (`precis.structsolve`): force-density
form-finding, Pellegrino–Calladine rigidity + prestress
stability, and an active-set complementarity solver for unilateral
members (tension-only cables, compression-only struts,
must-contact stops — "which members carry, and does every member
stay on its legal sign"), with a two-state bistability probe. A
SIMP topology-optimisation engine (matrix-free, AM overhang
filter, gyroid lattice fill) ships alongside.
- **Design viewer** (web): per-design SVG projection reader —
force-coloured members, part isolation, stepped semantic
abstraction levels (envelope → interfaces → refined → realized) —
plus a three-cad-viewer 3D route with drawn connectivity,
exploded view, and a linked topology graph.
- Scale-relative kernel tolerances (an AST-gated no-absolute-epsilon
rule) make the same machinery exact from metres to Ångströms.
Where this is heading — one geometry currency from tolerance boxes
to atoms, situations/verdict tables, pattern groups, cost-aware
optimisation — is mapped in
[`docs/backlog/multiscale-design-architecture.md`](docs/backlog/multiscale-design-architecture.md).
## Design highlights
- **Eight verbs, one `kind=`**. The whole surface is
`get`/`search`/`put`/`edit`/`delete`/`tag`/`link`/`more`. No
per-kind bespoke tools.
- **Content-anchored edits.** `edit(find=..., before=..., after=...)`
resolves by literal content match; unique/first/all/nth policy;
fuzzy nearest-line hint on not-found. Pure resolver in
`precis.utils.edit_resolve`; ships for `markdown`, `plaintext`, and
`python`.
- **Hybrid search.** Lexical `tsvector` + semantic `pgvector` (bge-m3)
with Reciprocal Rank Fusion. Block-level; paper chunks, markdown
paragraphs, Perplexity answers, web pages all searchable.
- **Per-chunk discovery layer (F20).** Every body chunk gets
KeyBERT keywords stored on `chunks.keywords TEXT[]` (GIN-indexed
canonical forms) + `chunks.keywords_meta JSONB` (versioned
short/long pairs with bge-m3 cosine scores), populated by the
`chunk_keywords` worker. The paper TOC view (`view='toc'`)
DP-clusters those keyword arrays at request time
(`src/precis/utils/toc_db.py`) — superseding the dropped
`ref_segments` / `ref_segment_sentences` precompute. The
`citation` kind closes the loop: an agent's writing-thread
workflow can persist verified `claim → source quote` records (see
[`precis-citation-help`](src/precis/data/skills/precis-citation-help.md)).
- **Progressive disclosure.** Eight verbs and a `kind=` argument is
the *whole* visible surface. Behind it sits a fan-out of ~25
per-kind help skills, dozens of read views, an anchored edit
protocol, args-dict view payloads, and a tag/link vocabulary —
none of which the agent has to know up front. Every response can
emit a `next=` breadcrumb, every error names the skill that
explains it, and `get(kind='skill', id='precis-<kind>-help')`
unfolds the manual for whichever capability the agent just
bumped into. Think *exploding pocket knife*: the tool grows
blades as you reach for them, instead of advertising 20
unfamiliar buttons in `tools/list`. (UX literature calls this
pattern progressive disclosure.)
- **The todo tree.** `kind='todo'` is a hierarchical todo graph — a
level gradient (`strategic` → `tactical` → `subtask`, plus
`recurring`), a PRIO sort key, `meta.auto_check` wait-for-condition
leaves, and `meta.schedule` recurring spawn (the *Watches*
umbrella). It is the unified substrate for intent, execution, and
review; `kind='job'` (an offline LLM run) always hangs off a todo
via `parent_id`, and the `minter` worker is the canonical path
from a todo's `meta.executor` to a queued job. See
[`precis-todo-tree-help`](src/precis/data/skills/precis-todo-tree-help.md).
- **Profiled worker.** Every background pass runs under
`precis worker --profile=system` (embeddings, keywords, minter,
sweepers — safe to run on every node), `--profile=agent` (the
LLM-heavy review/planner rotation, each pass self-gated by env + a
load-average ceiling), or `--profile=all` (the union — the collapsed
one-worker-per-host shape the cluster runs). Per-pass daemons are
retired.
- **HintBus.** Any layer can emit deduplicated, novelty-decayed tips
that are rendered after the verb's main output. Keeps slim models
from drowning in self-inflicted reminders.
- **Slim exception surface.** `BadInput` / `NotFound` / `Gone` /
`Unsupported` / `Upstream` / `RateLimited` / `Internal`, each
carrying a single copy-pasteable `next=` "breaking hint".
- **`psycopg 3` sync, raw SQL.** No SQLAlchemy, no Alembic, no async
below FastMCP — stdio's serial workload doesn't buy anything from
async.
- **In-tree handlers, entry-point plugins.** Core kinds are
hand-ordered in `precis.dispatch.boot()`. Third-party kinds can
register themselves via the `precis.handlers` entry-point group
without forking — the contract lives in the `precis.dispatch`
docstrings; `src/precis_chem/` is the richest first-party example.
## Extending
Write a plugin handler in 3 steps — the contract is documented in the
`precis.dispatch` docstrings (`_load_plugins`), with the
canonical tiny example in
[`src/precis/handlers/calc.py`](src/precis/handlers/calc.py).
```toml
# your plugin's pyproject.toml
[project]
dependencies = ["precis-mcp>=8.0.0"]
[project.entry-points."precis.handlers"]
wikipedia = "precis_wikipedia:WikipediaHandler"
```
Plugin failures are logged and skipped — one bad plugin cannot brick
the server.
## CLI
Routed EasyEDA Pro intake: `uv run precis pcb import-epro LOCAL.epro2 --slug PREVIEW`
preserves straight/arc tracks and through vias as fixed source copper. Use
`--dry-run` to inspect first or `--copper none` for measurement-only intake.
`precis memory mirror import DIR --namespace NAME` imports a flat YAML/Markdown
memory snapshot with conflict checks. `precis memory mirror export DEST
--namespace NAME` preserves original filenames and formatting in a new directory;
it never overwrites an existing destination or retires missing memories.
```text
# Serving
precis serve # Start the MCP stdio server.
precis serve-embeddings # HTTP embedding service (server side of
# PRECIS_EMBEDDER=remote; /healthz /readyz
# /model /embed /metrics).
precis web [--host H --port P] # Browser UI: Tasks / Papers / Console /
# Conversations / Status tabs (needs the
# [web] extra; binds 127.0.0.1:9100 behind
# HTTP Basic — create an account first, or
# every page answers 503).
# Background processing
precis worker [--profile system|agent|all]
# Drive the background passes. 'system'
# (default) = embeddings/keywords/minter/
# sweepers; 'agent' = the LLM-heavy review
# + planner rotation; 'all' = the union.
# --only X --once for ad-hoc backfills.
precis ingest --watch <dir> # Watch an inbox dir and ingest dropped PDFs
# (papers / books / presentations routing).
precis add <pdf|--doi ID|--arxiv ID>
# Ingest one paper on the spot.
# Web accounts (precis web logins; every account is fully authorized)
precis users add <login> --abbrev <ab> [--name N --email E]
# Create an account; password from a no-echo
# prompt (or --password-stdin). Never argv.
precis users list # The roster.
precis users passwd <login> # THE recovery path — Basic auth has no
# email reset flow, by design.
precis users edit|disable|enable|rm <login>
precis users feed-token <login> # Mint + print the private podcast feed URL
# (?t=… , since podcast apps handle Basic
# on enclosures inconsistently).
# Signed-in users do the self-service half —
# password, profile, podcast link — at
# /account in the web UI. Creating and
# removing accounts stays here.
# Database
precis migrate # Run pending forward-only SQL migrations
# (--dry-run reports, --from-scratch
# replays the chain ignoring the baseline).
precis db dump-schema # Regenerate migrations/baseline/schema.sql.
precis schema-doc # Generate the Mermaid ER diagram
# (docs/reference/schema.md) from a DSN.
# Interactive & inspection
precis repl # Interactive verb console (tab-complete).
precis draft ... # Manage / export draft-kind documents.
precis stats | logs | stubs | verify
# Corpus stats, event logs, stub triage,
# integrity checks.
precis stats --utilization [--hours N]
# Hourly CPU (host_heartbeat_log) + LLM
# (llm_call_log) utilization + idle gaps.
precis cron | heartbeat # Scheduler tick / liveness ping.
# Claim-hub curation (taproot)
precis taproot ... # Claim-hub authoring/repair: mint / refine /
# merge / backfill / backfill-grounding /
# repair-evidence / direct-mint / lint.
precis taproot verify-edges # Certify withheld/unverified evidence edges
# for the publish preflight (stamps the
# meta.support verdict; dry-run default).
precis taproot reword-sweep # LLM batch reword of lint-blocked claim hub
# sentences through the retitle door
# (dry-run default).
# One-shot jobs
precis jobs ingest / ingest-oracles # Pre-warm files under PRECIS_ROOT /
# seed the oracle kind.
precis jobs import-perplexity ... # Bulk-import Perplexity web-UI answers.
precis jobs watch-patents / list-patent-watches / run-patent-watches /
sweep-patent-fulltext # Saved CQL patent watches (patent kind).
precis jobs check-provenance / sync-retraction-watch
# Provenance + retraction audits.
```
Run any subcommand with `--help` for the full option list.
### Utility scripts
The `scripts/` dir holds workspace-side utilities that run *against*
a precis store but live outside the published CLI surface. See
[`scripts/README.md`](scripts/README.md) for full coverage; the
high-traffic ones:
- **`paper-monitor-ingest-dir`** — drop-and-go PDF ingest watcher.
- **`perplexity-monitor-ingest-dir`** — bulk-import Perplexity
markdown exports.
- **`find-citing-papers`** — sweep S2 for new papers citing the
precis corpus, with bge-m3 cosine rerank and several noise-
reduction filters; reports land in a `paper-ingest/` review dir.
- **`enrich-paper-identifiers`** / **`retrofit-acatome-external-ids`**
— backfill DOI / arXiv ids on legacy refs.
## Roadmap
- The multiscale design programme (shared design core, block
libraries with states, situation rule tables, pattern groups,
cost-aware optimisation) —
[`docs/backlog/multiscale-design-architecture.md`](docs/backlog/multiscale-design-architecture.md)
is the living map.
- `book`, `rmk` file handlers. (`tex` and `docx` shipped.)
- `web` bookmark mode + Wayback enrichment (gripe:3681 phase 2 + 4 — see [`docs/backlog/`](docs/backlog/README.md)).
- `voice` kind — STT/TTS bound to transcript refs (spec: [`docs/backlog/voice-kind-spec.md`](docs/backlog/voice-kind-spec.md)).
- SDK extraction (`precis-core`) once the plugin API has settled.
## Documentation
- [`AGENTS.md`](AGENTS.md) — **start here to contribute or change code.** The canonical guide: conventions, workflow, definition-of-done, ingest guarantees.
- [`docs/mission.md`](docs/mission.md) — the mission, the pitch narrative, and the current corpus facts (positioning, not architecture — the single source for decks and talks).
- [`docs/README.md`](docs/README.md) — the documentation landing index (directory-by-directory map).
- [`docs/codebase.md`](docs/codebase.md) — orientation: invariants, lifecycle, seams, and the generated package map (subsystem detail lives in each package's `__init__.py` docstring).
- [`docs/reference/schema.md`](docs/reference/schema.md) — the **generated** DB schema diagram (Mermaid ER, produced from the live database — can't drift).
- [`docs/reference/config-variables.md`](docs/reference/config-variables.md) — the full `PRECIS_*` config catalog: every var, its default, the value deployed to each cluster service, and a correctness assessment.
- [`docs/reference/schema.md`](docs/reference/schema.md) — generated schema (full ER view: `schema-v2.svg`).
- [`src/precis/data/skills/precis-citation-help.md`](src/precis/data/skills/precis-citation-help.md) — `citation` kind + verifier-workflow agent surface.
- [`src/precis/data/skills/precis-toc-help.md`](src/precis/data/skills/precis-toc-help.md) — TOC machinery (segments, sentences, matryoshka keywords).
- Git history (`git log`) — what shipped in each phase (no CHANGELOG file).
## Contributing
The repo lives at
[`retospect/precis-mcp`](https://github.com/retospect/precis-mcp).
Coordinated releases use `scripts/round gate` / `deploy`: exact release SHA,
fresh CI, then coordinator runtime evidence before immutable tagging and retirement.
Issues and PRs welcome. Development workflow:
For isolated Codex sessions in tmux, see [`scripts/fleet-codex`](scripts/fleet-codex)
and the [Codex fleet runbook](docs/runbooks/codex-fleet.md).
```bash
uv sync --all-extras --group dev
uv run pytest
uv run ruff check . && uv run ruff format --check .
uv run mypy src tests
```
Run the **full test suite in the dev container**, which bakes every
optional extra and wires the test database:
```bash
scripts/test # full suite, all extras
scripts/test --typecheck # mypy src tests
uv run ruff check . && uv run ruff format --check .
```
A host `uv run pytest` only sees the torch-free base install, so the
full run there fails with spurious missing-extra errors (`sympy`,
`marker`, `lxml`, …) — use it for targeted subsets only.
All tooling goes through `uv run` (host) or `scripts/dev` (container)
— see [`AGENTS.md`](AGENTS.md) for the full workflow and
definition-of-done.
## License
GPL-3.0-or-later. See the full text at
[gnu.org/licenses/gpl-3.0.html](https://www.gnu.org/licenses/gpl-3.0.html).
`precis nanopub supersede FI` stages a local successor candidate for an anchored,
unpublished claim artifact; review and same-key signing remain separate steps.
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessSlow