Skip to main content
Glama

linkedparticles

linkedparticles.org · docs.linkedparticles.org · PyPI · Apache-2.0

Particles is shared memory for humans and AI agents. Each particle is one claim, plus what you need to judge it: who said it, where, when, and how confident they were. Facts, opinions, and memories are all claims, recorded the same way as particles. Particles are not edited or deleted. Particles are superseded, retracted, or disputed in the open. How much to trust it is a perspective applied at query time, never baked into the record.

linkedparticles is the Engine of the Particles reference implementation: the package you install to actually run a belief store. Give it documents, pages, chat logs, or an agent's own session notes; get back claim-granularity beliefs, each carrying calibrated confidence, an uncertainty kind, a resolved subject, and provenance back to the exact source bytes. Ask a question and the answer cites the beliefs it was built from. Nothing is ever overwritten, so you can ask the store what it believed a year ago and why it stopped.

When your agent is wrong, you can see exactly why, and fix it at the source.

The Engine is a library first. The HTTP API, the CLI, the read-only MCP server, and the resident daemon are all surfaces over it.

Install

pip install linkedparticles

Python 3.11+. linkedparticles-core, the store-free Client layer, is pulled in automatically.

Extraction and the written answers call a language model. The quickstart below uses Anthropic, and any OpenAI-compatible endpoint works too, hosted or local (Ollama, llama.cpp, vLLM): each purpose names its provider in config.yaml (named providers). Deposit, the session digest and structural queries make no model call at all.

Related MCP server: memorygraph

Sixty seconds

export ANTHROPIC_API_KEY=sk-ant-...
particles db init

# Deposit a source (file, URL, or literal text) into the append-only corpus
particles deposit https://en.wikipedia.org/wiki/Pluto

# Extract claim-granularity beliefs with confidence, subjects, and provenance
particles extract --all-pending

# Ask in natural language; the answer cites the particles behind it
particles query "Why is Pluto not a planet?"

# Health-check the store: contradictions, staleness, orphaned links
particles lint

Because nothing is overwritten, the store can replay its own history. --as-of is the assertion-time lens. It answers what did the store believe at T, and why did it stop, not what was true of the world at T:

particles query "How many planets are in the Solar System?" --as-of 2000-01-01
# → the belief as it stood then, and why it no longer stands: SUPERSEDED,
#   retired 2006-08-24, superseded by "Pluto is a dwarf planet."

There is a clickable version of that belief history on the front door. Step by step: getting started, then as-of time travel.

Wiring it into an agent

particles mcp serve                 # read-only MCP server (stdio), any MCP client
particles init claude-code          # session-start digest, session-end harvest
particles engine serve              # HTTP API, for a shared or remote engine
particles export obsidian ./vault   # also: anki, wiki, logseq, notion, graph, jsonl

It can also stand in for the reference memory server, and it plugs into LangChain as a retriever and a tool set. See Claude Code memory, swapping in for the reference memory server, and using from LangChain.

Does it hold up?

Measured on LongMemEval, the multi-session agent-memory benchmark, with a full-context oracle and a no-memory floor run as controls in the same harness:

Recall@40

End-to-end QA

Particles memory (shipped default, top_k 40)

0.969

0.804

Full-context oracle (baseline, n=148)

—

0.878

No memory (floor)

—

0.047

The oracle and floor rows come from a separate control run in the same harness, the day before the three runs the Particles row averages; the benchmarks page names the report of record for each row.

Method, per-question-type breakdowns, comparator memories, and the budget-matched arm (including the arms where Particles loses) are on the benchmarks page, with the report JSONs of record beside them.

Security posture

A memory layer is an input-shaping attack surface: it does not merely hold data, it shapes what the agent believes and does next, so a poisoned claim is an instruction on a delay timer.

Three adversarial audits have covered this code, and each returned GO-WITH-FIXES. The verdicts are quoted as given.

Audit

Code audited

Verdict

Fixes shipped in

June 2026, before the code was opened: the HTTP, CLI and MCP surfaces, the filesystem writers, the egress layer, the CI and wheel build

v1.62.0

GO-WITH-FIXES

1.62.1 to 1.63.0; the last open finding closed in 1.128.0

2026-10-23: everything changed since v1.62.0, including the release and publication pipeline the first audit predates, and the claims on this page

v1.210.2

GO-WITH-FIXES

1.210.3 to 1.211.0

2026-10-24: everything changed since the second audit, every earlier finding, and the claims on this page again

v1.211.0

GO-WITH-FIXES

1.211.1 to 1.214.0

Since those fixes, a cloned repository can no longer configure Particles or supply the store an MCP server reads, an HTTP caller can no longer make the engine read a file on its own disk, and a web page can no longer send writes to an engine on loopback or read from one that runs without a key. The job that holds the PyPI publishing identity runs no code from a package index: it downloads the built files, checks them against the digests the build job recorded, and runs the pinned upload action. Not every finding is fixed: part of the second audit's finding on automatic retirements remains open, and SECURITY.md describes it and the other limits that remain.

