praxBLOCK
A self-hosted library for the papers and web pages one person reads: hybrid search, a graph whose links cite their sentence, and an MCP interface for agents
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
prax is a self-hosted library for the papers, web pages, manuals and notes one person reads. Its search matches words and meaning at once, its graph records what the documents say about each other, and an AI agent can search and read it through the same interface its owner uses. Everything lives in one SQLite file and a folder of originals, on your own machines, with models you choose.
pip install -e ".[serve,work]" export PRAXDATADIR=~/prax-data prax serve # http://127.0.0.1:8000/ui/
prax add paper.pdf prax add https://example.org/article prax search feedback delay networks prax ask --answer why do FDNs colour the tail
An empty store works from the first command. A new document is archived as it arrives, and prax work --watch, run on the machine with the models, does the rest: its text, title, graph links and vectors. To keep the parts running, list them under run: in prax.yaml and run prax up --install, which starts them at login on Windows, Linux or macOS. Setting up the Zotero import and the browser extension is in docs/howto.md.
Why I built it
My reading was spread over a Zotero library, an external disk I called zoetrope, a NAS and a year of browser tabs. I could only find a paper again if I remembered where I had put it. I wanted one place that keeps the originals and reads them closely enough to answer "which of my papers says this, and where". An agent working with me should be able to search it without being handed whole PDFs. I built prax with Claude Code over a few weeks in 2026. I decided what it should do and measured whether it did, and the log of that work is in docs/log.md. It is shaped by
3c0e79fe33d8OBSERVED · 2026-10-11Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add prax --env ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} --env HF_TOKEN=${HF_TOKEN} --env PRAX_TOKEN=${PRAX_TOKEN} -- uvx prax{
"mcpServers": {
"prax": {
"command": "uvx",
"args": [
"prax"
],
"env": {
"ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
"HF_TOKEN": "${HF_TOKEN}",
"PRAX_TOKEN": "${PRAX_TOKEN}"
}
}
}
}Exposed tools (41)
32 read · 9 write · 0 destructive.
| Tool | Risk | Description |
|---|---|---|
append_page | write | Add a section to an existing page as the agent, leaving what a |
ask | read | The context for answering a question from the library: one numbered |
blog | read | b |
capture_url | read | Fetch a web page or file by URL and keep it: a page is indexed at |
capture_urls | read | Fetch and keep several URLs in one call (at most 20), each as |
changes | read | What changed in a period (``since``/``until``: ``2026-09``, a day or |
cited_but_missing | write | What a set of papers cites that the library does not hold, ranked |
code-review | write | Quality review of prax code since a base commit: five dimensions, every finding re-checked |
connect | read | How ``a`` is connected to ``b`` (two names: papers, people, |
context | read | What places a document (by id) or a page (by slug) in the library, |
datasheet | read | a part |
documents | read | List documents, newest first, without their text: by ontology |
essay | read | an essay |
figure | read | Look at a figure: the picture itself, out of the document |
get | read | Fetch one document by id (ids come from search results). |
get_chunk | read | Fetch one chunk in full (ids come from search results). |
get_page | read | A page of the library |
health | read | Whether prax answers: the door |
ingest | read | Ingest raw text as a new document (deduped by content hash). |
ingest_file | read | Ingest a file from a path on this machine (the one running the MCP |
instructional | read | tells how |
link | write | Add a graph edge between two entities (created if missing). |
manual | read | a manual |
maths | read | A SymPy calculator for formulas, on a host that runs the maths pack. |
opinion | read | argues |
page_image | read | Look at one page of a document |
politics | read | policy |
promote | read | Flag a document for the expensive model |
references | read | A paper |
request_reading | read | Ask for a reading of a document the readers found nothing in, or |
search | read | Search the knowledge base. Returns compact snippets + ids. |
set_domains | write | Which ontology modules a document is read against (its domains, e.g. |
set_title | write | Give a document its title (a file name or an arXiv id where a |
society | read | people |
sociology | read | society |
status | read | Where documents are on their way to being read: ``indexed``, |
sync_project | write | Send a project |
traverse | read | Expand the knowledge graph 1-2 hops from a named entity. |
update_section | write | Replace the body under one heading of a page with ``text``, or add |
why | read | What a derived edge follows from (an INFERRED edge whose producer is |
write_page | write | Create a page (kind addendum, project or topic) or replace its text |
Trust audit
BLOCKgrade F · trust 48/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | FAIL |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (5 observation(s))
- Network
- declared (9 observation(s))
- Shell
- declared (5 observation(s))
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (25)
Promise.resolve().then(() => eval(arguments[0])).then((v) => done({ ok: true, v })).catch((e) => done({ ok: false, e: String(e && e.message || e) }));`, args: [expression] })p.add_option("--insecure", action="store_true", help="accept any TLS certificate")__import__(name)
return getattr(importlib.import_module(module), attr)
importlib.import_module(self.package)
module = importlib.import_module(home if "." in home else f"prax.steps.{home}")DEFAULT_DOOR = "http://127.0.0.1:8000"
r"^\s*([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)\s*([GMkmuμnp]?)\s*[A-Za-zΩ]*\s*$"
bars.webm
.zotero-ft-cache
zotero.sqlite
.zotero-ft-cache
.zotero-ft-cache
.zotero-ft-cache
.zotero-ft-cache
.zotero-ft-cache
# Hand scores of the maths eval (docs/symbolic-maths.md), R right, P partly,
hashlib.sha1(" ".join(str(r[0]).split()).encode("utf-8")).hexdigest()hashlib.sha1(" ".join(t.split()).encode("utf-8")).hexdigest()return hashlib.sha1(blob.encode("utf-8")).hexdigest()[:12]if doc is None and "/" not in path: # a topic's folder, "../../diffusion/"
"PDF: [the paper](../../DDPM-2006.11239.pdf). See [noise](../noise.md),"
" [attention](../../../attention/), [missing](../../gone.pdf),"
" [up](../../../outside.md) `pip install x` `*.md` and a sentence."
const lib = require("../../src/prax/ui/lib.js");Gates applied: no_behavioural_pass.
3c0e79fe33d8full audit observations/trust-audit/mcp-server/lodsb__prax.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-11 | 3c0e79fe33d8 | BLOCK | F | 48 | first audit |
Questions
What is the prax MCP server?
A self-hosted library for the papers and web pages one person reads: hybrid search, a graph whose links cite their sentence, and an MCP interface for agents
What tools does prax expose?
41 in total: 32 read-only, 9 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.
Is prax safe to connect to an agent?
No — not without reading the findings first. The audit graded it F (48/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on.
What credentials does prax need?
It reads ANTHROPIC_API_KEY, HF_TOKEN and PRAX_TOKEN from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How current is this page?
The grade is for one exact copy of the source (3c0e79fe33d8), read on 2026-10-11. The repository is watched and re-audited when it changes.