Skip to main content
Glama
norrietaylor

io.github.norrietaylor/distillery-mcp

Official
by norrietaylor

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}
logging
{}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
extensions
{
  "io.modelcontextprotocol/ui": {}
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
distillery_storeA

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)

distillery_store_batchA

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)

distillery_ingest_docA

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/" 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)

distillery_getA

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)

distillery_updateA

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)

distillery_correctA

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)

distillery_listA

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)

distillery_searchA

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)

distillery_find_similarA

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: { "": { 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)

distillery_classifyA

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)

distillery_resolve_reviewA

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)

distillery_watchA

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)

distillery_relationsA

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)

distillery_gh_syncA

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.

distillery_sync_statusA

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.

distillery_configureA

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)

distillery_statusA

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)

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
entry_type_schemasReturn the metadata schemas for all structured entry types as a JSON resource. Replaces the former ``distillery_type_schemas`` tool. Clients read this resource to discover the required/optional metadata fields and constraints for each entry type (session, bookmark, minutes, meeting, reference, idea, inbox, plus any structured types with richer schemas).

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/norrietaylor/distillery'

If you have feedback or need assistance with the MCP directory API, please join our Discord server