What holds today, and what does not:

  • Prompt injection is contained, not eliminated. Outside the benchmark harness, every model prompt that carries deposited, stored or harvested text keeps its instructions in the system turn and wraps that text in a per-call fence marked with a 128-bit random nonce. A test finds every call to the model's entry points, including calls through a wrapper that passes a system turn on, and fails the build on one that has not been classified and, if it carries such text, fenced. A call reached another way, such as through a function passed as a value, is outside what that test can find. Behind the fence sit structural checks: a JSON contract enforced at the parser, and a gate that rejects synthesized prose citing a claim it was not given. This raises the bar materially. It is hardening, not immunity.

  • The model has no tools, but its verdicts change what is stored. The model is never offered function calling, and nothing it emits is run as code or SQL or used as a fetch destination. Its output still has effects: subject names it extracts become Wikidata search terms; its verdicts retire claims (an older value a newer claim updates, a claim from the same passage that the re-anchor pass restates in words the model wrote, the less trusted side of a contradiction between sources of different trust) and return held claims to active, each recorded in the event log; and the beliefs it extracts are written into Claude Code's MEMORY.md, which an agent with tools reads as instructions. An injection can distort claims, and a distorted claim can steer an agent.

  • Fetches of URLs from deposited content are checked on every hop. The host is resolved, each address is checked against a blocklist, and the connection goes to that vetted address, again on every redirect, which closes DNS rebinding and redirect SSRF. The two fetches that run as subprocesses are pinned to addresses this process vetted, neither follows a redirect on its own, and the git clone runs under no system or global git config, so no filter driver (git-lfs among them) runs for the cloned files. Endpoints you configure yourself (a model provider, a remote engine, a telemetry collector) are held to the network.egress setting but not to the blocklist, since a LAN or local model server is a legitimate target.

  • Fail-closed auth, and no SQL built from input. With no bearer key set, the engine refuses to start on a non-loopback bind, reading the bind from the uvicorn command line when it is started that way and refusing a launch by another ASGI server whose bind it cannot read. On every path it then serves only a loopback client that names a loopback host or one listed in api.allowed_hosts, which turns away a DNS-rebinding page. Routes that act with the operator's authority (subject merges, operator retractions, review rulings, trust policy) need a real key even from loopback. The token comparison is constant-time. The data layer issues typed ORM statements with bound parameters; its few literal SQL statements (a schema-version read and the change-journal triggers) are constants that take no input.

  • Local by default, with three outbound defaults you should know. The engine binds to loopback, stores to a local SQLite file, keeps telemetry off, and serves MCP as a locally spawned stdio child. Out of the box it also contacts the model provider you configure, Wikidata for subject lookups during extraction (these carry extracted entity names), and the Hugging Face Hub, to download the embedding model and, while outbound traffic is open, to check for a newer copy when a process loads it. Settings come only from the file PARTICLES_CONFIG names or ~/.particles/config.yaml, never from the directory a command runs in. The store is a different matter: when nothing names one, the particles command line and engine serve open ./particles.db in the directory they run in, while an MCP server opens ~/.particles/particles.db. Set network.egress to none or allowlist to restrict outbound traffic.

The real answer to the residual is epistemic rather than technical: every particle carries its provenance, source trust is a read-time lens that discounts a distrusted source without rewriting anything, and lint / review turn your rulings on contradictions into a reusable trust policy. The store is a record of what sources said, weighted by how much you trust them, not an oracle, so a poisoned source is something you can see, discount, and retract with the audit trail intact.

The limitations we ask you to read before relying on any of this are in SECURITY.md: the read surface left open by default, verbatim storage of whatever you deposit (secrets included), model verdicts that retire claims, project scope as a relevance filter rather than isolation, the single-operator trust model, and the MCP write boundary. SECURITY.md is also where to report a vulnerability; please report privately.

Why Particles?

Most Retrieval-Augmented Generation systems re-derive knowledge from scratch on every query, operating over raw text chunks without any persistent record of what was learned, how confidently it was held, or where it came from. Particles takes a different approach: rather than retrieving passages, it stores discrete, citable, revisable claims (natural-language sentences paired with structured metadata for confidence, provenance, and uncertainty) so that an agent's knowledge accumulates as an auditable ledger rather than evaporating between sessions. Corpus-entry-level provenance is required at Core, meaning every belief can be traced back to the source that produced it, and the particle store itself is a derived view that can be rebuilt from the corpus by re-running extractors, giving the system both durability and reproducibility.

The Particles standard defines the particle schema, the source-corpus model, the extraction protocol, and a set of operations (deposit, extract, query, lint, review, and reindex) that together form the spine along which an agent's knowledge is built, queried, audited, and revised one belief at a time. A developer working with this loop deposits a source into the append-only corpus, extracts claim-granularity particles with resolved subjects, queries by effective-confidence ranking, lints for contradictions and staleness, and reviews inconsistencies into a reusable trust policy. Because particles carry explicit confidence and provenance, Particles can answer queries that require finding relevant claims about a subject and synthesising them with provenance intact, rather than returning a ranked list of chunks whose epistemic status is opaque.

Particles is a minimal interoperable substrate for claim-granularity agent knowledge: narrower than a formal-ontology knowledge graph such as RDF/SPARQL and more structured than augmented markdown. Anchoring every particle to a subject is what makes this precision possible: the Subject store is the standard's catalogue of real-world entities against which particles are indexed, aligning beliefs to canonical entities that can, in principle, be mapped to external ontologies. A developer choosing Particles is therefore choosing a substrate where each belief is a first-class object with an identity, a confidence score, a source, and a subject, not a position in a vector space.

Design rationale

The foundation of Particles is the guarantee that nothing already written is ever overwritten. The Source Corpus is constituted as an append-only archive of all materials from which particles have been or may be extracted, meaning that every ingested source and every derived claim accumulates in place rather than displacing what came before. Provenance is carried by each particle from the moment of its creation, and when a source must be handled in a mutable mode rather than a purely append-only one, the system does not silently absorb the change: particles whose provenance location falls within the changed regions are flagged with PROVENANCE_STALE, making the disturbance visible rather than burying it. Supersession and retraction therefore propagate deterministically through the provenance graph, touching every claim whose origin is implicated, so the ledger remains a faithful record of what was asserted and when, never a quietly revised version of the past.

Trust in Particles is not a property baked into a stored record but a lens applied at the moment of reading. The raw confidence value is stored immutably, calibrated at the time a particle is created and never subsequently altered; what changes with each query is the effective confidence, which is computed at query time rather than stored. Trust weighting, recency decay, and the as-of instant are all applied per observer at query time, never written back into the record. This means that a belief does not need to be retracted or rewritten to sink in the rankings as its source ages or as the extractor that produced it loses credibility: the stored particle remains intact while the effective confidence computed over it falls, allowing stale beliefs to recede naturally without any mutation of the underlying ledger. When as_of is set to a past instant T, the query evaluates the store on the assertion-time axis (what the store believed at T) rather than on any world-time validity dimension, so the same immutable corpus can answer questions about present belief and historical belief without ambiguity.

Contradictions in Particles are treated as first-class citizens of the knowledge graph rather than anomalies to be suppressed. When two sources or two principals disagree, the conflict-resolution ladder surfaces an INCONSISTENCY record for review instead of silently overwriting either side, preserving both competing claims in the ledger and making the disagreement legible to any downstream consumer. Contestedness, the property that marks a particle as being in tension with one or more others, must be computed at read time and is never stored; like effective confidence, it is a read-time lens rather than a durable annotation, which means that as new particles arrive or old ones are superseded, the contested status of any given claim is always freshly derived from the current state of the graph rather than from a stale flag written at some earlier moment.

