← Back to search

Distillery

norrietaylor Scanned 6h ago

Knowledge base for Claude Code with semantic search, feed intelligence, and teams

D
53.8 / 100

Versions

0.3.2latest
first seen Jun 5, 2026
PermissionsTool SafetyAuthAnnotationsCode QualityStabilitySpecVuln HistoryAuthorTransparencyCommunity

Tools 17

distillery_gh_sync
annotations: none low

Sync GitHub issues and PRs into the knowledge base using a batched pipeline. url: repository slug (owner/repo) or full GitHub URL. author: author field for created entries (default: gh-sync). project: optional project name to scope entries. background: when true, runs async and returns a job_id immediately.

ctx Context url str author str project string background bool
distillery_sync_status
annotations: none low

Check the status of background sync jobs. job_id: look up a specific job by ID. source_url: list jobs for a specific source URL. If neither is provided, lists all recent jobs.

ctx Context job_id string source_url string
distillery_store
annotations: none low

Store a new knowledge entry and return its ID with dedup/conflict information. USE WHEN: capturing a new piece of knowledge (session notes, bookmarks, meeting minutes, ideas, etc.) into the Distillery store. PARAMS: - content (str, required): The knowledge content to store. - entry_type (str, required): Entry classification. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - author (str, required): Who authored this entry. - project (str, optional): Project scope for the entry. - tags (list[str], optional): Tags for categorisation; supports namespaced tags (e.g. "topic/ai"). - metadata (dict, optional): Arbitrary key-value metadata. Some entry types REQUIRE specific metadata keys (TYPE_METADATA_SCHEMAS); omitting them returns INVALID_PARAMS naming the missing/invalid field: - person: expertise (list[str]) - project: repo (str) - digest: period_start, period_end (str) - github: repo, ref_type, ref_number; ref_type in [issue, pr, discussion, release] - feed: source_url, source_type; source_type in [rss, github] Other types (session, bookmark, minutes, meeting, reference, idea, inbox) accept arbitrary metadata. - source (str, optional, default="claude-code"): Origin of the entry. Valid: [claude-code, manual, import, inference, documentation, external]. - session_id (str, optional): Opaque session identifier for grouping related entries. - dedup_threshold (float, optional, default=config): Cosine similarity threshold (0-1) for near-duplicate warnings. - dedup_limit (int, optional, default=config): Max duplicates to report. - verification (str, optional, default="unverified"): Verification status. Valid: [unverified, testing, verified]. - expires_at (str, optional): ISO 8601 datetime; entries past expiry appear in stale results. - output_mode (str, optional, default="full"): Response verbosity. Valid: [full, summary]. Use "summary" for bulk imports to skip dedup/conflict checks. - include_conflict_prompt (bool, optional, default=False): When true, each conflict candidate carries the ~1–2 KB ``conflict_prompt`` LLM template required to round-trip through ``distillery_find_similar(conflict_check=true)``. Defaults to false to keep store responses small (issue #348). RETURNS (success): { entry_id: str, persisted: bool, dedup_action: str, conflicts?: list[{entry_id, content_preview, similarity_score, conflict_prompt?}], warnings?: list } RETURNS (error): { error: true, code: "INVALID_PARAMS" | "BUDGET_EXCEEDED" | "INTERNAL", message: "..." } RELATED: distillery_find_similar (for pre-store dedup checks), distillery_correct (to supersede an existing entry)

ctx Context tags string author str source string content str project string metadata string entry_type str expires_at string session_id string dedup_limit string output_mode string verification string dedup_threshold string include_conflict_prompt bool
distillery_store_batch
annotations: none low

Batch-store multiple knowledge entries in one call (no dedup/conflict checks). USE WHEN: bulk-importing entries (e.g. GitHub history sync, migration, backfill) where per-entry dedup is unnecessary and throughput matters. PARAMS: - entries (list[dict], required): List of entry dicts. Each must have: - content (str, required): The knowledge content. - author (str, required): Who authored this entry. - entry_type (str, optional, default="inbox"): Entry classification. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - tags (list[str], optional): Tags for categorisation. - metadata (dict, optional): Arbitrary key-value metadata. - source (str, optional, default="claude-code"): Origin of the entry. - project (str, optional): Per-entry project override. - project (str, optional): Default project applied to entries lacking one. RETURNS (success): { entry_ids: list[str | None], # per-item ids; null for failed items count: int, # number actually persisted results: list[dict], # per-item status preserving input order } - Successful items: { entry_id, persisted: true, dedup_action: "stored" } - Failed items: { entry_id: null, persisted: false, error: { code, message, details? } } Validation failures on individual items no longer abort the batch — valid entries are persisted and failures are reported per item in ``results`` (issue #364). Iterate ``results`` to discover failures. RETURNS (error): { error: true, code: "INVALID_PARAMS" | "BUDGET_EXCEEDED" | "INTERNAL", message: "..." } Top-level error is returned only for schema-level problems (``entries`` not a list, budget exhaustion, persistence failure). RELATED: distillery_store (single entry with dedup/conflict checks), distillery_watch (add feed sources with optional history sync)

ctx Context entries string project string
distillery_ingest_doc
annotations: none low

Ingest an arbitrary document (ADR, spec, decision, customer feedback). USE WHEN: importing a standalone document — a markdown ADR/spec/RFC, a design decision, or a customer-feedback transcript/doc — so it becomes queryable knowledge with provenance. Distinct from distillery_store (single entry, semantic dedup) and from PreCompact transcripts: this chunks large text into multiple linked entries and deduplicates idempotently by content hash, so re-ingesting identical content adds no second entry. PARAMS: - text (str, required): The full document text. Large text is split into multiple linked entries (relation_type="chunk"). - author (str, required): Who is ingesting / owns this document. - doctype (str, optional, default="doc"): Document kind. Valid: [adr, spec, decision, feedback, doc]. Applied as both a "doctype/<value>" tag and metadata.doctype for faceted retrieval. - source (str, optional): Provenance label (file path, Drive URL, etc.). Stored in metadata.source. - external_id (str, optional): Explicit dedup key. Defaults to the SHA-256 hash of text, making re-ingest idempotent. - title (str, optional): Human-readable title (stored in metadata.title). - project (str, optional): Project scope. - tags (list[str], optional): Extra namespaced tags. - metadata (dict, optional): Arbitrary extra metadata. RETURNS (success): { entry_ids: list[str], count: int, doctype: str, external_id: str, chunked: bool, persisted: bool, dedup_action: "stored" | "skipped" } On re-ingest of identical content, persisted=false, dedup_action="skipped", and entry_ids points at the existing entries. RETURNS (error): { error: true, code: "INVALID_PARAMS" | "INTERNAL", message: "..." } RELATED: distillery_store (single entry with semantic dedup), distillery_search (to retrieve ingested documents)

ctx Context tags string text str title string author str source string doctype string project string metadata string external_id string
distillery_get
annotations: none low

Retrieve a single knowledge entry by its unique ID. USE WHEN: fetching the full content and metadata of a specific entry (e.g. after finding its ID via search or list). PARAMS: - entry_id (str, required): UUID of the entry to retrieve. RETURNS (success): { id: str, content: str, entry_type: str, ... } RETURNS (error): { error: true, code: "NOT_FOUND" | "INTERNAL", message: "..." } RELATED: distillery_search (to find entries by content), distillery_list (to browse entries by filters)

ctx Context entry_id str
distillery_update
annotations: none low

Update one or more fields on an existing knowledge entry. USE WHEN: modifying an entry's content, type, tags, status, or other mutable fields. At least one updatable field must be provided. PARAMS: - entry_id (str, required): UUID of the entry to update. - content (str, optional): Replacement content. - entry_type (str, optional): New type. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - author (str, optional): New author. - project (str, optional): New project scope. - tags (list[str], optional): Replacement tag list. - status (str, optional): New status. Valid: [active, pending_review, archived]. - verification (str, optional): New verification. Valid: [unverified, testing, verified]. - metadata (dict, optional): Replacement metadata dict. - session_id (str, optional): Session identifier for grouping. - expires_at (str, optional): ISO 8601 datetime; pass null to clear. RETURNS (success): { id: str, content: str, entry_type: str, ... } (full updated entry) RETURNS (error): { error: true, code: "NOT_FOUND" | "INVALID_PARAMS" | "FORBIDDEN" | "INTERNAL", message: "..." } RELATED: distillery_correct (to supersede rather than edit), distillery_get (to read before updating)

ctx Context tags string author string status string content string project string entry_id str metadata string entry_type string expires_at string session_id string verification string
distillery_correct
annotations: none low

Store a correction that supersedes an existing entry. USE WHEN: an existing entry contains wrong information and you want to replace it with corrected content while preserving the audit trail. PARAMS: - wrong_entry_id (str, required): UUID of the entry being corrected. - content (str, required): The corrected content. - entry_type (str, optional): Override type; inherited from original if omitted. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - author (str, optional): Override author; inherited from original if omitted. - project (str, optional): Override project; inherited from original if omitted. - tags (list[str], optional): Override tags; inherited from original if omitted. - metadata (dict, optional): Additional metadata for the correction entry. RETURNS (success): { correction_entry_id: str, archived_entry_id: str } RETURNS (error): { error: true, code: "NOT_FOUND" | "INVALID_PARAMS" | "FORBIDDEN" | "INTERNAL", message: "..." } RELATED: distillery_update (for non-breaking edits), distillery_relations (to view the 'corrects' relation)

ctx Context tags string author string content str project string metadata string entry_type string wrong_entry_id str
distillery_list
annotations: none low

List knowledge entries with optional filters and pagination (newest first). USE WHEN: browsing or filtering entries without a semantic query. Use distillery_search instead when you have a natural-language question. By default, only entries with status in (active, pending_review) are returned — archived entries are hidden. Pass ``status="archived"`` to list only archived entries, ``status="any"`` to include every status, or ``include_archived=true`` to add archived entries to the default view. PARAMS: - entry_type (str | list[str], optional): Filter by type, or a list of types matched with OR (e.g. ["session", "reference"]) — pair with group_by to aggregate across several types in one call. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - author (str, optional): Filter by author. - project (str, optional): Filter by project scope. - tags (list[str], optional): Filter by tags (AND match). - status (str, optional): Filter by status. Valid: [active, pending_review, archived, any]. Default hides archived; use "any" to include all. - verification (str, optional): Filter by verification. Valid: [unverified, testing, verified]. - source (str, optional): Filter by origin. Valid: [claude-code, manual, import, inference, documentation, external]. As a convenience, a URL-shaped value (starting with "http://" or "https://") is aliased to ``feed_url`` so ``source="https://hnrss.org/frontpage"`` matches feed items ingested from that source (same semantics as passing ``feed_url=...``). - session_id (str, optional): Filter by session identifier. - date_from (str, optional): ISO 8601 lower bound on created_at. - date_to (str, optional): ISO 8601 upper bound on created_at. - limit (int, optional, default=20): Max entries to return (1-500). - offset (int, optional, default=0): Pagination offset. - tag_prefix (str, optional): Filter tags by namespace prefix. - output_mode (str, optional, default="summary"): Response shape. Valid: [full, summary, ids, review]. "summary" returns id/title/tags/project/ author/created_at plus a ~200-char content_preview (default — keeps responses small to conserve context). "full" returns entire content body. "ids" returns id/entry_type/created_at only. "review" filters to pending_review and enriches with confidence/classification_reasoning. - content_max_length (int, optional): Truncate content to N chars (full mode only). - stale_days (int, optional): Restrict to entries not accessed in N days (>= 1). - group_by (str, optional): Return grouped counts instead of entries. Valid: [entry_type, status, author, project, source, tags]. Mutually exclusive with output="stats". - output (str, optional): Set to "stats" for aggregate statistics. Mutually exclusive with group_by. - feed_url (str, optional): Filter to entries ingested from a registered feed source URL (matches metadata.source_url written by the poller). Use this to retrieve all items polled from e.g. "https://hnrss.org/frontpage". - include_archived (bool, optional, default=False): Include archived entries in the default view (same effect as status="any" when status is unset). - published_after (str, optional): ISO 8601 inclusive lower bound on metadata.published_at (the feed-item publication timestamp written by the poller). Use this to bound the /radar candidate set by the digest window. - published_before (str, optional): ISO 8601 inclusive upper bound on metadata.published_at. - include_evergreen (bool, optional, default=False): When False (default) and published_after/published_before is set, also drops entries flagged metadata.backfill=true so first-poll backfill items don't surface as "new intelligence". Set to True to surface older / evergreen items explicitly. See issue #444. - structural (list[str], optional): Surface entries with specific graph anomalies relative to ``entry_relations``. Accepted values: ["orphans"] — entries that do not appear as either endpoint of any relation row. Unknown values yield INVALID_PARAMS. Combines (AND) with every other filter (project, tags, status, date range, stale_days, etc.) — orphans are first restricted by those filters, then the no-relations predicate is applied. RETURNS (success): { entries: list, count: int, total_count: int, limit: int, offset: int, output_mode: str } — when ``structural`` is set, the payload additionally includes ``structural_filter`` (comma-joined applied filters, e.g. "orphans"). Existing fields are unchanged. RETURNS (error): { error: true, code: "INVALID_PARAMS" | "INTERNAL", message: "..." } RELATED: distillery_search (for semantic search), distillery_status (for lightweight server health/metadata)

ctx Context tags string limit int author string offset int output string source string status string date_to string project string feed_url string group_by string date_from string entry_type string session_id string stale_days string structural string tag_prefix string output_mode str verification string published_after string include_archived bool published_before string include_evergreen bool content_max_length string
distillery_search
annotations: none low

Search knowledge entries using semantic similarity (cosine distance, ranked descending). USE WHEN: finding entries that match a natural-language question or topic. Each result includes a similarity score (0-1, higher is more relevant). By default, only entries with status in (active, pending_review) are considered — archived entries are hidden. Pass ``status="archived"`` to search only archived entries, ``status="any"`` to include every status, or ``include_archived=true`` to add archived entries to the default candidate set. When ``expand_graph=true``, after the semantic search returns its seed result set, the tool BFS-expands 1 or 2 hops via ``entry_relations`` to surface structurally connected entries. Graph entries are scored at ``parent_score * 0.5 ** depth``, marked with ``provenance="graph"``, and merged into the result list (sorted by descending score, truncated to ``limit``). Seeds are tagged ``provenance="search"``. The envelope gains a ``graph_expansion`` summary. When ``expand_graph=false`` (default), the existing envelope is unchanged — strictly additive. PARAMS: - query (str, required): Natural-language search query. - entry_type (str | list[str], optional): Filter by type, or a list of types matched with OR (e.g. ["session", "reference"]). - author (str, optional): Filter by author. - project (str, optional): Filter by project scope. - tags (list[str], optional): Filter by tags (AND match). - status (str, optional): Filter by status. - source (str, optional): Filter by origin. - session_id (str, optional): Filter by session identifier. - date_from (str, optional): ISO 8601 lower bound. - date_to (str, optional): ISO 8601 upper bound. - limit (int, optional, default=10): Max results (1-200). - tag_prefix (str, optional): Filter tags by namespace prefix. - include_archived (bool, optional, default=False): Include archived entries in the candidate set. - published_after (str, optional): ISO 8601 inclusive lower bound on metadata.published_at (poller-recorded publication timestamp). Used by /radar to bound the candidate set by the configured digest window. - published_before (str, optional): ISO 8601 inclusive upper bound on metadata.published_at. - include_evergreen (bool, optional, default=False): When False (default) and published_after/published_before is set, also drops entries flagged metadata.backfill=true so first-poll backfill items don't surface as "new intelligence". Set to True to surface older / evergreen items explicitly. See issue #444. - expand_graph (bool, optional, default=False): When true, expand the seed result set via ``entry_relations`` and merge the neighbours into the results. - expand_hops (int, optional, default=1): Depth of graph expansion when ``expand_graph=true``. Must be 1 or 2. - output_mode (str, optional, default="summary"): Response shape. Valid: [summary, full, ids]. "summary" returns score plus a compact entry (id/title/~200-char content_preview, no full body — default, keeps responses small to conserve context). "full" returns score plus the entire entry (pre-output_mode behaviour). "ids" returns score + id only. RETURNS (success): { results: [{ score: float, ... }], count: int }. Result shape follows ``output_mode``: "summary" (default) nests a compact ``entry`` (no full content); "full" nests the complete ``entry``; "ids" returns ``score`` + ``id`` only. When ``expand_graph=true`` each result also has ``provenance`` ("search" or "graph"); graph results additionally carry ``depth`` and ``parent_id``, and the envelope includes ``graph_expansion: { seed_count, expanded_count }``. RETURNS (error): { error: true, code: "INVALID_PARAMS" | "BUDGET_EXCEEDED" | "INTERNAL", message: "..." } RELATED: distillery_list (for filter-based browsing without semantic ranking), distillery_find_similar (to compare against arbitrary text)

ctx Context tags string limit int query str author string source string status string date_to string project string date_from string entry_type string session_id string tag_prefix string expand_hops int output_mode str expand_graph bool published_after string include_archived bool published_before string include_evergreen bool
distillery_find_similar
annotations: none low

Find stored entries similar to the given text (cosine similarity). USE WHEN: checking for duplicates or conflicts before storing, finding entries related to arbitrary text, or surfacing hidden connections to a known entry (entries that are similar but not yet linked via relations). Supports progressive disclosure modes. PARAMS: - content (str, optional): Text to compare against stored entries. Required unless source_entry_id is provided. When both are set, content wins as the similarity probe. - threshold (float, optional, default=0.8): Cosine similarity cutoff (0-1). - limit (int, optional, default=10): Max results (1-200). - dedup_action (bool, optional, default=false): When true, includes dedup check with recommended action (create/skip/merge/link). - conflict_check (bool, optional, default=false): When true, includes conflict candidates with LLM evaluation prompts. - llm_responses (list[dict], optional): With conflict_check=true, evaluates LLM conflict verdicts. Each item: { entry_id: str, is_conflict: bool, reasoning: str }. - source_entry_id (str, optional): Anchor entry whose content is used as the similarity probe when content is omitted, and whose id is self-excluded from results. Required when exclude_linked=true. When set without content/dedup/conflict/accept_action, reuses the entry's STORED embedding (no re-embed, no embedding-budget spend). - source_entry_ids (list[str], optional): BATCH mode. Up to 50 seed ids. Reuses each seed's STORED embedding (no re-embed, no embedding-budget spend) and runs all similarity queries in ONE round-trip. Standalone — cannot be combined with content, source_entry_id, dedup_action, conflict_check, accept_action, or llm_responses (INVALID_PARAMS). Honours threshold, limit, and exclude_linked per seed; each seed always self-excludes. - exclude_linked (bool, optional, default=false): When true, filters out entries already linked to source_entry_id (or, in batch mode, to each seed) via entry_relations (any direction, any relation_type). Surfaces hidden connections. - accept_action (str, optional): When set, persists an entry_relations row from source_entry_id to each result above threshold. Valid: ['link' → related, 'merge' → merge_source, 'duplicate' → duplicate]. Requires source_entry_id. Idempotent via the unique (from_id, to_id, relation_type) index. RETURNS (success, single/content): { results: [{ score: float, entry: {...} }], count: int, threshold: float, dedup?: { action: str, similar_entries: list }, conflict_candidates?: list, conflict_evaluation?: dict, excluded_linked_count?: int } Note: excluded_linked_count is present whenever source_entry_id is set or exclude_linked=true. It counts both linked-source exclusions (when exclude_linked=true) and the self-exclusion of source_entry_id itself (when source_entry_id == candidate); a non-zero value is therefore possible even with exclude_linked=false. RETURNS (success, batch / source_entry_ids): { results_by_seed: { "<seed_id>": { results: [{ score: float, entry: {...} }], count: int, excluded_count: int } }, seed_count: int, threshold: float } A seed with no stored embedding maps to an empty results list (not an error). excluded_count is best-effort (reported as 0 in batch mode). RETURNS (error): { error: true, code: "INVALID_PARAMS" | "NOT_FOUND" | "BUDGET_EXCEEDED" | "INTERNAL", message: "..." } RELATED: distillery_store (stores with automatic dedup/conflict checks), distillery_search (for natural-language queries), distillery_relations (to inspect existing links between entries)

ctx Context limit int content string threshold float dedup_action bool accept_action string llm_responses string conflict_check bool exclude_linked bool source_entry_id string source_entry_ids string
distillery_classify
annotations: none low

Apply a pre-computed classification to an existing entry. USE WHEN: you have determined an entry's type and confidence via LLM or heuristic analysis and want to persist the classification result. PARAMS: - entry_id (str, required): UUID of the entry to classify. - entry_type (str, required): Assigned type. Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. Common intuitive aliases like ``"note"`` are NOT accepted but the error response includes a ``details.suggestion`` pointing to the canonical type (e.g. ``"note"`` -> ``"inbox"``). - confidence (float, required): Classification confidence (0-1). Entries below the configured threshold (default 0.6) go to pending_review. - reasoning (str, optional): Explanation of the classification decision. - suggested_tags (list[str], optional): Tags to merge onto the entry. - suggested_project (str, optional): Project to assign if entry has none. RETURNS (success): { id: str, entry_type: str, status: str, ... } (full updated entry) RETURNS (error): { error: true, code: "NOT_FOUND" | "INVALID_PARAMS" | "INTERNAL", message: "...", details?: { field, provided, allowed, suggestion? } } RELATED: distillery_resolve_review (to act on pending_review entries), distillery_list (with output_mode="review" to see the review queue)

ctx Context entry_id str reasoning string confidence float entry_type str suggested_tags string suggested_project string
distillery_resolve_review
annotations: none low

Resolve a pending-review entry by approving, reclassifying, or archiving it. USE WHEN: acting on entries in the review queue (entries with status=pending_review from low-confidence classifications). PARAMS: - entry_id (str, required): UUID of the pending-review entry. - action (str, required): Resolution action. Valid: [approve, reclassify, archive]. - new_entry_type (str, optional): Required when action="reclassify". Valid: [session, bookmark, minutes, meeting, reference, idea, inbox, github, person, project, digest, feed]. - reviewer (str, optional): Reviewer identity for audit metadata. RETURNS (success): { id: str, status: str, ... } (full updated entry). When the requested action is a no-op (e.g. approve on an already-active entry), the response also includes { already_in_state: true } and the entry is returned unchanged (version is NOT bumped, reviewed_at / archived_at are NOT rewritten). RETURNS (error): { error: true, code: "NOT_FOUND" | "INVALID_PARAMS" | "FORBIDDEN" | "INTERNAL", message: "..." } RELATED: distillery_classify (to classify entries), distillery_list (with output_mode="review" to see the queue)

ctx Context action str entry_id str reviewer string new_entry_type string
distillery_watch
annotations: none low

Manage monitored feed sources for ambient intelligence. USE WHEN: listing, adding, or removing RSS/GitHub feed sources that Distillery polls for new content. PARAMS: - action (str, required): Operation to perform. Valid: [list, add, remove]. - url (str, required for add/remove): Feed URL or GitHub owner/repo slug. - source_type (str, required for add): Feed type. Valid: [rss, github]. - label (str, optional): Human-readable label for the source. - poll_interval_minutes (int, optional, default=60): Polling frequency in minutes. - trust_weight (float, optional, default=1.0): Source trust weight (0-1). - thresholds (object, optional): Per-source overrides for the global ``feeds.thresholds`` values. Mapping with optional float keys ``alert`` and/or ``digest`` in [0.0, 1.0] (when both set, ``digest <= alert``). When omitted, the global cutoffs apply (pre-existing behaviour). Use this to raise the bar for noisy aggregators (HN/Lobsters/Reddit) since ``trust_weight`` only attenuates downward. - sync_history (bool, optional, default=false): When true and source_type is "github", kicks off an async background import of historical issues/PRs (returns immediately with job_id; use distillery_sync_status to check progress). - purge (bool, optional, default=false): When true and action is "remove", archives all entries from the removed source (soft-delete). Returns the count of archived entries in purged_entries. - probe (bool, optional, default=true): When adding, lightly probe the URL for reachability (HEAD with GET fallback, short timeout). Returns an INVALID_PARAMS error (with details.probe_failed=true) if the probe fails. - force (bool, optional, default=false): When adding, persist the source even if the reachability probe fails (useful for sites that block HEAD but work via the poller). - mode (str, optional, github only): Which content-bearing surface to poll. Valid: [releases, events]. Defaults to "releases" (one body-bearing entry per release). "events" is the opt-in contentless firehose. RETURNS (success): { sources: list, count: int } (list) or { added: dict, sources: list, sync_job?: dict } (add) or { removed_url: str, removed: bool, sources: list, purged_entries?: int } (remove) RETURNS (error): { error: true, code: "INVALID_PARAMS" | "CONFLICT" | "INTERNAL", message: "..." } RELATED: distillery_configure (to adjust feed thresholds), distillery_store_batch (for bulk entry ingestion)

ctx Context url string mode string force bool label string probe bool purge bool action str thresholds string source_type string sync_history bool trust_weight string poll_interval_minutes string
distillery_relations
annotations: none low

Manage typed relations between knowledge entries. USE WHEN: linking entries together (e.g. marking one as blocking another, citing a reference, or flagging duplicates), walking the relation graph from a seed entry to surface multi-hop neighbours, or computing graph metrics (bridges, communities) on the relations subgraph. PARAMS: - action (str, required): Operation. Valid: [add, get, remove, traverse, metrics, promote_entities]. - from_id (str, required for add): Source entry UUID. - to_id (str, required for add): Target entry UUID. - relation_type (str, required for add, optional for get/traverse): Relation type. Valid: [link, corrects, supersedes, related, blocks, depends_on, citation, duplicate, merge_source, sync_source, mentions, chunk]. - weight (float, optional for add): Edge strength (e.g. interest/engagement magnitude). On a re-assert of an existing edge, supplied attributes are upserted. - valid_at / invalid_at (str ISO 8601, optional for add): Bi-temporal validity window — when the relationship became / stopped being true (invalid_at null = current). - metadata (object, optional for add): Arbitrary per-edge attributes (JSON). - entry_id (str, required for get/traverse, required for metrics scope='ego'): Entry UUID to query relations for (BFS root for traverse / ego-graph). - direction (str, optional for get/traverse, default="both"): Filter direction. Valid: [outgoing, incoming, both]. - relation_id (str, required for remove): UUID of the relation to delete. - hops (int, optional for traverse, default=2): BFS depth, capped at [1, 3]. - metric (str, required for metrics): Graph metric to compute. Valid: [bridges, communities, constraint, link_prediction, orphans]. Requires the [graph] optional extra. - scope (str, optional for metrics, default="global"): Subgraph scope. Valid: [global, ego]. ``"ego"`` requires ``entry_id``. - limit (int, optional for metrics, default=10): top-k results. ``bridges`` = entries by betweenness centrality; ``communities`` = K largest communities; ``constraint`` = entries by lowest Burt constraint (strongest structural-hole brokers); ``link_prediction`` = top predicted edges by Adamic-Adar (pass ``entry_id`` to score adjacencies for one entry); ``orphans`` = sample (<=50) of entry IDs absent from the relations graph (unlinked entries — feeds a linking / gap-scan pass). - project / tags / date_from / date_to (optional, metrics global scope): restrict the entries whose relations participate in the graph. RETURNS (success): { relation_id: str, from_id: str, to_id: str, relation_type: str, weight: float | null, valid_at: str | null, invalid_at: str | null, metadata: object | null } (add) or { entry_id: str, relations: list, count: int } (get) or { relation_id: str, removed: bool } (remove) or { action: "traverse", root: str, hops: int, direction: str, relation_type: str | null, nodes: [{id: str, depth: int}], edges: [{from_id, to_id, relation_type}], node_count: int, edge_count: int } (traverse) or { action: "metrics", metric: str, scope: str, node_count: int, edge_count: int, total_entries: int, graph_node_count: int, orphan_rate: float, results: list, count: int, computed_at: str, cache_hit: bool } (metrics). ``orphan_rate`` = 1 - graph_node_count/total_entries (graph-health signal; 0.0 when total_entries is 0). Or { action: "promote_entities", entities_created: int, entities_reused: int, mentions_created: int, threshold: int } (promote_entities). Scans ``entity/*`` and ``tech/*`` tags and promotes any canonical tag meeting the configured ``tags.entity_promotion_threshold`` to an ENTITY entry node, linking each tagged entry with a ``mentions`` edge. Idempotent. RETURNS (error): { error: true, code: "NOT_FOUND" | "INVALID_PARAMS" | "INTERNAL", message: "..." } RELATED: distillery_correct (creates 'corrects' relations automatically), distillery_find_similar (to discover related entries)

ctx Context hops int tags string limit int scope str to_id string action str metric string weight string date_to string from_id string project string entry_id string metadata string valid_at string date_from string direction str invalid_at string relation_id string relation_type string
distillery_configure
annotations: none low

Read or update a runtime configuration value. USE WHEN: reading current thresholds/settings, or adjusting them at runtime without editing the config file directly. PARAMS: - section (str, required): Config section path (dotted notation). Valid: [feeds, feeds.thresholds, defaults, classification]. - key (str, required): Config key within the section. Valid keys by section: feeds: [user_agent]; feeds.thresholds: [alert, digest]; defaults: [dedup_threshold, dedup_limit, stale_days]; classification: [confidence_threshold, mode]. - value (str | int | float | None, optional): New value. Omit to read the current value. When provided, must satisfy type and range constraints for the given key. RETURNS (read): { section: str, key: str, value: any, message: str } RETURNS (write): { changed: bool, section: str, key: str, previous_value: any, new_value: any, disk_written: bool, message: str } RETURNS (error): { error: true, code: "INVALID_PARAMS" | "INTERNAL", message: "..." } RELATED: distillery_watch (to manage feed sources), distillery_status (to review current system state)

ctx Context key str value string section str
distillery_status
annotations: none low

Return a lightweight in-protocol health/metadata probe. USE WHEN: verifying MCP connectivity (e.g. from the ``/setup`` wizard) without relying on the HTTP-only ``/health`` endpoint. Works uniformly on stdio and HTTP transports. PARAMS: (none) RETURNS (success): { status: "ok", version: str, # distillery package version build_sha: str, # git SHA (or "dev") transport: "stdio" | "http" | "unknown", tool_count: int, # number of registered MCP tools store: { entry_count: int | null, db_size_bytes: int | null }, embedding_provider: str, # model name or provider class name last_feed_poll: { source_count: int, last_poll_at: str | null }, uptime_seconds?: int # seconds since server startup } RELATED: distillery_list (for entry counts, filtering, and per-group aggregates), distillery_configure (to inspect/adjust runtime configuration)

ctx Context

Permissions 4

network medium
Server uses network capabilities via: httpx, socket, urllib
filesystem low
Server uses filesystem capabilities via: open(), os, pathlib, shutil, tempfile
shell high
Server uses shell capabilities via: subprocess
env_vars low
Server uses env_vars capabilities via: os.environ

Scan Findings 73

low
Tool 'distillery_store_batch' has no annotations annotation_checker · 100%
low
Tool 'distillery_store' has no annotations annotation_checker · 100%
low
Tool 'distillery_ingest_doc' has no annotations annotation_checker · 100%
low
Tool 'distillery_get' has no annotations annotation_checker · 100%
low
Tool 'distillery_update' has no annotations annotation_checker · 100%
low
Tool 'distillery_correct' has no annotations annotation_checker · 100%
low
Tool 'distillery_list' has no annotations annotation_checker · 100%
low
Tool 'distillery_search' has no annotations annotation_checker · 100%
low
Tool 'distillery_find_similar' has no annotations annotation_checker · 100%
low
Tool 'distillery_classify' has no annotations annotation_checker · 100%
low
Tool 'distillery_resolve_review' has no annotations annotation_checker · 100%
low
Tool 'distillery_watch' has no annotations annotation_checker · 100%
low
Tool 'distillery_relations' has no annotations annotation_checker · 100%
low
Tool 'distillery_gh_sync' has no annotations annotation_checker · 100%
low
Tool 'distillery_sync_status' has no annotations annotation_checker · 100%
low
Tool 'distillery_configure' has no annotations annotation_checker · 100%
low
Tool 'distillery_status' has no annotations annotation_checker · 100%
high
Hardcoded OAuth client secret in norrietaylor-distillery-d6697cc/tests/test_mcp_coverage_gaps.py auth_checker · 95%
high
Hardcoded OAuth client ID in norrietaylor-distillery-d6697cc/tests/test_mcp_auth.py auth_checker · 85%
high
Hardcoded OAuth client secret in norrietaylor-distillery-d6697cc/tests/test_mcp_auth.py auth_checker · 95%
high
Hardcoded OAuth client secret in norrietaylor-distillery-d6697cc/tests/test_gitlab_auth.py auth_checker · 95%
info
Sandbox failed to start for behavioral verification behavioral_verifier · 100%
medium
Vulnerable dependency: pyyaml@6.0,<7.0 (GHSA-8q59-q68h-6hv4) dependency_analyzer · 95%
medium
Vulnerable dependency: pyyaml@6.0,<7.0 (GHSA-rprw-h62v-c2w7) dependency_analyzer · 95%
medium
Vulnerable dependency: pyyaml@6.0,<7.0 (PYSEC-2018-49) dependency_analyzer · 95%
medium
Vulnerable dependency: pyyaml@6.0,<7.0 (PYSEC-2021-142) dependency_analyzer · 95%
medium
Vulnerable dependency: httpx@0.24.0,<1.0 (GHSA-h8pj-cxx2-jfg2) dependency_analyzer · 95%
medium
Vulnerable dependency: httpx@0.24.0,<1.0 (PYSEC-2022-183) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-5h2m-4q8j-pqpj) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-c2jp-c369-7pvx) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-m8x7-r2rg-vh5g) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-mxxr-jv3v-6pgc) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-rcfx-77hg-w2wv) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-rj5c-58rq-j5g5) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-rww4-4w9c-7733) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (GHSA-vv7q-7jx5-f767) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-1364) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-1365) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-2474) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-2475) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-2476) dependency_analyzer · 95%
medium
Vulnerable dependency: fastmcp@2.12.0,<4.0 (PYSEC-2026-338) dependency_analyzer · 95%
medium
Vulnerable dependency: python-multipart@0.0.30 (GHSA-v9pg-7xvm-68hf) dependency_analyzer · 95%
medium
Vulnerable dependency: python-multipart@0.0.30 (PYSEC-2026-3040) dependency_analyzer · 95%
medium
Hex string literal (>50 chars) in norrietaylor-distillery-d6697cc/src/distillery/eval/longmemeval_dataset.py:49 entropy_analyzer · 70%
info
pyproject.toml metadata manifest_parser · 100%
info
Tool: distillery_store manifest_parser · 90%
info
Tool: distillery_store_batch manifest_parser · 90%
info
Tool: distillery_ingest_doc manifest_parser · 90%
info
Tool: distillery_get manifest_parser · 90%
info
Tool: distillery_update manifest_parser · 90%
info
Tool: distillery_correct manifest_parser · 90%
info
Tool: distillery_list manifest_parser · 90%
info
Tool: distillery_search manifest_parser · 90%
info
Tool: distillery_find_similar manifest_parser · 90%
info
Tool: distillery_classify manifest_parser · 90%
info
Tool: distillery_resolve_review manifest_parser · 90%
info
Tool: distillery_watch manifest_parser · 90%
info
Tool: distillery_relations manifest_parser · 90%
info
Tool: distillery_gh_sync manifest_parser · 90%
info
Tool: distillery_sync_status manifest_parser · 90%
info
Tool: distillery_configure manifest_parser · 90%
info
Tool: distillery_status manifest_parser · 90%
info
Transport: streamable-http manifest_parser · 80%
info
Required env vars (30) manifest_parser · 80%
medium
Hardcoded OAuth client ID in norrietaylor-distillery-d6697cc/tests/test_mcp_auth.py oauth_scope_analyzer · 80%
info
Sandbox failed to start for output poisoning scan output_poisoning · 100%
medium
Permission: network access detected permission_analyzer · 90%
low
Permission: filesystem access detected permission_analyzer · 90%
high
Permission: shell access detected permission_analyzer · 95%
low
Permission: env_vars access detected permission_analyzer · 90%
info
No dependency files found for SBOM generation sbom_generator · 100%
medium
No build provenance detected (SLSA L0) slsa_assessor · 90%