io.github.norrietaylor/distillery-mcp
OfficialAllows syncing GitHub issues and pull requests into the knowledge base, and monitoring GitHub repositories as feed sources.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@io.github.norrietaylor/distillery-mcprecall distributed caching strategies"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
What is Distillery?
Distillery is a team knowledge base accessed through Claude Code skills. It refines raw information from working sessions, meetings, bookmarks, and conversations into concentrated, searchable knowledge — stored as vector embeddings in DuckDB and retrieved through natural language. Runs locally over stdio or as a hosted HTTP service with GitHub OAuth for team access.
Distillery captures the highest-value transformation — from noise to signal — and makes it a tool the whole team can use.
Full documentation: norrietaylor.github.io/distillery
Related MCP server: Rememberizer MCP Server
Skills
Distillery provides 15 Claude Code slash commands:
Skill | Purpose | Example |
| Capture session knowledge with dedup detection |
|
| Semantic search with provenance |
|
| Multi-entry synthesis with citations |
|
| Contrast internal knowledge vs. ambient intelligence for a directional assessment |
|
| Store URLs with auto-generated summaries |
|
| Meeting notes with append updates |
|
| Classify entries and triage review queue |
|
| Manage monitored feed sources |
|
| Ambient feed digest with source suggestions |
|
| Adjust feed relevance thresholds |
|
| Team activity summary from internal entries |
|
| Sync GitHub issues/PRs into the knowledge base |
|
| Deep context builder with relationship traversal |
|
| Team knowledge dashboard with metrics |
|
| Onboarding wizard for MCP connectivity and config |
|
Quick Start
Step 1: Install the Plugin
claude plugin marketplace add norrietaylor/distillery
claude plugin install distilleryThis installs all 15 skills. The plugin does not configure an MCP server automatically — run /setup (below) to add one. The recommended setup runs locally via uvx --from 'distillery-mcp[fastembed]>=0.6.0' distillery-mcp — a private, self-contained knowledge base on your machine, with on-device fastembed embeddings (no API key required). Requires Python 3.11+ and uv (install: curl -LsSf https://astral.sh/uv/install.sh | sh).
Step 2 (Optional): Use Jina or OpenAI Instead
The default fastembed provider runs offline with no API key. If you'd rather use a hosted embedding service, set DISTILLERY_EMBEDDING_PROVIDER and provide the matching API key:
# Jina (free tier at jina.ai)
export DISTILLERY_EMBEDDING_PROVIDER=jina
export JINA_API_KEY=jina_...
# Or OpenAI
export DISTILLERY_EMBEDDING_PROVIDER=openai
export OPENAI_API_KEY=sk-...uvx inherits these from your shell environment. See distillery.yaml.example for the full provider configuration block (including Option C for fastembed model selection).
Restart Claude Code and run the onboarding wizard:
/setupTry the Hosted Demo (Opt-In)
Want to evaluate without installing anything locally? Configure the hosted demo at distillery-mcp.fly.dev instead of a local server:
claude mcp add distillery --scope user --transport http --url https://distillery-mcp.fly.dev/mcpDemo Server:
distillery-mcp.fly.devis for evaluation only. Do not store sensitive or confidential data.
See the Local Setup Guide for full configuration options, or deploy your own instance for team use.
Development
uv pip install -e ".[dev]"
# or
pip install -e ".[dev]"
pytest # run tests
mypy --strict src/distillery/ # type check
ruff check src/ tests/ # lintSee Contributing for the full guide.
License
Apache 2.0 — see LICENSE for details.
Available Tools
17 toolsdistillery_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 adetails.suggestionpointing 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)
| Name | Required | Description | Default |
|---|---|---|---|
| entry_id | Yes | ||
| reasoning | No | ||
| confidence | Yes | ||
| entry_type | Yes | ||
| suggested_tags | No | ||
| suggested_project | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full behavioral disclosure. It reveals that entries below threshold (default 0.6) go to pending_review, that invalid types trigger a suggestion in the error response, and that successful calls return the full updated entry. It also explains tag merging and project assignment side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED) and front-loads the core purpose. Each sentence earns its place: parameter explanations, return formats, error codes, and related tools are all information-dense with no repetition or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 6 parameters, no output schema, and no annotations, the description is remarkably complete. It covers input semantics, success/error return structures, error codes with suggestion details, and names related tools. The only minor omission is whether existing classifications are overwritten, but this is not critical given the overall thoroughness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description compensates fully. For entry_type it lists all valid values and explicitly notes that aliases like 'note' are rejected but the error includes a suggestion pointing to canonical type 'inbox'. For confidence it explains the threshold behavior. All six parameters are described with semantics beyond their schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb-resource pair: 'Apply a pre-computed classification to an existing entry.' It then clarifies the intended context (persisting results from LLM/heuristic analysis) and distinguishes this from sibling tools by focusing on classification persistence rather than storage, retrieval, or review.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'USE WHEN' section gives a clear precondition: when you have determined type and confidence and want to persist it. It also names related tools with their specific purposes, distillery_resolve_review for acting on pending_review entries and distillery_list for seeing the queue, effectively telling when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | ||
| value | No | ||
| section | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It clearly states the tool can read or write, specifies the return shapes for read, write, and error cases, and mentions the `disk_written` boolean in the write return, exposing the side effect of persisting changes. It also notes that `value` 'must satisfy type and range constraints for the given key,' implying validation. This is thorough, honest disclosure with no contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but every section earns its place: USE WHEN, PARAMS, RETURNS, RELATED. It is front-loaded with the core purpose, then structured so the agent can quickly scan for the information it needs. No redundant filler or restatement of the schema – each line adds new value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 parameters, no output schema, and no annotations, this description is encyclopedic. It covers when to use the tool, all valid input combinations, the exact return contracts for success and failure (including error codes), and points to relevant sibling tools. An agent has everything it needs to invoke this tool correctly without further inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema provides zero descriptions (coverage 0%), so the description must compensate – and it does brilliantly. For `section` it lists the four valid dotted-notation paths. For `key` it gives a per-section breakdown of valid keys. For `value` it clarifies optionality and type constraints. This is more actionable than most descriptions, leaving no ambiguity about parameter meaning or allowed inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Read or update a runtime configuration value' – a specific verb-resource pair that defines the tool's scope. It then enumerates valid sections and keys, making the exact target clear. Among the sibling tools (store, ingest, classify, watch, etc.), this is the only one that reads/updates runtime config, so it is unambiguously distinguishable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides an explicit 'USE WHEN' clause: 'reading current thresholds/settings, or adjusting them at runtime without editing the config file directly.' It also names related tools in the RELATED line: distillery_watch (to manage feed sources) and distillery_status (to review current system state), giving the agent clear guidance on when to prefer those alternatives. This is textbook usage differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| author | No | ||
| content | Yes | ||
| project | No | ||
| metadata | No | ||
| entry_type | No | ||
| wrong_entry_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavior: it supersedes the original, preserves audit trail, returns archived_entry_id, and includes a detailed error code list. It also explains inheritance defaults, making side effects and edge cases transparent to the agent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but efficiently structured with clear headers (USE WHEN, PARAMS, RETURNS, RELATED). The core purpose is front-loaded in a single sentence, and each section adds essential information without redundancy. Bullet-like formatting makes it scannable for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers all operational aspects: purpose, usage conditions, parameter semantics, return values (success and error), and related tools. It also explains inheritance behavior and error codes. No missing information that an agent would need to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description carries the entire burden. It describes every parameter, marks required vs optional, explains inheritance for optional fields, and enumerates valid values for entry_type. This fully compensates for the lack of schema descriptions and exceeds what a schema alone would provide.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb ('store a correction') and resource ('an existing entry') with clear intent to supersede. The RELATED line explicitly differentiates from distillery_update and distillery_relations, eliminating ambiguity about which tool to call.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit 'USE WHEN' condition that describes the exact scenario (wrong information, need to replace while preserving audit trail) and names alternative tools for other cases. The RELATED section gives clear routing guidance, so an agent knows exactly when to pick this over its siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| content | No | ||
| threshold | No | ||
| dedup_action | No | ||
| accept_action | No | ||
| llm_responses | No | ||
| conflict_check | No | ||
| exclude_linked | No | ||
| source_entry_id | No | ||
| source_entry_ids | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden — and it does so comprehensively. It discloses embedding-budget implications ('reuses the entry's STORED embedding (no re-embed, no embedding-budget spend)'), idempotency via the unique (from_id, to_id, relation_type) index, the nuanced excluded_linked_count semantics (counts both linked-source exclusions and self-exclusion), batch-mode edge cases (seed with no embedding maps to empty results, excluded_count best-effort reported as 0), and the full error-code surface. Genuinely rich behavioral context beyond any structural field.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but appropriately so for a 10-parameter, three-return-mode tool at 0% schema coverage. It is disciplined in structure: front-loaded purpose, then USE WHEN, PARAMS, RETURNS (single/batch/error), and RELATED. Each sentence carries information — batch embedding reuse, idempotency, excluded_count semantics — with no filler or repetition. The length earns its place given the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 10 parameters, three distinct return shapes, a standalone batch mode, idempotency, and embedding-budget side effects — with zero schema descriptions and no output schema — the description is remarkably complete. It documents every parameter, every return shape including the batch variant and error codes, plus edge cases (missing embeddings, best-effort counts). The minor mention of 'progressive disclosure modes' without elaboration is the only slight gap, and it does not undermine completeness for a tool this complex.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description fully compensates for every one of the 10 parameters. Each param gets purpose and constraints: content's precedence rule ('When both are set, content wins'), threshold's cutoff range (0-1), limit's bounds (1-200), the batch-mode exclusivity rule for source_entry_ids ('cannot be combined... INVALID_PARAMS'), and accept_action's valid enum plus idempotency note. At zero schema coverage, this is maximal compensation — no parameter is left without semantic grounding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource statement, 'Find stored entries similar to the given text (cosine similarity),' and immediately distinguishes itself from siblings via the USE WHEN section ('checking for duplicates or conflicts before storing, finding entries related to arbitrary text, or surfacing hidden connections'). The RELATED block explicitly contrasts against distillery_search (natural-language) and distillery_relations (inspecting links), leaving no ambiguity about what this tool is versus its siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit USE WHEN list with concrete selection scenarios (duplicate/conflict checking before storing, relating arbitrary text, surfacing hidden connections), and names alternatives in RELATED: distillery_store for storing with automatic checks, distillery_search for natural-language queries, distillery_relations for inspecting existing links. Both positive selection conditions and exclusions are articulated; an agent can route correctly without inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| entry_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must disclose behavior. It does so by specifying the return structure for both success (id, content, entry_type) and error (code, message). While 'Retrieve' implies a read-only operation, it does not explicitly state that no mutation occurs, but the provided return/error formats give substantial behavioral insight for a simple GET.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED), front-loading the purpose. Every sentence provides essential information without redundancy. The format is scannable for an agent and not overly verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter retrieval tool with no output schema and no annotations, the description is complete. It covers when to use it, the parameter meaning, expected return types, and error handling, and even suggests sibling tools for related use cases. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaning beyond the schema by explaining that entry_id is a 'UUID of the entry to retrieve.' The schema only defines it as a string, so this clarifies the expected format and purpose, fully compensating for the 0% schema description coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Retrieve') and resource ('knowledge entry') with a unique ID, clearly distinguishing from siblings like distillery_search and distillery_list. The description explicitly notes the tool retrieves a single entry by ID, which is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides an explicit 'USE WHEN' section that tells the agent exactly when to use this tool (fetching full content/metadata of a specific entry). It also lists related tools (search, list) as alternatives, giving clear routing context without needing to inspect other schemas.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | ||
| author | No | gh-sync | |
| project | No | ||
| background | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It mentions batched processing and async operation, and notes that background mode returns a job_id. However, it omits crucial details such as whether the sync updates existing entries, creates duplicates, or requires authentication. It also lacks information on error handling or rate limits, so the behavioral picture is incomplete.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a single opening sentence states the purpose, followed by a bulleted list of parameter explanations. Each line adds value and the format is easy for an agent to parse. There is no waste or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
While parameter semantics are well covered, the description lacks details on the return value (except in background mode), error conditions, prerequisites such as authentication tokens, and the exact semantics of the sync operation. Given the absence of an output schema and annotations, the description should provide more context about side effects and expected outcomes. It is sufficient for a basic call but not fully complete for autonomous decision-making.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has zero descriptions (0% coverage), so the description must compensate. It does this thoroughly by explaining each parameter: url is a repository slug or full URL, author has a default, project is optional, and background enables async mode with an immediate job_id return. This fully clarifies the meaning and defaults beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool syncs GitHub issues and PRs into the knowledge base using a batched pipeline. It identifies the specific verb and resource, making the purpose clear. While it doesn't explicitly differentiate from sibling tools, the 'sync' action and GitHub focus distinguish it from store, get, search, and other operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies that this tool is for syncing GitHub data into the knowledge base, which gives a general sense of when to use it. However, it does not explicitly state when to prefer this over alternatives like distillery_store or distillery_ingest_doc, nor does it provide exclusions or cautionary notes. The usage context is adequate but not fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| text | Yes | ||
| title | No | ||
| author | Yes | ||
| source | No | ||
| doctype | No | ||
| project | No | ||
| metadata | No | ||
| external_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the full burden of behavioral disclosure. It explains key behaviors: chunking of large text, idempotent deduplication by content hash, and the exact response on re-ingest (persisted=false, dedup_action='skipped'). It does not explicitly mention permissions or failure modes beyond simple error codes, but the core side effects are clearly disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (intro, USE WHEN, PARAMS, RETURNS, RELATED) and front-loaded with the core purpose. It is somewhat long, but every section adds necessary detail for correct usage, so the length is justified. The use of headings improves scannability for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 9 parameters, no annotations, and no output schema, the description is remarkably complete. It explains the dedup/chunking behavior, provides detailed parameter guidance, explicitly lists success and error return shapes, and references related tools. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage, the description fully compensates. It documents every parameter (text, author, doctype, source, external_id, title, project, tags, metadata) with explanations of defaults, valid values, and how they are stored (e.g., doctype applied as tag and metadata, external_id defaults to SHA-256 hash). This goes far beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Ingest an arbitrary document (ADR, spec, decision, customer feedback)'. It uses a specific verb and resource and explicitly distinguishes itself from siblings like distillery_store (single entry) and PreCompact transcripts, so an agent can easily identify when to use it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE WHEN' section explicitly states when to use this tool: 'importing a standalone document... so it becomes queryable knowledge with provenance'. It also contrasts with distillery_store and PreCompact transcripts, providing clear alternatives and the conditions that select this tool over them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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_urlsosource="https://hnrss.org/frontpage"matches feed items ingested from that source (same semantics as passingfeed_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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| limit | No | ||
| author | No | ||
| offset | No | ||
| output | No | ||
| source | No | ||
| status | No | ||
| date_to | No | ||
| project | No | ||
| feed_url | No | ||
| group_by | No | ||
| date_from | No | ||
| entry_type | No | ||
| session_id | No | ||
| stale_days | No | ||
| structural | No | ||
| tag_prefix | No | ||
| output_mode | No | summary | |
| verification | No | ||
| published_after | No | ||
| include_archived | No | ||
| published_before | No | ||
| include_evergreen | No | ||
| content_max_length | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are provided, the description carries the full burden. It discloses default status filtering, pagination ordering ('newest first'), response modes (summary/full/ids/review), content preview behavior, source-to-feed_url aliasing, mutual exclusions (group_by/output='stats'), stale_days semantics, include_evergreen backfill handling, and structural filter behavior. It also details return fields and error codes. This is exhaustive and beyond what any annotation could provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but necessary given 24 parameters. It is well-structured with sections (PARAMS, RETURNS, RELATED) and front-loads the core purpose and usage. Some redundancy exists (status behavior repeated in the intro and status parameter, include_archived explanation overlaps), but it remains efficient and each parameter earns its place. A minor trim would push it to 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a highly complex tool with no output schema and no annotations, the description is exceptionally complete. It explains return shape, error codes, mutual exclusions, edge cases (e.g., include_evergreen, structural orphan behavior), and references related tools. An agent would have everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 for all 24 parameters. It does so thoroughly: each parameter explains its purpose, valid values (e.g., entry_type enums, status options, source origins), defaults, and special behaviors (e.g., source URL alias to feed_url, structural filter combination, content_max_length truncation). This adds substantial meaning far beyond the bare schema types.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 knowledge entries with optional filters and pagination (newest first).' It immediately distinguishes from distillery_search by stating it is for browsing/filtering without a semantic query, and it names the alternative explicitly. The purpose is unambiguous and differentiates from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states 'USE WHEN: browsing or filtering entries without a semantic query' and directs to 'Use distillery_search instead when you have a natural-language question.' It also explains the default status behavior (active/pending_review with archived hidden) and how to override it, giving clear when-to/not-to guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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"requiresentry_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 (passentry_idto 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)
| Name | Required | Description | Default |
|---|---|---|---|
| hops | No | ||
| tags | No | ||
| limit | No | ||
| scope | No | global | |
| to_id | No | ||
| action | Yes | ||
| metric | No | ||
| weight | No | ||
| date_to | No | ||
| from_id | No | ||
| project | No | ||
| entry_id | No | ||
| metadata | No | ||
| valid_at | No | ||
| date_from | No | ||
| direction | No | both | |
| invalid_at | No | ||
| relation_id | No | ||
| relation_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Given there are no annotations, the description carries the full burden of behavioral disclosure. It details side effects (upsert on re-assert), idempotency of promote_entities, error codes (NOT_FOUND, INVALID_PARAMS, INTERNAL), return structures for every action, and even explains the orphan_rate formula. No contradictions with annotations (none provided).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured with sections (USE WHEN, PARAMS, RETURNS, ERROR, RELATED). It is front-loaded with the core purpose and then provides exhaustive details. While some verbosity exists (e.g., repeating default values that are already in the schema), the density is justified given the tool's complexity (6 actions, 19 params). A 5 would require even tighter prose; a 3 would be too short. 4 reflects a strong but not perfect balance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 19 parameters, 6 actions, no schema descriptions, and no output schema, the description is comprehensive. It documents all input parameters, return shapes for every action, error handling, and even extra requirements (e.g., metrics requiring the [graph] extra). Nothing an agent needs to correctly invoke the tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has 0% description coverage, so the description must explain every parameter. It does: each parameter's type, required condition, valid values (e.g., action values, relation_type enum), defaults, and semantic meaning (e.g., weight as edge strength, valid_at/invalid_at bi-temporal window, metric behaviors like betweenness vs. Adamic-Adar). This is a textbook example of description compensating for schema gaps.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Manage typed relations between knowledge entries.' This is a specific verb and resource. It then enumerates concrete use cases (linking entries, walking the graph, computing metrics) and names two sibling tools (distillery_correct, distillery_find_similar) that it is not, distinguishing it clearly from the related tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE WHEN' section explicitly tells the agent when to employ this tool (linking, traversing, metrics) and the 'RELATED' section points to alternatives: distillery_correct for auto-creating 'corrects' relations and distillery_find_similar for discovering related entries. This is explicit when/when-not guidance, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | ||
| entry_id | Yes | ||
| reviewer | No | ||
| new_entry_type | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and it delivers: it details success response format, error codes, and the no-op behavior (already_in_state, version not bumped, timestamps not rewritten). It also explains the conditional requirement for new_entry_type, giving agents a complete picture of what happens.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear sections (USE WHEN, PARAMS, RETURNS, RELATED) and uses bullet points for readability. Every sentence carries needed information; there is no padding. The purpose is front-loaded, and the length is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 4 parameters, conditional logic, and no output schema, the description is comprehensive. It covers all parameter semantics, return shapes, error scenarios, and related tools. An agent has everything needed to invoke it correctly without additional lookup.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The PARAMS section goes far beyond the bare schema. It lists valid values for action and new_entry_type, marks new_entry_type as required when action='reclassify', and describes reviewer as audit metadata. Since the schema has zero parameter descriptions, this text is essential and fully compensates.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb and resource: 'Resolve a pending-review entry by approving, reclassifying, or archiving it.' It explicitly ties the tool to the review queue and low-confidence classifications, clearly distinguishing it from the many sibling tools that handle storage, retrieval, or classification.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE WHEN' section explicitly states the condition for using this tool (entries with status=pending_review). It also provides alternatives in 'RELATED' by naming distillery_classify and distillery_list with output_mode='review', making the choice unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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_relationsand 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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| limit | No | ||
| query | Yes | ||
| author | No | ||
| source | No | ||
| status | No | ||
| date_to | No | ||
| project | No | ||
| date_from | No | ||
| entry_type | No | ||
| session_id | No | ||
| tag_prefix | No | ||
| expand_hops | No | ||
| output_mode | No | summary | |
| expand_graph | No | ||
| published_after | No | ||
| include_archived | No | ||
| published_before | No | ||
| include_evergreen | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and meets it thoroughly. It discloses the default status candidate set, the graph expansion mechanism (BFS hops, scoring formula parent_score * 0.5 ** depth, provenance tagging, additive merging), the output_mode effects on result shape, and the exact error code list. Nothing about the tool's runtime behavior is omitted.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long, but it is extremely well-structured: a one-line purpose, then USE WHEN, then a clearly formatted PARAMS block, then RETURNS (success and error), then RELATED. It is front-loaded with the core semantics. Every section earns its place given the tool's complexity (19 params, graph expansion, multiple output modes); there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 19 parameters, no output schema, and no annotations, the description is fully self-sufficient. It explains every parameter, the exact return envelope shape for each output_mode, the graph_expansion summary fields, and the error contract. It also covers edge cases like archived status handling, published windows, and evergreen inclusion. There is nothing an agent would need to infer or look up elsewhere.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 comprehensively. Every single parameter is described with its purpose, defaults, and sometimes extra context (e.g., include_evergreen explains the backfill flag and references issue #444, published_after notes it is used by /radar). The PARAMS section adds meaning far beyond the schema's bare types and defaults.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a precise verb (Search), a specific resource (knowledge entries), and the method (semantic similarity using cosine distance, ranked descending). It explicitly differentiates from related tools at the end (distillery_list for filter-based browsing without semantic ranking, distillery_find_similar for comparing against arbitrary text), so an agent can immediately tell this apart from siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit USE WHEN condition ('finding entries that match a natural-language question or topic') and then details the default status filtering behavior with concrete instructions for overriding it via status or include_archived. It also names the two related tools and their purposes, making alternatives clear. No gaps in when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. While it details the return schema (which implies a read-only probe), it does not explicitly state side effects, authentication requirements, or error conditions. For a status tool, this is acceptable but not fully transparent about whether any modification occurs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED). The main purpose is front-loaded in the first line, and every section adds relevant information without redundancy. It is appropriately sized for a status probe.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Since there is no output schema, the description provides a detailed return schema covering all expected fields and types. It also gives usage guidance and related alternatives. For a tool with no parameters, this is comprehensive and leaves no ambiguity about what the agent can expect when calling it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and the description states 'PARAMS: (none)' while the schema is an empty object. The baseline for 0 params is 4; the description adds no extra meaning but confirms the absence of required inputs, which is mildly helpful.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Return a lightweight in-protocol health/metadata probe.' This clearly distinguishes it from siblings like distillery_list (entry counts/filtering) and distillery_configure (runtime configuration). The related section also reinforces the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'USE WHEN: verifying MCP connectivity... without relying on the HTTP-only /health endpoint.' It also names alternatives (distillery_list, distillery_configure) and explains what they are for, providing clear routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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_promptLLM template required to round-trip throughdistillery_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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| author | Yes | ||
| source | No | ||
| content | Yes | ||
| project | No | ||
| metadata | No | ||
| entry_type | Yes | ||
| expires_at | No | ||
| session_id | No | ||
| dedup_limit | No | ||
| output_mode | No | ||
| verification | No | ||
| dedup_threshold | No | ||
| include_conflict_prompt | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It covers return formats for both success and error cases, explains dedup behavior, conflict_prompt inclusion (with size and default rationale), metadata requirements per entry type, expiry semantics, and output_mode effects. It also notes the performance tradeoff of include_conflict_prompt. This is exceptionally transparent for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Though lengthy, the description is highly structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED). Every sentence provides necessary information—there is no filler. The purpose is front-loaded, and the parameter documentation is organized and scannable. Given the tool's complexity (14 parameters with conditional logic), the length is justified and the layout enhances usability.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers everything an agent needs to invoke the tool correctly: all required and optional parameters, enum values, defaults, metadata requirements, return structures for both success and error, error codes, and related tools. With no output schema, it fully documents return values. It even includes edge-case details like default conflict_prompt behavior. Nothing essential is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully explain every parameter. It does: each parameter is listed with its type, required/optional status, defaults, valid enums, and special conditional requirements (e.g., metadata schemas per entry_type). This adds immense value beyond the raw input schema, which only provides types and defaults without semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource: 'Store a new knowledge entry and return its ID with dedup/conflict information.' It clearly identifies the action and output. The RELATED section names sibling tools (distillery_find_similar, distillery_correct) and states their different purposes, effectively distinguishing this tool from its siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE WHEN' section explicitly states the intended usage scenarios (capturing new knowledge like session notes, bookmarks, meeting minutes). It also provides guidance on when to use the summary output_mode for bulk imports and names alternatives (distillery_find_similar for pre-store dedup checks, distillery_correct to supersede an entry), giving clear when-to-use vs. when-not-to-use direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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). Iterateresultsto discover failures. RETURNS (error): { error: true, code: "INVALID_PARAMS" | "BUDGET_EXCEEDED" | "INTERNAL", message: "..." } Top-level error is returned only for schema-level problems (entriesnot a list, budget exhaustion, persistence failure).
RELATED: distillery_store (single entry with dedup/conflict checks), distillery_watch (add feed sources with optional history sync)
| Name | Required | Description | Default |
|---|---|---|---|
| entries | Yes | ||
| project | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With zero annotations, the description carries the full burden, and it delivers: explains batch semantics (no dedup/conflict), per-item failure handling (valid entries persisted, failures reported in 'results'), top-level error conditions, and the return shape. It also mentions budget exhaustion and issue #364, showing up-to-date behavioral detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but modularly structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED). Every sentence adds value—the length is warranted by the tool's complexity. Front-loading the purpose and using headers makes it scannable and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations, no output schema, and a complex per-item batch API, the description covers all essential aspects: usage context, parameter specifications, success and error return formats, and related tools. An agent has everything needed to invoke it correctly without ambiguity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, but the description provides exhaustive detail for each entry field: content, author, entry_type with valid values, tags, metadata, source, project, plus defaults. It also explains the top-level 'project' parameter. This fully compensates for the sparse schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line 'Batch-store multiple knowledge entries in one call (no dedup/conflict checks)' clearly states the verb, resource, and key distinguishing feature. It immediately contrasts with single-entry storage, making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Includes a dedicated 'USE WHEN' section specifying exact scenarios (bulk import, migration, backfill) and the trade-off (no dedup, throughput matters). Also names related tools (distillery_store, distillery_watch) and their differentiation, fully routing the agent to the correct alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| job_id | No | ||
| source_url | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the tool's primary behavior (checking sync job status, filtering by job_id or source_url, and listing all recent jobs when neither is given). However, it does not explicitly state that the tool is read-only, nor does it describe the response format, pagination, or potential errors. This leaves some ambiguity about side effects and output structure, though the name and purpose imply a non-mutating status check.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured. It opens with the primary purpose, then lists each parameter in a clear format, and concludes with the default behavior. Every sentence contributes to understanding the tool without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The core usage is covered, but for a status tool with no output schema and no annotations, the description omits details about the response structure (e.g., what fields are in each job status), whether there are any access limitations, or what constitutes a valid job_id or source_url format. Given the simplicity of the tool, this is partially acceptable, but an agent might still need to infer expected output.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 clearly explains the semantic meaning of both job_id and source_url, including the fallback behavior when neither is provided. It does not detail whether both can be combined or the expected data format, but it adds significant value beyond the bare type information in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Check the status of background sync jobs'), which clearly distinguishes it from siblings like distillery_status (general status) and other distillery tools. The purpose is unambiguous and the parameter examples reinforce the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains exactly when to use each parameter (job_id, source_url, or none) and what result each produces. It does not explicitly mention alternatives or when not to use this tool, but the context of 'background sync jobs' differentiates it from other distillery tools. The lack of a direct contrast with distillery_status is a minor gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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)
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | ||
| author | No | ||
| status | No | ||
| content | No | ||
| project | No | ||
| entry_id | Yes | ||
| metadata | No | ||
| entry_type | No | ||
| expires_at | No | ||
| session_id | No | ||
| verification | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It clearly describes success and error return shapes, including error codes like NOT_FOUND and INVALID_PARAMS. It also implies partial-update semantics by saying 'one or more fields'. However, it does not explicitly state that non-provided fields remain unchanged, and it does not detail permission or validation behavior beyond error codes. Still, it gives substantial behavioral context for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (USE WHEN, PARAMS, RETURNS, RELATED). It front-loads the core purpose and usage, then enumerates all parameters in a compact list, followed by return formats and related tools. Every sentence contributes valuable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 11 parameters, no output schema, and no annotations, the description covers all essential information: parameter names and valid values, return formats, error codes, the requirement of at least one updatable field, and relationships to sibling tools. An agent has everything needed to call the tool correctly without further research.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must fully explain each parameter. It does so by listing every parameter with its type, purpose, and valid enum values (e.g., for entry_type, status, verification). This adds meaningful semantics that the schema alone cannot convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Update') and a clear resource ('existing knowledge entry'), and it explicitly distinguishes itself from sibling tools like distillery_correct (for superseding) and distillery_get (for reading). This removes ambiguity about when this tool applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'USE WHEN' section explicitly tells the agent when to use the tool (modifying fields) and even specifies a precondition (at least one updatable field must be provided). The RELATED section names the alternative tool (distillery_correct) and the condition that selects it, leaving no ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.thresholdsvalues. Mapping with optional float keysalertand/ordigestin [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) sincetrust_weightonly 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)
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | ||
| mode | No | ||
| force | No | ||
| label | No | ||
| probe | No | ||
| purge | No | ||
| action | Yes | ||
| thresholds | No | ||
| source_type | No | ||
| sync_history | No | ||
| trust_weight | No | ||
| poll_interval_minutes | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden and does so thoroughly. It discloses return payloads for success (list/add/remove) and error codes with structure, explains async behavior (sync_history returns immediately with job_id), soft-delete semantics (purge archives entries), probe behavior (HEAD with GET fallback, INVALID_PARAMS on failure), and even the thresholds constraint (digest <= alert). No contradictions exist.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long due to the 12 parameters and rich behavioral detail, but it is well-organized with clear sections (USE WHEN, PARAMS, RETURNS, RELATED). Every sentence earns its place, though a few lines (e.g., thresholds rationale) could be tighter without losing value. Still, it remains efficient relative to the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 12 params and no output schema, the description covers everything an agent needs: full return shapes for all actions, error handling, per-parameter constraints, async job linkage, and cross-references to related tools. No information is missing for correct invocation, making it complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero property descriptions, so the description must compensate entirely. It does: every parameter (action, url, source_type, label, poll_interval_minutes, trust_weight, thresholds, sync_history, purge, probe, force, mode) gets a meaning, valid values, defaults, and often context (e.g., why use thresholds for noisy aggregators). This is far beyond a baseline, fully bridging the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Manage monitored feed sources' and immediately narrows scope with 'USE WHEN: listing, adding, or removing RSS/GitHub feed sources'. It distinguishes itself from siblings by mentioning distillery_configure (thresholds) and distillery_store_batch (bulk ingestion) in RELATED, making the tool's unique role unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'USE WHEN' section defines the exact conditions for invoking this tool. It also provides exclusions and alternatives: distillery_configure for threshold adjustment, distillery_store_batch for bulk ingestion, and distillery_sync_status for checking background sync progress. The criterion for choosing this tool over siblings is clear.
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. Dates show when Glama detected each change.
17 tool updates
v0.7.0- First observed
distillery_classify - First observed
distillery_configure - First observed
distillery_correct - First observed
distillery_find_similar - First observed
distillery_get - First observed
distillery_gh_sync - First observed
distillery_ingest_doc - First observed
distillery_list - First observed
distillery_relations - First observed
distillery_resolve_review - First observed
distillery_search - First observed
distillery_status - First observed
distillery_store - First observed
distillery_store_batch - First observed
distillery_sync_status - First observed
distillery_update - First observed
distillery_watch
TDQS
Each tool has a clearly distinct purpose: store vs store_batch vs ingest_doc handle different ingestion paths, get/update/correct handle modification, list/search/find_similar handle retrieval with different modes, and watch/gh_sync/relations cover external sources and graph operations. The descriptions explicitly call out when to use each over related tools.
All tools share the 'distillery_' prefix and generally follow a verb-first pattern (store, get, update, list, search, watch, configure, status). Mixed single verbs and compound verb_noun forms (store_batch, ingest_doc, find_similar, resolve_review, gh_sync) are consistent in style; 'relations' is a noun-based command but remains clear. No camelCase or chaotic mixing.
17 tools is slightly above the typical 3-15 range but fully justified given the server's broad scope: entry lifecycle, semantic search, duplicate detection, relation graph management, feed monitoring, GitHub sync, and configuration. Each tool addresses a distinct aspect of the domain without redundancy.
The surface covers create (store, ingest), read (get, list, search), update, and archival (via correct and resolve_review's archive action), plus relation management and feed/sync operations. The only notable gap is the lack of a direct hard-delete tool for entries; archiving effectively serves as a soft delete, but a permanent removal option is missing.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Intelligent context infrastructure for AI teams: knowledge graph, sessions, tasks, documents.
Your company's brain for AI agents. Cited, permission-aware knowledge across every system.
Persistent knowledge graph for AI-augmented teams. Store decisions, findings, and standing rules across agent sessions with semantic search and typed connections. Includes cross-session memory, audit trail, workspace isolation, and secret detection. Built for teams running agents that need to remember. Free until launch with team tier as default, anon trial available.
- KumbukaOAuthai.kumbuka
Governed, auditable knowledge your team curates for its AI assistants, self-hostable
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI systems to remember interactions, understand document context through semantic search, and intelligently route requests with persistent memory and quality-scored content synthesis.-
- AlicenseNot gradedqualityDmaintenanceEnables semantic search and retrieval of personal and team knowledge from connected sources like Slack, Gmail, Google Drive, and Dropbox, with the ability to save new information for future recall.Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables semantic search and retrieval of information from personal and team knowledge repositories including Slack, Gmail, Dropbox, Google Drive, and uploaded files. Allows storing new information for future recall through AI-powered search.Apache 2.0
- AlicenseAqualityDmaintenanceEnables AI assistants to search, browse, and save to a semantic knowledge graph with vector search and hierarchical organization.51MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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