Memory in Particles maintains itself through a periodic, automated health discipline. The Lint operation performs health checks for contradictions, stale claims, orphan pages, and missing cross-references, scanning the corpus on a scheduled basis so that problems accumulate into visible findings rather than silently degrading the quality of the belief store. Because nothing is overwritten and contradictions are surfaced rather than resolved by fiat, Lint operates on a stable substrate: it traverses the same immutable record that queries read, and its findings feed back into the trust-policy review cycle, closing the loop between ingestion, querying, and the ongoing stewardship of the ledger's integrity.

Architecture

A Particles deployment is organized around two distinct storage subsystems: a Source Corpus store and a Particle store. The Source Corpus store is an append-only object store, compatible with a local filesystem, an S3-compatible backend, or a content-addressed store, while corpus entries and snapshot metadata are held in queryable form, either relational or document store. Together these two subsystems form the durable foundation on which all operations act.

The Core SDK exposes both a clean Python API and a CLI, and the six core operations (Deposit, Extract, Query, Lint, Reindex, and Review) each map to a CLI subcommand and a POST API endpoint in the reference SDK. A developer therefore has two symmetric surfaces for every operation: a scriptable command line suitable for pipelines and a programmatic endpoint suitable for application integration.

The journey from a raw source to a set of particles begins with Deposit, which writes the source into the append-only corpus, and continues with Extract, which drives the extraction pipeline. That pipeline selects the most specific registered extractor whose applicability specification matches the deposited source; the general extractor is used if and only if no domain-specific extractor applies. Once particles exist in the Particle store, Query retrieves them ranked by effective confidence, Lint checks for contradictions and staleness, Reindex rebuilds derived indexes, and Review consolidates inconsistencies into a reusable trust policy. Each step in this sequence is a discrete, named operation rather than an implicit side effect, which means a developer can invoke any stage independently and observe its inputs and outputs in isolation.

The Why Particles?, Design rationale, and Architecture sections are cited projections of a particle store, not hand-authored prose. Each marked block is rendered from docs/projection/readme.yaml and the corpus bundle committed beside it, and the trailer under each block names the exact claims it was built from. Edit the manifest or the underlying particles and re-render, never the prose between the sentinels. Check it yourself: python scripts/projection_drift.py restores the bundle into a throwaway store, re-derives the deterministic render, and fails if any block has drifted from the claims it cites.

This is the project eating its own dogfood: the README argues for claim-granularity knowledge with provenance, and is itself assembled that way.

Documentation

Everything below is served at docs.linkedparticles.org.

Guide

What it covers

User guide

Depositing, extracting, querying, as-of time travel, exporting, agent integrations

Operator guide

Configuration, tuning, lint and review, remote engines, containers, observability, troubleshooting

Plugin-author guide

Writing extractors, exporters, and benchmark suites

CLI reference

Every verb and flag

HTTP API

The OpenAPI contract

Benchmarks

LongMemEval results, method, and comparators

The standard itself (whitepaper, technical specification, and the normative schema, context, and vocabulary artifacts) lives at linkedparticles.org.

The three repositories

Repo

What it is

particles-standard

The standard: whitepaper, technical specification, normative schema + SHACL artifacts, conformance fixtures

particles-core-py

The Python Client layer (linkedparticles-core)

particles-engine-py

This repo: the Python Engine layer + surfaces (linkedparticles)

Deployment

Container and chart artifacts live under deploy/. The engine ships as a single-writer service; see running in a container.

Contributing

See CONTRIBUTING.md and ARCHITECTURE.md. Contributions are accepted under a Developer Certificate of Origin sign-off; there is no CLA.

License

Apache-2.0. See LICENSE and NOTICE.

Available Tools

16 tools
event_showB

Show one operator event in full — header, refs, and payload.

Args:
    event_id: The event's id.
NameRequiredDescriptionDefault
event_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full load; it does disclose the returned components (header, refs, payload), which is real behavioral context. It does not state that the operation is read-only, what happens when event_id is unknown, or any access constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loads the purpose in the first sentence. The "Args:" block is redundant against the schema but costs little.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained further, and for a single-record fetch the description is close to sufficient. It still leaves the source of the event_id and error behavior unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, but "event_id: The event's id." is a tautology that adds nothing. It omits where an id comes from (presumably events_list) or any format expectation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Show one operator event") and enumerates the returned sections (header, refs, payload), which distinguishes it from a bulk list operation. It never names the sibling events_list, so the differentiation is implied by "one" rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance, and the obvious alternative (events_list) is never referenced. The agent must infer that this is the detail-fetch counterpart to the list tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

events_listA

List operator events, newest first, optionally filtered.

Args:
    particle: Only events touching this particle id.
    subject: Only events touching this subject id.
    corpus_entry: Only events touching this corpus entry id.
        (At most one of ``particle`` / ``subject`` / ``corpus_entry``.)
    event_type: Only events of this type, e.g. ``SOURCE_RETRACTED``,
        ``SUBJECTS_SPLIT``, ``TRUST_CHANGED``, ``REVIEW_RESOLVED``.
    limit: Maximum events to return (default 50).
NameRequiredDescriptionDefault
limitNo
subjectNo
particleNo
event_typeNo
corpus_entryNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description carries the full behavior burden. It usefully discloses ordering (newest first), the default limit of 50, and the mutual-exclusivity constraint on the three filter ids, but says nothing about whether limit is capped, how to page past 50 results, or what happens with zero matches.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded one-line summary followed by a compact Args block; every line carries information. The docstring formatting is slightly heavy for a tool description but there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values need not be explained, and all five parameters are documented. What is missing is paging behavior: with a limit default of 50 and no offset/cursor documented, an agent cannot tell how to retrieve further events, nor whether events feed into event_show by id.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate and mostly does: it defines all five parameters, explains the 'touching this id' semantics of the three filter ids, and gives concrete event_type examples (SOURCE_RETRACTED, SUBJECTS_SPLIT, TRUST_CHANGED, REVIEW_RESOLVED). It stops short of saying what form the ids take or listing the complete set of event types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List operator events') plus ordering ('newest first') and filtering scope. It does not differentiate itself from siblings like event_show or the other *_list tools, but the verb+resource pairing is unambiguous about what it returns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the reader infers this is the enumeration tool versus event_show for a single event. The one genuinely useful routing rule is the parenthetical that at most one of particle/subject/corpus_entry may be supplied, but there is no explicit 'use this when' or named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

graph_viewA

Render one scoped epistemic subgraph of the particle store.

Scope is mandatory — pass exactly one of ``subject_id`` / ``query`` /
``inconsistency_id`` / ``manifest``+``section`` (a whole-store render
does not exist; the anti-hairball invariant). Every
epistemic quantity in the result (effective confidence, contested
badges, as-of visibility, utility evidence) is computed at render time
by the engine and never stored.

Args:
    subject_id: Neighbourhood scope — this Subject, its particles, and
        subjects reachable within ``hops`` via multi-subject particles.
        Accepts a subject id or an exact (case-insensitive) canonical
        name / alias; the render's ``scope_ref`` is the resolved id.
    query: Retrieval-set scope — the top-K hits of the existing query
        ranking rendered as their subjects plus the hit particles
        ("the picture of the knowledge the agent consulted").
    inconsistency_id: Evidence scope — a contradiction's
        picture: the INCONSISTENCY particle as the anchor, its two
        disputant beliefs shown with their true statuses (the
        quarantined side included), their subjects and sources. Accepts
        a full particle id or a unique prefix (a contested badge's
        ``inconsistency_id`` is the usual source).
    manifest: With ``section``, projection scope — an
        manifest section's deterministic selection rendered as
        a graph. The manifest path resolves on the engine host.
    section: The manifest section's ``region`` id, or its exact
        (case-insensitive) title.
    hops: Neighbourhood radius for subject scope (clamped to
        ``graph.max_hops``).
    history: Also include retired supersession-chain ancestors, rendered
        as ghosts.
    as_of: ISO-8601 past instant (a bare date means start of that day,
        UTC): render the graph as believed at T. A future
        instant is rejected.
    max_nodes: Per-call node cap (clamped to ``graph.max_nodes``).
    store: Store handle to render from; ``"default"`` is the
        canonical store.
    all_projects: On a server bound to one project, render from
        the whole store instead of that project's view. The result says so.
        No effect on an unbound server.

Returns:
    The ``GraphData`` render as JSON — ``nodes`` (subjects with display
    aggregates), ``edges`` (multi-subject particles), ``particles``
    (per-particle epistemics payloads keyed by id), ``supersessions``,
    the ``census``, and human-readable ``disclosures`` for any cap that
    bound. When ``engine.base_url`` is configured, a ``url`` field
    additionally deep-links the same scope on the unified web UI
    (``/app#/browse?…``) so the operator can open the
    interactive picture — the default stdio install has no HTTP server,
    so the field is additive, never assumed.
NameRequiredDescriptionDefault
hopsNo
as_ofNo
queryNo
storeNodefault
historyNo
sectionNo
manifestNo
max_nodesNo
subject_idNo
all_projectsNo
inconsistency_idNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does so well: it discloses that all epistemics are computed at render time and never stored, that hops/max_nodes are clamped by graph config with human-readable disclosures, that future as_of instants are rejected, that all_projects has no effect on an unbound server, and that the url field only appears when base_url is configured. This is exactly the behavioral context an agent needs for a tool with no annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The mandatory-scope rule is front-loaded ahead of the argument list, and the Args/Returns structure is easy to scan. It is long and occasionally florid ('the anti-hairball invariant', 'the picture of the knowledge the agent consulted'), but those phrases are doing real disambiguation work rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter tool with zero schema coverage, the description covers scope exclusivity, aliasing and clamping behavior, ordering/filter semantics, and the conditional url field. Output schema exists and is still summarized usefully (nodes, edges, particles, supersessions, census, disclosures), so an agent can call this correctly without opening any other resource.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 11 parameters, so the description must compensate entirely and does: it documents accepted id forms (exact case-insensitive names/aliases for subject_id, unique prefixes for inconsistency_id, region id or title for section), defaults ('default' is the canonical store), and edge semantics (bare date = start of day UTC, future rejected, hops clamped). Nearly every parameter gains meaning beyond its bare title and type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb ('Render') and a precise resource ('one scoped epistemic subgraph of the particle store'), and immediately constrains the scope modes. An agent can distinguish it from particles_list, query, or subjects_show because this returns a graph render rather than a flat listing or search result.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states the when-not ('a whole-store render does not exist; the anti-hairball invariant') and explains which scope argument selects which mode, effectively describing four alternative entry points. It does not, however, route the agent to sibling tools for simpler needs (e.g., particle_show for one particle), so it stops just short of full alternative guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lintA

Run structural lint checks over the particle store (no fixes, no LLM).

The MCP surface is read-only, so ``--fix`` is forced off and the
LLM-assisted semantic checks are disabled — agents read findings
and surface them to the operator, who decides whether to act.

Args:
    category: Optional ``finding_type`` filter (e.g. ``STALENESS``,
        ``PHANTOM_SUBJECT``, ``WIKIDATA_LINK_MISMATCH``). When set,
        only findings of that kind are returned; ``summary`` is
        always the full counts dict and reflects every category
        actually emitted by this run.
    summary_only: When ``True``, drop the ``findings`` list and
        return only the ``summary`` counts dict (plus ``run_at``).
        Useful when the agent only needs to know what *kinds* of
        problems exist before drilling in with ``category``.
    limit: Maximum findings to include after filtering (default
        100). Hard cap to keep the response under per-tool-result
        size limits even when many findings of one category exist.
        A ``truncated`` flag is added when the cap fires.

Returns:
    ``{run_at, findings, summary}`` matching the ``LintReport``
    schema, optionally with ``truncated: True`` and (when
    ``summary_only``) without the ``findings`` key.
NameRequiredDescriptionDefault
limitNo
categoryNo
summary_onlyNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations present, the description carries the full burden and does so: it declares the tool is read-only, that --fix is forced off, that LLM semantic checks are disabled, and what the agent is expected to do with results. It also discloses the response cap behavior (default 100, hard cap, truncated: True when it fires) and that summary always reflects full counts regardless of category filtering.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The key constraint (read-only, no fixes, no LLM) is front-loaded before the Args block, and each argument paragraph adds real information rather than restating the schema. The Args/Returns layout is well structured, though the prose is slightly longer than strictly necessary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-required-parameter read tool with an output schema and no annotations, the description covers purpose, safety profile, parameter semantics, truncation behavior, and return shape. The Returns section slightly overlaps the output schema but adds the truncated flag and the summary_only shape variation, which are not otherwise obvious.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for all three parameters. It explains category as a finding_type filter with concrete example values and notes summary is unaffected by it; summary_only as dropping the findings list and returning only summary plus run_at; and limit as a post-filter cap defaulting to 100 with a truncated flag.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb and resource ("Run structural lint checks over the particle store") and immediately scopes it with "no fixes, no LLM." That scope clause separates it from mutation-oriented or LLM-assisted siblings such as links_suggest and quality_report.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear operational context — agents read findings and surface them to the operator, who decides whether to act — and describes a concrete workflow (use summary_only to learn what kinds of problems exist, then drill in with category). It never names a sibling alternative or states when a different tool would be preferable, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_corpus_entriesA

List recent corpus entries (most-recently-deposited first).

Args:
    limit: Maximum entries to return (default 50).
    source_type: Optional filter (e.g. ``"WIKIDATA_API"``).
NameRequiredDescriptionDefault
limitNo
source_typeNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the behavioral burden. It discloses the ordering and the limit default, which are useful, but it does not explicitly confirm read-only behavior, pagination semantics, permissions, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loaded: the core action and ordering appear first, followed by compact Args explanations. Every sentence adds useful information with no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter list tool, the description covers the key call semantics, and the presence of an output schema means return values need not be explained. The main remaining gap is the absence of explicit read-only or permission context due to missing annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It documents both parameters: limit as maximum entries with default 50, and source_type as an optional filter with an example value, though it does not enumerate all valid source_type values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: "List recent corpus entries," and adds the ordering "most-recently-deposited first." This clearly distinguishes it from sibling tools that list other resources, though it does not explicitly name an alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage by specifying recent entries and an optional source_type filter, but it does not say when to choose this tool over alternatives such as corpus_links_suggest or query. No explicit when-not or alternative guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_taxonomiesA

List every taxonomy + its full tag tree.

Args:
    limit: Maximum taxonomies to return (default 50). Each
        taxonomy embeds its full tag tree, so even a handful of
        large taxonomies can push the response past the
        per-tool-result token cap.
    offset: Number of taxonomies to skip before returning results
        (default 0). Results are ordered by name so pagination is
        stable.
NameRequiredDescriptionDefault
limitNo
offsetNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does substantial work: it warns that each taxonomy embeds its full tag tree, that even a few large taxonomies can exceed the per-tool-result token cap, and that results are name-ordered so pagination is stable. It omits any permission/auth context or statement that the call is a read-only, non-mutating operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in one sentence, followed by tightly scoped parameter notes. Every sentence carries information an agent needs to size its request correctly; there is no restatement of the tool name or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-shape explanation is unnecessary, and the description covers the real risk factors (payload size, pagination ordering). It leaves unstated whether results are scoped by permissions or whether there is a total-count signal to drive pagination termination, which an agent planning a full sweep would want.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must fully compensate, and it does: both params get defaults, a definition of their effect, and the operational reason behind each. The limit explanation (embedded tag trees causing token-cap overflow) is exactly the kind of guidance the bare integer schema cannot convey, and offset is tied to the stable name ordering.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line states a specific verb and resource ('List every taxonomy') and adds a meaningful scope detail ('its full tag tree'), which tells the agent this is an exhaustive browse rather than a search. It does not name a sibling, but the sibling set (subjects_list, particles_list, etc.) is resource-disjoint, so ambiguity is low.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the agent infers this is the way to enumerate all taxonomies with their tags. There is no explicit 'use this when... instead use X' routing, and no statement of when browsing is preferable to querying or searching.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

particle_showA

Show one particle with its provenance, subjects, and tags.

Args:
    particle_id: Full UUID or unambiguous prefix (≥ 8 chars).

Returns:
    Dict with ``particle`` (Pydantic JSON), ``subjects`` (list of
    ``{id, canonical_name}``), and ``provenance`` (list of
    ``{type, corpus_entry_id, uri_r, source_type, snapshot_id}``).
    When the source now states the claim in other words, ``restated_as``
    holds that wording and its snapshot; the claim's
    ``content`` keeps its first wording. Raises if the prefix matches zero
    or multiple particles.
NameRequiredDescriptionDefault
particle_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden well: it describes the returned structure, explains restated_as and that content keeps its first wording, and states that zero or multiple prefix matches raise. It does not explicitly restate read-only/safety properties, but 'show' clearly implies a non-mutating retrieval.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the tool's purpose, then cleanly structured into Args and Returns sections. The return-value detail is dense but each element adds useful semantics, especially around restated_as and content wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Although an output schema exists, the description adds needed semantic context about provenance and restated_as, and it fully explains the single argument and error behavior. An agent has enough information to invoke this correctly and interpret key return fields.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must explain the only parameter. It does so fully: particle_id accepts a full UUID or an unambiguous prefix of at least 8 characters, and ambiguous prefixes raise.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: 'Show one particle with its provenance, subjects, and tags.' This clearly distinguishes a single-entity retrieval from list/search siblings such as particles_list and particle_search, though it does not explicitly name those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the single-particle scope, and the description helpfully notes that ambiguous prefixes raise an error. However, it does not explicitly say when to use this tool versus particle_search, particles_list, or other retrieval siblings, leaving selection mostly to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

particles_listA

List particles, optionally filtered by status or subject.

Lightweight alternative to ``query`` and ``lint`` when an agent
just needs the IDs of particles in a particular state — e.g. the
open INCONSISTENCY queue, RETRACTED particles for cleanup, or
every ACTIVE particle linked to a subject. Embeddings are never
included; responses are designed to stay within MCP tool-result
size caps.

Args:
    status: Optional status filter — one of
        ``ACTIVE``, ``SUPERSEDED``, ``RETRACTED``,
        ``PROVENANCE_STALE``, ``INCONSISTENCY``. Unset returns
        particles in any status.
    subject_id: Optional subject: a full ID, an ID prefix,
        or a name or alias, resolved as ``subjects_show`` resolves it.
        When set, only particles linked to that subject via the
        ``particle_subjects`` join table are returned, and the result
        echoes the resolved ``subject_id``. A reference that matches no
        subject, or more than one, raises.
    limit: Maximum particles to return (default 50). Must be > 0.
    offset: Number of particles to skip before returning results
        (default 0). Combine with ``limit`` to page through the
        full set.
    all_projects: On a server bound to one project, read the whole
        store instead of that project's view. The result says so. No effect
        on an unbound server.

Returns:
    Dict with ``particles`` — a list of summary dicts containing
    ``id``, ``status``, ``content``, ``confidence``,
    ``subject_ids``, ``asserted_at``, and ``status_reason``. Each
    entry's ``contested`` key is the id of an open INCONSISTENCY
    referencing it, else null; ``contested_bases``
    rides beside it with the fired basis labels —
    composed by the same composer the ``query`` tool uses, so all
    three bases (stance / divergence / inconsistency) are evaluated
    and the two surfaces on one server always agree. Plus
    ``limit``/``offset`` echoed back so the agent can drive
    pagination. Embeddings are intentionally omitted.
NameRequiredDescriptionDefault
limitNo
offsetNo
statusNo
subject_idNo
all_projectsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses important traits: embeddings are never included, responses are size-capped, subject resolution can raise on no-match or multi-match, and `all_projects` changes scope on bound servers. It does not explicitly state read-only/no-side-effect semantics, but the listing behavior is strongly implied and well contextualized.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and organized into Args and Returns sections. It is longer than strictly necessary, especially in the Returns block where an output schema already exists, but the added detail remains relevant and usable rather than redundant fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given five optional parameters, 0% schema description coverage, no annotations, and a rich output schema, the description is complete enough for an agent to call the tool correctly. It covers filtering semantics, pagination, scope behavior, error conditions, and what the response contains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does. It documents each parameter: valid `status` values, `subject_id` resolution and join-table behavior including error cases, `limit` and `offset` defaults and pagination use, and the exact effect of `all_projects` depending on server binding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List particles, optionally filtered by status or subject.' It also distinguishes this tool from siblings by calling it a lightweight alternative to `query` and `lint`, making its intended role clear without requiring schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool (`when an agent just needs the IDs of particles in a particular state`) and gives concrete examples such as the open INCONSISTENCY queue, RETRACTED cleanup, and ACTIVE particles linked to a subject. It also names the alternatives it replaces for lightweight ID-only needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

quality_reportA

Return the extraction-quality dashboard snapshot.

Particle counts by status / calibration_source / schema_version,
plus the structural-mix percentages, the store's recorded LLM spend
(``llm_spend``), and the curation queue's precision over the default
window (``curation_precision``: per card kind, the cards acted on,
dismissed, snoozed and untouched, with the denominator). Computed
entirely from live DB queries — no LLM involvement.
NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description does real work: it discloses that results are "Computed entirely from live DB queries — no LLM involvement," which tells the agent the call is deterministic, costs no model spend, and is safe to repeat. It also names the underlying signals (recorded llm_spend, curation precision with its denominator) so the agent knows facts are derived, not estimated. It stops short of stating read-only guarantees, freshness/latency, or whether the snapshot is expensive to compute — the main remaining gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-sentence purpose, then a structured enumeration of contents with backticked field names, ending with the cost/disclosure caveat. It is dense but readable and every clause identifies a distinct metric family. Slight redundancy: since an output schema exists, spelling out the returned fields in prose partly duplicates structured data.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only reporting tool whose return shape is already captured by an output schema, this description covers what the agent still needs: what dimensions are reported, that the numbers come from live DB queries with no LLM cost, and what "precision" is measured against. Nothing required to decide to call it or to interpret the headline metrics is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate; baseline 4 applies. One minor wrinkle: it says precision is measured "over the default window" even though no window argument exists, which could momentarily suggest a parameter that isn't there.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ("Return") and a specific resource ("extraction-quality dashboard snapshot"), then enumerates the exact metric families contained (particle counts by status/calibration_source/schema_version, structural-mix percentages, llm_spend, curation_precision). It is unmistakably distinct from data-access siblings like particles_list, query, or lint — an agent can tell this is the read-only quality aggregation endpoint without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied: the enumerated contents make it obvious this is the tool for quality/health monitoring rather than data retrieval, but there is no explicit "use this when you need X instead of Y" statement or exclusion against siblings such as query or particles_list. Adequate for routing a competent agent, but the selection rule is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

queryA

Run a tag-aware semantic query against the particle store.

Args:
    question: Natural-language question. Optional since: omit it
        and set structural claim filters (or an aggregate / the predicate
        listing) for the deterministic modes — no embedding, no LLM call.
    tags: Subtree-expanded tag filters, repeatable.
    subject_id: Restrict to particles about this subject.
    min_confidence: Minimum confidence value (0.0–1.0).
    top_k: Number of particles to retrieve (1–200).
    audience: "GENERAL" | "EXPERT" | "REGULATORY".
    summary: When ``True``, each hit in ``particles`` is reduced to
        ``{id, content, confidence, effective_confidence,
        subject_ids}`` — provenance, tags, properties, and
        embeddings are dropped. The NL ``answer`` string and
        coverage gaps are unchanged. Use this when the agent only
        needs to surface the answer and pick particles to
        ``particle_show`` later. Default ``False`` preserves the
        full ``QueryResponse`` shape for backward compatibility.
    as_of: ISO-8601 past instant (a bare date means start of that
        day, UTC): answer what the store believed at T.
        Retired hits carry an ``as_of_notes`` entry (current status,
        retirement instant + basis, and the superseding belief);
        ``as_of_excluded_undatable`` discloses retirements the store
        cannot date. A future instant is rejected.
    during_start: With ``during_end``, a window of world time (ISO-8601
        dates, inclusive; either may be omitted for an open end): answer
        about what began in, or was in force during, that period.
        The window prefilters the candidate set before ranking;
        with no question it returns the claims in date order, each with a
        ``window_hits`` reading (``BEGAN``, ``IN_FORCE``, ``HELD_AT``,
        ``WITHIN``). A retired claim is admitted for the period it held,
        marked with its retirement and its close. Reads ``valid_from``;
        ``window_coverage`` discloses the undated and unkinded claims the
        window could not judge. Resolve the anchor first ("when did the
        user move?"), then ask with dates: the anchor step is the caller's.
    during_end: The inclusive end date of the window; see ``during_start``.
    on: The point form: what held or happened on this date (ISO-8601).
        Alternative to ``during_start`` / ``during_end``.
    predicate: Structural filter — claims whose predicate term
        equals this string (case-insensitive, exact: a CURIE and its
        expanded IRI are different strings; discover terms with
        ``list_predicates``). With a question it prefilters the semantic
        candidate set; without one it selects the deterministic listing.
    object_eq: Claims whose object equals this value (typed comparison
        when both sides normalize — numbers and ISO dates — else
        case-insensitive text).
    object_gt: Claims whose object is greater than this number or ISO
        date; claims whose object would not normalize are excluded and
        disclosed in ``claim_coverage.not_normalizable_excluded``.
    object_lt: Claims whose object is less than this number or ISO date
        (same normalization and disclosure as ``object_gt``).
    object_contains: Claims whose object contains this substring
        (case-insensitive; every term kind).
    count: Deterministic aggregate — the number of matching claims with
        their effective-confidence distribution. Rejects a simultaneous
        question.
    group_by: Deterministic aggregate — bucket matching claims by
        "subject", "predicate", or "object" with per-bucket counts and
        confidence distribution. Rejects a simultaneous question.
    min_effective_confidence: Explicit confidence floor for the aggregate
        modes; excluded rows are disclosed. There is no default floor.
    list_predicates: List the distinct predicate terms with kind and
        claim count (``predicate_vocabulary`` in the response) — the
        discovery surface for the exact-string predicate filter.
    all_projects: On a server bound to one project, read the whole
        store instead of that project's view. The result says so. No effect
        on an unbound server.
    grounded: Compose a grounded answer: every sentence ends
        with the ids of the retrieved particles it rests on (``[p-1a2b3c4d]``,
        the form ``particle_show`` accepts), or with ``[inference]`` (the
        model's own inference over cited claims) or ``[background]`` (from
        nothing in the store). Cited ids are checked against the retrieved
        set; a sentence with no valid citation and no label is
        ``[unattributed]``. Nothing is dropped and nothing is stored.
        ``answer_attribution`` carries the per-sentence labels and full
        cited ids. Omit to use the server's ``query.grounded_answers``.

Returns:
    The full ``QueryResponse`` as JSON — answer string plus the
    ranked particles, effective confidences, coverage gaps, and
    any truncation warning. A structural call returns rows
    or counts, not generated prose: the deterministic listing fills
    ``particles`` ordered by effective confidence, the aggregates fill
    ``structural_aggregate``, the vocabulary listing fills
    ``predicate_vocabulary``, and every structural result carries
    ``claim_coverage`` (the annotated-fraction footer plus the
    non-normalizable exclusion disclosure). Each particle's ``contested`` key is
    the id of an open INCONSISTENCY referencing it,
    else null; the composed contested badge rides
    beside it — the response-level ``contested`` list carries one
    badge (fired bases + drill-downs) or null per ranked particle,
    and with ``summary=True`` each slim hit carries
    ``contested_bases`` (the fired basis labels, else null) beside
    its ``contested`` id. When ``summary=True``, each particle
    entry is a small dict instead of the full Pydantic model.
NameRequiredDescriptionDefault
onNo
tagsNo
as_ofNo
countNo
top_kNo
summaryNo
audienceNoGENERAL
groundedNo
group_byNo
questionNo
object_eqNo
object_gtNo
object_ltNo
predicateNo
during_endNo
subject_idNo
all_projectsNo
during_startNo
min_confidenceNo
list_predicatesNo
object_containsNo
min_effective_confidenceNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does so richly: deterministic modes use no embedding or LLM call, count/group_by reject simultaneous questions, future as_of instants are rejected, summary drops provenance/tags/properties/embeddings, grounded answers cite or label every sentence, and all_projects has no effect on an unbound server. It also discloses exclusions, coverage gaps, and retired-claim handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a clear purpose and organized into Args/Returns, which suits a 22-parameter tool. It is necessarily dense, but some return-detail text is verbose and partially duplicates the output schema, so it is not maximally concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 22 parameters, 0% schema description coverage, no annotations, and an output schema, the description is complete enough to call the tool correctly. It covers every parameter, mode interactions, rejection rules, response shapes, coverage gaps, and attribution behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 22 parameters, so the description must compensate entirely, and it does: every parameter is explained with meaning, accepted values, interactions, and defaults. Examples include predicate's exact-string/CURIE caveat, object_gt/object_lt normalization and disclosure, count/group_by rejection of question, and during_start's window semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb and resource: 'Run a tag-aware semantic query against the particle store.' It also explains the major operating modes (semantic question, deterministic structural listing, aggregates, predicate vocabulary, grounded answers). It does not explicitly differentiate itself from sibling tools such as particle_search, though it references particle_show for follow-up inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit conditional guidance within the tool: omit question for deterministic modes, use summary when only answer and particle IDs are needed, use as_of for point-in-time beliefs, use during_start/during_end for windows, and notes that count/group_by reject a simultaneous question. It does not, however, say when to choose this tool over sibling search/list tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

subjects_listA

List subjects in the knowledge graph (alphabetical by canonical_name).

Paginated to keep responses within an MCP-client-friendly size — the
full subject set can easily exceed per-tool-result token caps.

Args:
    limit: Maximum subjects to return (default 50).
    offset: Number of subjects to skip before returning results
        (default 0). Combine with ``limit`` to page through the
        full set.
    order: ``"name"`` (alphabetical, default) or ``"degree"`` —
        most-connected first, by descending count of ACTIVE
        particles linked to each subject (name tie-break). Use
        ``"degree"`` to find a store's hub subjects, e.g. as a
        ``graph_view`` starting scope.
NameRequiredDescriptionDefault
limitNo
orderNoname
offsetNo

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full load. It explains the pagination rationale (token caps) and clarifies that order='degree' uses active particle counts with a name tie-break. It does not state read/write intent, but 'List' implies read-only. The added behavioral context is solid, though not exhaustive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: a front-loaded purpose sentence, a short paragraph on pagination rationale, and a clear Args section. Every sentence serves a purpose. It could be slightly tightened, but overall it is appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a simple list tool with three parameters, no annotations, and an output schema that handles return values, the description covers purpose, pagination, parameter semantics, and ordering. Nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the input schema has 0% description coverage, the description includes a detailed Args section explaining limit, offset, and order, including defaults and the meaning of order values. This fully compensates for the schema gap and gives the agent everything needed to invoke the tool correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb and resource: 'List subjects in the knowledge graph (alphabetical by canonical_name).' It distinguishes from a search by using 'List' and specifying the default ordering. However, it does not explicitly contrast with sibling tools like subjects_search or subjects_show, so it misses the top score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives some usage context, e.g., using order='degree' to find hub subjects as a graph_view starting scope. But it offers no explicit when-to-use guidance relative to alternatives such as subjects_search or subjects_show, so the agent has to infer its place among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

subjects_showA

Show one subject with the particle IDs linked to it.

Args:
    subject_id: A full UUID, an unambiguous prefix (≥ 8 chars), or a
        name or alias, matched case-insensitively and exactly. A
        reference that matches more than one subject (a prefix shared
        by several IDs, a name two subjects share, or a string that is
        both a prefix and a name) raises with the candidates named. A
        remote engine resolves IDs and prefixes only.
    particle_id_limit: Maximum particle IDs to include in
        ``particle_ids`` (default 100). For hot subjects the full
        list can blow the per-tool-result token cap; use
        ``particles_list(subject_id=…, limit=…, offset=…)`` for
        the full set when ``particle_count > particle_id_limit``.

Returns:
    Dict with ``subject`` (Pydantic JSON), ``particle_ids`` (capped
    at ``particle_id_limit``, ordered by id for stable pagination),
    and ``particle_count`` — the true total of linked particles,
    so callers can detect when the list was truncated.
NameRequiredDescriptionDefault
subject_idYes
particle_id_limitNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so: ambiguity raises an error naming candidate subjects, remote engines restrict resolution to IDs and prefixes, results are capped and ordered by id for stable pagination, and particle_count reveals truncation against the token cap. These are non-obvious failure modes and limits an agent could not infer elsewhere.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The opening sentence front-loads the core behavior, and the Args/Returns blocks are dense with genuinely useful detail. The RST-style code markup and docstring formatting add a little visual noise, but no sentence is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter lookup with no annotations, the description covers resolution rules, error behavior, truncation detection, and pagination escape hatch. Although an output schema exists, the Returns block still clarifies the meaning of particle_count and the ordering of particle_ids, which the schema alone would not convey.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate and it does fully: subject_id accepts a full UUID, an unambiguous prefix of at least 8 characters, or a name/alias, matched case-insensitively and exactly, with the ambiguity conditions spelled out. particle_id_limit is explained as a cap with a stated default of 100 and the reason for its existence.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Show one subject') plus the associated payload ('particle IDs linked to it'). The singular 'one subject' implicitly separates it from siblings subjects_list and subjects_search, so an agent can select it without reading either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent to particles_list(subject_id=…, limit=…, offset=…) when the linked list is truncated, which is a concrete alternative with a triggering condition. It also warns that a remote engine resolves IDs and prefixes only, which governs how the tool can be called. It never says when to prefer subjects_search to resolve an unknown reference, so it falls just short of full when/when-not coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 16 tool updatesv1.210.2
    • First observedcorpus_links_suggest
    • First observedevent_show
    • First observedevents_list
    • First observedgraph_view
    • First observedlinks_suggest
    • First observedlint
    • First observedlist_corpus_entries
    • First observedlist_taxonomies
    • First observedparticle_search
    • First observedparticle_show
    • First observedparticles_list
    • First observedquality_report
    • First observedquery
    • First observedsubjects_list
    • First observedsubjects_search
    • First observedsubjects_show

TDQS

A3.7/5.0

Scored across 16 tools

Disambiguation4/5

Most tools target clearly distinct operations: particle listing/show/search, subject listing/search/show, taxonomy listing, corpus listing, lint, quality reporting, event inspection, link suggestions, and graph rendering. The broad `query` tool overlaps somewhat with `particles_list` and `particle_search`, but the descriptions make the lightweight/fingerprint/semantic boundaries reasonably clear. The two link-suggestion tools are similar in naming but operate on different domains, so careful reading is still needed.

Naming Consistency3/5

The set mixes conventions: core tools mostly use noun_action patterns (`particles_list`, `particle_show`, `subjects_search`), but others use verb_noun (`list_taxonomies`, `list_corpus_entries`) or standalone names (`query`, `lint`, `graph_view`, `quality_report`). Singular/plural usage also varies (`particle_show` vs `subjects_show`, `events_list` vs `event_show`). All names remain readable and snake_case, but the pattern is not fully predictable.

Tool Count4/5

At 16 tools, the surface is slightly above the typical ideal range, but the domain is complex and each tool maps to a fairly distinct read-only inspection, query, reporting, or suggestion capability. The count feels justified rather than bloated, though a few tools could conceivably be consolidated.

Completeness4/5

The read-only surface covers particles, subjects, taxonomies, corpus entries, events, lint findings, quality reporting, link suggestions, and graph views, which is broad lifecycle coverage for an inspection-oriented MCP server. Minor gaps remain: there is no dedicated tool to show a full corpus entry, and `graph_view`'s manifest scope has no manifest/section discovery tool. These are workable gaps rather than severe dead ends.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Local-first, source-grounded memory for AI agents, with citations, bitemporal history, review-gated corrections, and MCP tools for search and recall.
    66 PyPI
    3
    Apache 2.0
  • A
    license
    A
    quality
    B
    maintenance
    Enables AI agents to record, recall, correct, and forget evidence-backed factual claims with temporal history, while explaining whether remembered information is current, historical, or contested.
    5
    Apache 2.0
  • A
    license
    Not graded
    quality
    A
    maintenance
    Belief-tracking memory for AI agents. Remember, recall, and ask why: every memory carries evidence, contradictions are surfaced, and retracted facts take their conclusions with them. Zero dependencies, local, MIT.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Local memory for AI agents in one SQLite file on your own machine. Facts carry a validity window and a confidence score, so an outdated one is superseded and downweighted rather than deleted, and retrieval fuses BM25, vector similarity and a knowledge graph.
    2
    Business Source 1.1