Skip to main content
Glama

Server Details

Citation-anchored Eurorack module reference: specs, compatibility, and patch techniques.

Status
Healthy
Last Tested
Transport
Streamable HTTP
URL

Glama MCP Gateway

Connect through Glama MCP Gateway for full control over tool access and complete visibility into every call.

MCP client
Glama
MCP server

Full call logging

Every tool call is logged with complete inputs and outputs, so you can debug issues and audit what your agents are doing.

Tool access control

Enable or disable individual tools per connector, so you decide what your agents can and cannot do.

Managed credentials

Glama handles OAuth flows, token storage, and automatic rotation, so credentials never expire on your clients.

Usage analytics

See which tools your agents call, how often, and when, so you can understand usage patterns and catch anomalies.

100% free. Your data is private.
Tool DescriptionsA

Average 4.9/5 across 17 of 17 tools scored.

Server CoherenceA
Disambiguation4/5

Each tool targets a distinct resource/action: get_module(s) for specs, search_modules for filtered queries, resolve_modules for name mapping, find_compatible_with for per-module relations, reachable_pairings/techniques for rack-level analysis. Minor overlap between get_module/get_modules and the relationship tools (find_compatible_with vs reachable_pairings) could cause misselection, but descriptions clarify scope.

Naming Consistency3/5

Mostly verb_noun snake_case (get_, search_, find_, resolve_, visualize_, report_, lookup_), but three tools break the pattern: rack_redundancy, reachable_pairings, reachable_techniques use noun/adjective phrases without a verb. The get_* cluster is consistent but the overall set mixes conventions.

Tool Count4/5

17 tools is slightly above the ideal 3-15 range but justified by the server's broad scope: module specs, search, manuals, relationships, rack analysis, visualization, and feedback. Each tool has a clear role; the count is reasonable for the domain's complexity.

Completeness5/5

The surface covers the full read-only Eurorack knowledge workflow: module lookup (get_module, search_modules, resolve_modules), manual prose (get_manual_chunk, search_manual), concepts (lookup_concept), techniques (search_techniques, find_role_realizations), compatibility (find_compatible_with, reachable_pairings), rack analysis (reachable_techniques, rack_redundancy), visualization, and provenance (get_source). report_gap even enables self-improvement. No obvious missing operations.

Available Tools

17 tools
draw_patch_diagramPatch DiagramA
Read-onlyIdempotent
Inspect

Patch diagram tool. Use when the user describes routing across multiple Eurorack corpus modules. Renders modules as boxes laid out by wire topology (matrix-shaped patches anchor on a hub; otherwise modules step left-to-right by signal-flow rank), jacks as colored ports keyed to signal type, wires as bezier curves. Inline SVG on claude.ai surfaces (web, Desktop chat, mobile); JSON elsewhere. (When to offer a diagram unprompted: SKILL.md §4.)

Trigger phrases: "show me the patch", "draw what I just described", "remind me what's connected to what", "explain the routing", or any time you'd otherwise hand-draw a patch in SVG/text — use this instead of drawing.

Strict gate — call only when ALL of:

  1. At least 3 named corpus modules.

  2. Explicit wire connections between them (user-stated or derived from a coherent description).

  3. The patch is concrete — user is following a tutorial, describing their own rack, or referencing back what's connected to what.

Do NOT call for: a single module, a question about one module's jacks, "what should I patch X to?" (that's a recommendation, not a graph), or hypothetical patches with unnamed placeholders ("connect a VCO to a filter").

Jack names. Corpus jack names are descriptive ("V/Oct CV input", "TRIG input", "Strumming trigger input"), not panel-text shorthand ("V/OCT", "TRIG"). The resolver accepts panel-text as a fallback when it unambiguously substring-matches one jack of the right direction (e.g. "TRIG" → "TRIG input"); successful resolutions surface as panel_text_resolved warnings so you can confirm. Ambiguous panel text ("OUT" on a multi-output module) errors with the candidate list. To skip the fallback entirely, call get_modules to discover the exact corpus names up front (one round trip for the whole batch).

Multi-channel modules require a CH prefix. Modules with per-channel jacks (Quadrax, Maths, Tangrams, Stages, Optomix, QMMG, DXG, Pamela's New Workout, Cold Mac, etc.) enumerate each channel separately — e.g. CH1 TRIG, CH2 TRIG, CH3 TRIG, CH4 TRIG on Quadrax. Bare names like "TRIG" on these modules will resolve as ambiguous; always pick a specific channel. When the patch doesn't specify which channel, default to CH1.

Role per use, not per identity. A module that's a modulator in one patch can be a voice in another (Maths slow-cycle vs audio-rate cycle). Pick the role for THIS patch. The enum is intentionally coarse — four buckets, not a taxonomy — so map the edge cases:

  • clock — anything emitting timing: clocks, but also trigger/gate sequencers and drum sequencers (a sequencer is a clock that emits a pattern).

  • modulator — CV/envelope/LFO sources shaping another module (envelopes, LFOs, random, function generators, S&H).

  • voice — anything generating the sound being processed: oscillators, drum voices, noise, sample players, physical-modeling/granular sources.

  • processor — anything acting on an incoming signal: filters, VCAs, effects (delay/reverb), waveshapers, granular/spectral sound-processors, and all utilities (mixers, attenuators, mults, switches). When a module both makes and processes sound, bucket by its job in THIS patch — a granular module sculpting an external input is a processor; running free as a source it's a voice. Role is currently informational — the renderer lays out by wire topology, not by role bucket — but it's still a required field, so declare it accurately for future renderer use and so the spec reads correctly.

notes[] is patch-level prose displayed below the diagram — settings, signal-flow narration ("PNW OUT1 firing 1/16 gates", "Channel 1 cycle mode, long rise").

Errors (descriptive — they point at fixes):

  • "Module not found: "

  • "Unknown jack "" on . Available <inputs|outputs>: ..." — pick from the list, or call get_modules

  • "Ambiguous jack "" on : matches ..." — name a specific jack from the candidates

  • "Patch must have at least 3 modules"

  • "Wire source ... is not an output" / "Wire destination ... is not an input"

  • "Wire to/from unknown module ref: "

  • "Duplicate ref: "

Cross-type wires (e.g. audio into a CV input) render normally with a warning panel below the diagram — Eurorack tolerates type mismatches by design, but warnings catch unintended ones.

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNoOptional patch-level prose hints displayed below the graph.
wiresYes
modulesYes
Behavior5/5

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

Beyond the annotations (read-only, idempotent, non-destructive), the description discloses layout algorithms (matrix vs signal-flow rank), rendering specifics (colored ports, bezier curves), output medium differences (inline SVG vs JSON), error behaviors, and cross-type wire warnings. This richly supplements the structured annotation hints.

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

Conciseness4/5

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

The description is long but well-structured with clear sections (Trigger phrases, Strict gate, Jack names, Role, Errors). Every paragraph covers a distinct aspect of tool behavior, so nothing is redundant. It earns its length for a complex tool, though it is at the upper limit of what could be considered concise.

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

Completeness5/5

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

For a complex diagram tool with no output schema, the description covers return formats (SVG vs JSON), error lists, input validation rules, role semantics, and usage constraints. It addresses all major behavioral aspects an agent would need to invoke and interpret results correctly.

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

Parameters5/5

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

Despite moderate schema coverage (33%), the description significantly enriches parameter meaning: it explains jack naming conventions (corpus vs panel text), multi-channel CH<N> prefixes, role bucket definitions with edge-case mapping, endpoint string format, and the content/purpose of notes. This goes far beyond the schema descriptions.

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

Purpose5/5

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

The description opens with a specific verb+resource pairing ('Patch diagram tool... Renders modules as boxes laid out by wire topology') and immediately distinguishes from siblings by stating when to use it ('Use when the user describes routing across multiple Eurorack corpus modules') and when not to ('Do NOT call for: a single module...'). This clearly differentiates it from sibling tools like visualize_module.

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

Usage Guidelines5/5

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

Provides an extensive, explicit usage policy: a strict gate with three numbered conditions, concrete do-not-call scenarios, and a direct alternative ('use this instead of drawing'). It also names a sibling tool for discovery (get_modules) when jack names are unclear, offering clear decision guidance.

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

find_compatible_withFind Compatible ModulesA
Read-onlyIdempotent
Inspect

Return modules that have a typed compatibility relationship with the given module. Both edge directions are returned and tagged via the per-match direction field — so a single call answers both "what is X a R for?" and "what is a R for X?".

relationship is OPTIONAL. Omit it to get EVERY edge touching the module across all relationship kinds — the bare "what pairs with / relates to X?" question — with each match self-describing via its own relationship. Pass a relationship to restrict to that one kind. Prefer the relationship-less call when you don't already know which kind exists; reach for the typed form only when the question names a specific role ("what clocks X?").

Use this for two question shapes:

  1. Patch-time compatibility — "what could I use as a clock source for X?" (returns matches with direction='inbound'), or "what does X clock?" (direction='outbound').

  2. Catalog comparison — "what's an alternative to X?" (symmetric), "what does X replace?" (outbound) / "what replaces X?" (inbound), "is there an expander for X?" (inbound).

The vocabulary describes the edge as stored (from = role-bearer, to = target):

Patch-time:

  • clock-source-for — A clocks B

  • cv-source-for — A produces CV that B consumes

  • modulator-for — A is a modulator suitable for B (LFO, S&H, random)

  • audio-source-for — A is an audio source for B (typically a VCO into a VCF)

  • quantizer-for — A quantizes for B

  • trigger-source-for — A produces triggers that B consumes

  • envelope-target-for — A is something B's envelope output is designed to drive Catalog:

  • replaces — A is the newer successor to B (Morphagene replaces Phonogene)

  • alternative-to — symmetric: A and B occupy similar design space with different character

  • expander-for — A is an expander module for the host module B

Direction tag on each match:

  • outbound: queried module is the FROM side (role-bearer). Match is what the queried module does as R.

  • inbound: queried module is the TO side. Match is the R-for the queried module.

  • symmetric: only for alternative-to.

Args:

  • module_id (string, required): "/"

  • relationship (string, optional): one of the values above. Omit for all edges.

  • limit (number): default 50, max 200

Returns: { "module": { id, name }, "relationship": | null, // null when none was passed (all-edges query) "matches": [{ id, name, manufacturer, notes, source_id, direction, relationship }] }

If the module is unknown, returns an error. If no relationships have been recorded in either direction, returns matches=[]. The notes field describes the edge in the canonical A→B direction; combined with direction the caller can read it correctly either way.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
module_idYes
relationshipNo
Behavior5/5

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

Beyond the readOnly annotation, the description discloses many behaviors: both edge directions are returned and tagged, unknown modules produce an error, empty matches array when no edges exist, the meaning of the notes field relative to direction, and default/max limits. It also clarifies that omitting relationship returns all edge types, each self-describing.

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

Conciseness5/5

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

The description is long but highly structured with clear sections for usage, vocabulary, direction semantics, arguments, and return shape. Every sentence carries information; there is no repetition or fluff. It is front-loaded with the core purpose and then details.

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

Completeness5/5

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

With no output schema, the description provides an explicit return object example, covers error and empty cases, and explains how to interpret the notes field. For a tool with ten relationship types and bidirectional semantics, the description is complete and self-contained.

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

Parameters5/5

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

Schema coverage is 0%, but the description fully compensates: it explains each enum value (e.g., clock-source-for, alternative-to), specifies the module_id format ("<manufacturer-slug>/<module-slug>"), describes the optional behavior of relationship, and documents limit's default and maximum. This is a textbook example of description adding meaning beyond the schema.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Return modules that have a typed compatibility relationship with the given module.' It immediately clarifies bidirectional results and the optional relationship filter, distinguishing it from a simple one-direction lookup.

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

Usage Guidelines4/5

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

The description gives explicit guidance for when to omit vs. pass the relationship parameter, and enumerates two concrete question shapes (patch-time compatibility, catalog comparison) with examples. However, it does not name alternative sibling tools or explicitly say 'use this instead of X', so it stops short of full alternative differentiation.

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

find_role_realizationsFind Role RealizationsA
Read-onlyIdempotent
Inspect

For a (technique_id, role_id) pair, return modules that can fill the role, ranked by affordance match.

Use this when the user has named a technique and you need to recommend modules for a specific role within it (e.g., "what should I use for the lpg role in a lowpass-gate-pluck patch?"). Optionally pass available_modules to restrict the search to the user's rack — the tool surfaces both documented realizations in the rack AND undocumented candidates whose capability tags match the role's required affordances (or, for roles that declare only optional affordances, those optional ones).

This tool exists to STOP the model from inventing module-role recipes from training-data priors. The output is editorially grounded: documented realizations carry corpus-curated notes; undocumented candidates are explicitly tagged so the agent can weigh confidence.

Args:

  • technique_id (required): kebab-case technique id (see list_techniques).

  • role_id (required): kebab-case role id (e.g., "lpg", "voice", "env", "clock"). See list_techniques → role_definitions for the roles a technique declares.

  • available_modules (optional): array of "/" ids — typically the user's rack. When supplied, restricts results AND surfaces undocumented candidates whose module_capabilities match the role's required affordances — or, for an optional-only role (no required affordances), its optional affordances.

Returns: { "technique_id": "low-pass-gate-pluck", "role_id": "lpg", "role": { "label": "Low-Pass Gate", "description": "Vactrol-style..." }, "role_definition_description": "The vactrol-based or vactrol-emulating element...", "required_affordances": ["lowpass-gate"], "optional_affordances": [], "realizations": [ { "module_id": "make-noise/optomix", "documented": true, "affordances_provided": ["lowpass-gate"], "required_matched": ["lowpass-gate"], "optional_matched": [], "missing_required": [], "fit_score": { "required": 1, "optional": 0 }, "notes": "Two-channel vactrol-based LPG..." }, ... ], "_meta": { "available_modules_filter": null, "documented_count": 19, "candidate_count": 19 } }

Ranking: by required_matched.length desc, then optional_matched.length desc, then module_id asc. A candidate with missing_required.length > 0 is NOT a valid realization but is still returned (sorted last) so the agent can explain why a rack module isn't a fit.

satisfied_via: a rack module can fill a role through a capability-satisfaction edge rather than a literal affordance tag — e.g. a module with an internal low-pass gate (capability internal-lpg) fills the lpg affordance and self-plucks, so it realizes a low-pass-gate-pluck on its own. Such matches carry a satisfied_via:[{ affordance, via, kind }] entry (kind="self-contained" means it fills the role internally, not as an externally-routable instance you patch into) so you can distinguish "this module self-plucks" from "this is an external LPG." Present only on undocumented rack candidates and only for non-literal matches.

Errors:

  • "Technique not found: "

  • "Role not defined for technique: in "

  • Empty realizations[] with a feedback_hint when filters produce no matches.

ParametersJSON Schema
NameRequiredDescriptionDefault
role_idYes
technique_idYes
available_modulesNo
Behavior5/5

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

Beyond the annotations (readOnly, idempotent), the description discloses the ranking order, the behavior of returning invalid candidates with missing_required, the satisfied_via mechanism for non-literal matches, and exact error messages. This gives the agent a detailed behavioral contract.

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

Conciseness5/5

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

The description is long yet tightly organized with a summary line, usage triggers, args, return shape, ranking, satisfied_via, and errors. No sentence is redundant; each adds distinct operational detail.

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

Completeness5/5

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

With no output schema, the description supplies a complete return object example, defines the ranking algorithm, explains edge cases (missing_required, satisfied_via), lists error strings, and describes behavior when filters produce no matches. It fully equips the agent to invoke and interpret results.

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

Parameters5/5

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

Schema description coverage is 0%, but the description compensates fully: it defines technique_id as kebab-case with a pointer to list_techniques, role_id with examples and pointer to role_definitions, and available_modules with format restrictions and effect on results. This is exemplary parameter documentation.

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

Purpose5/5

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

The opening sentence is a precise spec: 'For a (technique_id, role_id) pair, return modules that can fill the role, ranked by affordance match.' It names the specific resource (role realizations) and action (return), and includes an example query, distinguishing it from siblings like find_compatible_with by focusing on role filling within a technique.

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

Usage Guidelines4/5

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

The description states 'Use this when the user has named a technique and you need to recommend modules for a specific role within it,' giving a clear trigger. It also explains how to optionally restrict to the user's rack. It doesn't explicitly name alternatives, but the rationale 'This tool exists to STOP the model from inventing module-role recipes' implies when to favor it over priors.

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

get_manual_chunkFetch Manual ChunkA
Read-onlyIdempotent
Inspect

Read one manual chunk by id to ground your answer in the manufacturer's documentation — the drill-in partner to get_module's manual_outline. Use it when a claim (voltage range, behavior, calibration step) benefits from the source's own account.

Read the chunk, then answer in your own words and point the user to the source (audit_url) to verify. Paraphrase the substance; do not paste the chunk back as your reply. Quote verbatim only when the exact wording is load-bearing for a specific contested detail, and then only a short phrase. Citation style is SKILL.md §8 (cite-and-point, don't reproduce).

text is capped (~800 chars): enough to ground an answer, not to reproduce the manual. If truncated:true, a " […]" marks the cut and the full passage is at audit_url — send the user there for the rest rather than stitching chunks together to rebuild it.

When to call:

  • You have a chunk_id from get_module's manual_outline that looks relevant to the question.

  • You're writing an answer with specific technical claims and want the source's account to ground (and, if needed, briefly cite) it.

  • The user asked a prose-shaped question ("what does the manual say about X?") — read the chunk, then explain it in your own words with a link to verify.

Prefer get_manual_chunk over search_manual when:

  • You already have the chunk_id from get_module's manual_outline.

  • You want exactly one chunk, not a ranked list.

Returns: { "chunk_id": number, "source_id": number, "source_type": string, // "manual" | "product_page" | "firmware_notes" "source_title": string | null, "heading_path": string | null, // e.g. "Calibration > Tuning Procedure" "text": string, // chunk text, capped ~800 chars; paraphrase, don't paste "truncated": boolean, // true if text was trimmed; full passage at audit_url "audit_url": string // human-readable audit page for the source }

Errors:

  • "Manual chunk not found: " if the chunk_id doesn't exist.

ParametersJSON Schema
NameRequiredDescriptionDefault
chunk_idYesChunk id from manual_outline[].chunk_id or a search_manual result.
Behavior5/5

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

Beyond the read-only/idempotent annotations, the description discloses the 800-char cap, truncation flag with audit_url fallback, and instructs to paraphrase and cite rather than paste. It also documents the error message. This adds substantial behavioral context without contradicting annotations.

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

Conciseness5/5

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

Structured with sections (When to call, Prefer, Returns, Errors), bold key rules, and no filler. Each sentence carries intent; the length is justified by the need to prevent manual reproduction.

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

Completeness5/5

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

Covers returns (inline JSON shape), error condition, truncation behavior, and citation policy. With no output schema, the description compensates fully.

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

Parameters4/5

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

Single param chunk_id is described in schema with source info; the description reinforces its provenance from manual_outline[].chunk_id and when to use it. It adds purpose and context beyond the schema's one-line description, though the schema already covers the source.

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

Purpose5/5

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

The description opens with a specific verb+resource: 'Read one manual chunk by id' and frames it as the 'drill-in partner to get_module's manual_outline'. It clearly distinguishes this tool from search_manual and get_module.

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

Usage Guidelines5/5

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

Explicit 'When to call' list and a 'Prefer get_manual_chunk over search_manual when' section, naming alternatives and exact conditions. This is textbook usage guidance.

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

get_moduleLook up moduleA
Read-onlyIdempotent
Inspect

Return the full citation-anchored specification for one Eurorack module by id.

Use this when the user names a specific module and you want its specs (HP, power, jacks, parameters), capabilities (envelope, quantizer, logic, etc.), or firmware history.

The typed prose fields (jack/parameter/mode descriptions) are paraphrased summaries; manual_outline → get_manual_chunk give the verbatim manual prose to quote against. How much to quote and overall answer shape live in SKILL.md (the "Answer shape" section + §8 citation) — this description is the data contract.

Provenance fields

Every typed row in the response — capabilities[], jacks[], parameters[], modes[], firmware_versions[], plus nested zones/assignments/tracking — carries a source_id pointing at the source the claim was extracted from. Cross-reference list_references(module_id=...) for the source title and canonical_url.

The typed prose fields — jacks[].description, parameters[].behavior, modes[].description, capabilities[].notes, firmware_versions[].notes — are extractor-synthesized summaries grounded in the manual, NOT verbatim quotes. Treat them as the corpus's stated claim about the field; they're authoritative for what the field does, but they are not direct manual text. For verbatim quotation in your answer, always pull the actual prose via get_manual_chunk(chunk_id) — the description fields are the typed claim, not the source quote.

manual_outline[] bundles a lightweight outline of the module's manual prose — one entry per chunk with heading, source, and a ~140-char preview snippet. Always scan it before answering — for prose-shaped questions to find the relevant chunk, for spec-shaped questions to find a chunk to quote alongside the typed data. When a snippet looks relevant, call get_manual_chunk(chunk_id) to pull the full text. manual_outline_total is set ONLY when the outline was truncated for a verbose module; its absence means the returned outline is complete. When set, use search_manual to reach chunks beyond the cap.

Module IDs are slug-shaped: "/". For example:

  • alm-busy-circuits/pamelas-new-workout

  • make-noise/maths

Optional args — trim the payload, target the outline

By default this returns the full spec. For narrow questions you can shrink it:

  • view: "concise" returns just the id-card fields (name, manufacturer, hp, description, capabilities, production_status, replaced_by) and drops the heavy arrays — use it for triage ("which of these is the quantizer?") or when you only need to confirm what a module is. "full" (default) returns everything. Ignored when fields is set.

  • fields: array of top-level keys to include (e.g. ["jacks","parameters"]). id and _meta are always returned. Use this for a quick jacks-only or specs-only read instead of paying for character[]/common_problems[]/role_fitness[]/the full manual_outline. Takes precedence over view.

  • heading_filter: case-insensitive substring on manual_outline heading_path — e.g. "calibration" returns only outline chunks under a Calibration heading, so you skip scanning a long outline.

  • outline_offset / outline_limit: page through manual_outline (default 100 per page, hard max 250). Combined with manual_outline_total this lets you reach chunks past the cap without falling back to search_manual.

Returns:

  • id, name, manufacturer { id, name }

  • hp, depth_mm

  • power: { plus_12, minus_12, plus_5 } (mA)

  • description (manufacturer's prose summary, citation-backed)

  • capabilities[]: functional tags with per-module realization notes (source_id per row)

  • jacks[]: inputs and outputs with voltage range, signal_type, prose description (a paraphrased summary, NOT a verbatim quote — to quote the manual, pull the source prose via get_manual_chunk), plus assignments[] for assignable jacks (destination menu — empty for fixed-function jacks). When mirrors_parameter is set, the jack mirrors that knob's current assignment (e.g. Pizza CTRL CV mirrors the CTRL knob). normalled_from { id, name } is set when this input has a hardware normal — i.e. when unpatched, it receives the signal at the named source jack (e.g. Multigrain GATE normalled from NEXT). null when no normal exists. V/Oct inputs may carry an optional tracking { tracking_range_octaves, tracking_quality, temperature_compensated } object — present only on jacks that have been audited for V/Oct metadata. Fields inside may be null when the source is silent on that aspect. Optional _field_absent: { : { source_id, note } } records fields that were audited and found to be source-silent — read it before hedging: an entry under voltage_min means "the manual doesn't state this" (so a confident "the manual doesn't specify" answer is appropriate); the field being null without an entry means "not yet extracted" (hedge differently — recommend the user check the manual).

  • parameters[]: knobs, switches, menu settings with range, unit, behavior (paraphrased summary, NOT a verbatim quote — same as jacks[].description; quote get_manual_chunk for source text), plus zones[] (labeled regions along the control's travel — e.g. Swells FLOW "Sine" / "Random" halves, optionally mode-scoped) and assignments[] (destination menu for assignable knobs/menu-settings) — both empty arrays for plain controls. Modal-module params may also carry per_mode_notes (rebinding text keyed by mode_id slug, present only when the param rebinds per mode — e.g. Plaits MORPH, Swells EBB/FLOW). Same _field_absent convention as jacks[] — when default_value is null and _field_absent.default_value is present, the manual doesn't state a default.

  • modes[]: mode list for modal modules (Plaits, Swells, MFX) — { id, label, description, behavior_model_id, scope? }. Empty for modeless modules. Mode ids cross-reference parameters[].per_mode_notes keys and parameters[].zones[].mode_id. Optional scope is set when modes are selectable independently per member rather than module-wide — 'per-segment' (Stages hold/ramp/step), 'per-envelope' (Tangrams cycle/single), 'per-output' (PNW), 'per-channel'. Member count is carried by the corresponding enumerated parameters/jacks (e.g. Stages' six Type Button N parameters), not duplicated on the mode rows.

  • hidden_functions[]: functions reached via a trigger other than a single labeled control — { id, trigger_type, affected_control, label, description }. trigger_type is a controlled vocabulary ('long-press' | 'hold' | 'combo' | 'double-press' | 'power-on-hold' | 'held-turn') so recall/menu-diving load is countable; affected_control names the panel control the trigger acts on (null for module-global functions like hold-on-power-up calibration). Empty for modules whose controls are all directly labeled. Read this for "how do I get to X?" / menu-diving questions and when assessing how much hidden state a module carries — the same info used to live buried in parameters[].behavior prose.

  • panel_sections[]: manufacturer-named regions of the front panel (e.g. Multigrain "Dedicated Sound CV inputs" grouping GATE/NEXT/SELECT, "Morph section" grouping the MORPH knob + MORPH CV jack). Each entry has { label, description, members: [{ kind, id, name }] } where members cross-reference jacks[] / parameters[] by id. Empty for modules without manufacturer-named groupings.

  • character[]: curated subjective-character claims (vocal/aggressive/clean/gritty/lush/...) with source citations. Read this when the user asks about sound or feel rather than specs — filter choice for "carve rhythmic transients" or "warm pad voice" hinges on character, which the typed-fields surface can't carry. Each entry: { tag, note (prose elaboration), source_id (when archived in sources), citation_url + citation_quote (when sourced from a review/forum/video we don't archive per-module) }. Empty for modules that haven't been character-audited yet — distinguish "empty array, audit pending" from "no character worth noting." Tags are open-vocab; common starter set: vocal, aggressive, clean, gritty, acidic, lush, dark, bright, smooth, woody, formant, screaming.

  • common_problems[]: curated first-aid lore — repeatable failure modes that owners hit but the manual doesn't cover (calibration drift, hum, screen offset, firmware-flash brick recovery, bus-normalling caveats). Read this when the user asks "anything I should watch out for with X?" or describes a symptom matching a known module quirk. Each entry: { problem_summary (one sentence), cause (prose), fix_or_workaround (prose), confidence ('confirmed' | 'likely' | 'anecdotal'), source_id, citation_url, citation_quote }. Empty array means "no curated problems on file" — agents should NOT extrapolate to "no known problems"; the audit is opt-in per module and most modules have not been touched yet.

  • role_fitness[]: role-realization rollup — canonical techniques whose role_realizations this module fills, with the affordances it brings to that role. Use this when the user wants to know "what roles can this module play?" — e.g. Optomix → lpg role in low-pass-gate-pluck, affordances_provided=[lowpass-gate]. Each entry: { technique_id, technique_label, role_id, role_label, affordances_provided, notes }. Pair with list_techniques(filter={ module_id }) for the full role_definition + sibling realizations, or find_role_realizations(technique_id, role_id) to substitute other modules into the same role.

  • firmware_versions[]: version + release_date (may be partial: YYYY | YYYY-MM | YYYY-MM-DD) + notes (per-version changelog prose when the source provides one — e.g. "Added Smooth Random waveform type. Added Logic parameter (AND/OR/XOR)."). Use this to answer "what changed in v2?" without web search.

  • reference_url: canonical URL of the primary manual on the manufacturer site

  • audit_url: human-readable audit page on the audit site (per-claim citations)

  • production_status: "current" or "discontinued" — flag for recommendation safety

  • replaced_by: { id, name } when the module is discontinued and a successor exists; null otherwise

  • manual_outline[]: lightweight outline of the module's manual chunks — { chunk_id, source_id, source_type, source_title, heading_path, snippet, text_length }. Ordered by (source_id, chunk_index). When the snippet looks worth reading in full, call get_manual_chunk(chunk_id). Empty when no manual prose has been ingested yet for this module.

  • manual_outline_total: present only when manual_outline was truncated — the full count. Hit search_manual to reach the rest.

  • _meta: source_count, last_verified

Errors:

  • "Module not found: " if no module with that id exists.

If the user asks something the manual does not cover (e.g. subjective "is this good for percussion?"), say so explicitly — never confabulate from spec data.

ParametersJSON Schema
NameRequiredDescriptionDefault
viewNoOptional: "concise" returns the id-card subset (name, manufacturer, hp, description, capabilities, production_status, replaced_by) and drops the heavy arrays — good for triage or multi-module sweeps. "full" (default) returns the complete spec. Ignored when `fields` is set.
fieldsNoOptional: top-level keys to include (e.g. ["jacks","parameters"]) when you only need a slice and want to skip the full payload. Omit for everything. id and _meta are always returned. Takes precedence over `view`. Selectable: manufacturer, name, hp, depth_mm, power, description, capabilities, jacks, parameters, modes, hidden_functions, _field_absent, panel_sections, character, common_problems, role_fitness, firmware_versions, reference_url, audit_url, production_status, replaced_by, manual_outline, manual_outline_total.
module_idYesStable module id, "<manufacturer-id>/<module-slug>" (e.g. "alm-busy-circuits/pamelas-new-workout").
outline_limitNoOptional: max manual_outline entries to return this call (default 100, hard max 250).
heading_filterNoOptional: case-insensitive substring matched against manual_outline heading_path. Narrows the outline to chunks under a heading (e.g. "calibration") so you skip scanning a long outline.
outline_offsetNoOptional: zero-based offset into the (optionally heading-filtered) manual_outline. Page past the default cap instead of falling back to search_manual.
Behavior5/5

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

Annotations already declare readOnlyHint=true and idempotentHint=true, and the description adds substantial behavioral context: typed prose fields are paraphrased summaries, not verbatim quotes; manual_outline_total is only set when truncated; _field_absent distinguishes 'source-silent' from 'not yet extracted'; field precedence (fields over view) is disclosed; and error handling ('Module not found: <id>') is documented. It also warns agents never to confabulate subjective claims beyond spec data — a valuable behavioral guardrail.

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

Conciseness4/5

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

The description is long and highly detailed, but it is well-structured with clear headings (## Provenance fields, ## Optional args, Returns) and each section earns its place given the tool's rich return fields and nuanced behaviors. Some redundancy exists (e.g., the paraphrase warning is repeated for jacks and parameters), and the 'Returns' enumerate every field with lengthy explanations, which could be tighter. Still, it remains organized and front-loaded with the core purpose and usage guidance.

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

Completeness5/5

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

Despite lacking an output schema, the description fully documents every return field, their nested structures, and special conventions (_field_absent, tracking, normalled_from, per_mode_notes). It covers errors, optional argument interactions, and when to fall back to sibling tools. It is complete for a tool of this complexity — all potential agent questions about data provenance, truncation, and citation are addressed.

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

Parameters5/5

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

Schema description coverage is 100%, but the description goes far beyond the schema. It explains module_id format with concrete examples ('alm-busy-circuits/pamelas-new-workout'), describes when view='concise' is appropriate vs 'full', clarifies that fields takes precedence over view, and explains heading_filter matching ('case-insensitive substring... e.g. "calibration"') and pagination semantics for outline_offset/limit. This adds deep semantic value that the schema's terse descriptions do not provide.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Return the full citation-anchored specification for one Eurorack module by id.' It clearly distinguishes from siblings by explicitly directing agents to get_manual_chunk for verbatim manual prose and search_manual for outline pagination, and by stating 'Use this when the user names a specific module' — a clear scope that differentiates it from list/search tools like get_modules and search_modules.

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: 'Use this when the user names a specific module and you want its specs...' It also provides alternatives for related needs: 'manual_outline → get_manual_chunk give the verbatim manual prose to quote against' and 'use search_manual to reach chunks beyond the cap' when manual_outline_total is set. It even specifies when to use optional args (e.g., 'Use this for triage' for view='concise'), making usage context crystal clear.

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

get_modulesLook up modulesA
Read-onlyIdempotent
Inspect

Batched get_module — returns { modules: [...], errors: [...] } with full citation-anchored specs for up to 25 modules in one call.

Prefer this over multiple get_module calls when you have a known list of modules to fetch (e.g. preparing to call draw_patch_diagram across N modules, comparing several candidates side-by-side). One round trip vs. N.

Args:

  • module_ids: array of "/" strings. Up to 25 per call; duplicates are deduplicated.

Optional args (apply to every module in the batch, same semantics as get_module):

  • view: "concise" returns the id-card subset (name, manufacturer, hp, description, capabilities, production_status, replaced_by) for every module and drops the heavy arrays — the cheapest way to triage a list ("which of these are LFOs?"). "full" (default) returns complete specs. Ignored when fields is set.

  • fields: top-level keys to include on each module (e.g. ["jacks","parameters"]). id and _meta are always returned. Use this when you only need a slice across N modules (e.g. just jacks for draw_patch_diagram) instead of N full specs.

  • heading_filter / outline_offset / outline_limit: narrow and paginate each module's manual_outline.

Returns:

  • modules[]: GetModuleResponse for each id that resolved (same shape as get_module; narrowed when fields is set).

  • errors[]: { id, message } for each id that failed (e.g. unknown module). Other ids in the batch still resolve.

If you only need a single module, use get_module — same shape, one element. Need only jacks (e.g. for draw_patch_diagram)? Pass fields: ["jacks"] to skip the full specs.

ParametersJSON Schema
NameRequiredDescriptionDefault
viewNoOptional: "concise" returns the id-card subset for every module in the batch and drops the heavy arrays — cheapest way to triage a list. "full" (default) returns complete specs. Ignored when `fields` is set.
fieldsNoOptional: top-level keys to include on every module in the batch (e.g. ["jacks","parameters"]) when you only need a slice — keeps a multi-module fetch from returning full specs. Omit for everything. id and _meta are always returned. Takes precedence over `view`. Same selectable keys as get_module.
module_idsYes
outline_limitNoOptional: max manual_outline entries per module (default 100, hard max 250).
heading_filterNoOptional: case-insensitive substring matched against manual_outline heading_path, applied to every module in the batch.
outline_offsetNoOptional: zero-based manual_outline offset, applied to every module in the batch.
Behavior5/5

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

The description explains deduplication ('duplicates are deduplicated'), error handling ('errors[]: { id, message } for each id that failed... Other ids in the batch still resolve'), and parameter precedence ('Ignored when fields is set'). Annotations already mark read-only/idempotent, and the description enriches with batch semantics.

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

Conciseness5/5

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

Though substantial, every section serves a purpose: batched behavior, usage context, arg explanations, return shape, and alternative recommendations. The structure uses clear labels ('Args', 'Optional args', 'Returns') and avoids redundancy.

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

Completeness5/5

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

No output schema exists, but the description specifies the exact return format and edge cases (failed ids, deduplication). It also covers all 6 parameters with behavior and examples, making it fully actionable for an agent.

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

Parameters5/5

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

Schema coverage is 83%, but the description adds critical behavioral details: 'same semantics as get_module,' 'id and _meta are always returned,' and 'applies to every module in the batch.' It also gives concrete examples like 'fields: ["jacks"]' for draw_patch_diagram.

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

Purpose5/5

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

The description opens with a precise statement: 'Batched get_module — returns `{ modules: [...], errors: [...] }` with full citation-anchored specs for up to 25 modules in one call.' This clearly distinguishes it from the sibling get_module tool and other lookup tools by emphasizing batch capability and known-list fetching.

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

Usage Guidelines5/5

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

It explicitly instructs: 'Prefer this over multiple get_module calls when you have a known list of modules to fetch... One round trip vs. N.' It also names alternatives: 'If you only need a single module, use get_module — same shape, one element,' and provides guidance for using fields to optimize.

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

get_sourceGet Source MetadataA
Read-onlyIdempotent
Inspect

Return provenance metadata for one source by integer source_id.

Sources include manufacturer manuals, product pages, firmware notes, schematics, errata, and (in v2) field notes. Source ids are surfaced wherever facts cite their origin — in get_module's reference list, in the audit page citation links, and (in v2) in the claims table.

Args:

  • source_id (integer, required)

Returns metadata only — not the document content. The audit_url field links to the audit site's per-source page where the document can be viewed. The archived_url field is a path on the worker that streams the archived bytes from R2 (e.g. /sources/123/document).

Returns: { "id": number, "source_type": "manual" | "firmware_notes" | "product_page" | ..., "format": "pdf" | "html" | "text" | ..., "title": string | null, "canonical_url": string, // manufacturer-hosted URL "archived_url": string | null, // worker route to the R2-archived copy "content_hash": string | null, // sha256 of archived bytes "fetched_date": string, // when first archived "last_verified": string | null, // when canonical was last confirmed "canonical_changed_at": string | null, // null until manufacturer side changes "module_id": string | null, // owning module, if any "manufacturer_id": string | null, "audit_url": string // audit site page for this source }

The pair (canonical_changed_at, last_verified) is the staleness signal: if canonical_changed_at > last_verified, the manufacturer document changed since we last checked it. Surface that to the user when relevant.

ParametersJSON Schema
NameRequiredDescriptionDefault
source_idYes
Behavior5/5

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

Despite having readOnlyHint, idempotentHint, and destructiveHint annotations, the description adds substantial behavioral context: it clarifies that only metadata is returned, explains the meaning of audit_url and archived_url (including the worker path for streaming bytes), and highlights the staleness signal (canonical_changed_at > last_verified) with an instruction to surface it to users. This goes well beyond the annotations.

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

Conciseness5/5

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

The description is structured with clear sections: purpose, context, args, return object, and guidance. Although lengthy, it is efficient because every sentence adds value—especially the return object details, which are necessary given no output schema exists. It is front-loaded with the core purpose.

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

Completeness5/5

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

For a simple tool with one parameter and no output schema, the description is remarkably complete. It defines the return object with types and comments, explains the two URL fields, and provides actionable staleness logic. It also gives context on how source_ids are obtained, making the tool self-contained.

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

Parameters4/5

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

The input schema has no description for source_id (0% coverage), so the description carries the burden. It explains source_id is an integer and required, and elaborates on its meaning by explaining where source IDs come from. It doesn't mention constraints like minimum value (already in schema) but fully compensates for the missing schema description.

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

Purpose5/5

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

The description opens with a specific verb+resource: 'Return provenance metadata for one source by integer source_id.' It clearly distinguishes from siblings by stating it returns metadata only, not document content, and lists specific source types. It also explains where source IDs are surfaced, making the tool's role unambiguous.

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

Usage Guidelines4/5

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

The description provides clear context on when to use this tool (when you have a source_id from citations, reference lists, etc.) and what it does not do ('not the document content'). However, it does not explicitly name alternative tools for fetching content, so it stops short of explicit when/when-not guidance.

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

lookup_conceptLook Up ConceptA
Read-onlyIdempotent
Inspect

Return a canonical definition for a primitive Eurorack / synthesis concept and its relations to other concepts in the corpus.

Use this for VOCABULARY questions, not module questions — when the user is asking what a term means or how two terms relate, not which modules implement it. Typical shapes:

  • "Is four-quadrant mult the same as through-zero AM?" → lookup_concept("four-quadrant mult")

  • "What's the difference between a gate and a trigger?" → lookup_concept("gate")

  • "Modular signal level vs line level — when does it matter?" → lookup_concept("modular signal level")

  • "Are clock dividers just pulse counters?" → lookup_concept("clock divider")

  • "Are polyphonic patch cables TRRRRRS?" → lookup_concept("polyphonic cable")

Lookup is case-insensitive across three axes, tried in order: the canonical id ("through-zero-fm"), the canonical label ("Through-Zero FM (TZFM)"), and any registered alias ("tzfm", "through zero fm"). Spaces and hyphens are matched literally; the lookup does NOT normalize whitespace beyond lowercasing. If the term doesn't match anything, the response includes up to 5 substring-matched suggestions.

Args:

  • name (string, required, min length 2): the term to look up. Examples: "AM", "ring mod", "four-quadrant mult", "TZFM", "clock divider", "gate", "trigger".

Returns: { "concept": { "id": "amplitude-modulation", "label": "Amplitude Modulation (AM)", "description": "A multiplication of two signals: the carrier...", "aliases": ["am", "amplitude modulation", "amplitude mod"], "related_concepts": [ { "related_concept_id": "ring-modulation", "related_concept_label": "Ring Modulation (RM)", "relation_kind": "commonly_confused_with", "note": "AM with a unipolar modulator preserves the carrier..." }, ... ], "source_id": null, "citation_url": "https://learningmodular.com/glossary/...", "citation_quote": "Amplitude modulation is when..." } | null, "_meta": { "query": "", "matched_via": "id" | "label" | "alias" | "none", "concept_suggestions": [ { "id": "...", "label": "...", "matched_via": "alias", "matched_text": "..." } ], "feedback_hint": "...?" } }

Relation kinds:

  • "related_to" — see-also link (default; symmetric in spirit).

  • "subtype_of" — X is a specific case of Y (RM ⊂ AM, TZFM ⊂ linear FM).

  • "inverse_of" — X is the opposite of Y (clock-divider ↔ clock-multiplier).

  • "commonly_confused_with" — they're distinct, but people conflate them (gate vs trigger, AM vs RM, modular level vs line level).

When to cite: every concept carries either source_id or citation_url + citation_quote. Surface the citation when the answer affects a decision (e.g. "the corpus cites learningmodular.com — TRS cables are physically the same connector whether carrying balanced mono or unbalanced stereo; only the destination determines the role").

When the result is null and concept_suggestions are provided, present 2–3 closest matches to the user. If none look right, the corpus genuinely doesn't carry that concept — call report_gap with kind="missing_field" and tool_name="lookup_concept" naming the term and its expected definition.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
Behavior5/5

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

The description deeply discloses behavioral traits: case-insensitivity, matching order (id, label, alias), literal space/hyphen matching, no whitespace normalization, substring suggestion behavior, null handling, and relation kinds. Annotations only state readOnly and idempotent, so the description carries and enriches the behavioral disclosure.

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

Conciseness5/5

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

Long but tightly organized: purpose, usage, matching behavior, Args, Returns, relation kinds, citation guidance, null handling. Every section adds needed information, with front-loaded purpose and clear formatting. No filler or redundancy.

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

Completeness5/5

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

For a deceptively simple tool (one parameter), the description covers all necessary context: matching semantics, return shape, relation type meanings, citation expectations, and null/suggestion handling. With no output schema, this is exceptionally complete.

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

Parameters5/5

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

Schema coverage is 0% (the name parameter has only type/minLength), so the description must carry all semantic weight. It does this with an 'Args' section listing the parameter, type, required status, min length, and several concrete examples. This fully compensates for the bare schema.

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

Purpose5/5

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

The description clearly and specifically states the tool's purpose: 'Return a canonical definition for a primitive Eurorack / synthesis concept and its relations to other concepts.' It explicitly separates vocabulary questions from module questions, and the examples show concrete use cases, distinguishing it from sibling tools like get_module or search_modules.

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

Usage Guidelines5/5

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

Provides explicit usage guidance: 'Use this for VOCABULARY questions, not module questions.' It gives typical question shapes, explains when to cite, and instructs what to do when the result is null (present suggestions, then call report_gap). This is far beyond minimal guidance.

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

rack_redundancyRack Redundancy / What Can I SellA
Read-onlyIdempotent
Inspect

Call this when the user asks what they can SELL, remove, downsize, or trim — "what can I sell?", "which modules are redundant?", "what's doing double duty?", "I have too many modules, what can go?", "what's not pulling its weight?". The inverse of reachable_techniques: where that adds, this prunes.

Given the user's COMPLETE rack, it runs a leave-one-out over the same technique matcher reachable_techniques uses — for each module, does removing it cost any currently-reachable technique? Returns three buckets plus the overlap map:

  • load_bearing: removing the module drops ≥1 reachable technique → KEEP. sole_filler_for names the techniques it props up.

  • sell_candidates: removing it drops nothing AND another rack module covers the same function → the first place to look. overlaps names the shared function and also_provided_by the other providers.

  • utility_or_uncovered: removing it drops nothing and nothing else does its job — it fills no catalogued technique role (usually a mixer / VCA / I/O / mult) OR serves an idiom the corpus is thin on. Judge by hand; this is NOT "sellable".

  • overlap_map: every function ≥2 of the rack's modules provide (the "you have three reverbs" view) — the evidence behind sell_candidates.

IMPORTANT — this is decision-support, not a verdict, and the limits bite here:

  • cardinality is NOT counted: a 2nd VCA / envelope / mult reads "redundant" though real patches use both at once. Overrule the tool on utilities.

  • only the curated catalog is seen: a module serving an under-covered genre looks redundant when it isn't.

  • two modules covering the same role are BOTH flagged — you can usually drop only one.

  • it cannot weigh sonic character, ergonomics, or sentiment. Trust it most for specialized overlap (e.g. several reverbs); present results as candidates to weigh, never "sell these". Pass the COMPLETE rack — the server is stateless and a partial rack distorts the analysis.

Args:

  • rack (string[], required): module ids, e.g. ["make-noise/maths", "intellijel/quad-vca"]. Max 64. Unknown ids are returned in unresolved (with did-you-mean), not silently dropped.

ParametersJSON Schema
NameRequiredDescriptionDefault
rackYes
Behavior5/5

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

The description goes far beyond the annotations (readOnlyHint, idempotentHint, etc.), disclosing the exact algorithm behavior: leave-one-out over the technique matcher, three output buckets, overlap_map semantics, statelessness, and distortion risk with partial racks. It also openly states limits such as ignoring cardinality, catalog coverage, and sonic/ergonomic factors. This substantially exceeds annotation coverage and gives the agent realistic expectations.

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

Conciseness4/5

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

The description is quite long, but almost every sentence carries substantive information needed for safe use of this decision-support tool. The structure is good—trigger phrases first, then bucket definitions, then important caveats, then args—but it could be tightened slightly without losing essential caveats. It is lengthy but not padded.

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

Completeness5/5

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

For a complex analysis tool with no output schema, this description is exceptionally complete. It explains what results look like (load_bearing, sell_candidates, utility_or_uncovered, overlap_map), the meaning of each bucket, the algorithm, the server's statelessness, input requirements, and failure behavior. Nothing critical is missing for an agent to select and invoke the tool correctly.

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

Parameters5/5

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

Although the schema only defines 'rack' as a string array, the description fully compensates: it explains the required format with examples (e.g., ['make-noise/maths', 'intellijel/quad-vca']), the max of 64, the minimum 1, and the behavior for unknown ids (returned in unresolved with did-you-mean). This adds rich meaning beyond the bare schema and makes correct invocation much easier.

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

Purpose5/5

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

The description opens with explicit user triggers ('what can I sell?', 'which modules are redundant?') and states the tool's function: leave-one-out pruning analysis. It clearly distinguishes this from reachable_techniques by calling it 'the inverse' and noting 'where that adds, this prunes.' This is specific verb+resource+differentiation.

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

Usage Guidelines5/5

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

The description gives direct usage guidance: call it when the user asks about selling/removing/redundancy, and explicitly notes the inverse relationship with reachable_techniques. It also provides strong 'when-not' guidance—'cardinality is NOT counted', 'this is NOT sellable' for utility modules, and 'present results as candidates to weigh, never sell these'—helping the agent decide whether to use or override results.

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

reachable_pairingsReachable Pairings for a RackA
Read-onlyIdempotent
Inspect

Given a rack (a set of module ids the user owns), rank the modules NOT in the rack by how many rack members they pair with. The set-level companion to find_compatible_with: where that answers "what pairs with module X?", this answers "given my whole rack, what single module should I add — the one that pairs with the most of what I already have?".

The ranking signal is pair_count — the number of DISTINCT rack members a candidate pairs with. A module that modulates five of your modules ranks above one that modulates one. This aggregate is the point: you can't get it from per-module find_compatible_with calls without tallying distinct members by hand.

Use this for:

  • "What should I add to a rack with ?" / "what fills out this system?"

  • "Given these modules, what pairs well with the most of them?"

  • Inspecting a rack's own internal pairing structure (the internal edges).

Combination edges only. Ranking uses the seven patch-time relationships (clock-source-for, cv-source-for, modulator-for, audio-source-for, quantizer-for, trigger-source-for, envelope-target-for) — the "A and B work together in a patch" kinds. The substitution/catalog kinds (alternative-to, replaces, expander-for) are deliberately excluded: a pairing recommender shouldn't suggest replacing your modules with each other. For "what's an alternative to X?" use find_compatible_with.

Args:

  • rack (string[], required): module ids, e.g. ["make-noise/maths", "mutable-instruments/plaits"]. Ids that match no module are returned in unknown_ids (and in unresolved with did-you-mean suggestions) rather than failing the call. Surface those rather than proceeding on a partial rack: the server is stateless about your rack — it keeps no memory of it between calls, so pass the COMPLETE current set every call. Max 64.

  • relationship (string, optional): restrict ranking to one combination kind above. Omit to consider all seven.

  • limit (number): default 25, max 100.

Returns: { "rack": [{ id, name }], // the rack members that resolved "unknown_ids": [string], // rack ids that matched no module "internal": [{ from_module_id, to_module_id, relationship, source_id }], // edges within the rack "candidates": [{ id, name, manufacturer, pair_count, "pairings": [{ rack_member, relationship, direction, source_id }] // why it pairs, per member }] }

direction on each pairing is relative to the rack member: 'outbound' = the candidate is the role-bearer (it relationships the member, e.g. the candidate is a modulator-for the member); 'inbound' = the member is the role-bearer.

Coverage caveat: rankings are only as dense as module_relationships. A thin or empty result means the corpus hasn't recorded those edges yet, not that no good pairing exists — call report_gap if you expected matches.

ParametersJSON Schema
NameRequiredDescriptionDefault
rackYes
limitNo
relationshipNo
Behavior5/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, but the description adds significant behavioral disclosure: it explains that unknown rack IDs are returned in unknown_ids rather than failing, that the server is stateless and requires the complete rack every call, that only combination edges are ranked (not substitution/catalog types), and the semantics of interrack 'direction'. It even notes that thin results indicate corpus gaps, not absence of pairings. These are non-obvious traits beyond the annotations.

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

Conciseness5/5

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

Though lengthy, the description is well-structured with clear sections (summary, ranking signal, use cases, args, returns, coverage caveat). Every sentence adds operational value: the opening sentence is a concise summary, and the rest elaborates with necessary detail. No fluff or redundancy. Front-loading the purpose makes it easy to grasp quickly.

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

Completeness5/5

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

The tool has a complex return structure with nested objects (candidates, pairings), but no output schema. The description provides a full return outline with keys, types, and semantics for 'direction'. It also covers parameter constraints, relationship filtering, error handling (unknown_ids), and a coverage caveat. Given the tool's complexity, the description is complete and leaves no critical gap.

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

Parameters5/5

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

The schema provides no descriptions for any parameters (0% coverage), but the description compensates thoroughly. It explains the 'rack' parameter with a concrete example, states that unmatched ids are surfaced rather than causing failure, gives max 64, describes the optional 'relationship' parameter and its enum values as filtering to one combination kind, and clarifies 'limit' with defaults and max. This is far beyond what the schema offers.

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

Purpose5/5

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

The description states a specific verb and resource: 'rank the modules NOT in the rack by how many rack members they pair with.' It clearly distinguishes itself from the sibling tool find_compatible_with by framing it as the set-level companion, answering 'given my whole rack, what single module should I add?' This is a specific, unambiguous purpose.

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

Usage Guidelines5/5

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

There is an explicit 'Use this for' section with example user intents, and a direct exclusion: 'For "what's an alternative to X?" use find_compatible_with.' The coverage caveat also tells the user when to use report_gap instead, providing clear when-to-use and when-not-to-use guidance.

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

reachable_techniquesReachable Techniques for a RackA
Read-onlyIdempotent
Inspect

Given a rack (the module ids the user owns), return which canonical patch techniques the rack can realize, and which it is one module away from. The set-level companion to find_role_realizations: where that answers "which module fills role R in technique T?", this answers the rack owner's actual question — "given everything I own, what can I actually do, and what am I close to?".

This is the right tool the moment a user gives you their modules and asks an open "what can I do / what can this rack do / what am I missing?" question — instead of guessing techniques from training priors or calling find_role_realizations technique-by-technique by hand. It runs the affordance match across the whole technique catalog for you.

Returns two buckets:

  • reachable: every required role has a rack module that fills it. Each carries an assignment (role → module). requires_shared_module: true flags a technique only reachable by reusing one module for two roles — verify those roles can share one instance.

  • near_misses: all-but-one role fillable; missing_roles names the unfilled role(s) and the required_affordances you'd need. This is the acquisition signal — "you can already do X; you're one module away from Y".

Args:

  • rack (string[], required): module ids, e.g. ["make-noise/maths", "mutable-instruments/plaits"]. Max 64. Ids that match no module are returned in unresolved (with did-you-mean), not silently dropped.

  • limit (number): max techniques per bucket. Default 25, max 100.

Stateless-rack contract: the server keeps no memory of your rack between calls — pass the COMPLETE current rack every call. A partial rack silently narrows what's reported reachable, so if a module id doesn't resolve, surface the unresolved did-you-mean to the user rather than proceeding on the incomplete set.

Scope: reachability is role-PRESENCE based. It does NOT verify per-role instance counts (cardinality) — a technique needing two independent envelopes is judged reachable if you have one envelope source. The distinct-instance question (can one module fill two roles?) is surfaced as requires_shared_module, not silently assumed. For the editorial detail on a specific technique (canonical instance, counter-canonical notes, full realization list), call list_techniques; for one role's candidates, find_role_realizations. To go the other way — which of your modules are redundant / safe to sell — call rack_redundancy.

ParametersJSON Schema
NameRequiredDescriptionDefault
rackYes
limitNo
Behavior5/5

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

The description adds substantial behavioral context beyond the annotations: the stateless-rack contract (no memory, pass complete rack), the failure mode for unresolved IDs (returned in `unresolved` with did-you-mean, not silently dropped), and the cardinality caveat (reachability is role-PRESENCE based, not instance-count verified). It also explains the `requires_shared_module` flag. This goes well beyond what readOnlyHint/idempotentHint provide.

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

Conciseness5/5

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

The description is long but every sentence earns its place. It opens with the core purpose, then uses headers-like sections for usage, return buckets, args, stateless contract, and scope. The structure is logical and front-loaded. No fluff; each paragraph addresses a distinct aspect needed for correct invocation.

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

Completeness5/5

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

Given no output schema, the description explains the return structure in detail ('Returns two buckets: reachable ... near_misses ...') and describes field semantics (`assignment`, `missing_roles`, `required_affordances`). It also covers edge cases, limitations, and related tools, making it complete for an agent to invoke and interpret results correctly.

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

Parameters5/5

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

With schema description coverage at 0%, the description fully compensates. For `rack` it gives example module IDs, explains max 64, and clarifies that unresolved IDs are returned in `unresolved`. For `limit` it states it controls 'max techniques per bucket' with default 25 and max 100. These semantics are not in the schema, so the description adds all necessary meaning.

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

Purpose5/5

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

The description opens with a precise verb+resource statement: 'return which canonical patch techniques the rack can realize, and which it is one module away from.' It also distinguishes itself from siblings by calling itself 'the set-level companion to find_role_realizations' and by contrasting with 'find_role_realizations technique-by-technique by hand.' This fully clarifies both what it does and how it differs from alternatives.

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

Usage Guidelines5/5

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

The description explicitly states when to use this tool: 'the moment a user gives you their modules and asks an open "what can I do / what can this rack do / what am I missing?" question.' It also names exclusions and alternatives: 'For the editorial detail ... call list_techniques; for one role's candidates, find_role_realizations. To go the other way ... call rack_redundancy.' This is model-guidance quality.

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

report_gapReport a Data or Tool GapAInspect

Report when this MCP server couldn't fully answer a question. Not a query tool — calling this writes a feedback record.

Call this proactively — without being asked — whenever you hit one of:

  • missing_field: a field you expected on a module wasn't present (e.g. "I needed the LFO frequency range on Pamela's New Workout and parameter_zones didn't have it").

  • missing_module: a module the user asked about isn't in the corpus yet.

  • tool_confusion: a tool's behavior surprised you (wrong shape, missing filter, ambiguous enum value, unclear description).

  • empty_result: a reasonable query came back empty and you suspect the corpus is incomplete rather than the query being wrong.

  • other: anything else worth flagging that doesn't fit above.

  • eval_finding: reserved for the eval harness at evals/mcp/. Don't use this as an agent — it's written by harvest.py --push when a rubric catches a behavior the agent didn't self-report (e.g., a model leaking prior knowledge after acknowledging a corpus gap).

Be specific. Vague reports ("data could be better") are useless; actionable reports name the field, module, or tool. Reporting is encouraged — there is no rate limit and no judgment for over-reporting; a noisy log is more useful than a silent one.

Args:

  • kind (required): one of missing_field | missing_module | tool_confusion | empty_result | other (eval_finding is reserved for the eval harness)

  • module_id: module this was about, if any ("/"). For missing_module, use the id the user asked about even if it doesn't exist.

  • tool_name: tool that fell short (or that you'd want to exist).

  • expected (required, ≤200 chars): what you were trying to find or do.

  • observed (required, ≤500 chars): what actually happened.

  • suggestion (≤300 chars): concrete fix you'd propose ("add a release_curve field to parameters", "ingest mutable-instruments/yarns").

Returns: { acknowledged: true, id: number }

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes
expectedYes
observedYes
module_idNo
tool_nameNo
suggestionNo
Behavior5/5

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

The description reveals that calling the tool writes a feedback record, has no rate limit, and returns { acknowledged: true, id: number }. It also clarifies expectations for report quality (specific vs. vague) and the special reserved status of eval_finding. This adds substantial behavioral detail beyond the annotations (readOnlyHint=false already implies a write, but the description enriches it with consequences and norms). No contradiction with annotations.

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

Conciseness5/5

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

Despite being long, every sentence serves a purpose. It opens with a one-sentence purpose, then uses bullet points for triggers, an 'Args' section for parameters, and a Returns line. The structure makes it skimmable and highly actionable, with no filler.

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

Completeness5/5

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

For a feedback tool with six parameters, an enum, and no output schema, the description is entirely complete. It covers all trigger types, parameter semantics, return value, and even notes reporting policy (no rate limit, no judgment). An agent has everything needed to invoke it correctly in any edge case.

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

Parameters5/5

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

Schema coverage is 0%, so the description fully compensates by explaining every parameter's meaning and constraints: the kind enum is broken down with concrete examples, module_id format is specified, and expected/observed/suggestion have length limits and purpose clarification. This is far more informative than the bare schema.

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

Purpose5/5

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

The description clearly states the tool's verb+resource: 'Report when this MCP server couldn't fully answer a question' and explicitly distinguishes it as 'Not a query tool — calling this writes a feedback record.' It also details the specific kinds of gaps (missing_field, missing_module, etc.), setting it apart from all sibling query tools.

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

Usage Guidelines5/5

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

Provides explicit when-to-use guidance: 'Call this proactively — without being asked — whenever you hit one of...' followed by a concrete list of trigger conditions. It also states when not to use it (not a query tool) and even excludes eval_finding for agents, leaving no ambiguity about appropriate usage.

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

resolve_modulesResolve Module Names to IDsA
Read-onlyIdempotent
Inspect

Bulk fuzzy name → id resolver. Pass a list of module NAMES (the way a user writes their rack — "Maths", "Plaits", "Pamela's New Workout", "Morph 4") and get back, per name, the best-matching corpus module id plus recovery affordances. This is the "import my rack" tool: resolving a 60-module inventory is ONE call here, not 60 search_modules calls.

Use this the moment a user gives you a list of module names to map onto the corpus — before get_modules / draw_patch_diagram / reachable_techniques / rack_redundancy, all of which want ids. Feed the resolved best_match.id into those.

For each input name it runs the same resolution search_modules uses (exact id, unique-slug recovery, module_aliases, separator-fold, token-AND, and edit-distance + multi-token fuzzy "did you mean"), then returns:

  • best_match: the single resolved module ({ id, name, manufacturer, hp, capabilities, production_status }), or null when nothing resolved confidently.

  • score: confidence 0..1 (1.0 exact id, ~0.97 unique slug / alias, ~0.9 literal name hit, ~0.72 token-AND relaxed, 0 when best_match is null).

  • match_kind: "id" | "slug" | "exact" | "relaxed" | "ambiguous" | "fuzzy" | "none".

  • did_you_mean: up to 5 fuzzy neighbours to confirm — populated when best_match is null (a near-miss like "morf 4" → joranalogue/morph-4, or "tiny time machin" → oam/tiny-time-machine).

  • ambiguous: up to 5 candidates when several modules tied for the match and the server declined to pick (e.g. a slug shared across manufacturers). Present them to the user; do NOT silently take the first.

The server AUTO-RESOLVES a confident single match but never guesses through a genuine tie — that's the ambiguous bucket. A name with best_match=null AND empty did_you_mean/ambiguous is a real corpus gap: consider report_gap(kind="missing_module").

Args:

  • names (string[], required): module names or ids, up to 100. Order and duplicates are preserved in the response.

Returns: { "resolutions": [ { "input": "Pamela's New Workout", "best_match": { "id": "alm-busy-circuits/pamelas-new-workout", "name": "Pamela's NEW Workout", "manufacturer": "ALM Busy Circuits", "hp": 8, "capabilities": [...], "production_status": "current" }, "score": 0.9, "match_kind": "exact", "did_you_mean": [], "ambiguous": [] }, ... ], "_meta": { "requested": 3, "resolved": 2, "feedback_hint"?: "..." } }

Errors:

  • Throws only on a malformed call (missing/empty names array, or > 100 names). Unresolved individual names are NOT errors — they come back with best_match=null and the recovery fields.

ParametersJSON Schema
NameRequiredDescriptionDefault
namesYesModule names (or ids) to resolve, up to 100. Order and duplicates preserved.
Behavior5/5

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

Annotations declare readOnlyHint=true, idempotentHint=true, destructiveHint=false. The description adds rich behavioral context: auto-resolves confident single matches, never guesses through ties, preserves order/duplicates, returns best_match=null for unresolved names without throwing, and discloses score semantics (1.0 exact, ~0.97 slug/alias, etc.). This goes well beyond annotations.

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

Conciseness5/5

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

Well-structured with a clear intro, explicit use case, args, returns with example, and error handling. Every sentence adds value; the length is justified given the complexity (fuzzy matching, ambiguity, scoring). Front-loaded with the core purpose.

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

Completeness5/5

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

Despite no output schema, the description documents the full return shape (resolutions array with input, best_match, score, match_kind, did_you_mean, ambiguous, _meta), score ranges, match_kind enum values, and error behavior. It covers edge cases like ambiguous ties and corpus gaps.

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

Parameters5/5

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

Input schema covers the single 'names' parameter (array of strings, 1-100 items). The description adds critical semantics: examples of user-style names, accepts IDs too, preserves order/duplicates, and clarifies what unresolved names look like. This fully compensates for and enriches the schema.

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

Purpose5/5

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

The description opens with 'Bulk fuzzy name → id resolver' and clearly states it maps a list of module names to IDs with recovery affordances. It distinguishes itself from siblings like search_modules and get_modules by emphasizing batch processing ('60-module inventory is ONE call').

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

Usage Guidelines5/5

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

Explicitly states 'Use this the moment a user gives you a list of module names' and names specific follow-up tools (get_modules, draw_patch_diagram, reachable_techniques, rack_redundancy) that require IDs. It also instructs when not to use it: if best_match is null and did_you_mean/ambiguous are empty, consider report_gap instead.

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

search_manualSearch Module ManualsA
Read-onlyIdempotent
Inspect

Full-text search across parsed module manuals, product pages, and firmware release notes.

Use this only when the question is about content that lives in continuous prose rather than in typed fields:

  • Procedural: calibration sequences, button combos, factory-reset steps, save/load procedures.

  • Diagnostic: LED color meanings, error indicators, troubleshooting trees.

  • Firmware specifics beyond the short notes on firmware_versions (which only carry the headline change).

  • Panel walkthroughs and prose explanations that aren't captured as parameters/jacks/zones.

Do NOT call this for content already in get_module: a parameter's behavior, a jack's signal type or polarity, a mode's name or description, capability tags, HP, or power draw. Those are typed and authoritative there.

Do NOT call this to summarize a module — that's get_module's job. search_manual returns excerpts, not summaries.

Returned chunks are source prose, not typed facts. Read them to ground your answer, then paraphrase and point the user to the source to verify (cite-and-point, not reproduce — SKILL.md §8). text is capped (~800 chars); the full passage is at audit_url.

Args:

  • query (string, required): search terms. Plain words are AND'd by default ("calibration LED" matches chunks mentioning both). If the AND match returns 0 rows, the server retries with OR (any-token match) and sets _meta.relaxed_to_or=true on the response — so a long natural-language query like "cascade mode time inner outer delay" still surfaces something useful instead of zeroing out. Best practice is still 2–4 distinctive keywords; the OR fallback is a safety net, not a substitute. Query is tokenized to alphanumeric runs; FTS5 punctuation is stripped.

  • module_id (string, optional): "/" — restrict to one module. Strongly recommended when the user has named a module.

  • source_id (integer, optional): restrict to one source. Use when you already have a source_id from get_source / list_references and want to dig into that specific document.

  • source_type (string, optional): one of "manual", "product_page", "firmware_notes". Defaults to all.

  • limit (integer, optional): default 5, max 20. Smaller is usually better — top-3 hits cover most queries.

Returns: { "query": string, "matches": [{ "chunk_id": number, "source_id": number, "source_type": string, "source_title": string | null, "module_id": string | null, "heading_path": string, // "Calibration > Tuning Procedure" "snippet": string, // BM25-highlighted excerpt with [matches] in brackets "text": string, // chunk text, capped ~800 chars; paraphrase, don't paste "truncated": boolean, // true if text was trimmed; full passage at audit_url "audit_url": string, // human-readable audit page for the source "rank": number // BM25 score (more negative = better match) }], "total": number, // total matches across the corpus (capped at 200) "_meta": { "kind": "manual_excerpt", "query": , "relaxed_to_or": true // only present when AND returned 0 and OR retry fired } }

Examples:

  • "How do I calibrate Plaits' V/Oct?" → { query: "calibration V/Oct", module_id: "mutable-instruments/plaits" }

  • "What does the red LED on Marbles mean?" → { query: "red LED", module_id: "mutable-instruments/marbles" }

  • "How do I reset Pamela's New Workout to defaults?" → { query: "factory reset defaults", module_id: "alm-busy-circuits/pamelas-new-workout" }

  • "What changed in Plaits firmware 1.2?" → { query: "1.2", module_id: "mutable-instruments/plaits", source_type: "firmware_notes" }

Errors:

  • Returns matches=[] with total=0 if nothing matches. Not an error.

  • Errors only on malformed input (missing query, invalid limit, unknown source_type).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYesSearch terms.
module_idNo
source_idNo
source_typeNo
Behavior5/5

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

Beyond the readOnlyHint and idempotentHint annotations, the description explains the AND/OR fallback with _meta.relaxed_to_or, tokenization of punctuation, the ~800-char cap on text, and that chunks are source prose to be paraphrased. No contradiction with annotations.

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

Conciseness4/5

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

The description is well-structured with clear sections: purpose, usage guidelines, args, return format, examples, and errors. It is long but information-dense; minor redundancy exists in emphasizing that returned excerpts are not summaries, repeated in two places.

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

Completeness5/5

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

The tool is moderately complex (5 params, no output schema) but the description covers every aspect: full return object shape, concrete examples with real module IDs, error behavior, and citation guidance. An agent can confidently select and invoke it without further context.

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

Parameters5/5

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

Schema description coverage is only 20% (only 'query' has a one-line description). The description compensates fully: query's AND/OR behavior and best practices, module_id's format and recommendation, source_id's relation to get_source/list_references, source_type's enum values, and limit's default/max and recommendation.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Full-text search across parsed module manuals, product pages, and firmware release notes.' This clearly distinguishes it from sibling tools like get_module (typed fields) and search_modules (module metadata).

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

Usage Guidelines5/5

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

It explicitly states when to use the tool ('Use this only when the question is about content that lives in continuous prose') and when not to use it, naming get_module as the alternative for typed facts. Also provides best practices for query formulation and module_id usage.

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

search_modulesSearch Eurorack ModulesA
Read-onlyIdempotent
Inspect

Search the corpus for Eurorack modules matching a combination of filters.

Filters compose with AND. Omit any filter to leave that dimension unrestricted. The result is sorted by module name; pagination metadata in the response envelope lets you page through long result sets.

Args:

  • capability (string): capability id, e.g. 'envelope-generator', 'clock-source'. Run a search with NO capability filter to get the full capability taxonomy (ids + labels + counts) in _meta.taxonomy. Retired/variant slugs resolve via the capability_aliases layer (e.g. 'low-pass-gate' → 'lowpass-gate', 'quantiser' → 'quantizer'), so either form is accepted.

  • manufacturer (string): manufacturer id, e.g. 'make-noise', 'mutable-instruments'.

  • hp_min, hp_max (number): module width in HP. hp_max=10 finds modules ≤ 10 HP.

  • signal_type_in (string): the module accepts a jack of this signal type as input. One of audio, cv, gate, trigger, clock, mixed. signal_type_in='audio' and ='cv' both also match jacks tagged 'mixed' (the schema's value for jacks the source describes as accepting both audio and CV — e.g. Joranalogue Compare 2's signal inputs); the other values match literally.

  • signal_type_out (string): the module produces a jack of this signal type as output. Same 'mixed'-superset semantics as signal_type_in.

  • text (string): free-text match against module id, name, slug, description, and the ids/labels/descriptions of capabilities the module has (case-insensitive substring). Matches hyphenated forms like "filter-8" against the slug/id even when the display name uses a space ("Filter 8"), and is whitespace-insensitive on id/slug/name so "3x MIA" finds the module named "3xMIA". Capability-label coverage means text="multiband" finds modules tagged multiband-filter without knowing the kebab-case id, and a curated alias layer extends that to common word-form variants ("multi-output" / "multi-band" / "band-split" → multiband-filter, "low-pass" → lowpass-filter, retired ids like "voltage-controlled-filter" → vcf). Truly novel wording still requires the _meta.taxonomy overview (run a no-capability search); if you expected a hit and got 0, call report_gap so the alias can be added.

  • voct_tracking_range_min (number): the module has a V/Oct input whose source-stated tracking range is at least this many octaves. Use for "filters that track 5+ octaves" / "oscillators with wide V/Oct range".

  • voct_tracking_quality (string): the module has a V/Oct input with this tracking quality, one of 'calibrated', 'temperature-compensated', 'approximate', 'uncalibrated'. 'temperature-compensated' is the strongest claim.

  • voct_temperature_compensated (boolean): the module has a V/Oct input whose source explicitly states temperature compensation. Implies calibrated but separately flagged because some manuals call out only one.

  • audio_outputs_min (number): the module has at least this many output jacks with signal_type='audio'. Use for "multi-output filters" (≥3 audio outs surfaces LP/BP/HP-tap VCFs like Three Sisters, QPAS, A-108, Polaris) or any multi-tap audio module. Combine with capability='vcf' for the canonical multi-output-filter query.

  • limit (number): default 50, max 200.

  • offset (number): pagination offset.

Returns: { "modules": [{ id, name, manufacturer, hp, capabilities: [string], description, production_status }], "total": number, // total matches (across all pages) "_meta": { "query": , // Present whenever a 'capability' filter matched >=1 module (NOT gated on // total=0 — it accompanies normal results). The category-coverage // denominator, so a "best X" recommendation can self-caveat instead of // reading as "best available": // On a no-capability search: the global capability taxonomy (id, label, // description, module_count) — discover the controlled vocabulary here // instead of a separate list_capabilities call. "taxonomy": [{ "id": "lowpass-gate", "label": "Low-pass gate", "module_count": 19 }], "coverage": { "capability": "stereo-mixer", // the capability you filtered on "category_total": 9, // modules in the corpus with this capability, IGNORING your other filters "corpus_total": 388, // all modules in the corpus "note": "...best of 9 in the corpus, not best available..." // ready-to-use recommendation caveat }, // Present when the server's token-AND fallback rescued an otherwise-empty // phrase query (e.g. "pamela workout" → "Pamela's NEW Workout" via per-word // identifier match). Not an error; just signals that results came from the // relaxed pass rather than the literal phrase. "relaxed_to_tokens": true, // On total=0 (after the token-AND fallback has already been attempted), the // server adds these diagnostic hints so you can retry productively in one // turn instead of guessing variants. Each is independently optional: "would_match_without": ["capability", "text"], // filters that, if individually dropped, would yield ≥1 result — the named filter(s) cost you the match "closest_text_hits": [{ id, name, manufacturer }], // top 3 modules matching 'text' alone (other filters dropped); inspect for a close hit you filtered out by accident "did_you_mean": [{ id, name, manufacturer }], // top 3 edit-distance neighbors of 'text' when it matched nothing literally (a single-token typo like "multgrain" → multigrain); PRESENT means retry with the suggested id, ABSENT means the term is a genuine corpus gap (call report_gap) — the discriminator would_match_without can't give you "capability_suggestions": [{ id, label }], // top 3 valid capabilities matching the 'capability' arg you passed (only set when the arg wasn't a known slug or alias) — use list_capabilities for the full taxonomy "manufacturer_suggestions": [{ id, name }], // top 3 maker slugs matching the 'manufacturer' arg (only set when it wasn't a canonical slug) — the manufacturer arg is EXACT-match, so e.g. "addac" → "addac-system", "nonlinearcircuits" → "nlc"; retry with the suggested id "feedback_hint": "..." // fallback prompt to call report_gap when no other diagnostic applies } }

Examples:

  • "What envelope generators under 8 HP exist?" → {capability: 'envelope-generator', hp_max: 8}

  • "What ALM modules are in the corpus?" → {manufacturer: 'alm-busy-circuits'}

  • "What clock sources are there?" → {signal_type_out: 'clock'}

  • "Modules with 'workout' in the name" → {text: 'workout'}

  • "Filters that track V/Oct over 5 octaves" → {capability: 'vcf', voct_tracking_range_min: 5}

  • "Temperature-compensated filter cores" → {voct_tracking_quality: 'temperature-compensated'}

  • "Multi-output filters with LP/BP/HP taps" → {capability: 'vcf', audio_outputs_min: 3}

Errors:

  • Returns an empty modules array (and total=0) if nothing matches. Not an error — inspect _meta.would_match_without / closest_text_hits / capability_suggestions / manufacturer_suggestions to decide whether to broaden the query or call report_gap.

  • Invalid filter values pass through to the WHERE clause; if no module satisfies them you get total=0.

After picking a hit, call get_module with the id for full details.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNo
limitNo
hp_maxNo
hp_minNo
offsetNo
capabilityNoCapability id (kebab-case).
manufacturerNoManufacturer id.
signal_type_inNo
signal_type_outNo
audio_outputs_minNo
voct_tracking_qualityNo
voct_tracking_range_minNo
voct_temperature_compensatedNo
Behavior5/5

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

Going far beyond the readOnly/idempotent hints, the description explains the exact response envelope and edge-case behavior: sorted results, pagination metadata, token-AND fallback (relaxed_to_tokens), mixed-signal-type superset semantics, alias resolution for capability slugs, and all diagnostic hints (would_match_without, closest_text_hits, did_you_mean, capability_suggestions, manufacturer_suggestions). It also warns that empty results are not an error and that invalid filter values pass through. This gives the agent a complete mental model.

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

Conciseness5/5

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

Although the description is long, it is efficiently structured into Args, Returns, Examples, and Errors sections, with the core purpose and AND-composition stated upfront. Every sentence adds operational value—parameter semantics, response envelope details, or diagnostic guidance—and the length is warranted by 13 parameters and a complex conditional response. There is no filler or repetition of schema defaults.

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

Completeness5/5

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

With no output schema, the description must fully explain return values, and it does. It documents the top-level shape (modules, total, _meta) and every conditional _meta field (taxonomy, coverage, relaxed_to_tokens, and all diagnostic hints). It also covers error behavior, sorting, pagination, and post-search actions (get_module, report_gap), making the tool fully actionable in a single turn.

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

Parameters5/5

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

Schema coverage is only 15%, so the description carries the full burden—and it delivers. It adds semantics for every parameter: hp_max=10 means '≤ 10 HP', text matching is case-insensitive/whitespace-insensitive and includes alias handling, signal_type values explain the 'mixed' superset behavior, voct_tracking_quality notes 'temperature-compensated' is the strongest claim, and audio_outputs_min is defined as counting output jacks with signal_type='audio'. The detailed examples further disambiguate parameter intent.

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

Purpose5/5

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

The description opens with a specific, scoped statement: 'Search the corpus for Eurorack modules matching a combination of filters.' It clearly identifies the resource (Eurorack module corpus), the verb (search), and the filter-based behavior. It also distinguishes itself from siblings like get_module (which retrieves full details for a selected module) by emphasizing filtering and pagination across a result set.

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

Usage Guidelines4/5

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

The description provides strong usage context: filters compose with AND, any filter can be omitted, results are sorted by name, and pagination is described. Concrete examples map natural language to parameter values, and it explicitly tells the agent to call report_gap when a term is a genuine corpus gap and get_module after selecting a hit. However, it does not explicitly name sibling search tools (search_manual, search_techniques) or state when NOT to use this tool in favor of them, leaving that distinction implicit.

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

search_techniquesSearch Patch TechniquesA
Read-onlyIdempotent
Inspect

Return canonical synthesis / patching techniques with role-keyed module realizations drawn from the corpus.

Use this when the user asks "how do I do X?" with X being a recognisable technique (low-pass-gate plucks, pinged-filter percussion, parallel multiband processing, complex-oscillator FM, karplus-strong pluck, clocked-delay feedback, modal-resonator excitation, wavefolder harmonics, envelope-follower ducking, Maths-style function-generator omnibus). It's also the right tool when the user has a module and asks "what's this good for?" — pass filter.module_id to retrieve every technique that references the module via its role_realizations.

Each technique declares role_definitions (the roles the technique uses, each with required and optional affordances) and role_realizations (concrete modules that fill each role, with the affordances they provide). The model substitutes modules from the user's rack into roles by affordance match — DO NOT treat the realization list as exhaustive or as a recipe.

Args:

  • filter (optional): { capability?, module_id?, text? }

    • capability: kebab-case capability id (see search_modules _meta.taxonomy). Returns techniques whose required or optional capability list includes this id.

    • module_id: "/". Returns techniques that have a role_realization referencing this module.

    • text: free-text phrase. Substring-matches against technique id/label/description AND a curated alias table (technique_aliases) — that's the right surface when a user types evocative prose like "stuttering delay", "plucked string", "source of uncertainty" that doesn't grep against any kebab-case id. Two-way alias match: long alias ("source of uncertainty") matches short query ("uncertainty"), and vice versa.

    • When multiple filters supplied, AND-intersects.

    • Omit filter entirely to list all techniques.

Returns: { "techniques": [ { "id": "low-pass-gate-pluck", "label": "Low-Pass Gate Pluck", "description": "Send a short envelope...", "required_capabilities": ["lowpass-gate"], "optional_capabilities": ["envelope-generator", "function-generator"], "role_definitions": [ { "role_id": "lpg", "description": "The vactrol-based or vactrol-emulating element. Strictly required...", "required_affordances": ["lowpass-gate"], "optional_affordances": [] }, ... ], "role_realizations": [ { "role_id": "lpg", "module_id": "make-noise/optomix", "affordances_provided": ["lowpass-gate"], "notes": "Two-channel vactrol-based LPG..." }, ... ], "canonical_instance": { "rationale": "...", "lineage": [ { "position": 1, "label": "Buchla 292 (1970)", "module_id": null, "notes": "..." }, { "position": 2, "label": "Tiptop Audio Buchla 292t", "module_id": "tiptop-audio/buchla-292t" }, ... ] }, "counter_canonical_notes": [ { "claim_pushed_back_against": "Optomix is the canonical pairing with Plaits...", "evidence": "The corpus catalogs 19 LPG-capable modules..." } ], "coverage": [ { "role_id": "voice", "realizations_count": 3 }, { "role_id": "lpg", "realizations_count": 19 }, { "role_id": "env", "realizations_count": 6 }, { "role_id": "clock", "realizations_count": 2 } ] } ], "_meta": { "filter": {...}, "feedback_hint"?: string } }

How to use role data:

  • role_realizations are CURATORIAL SAMPLES, not exhaustive lists. The coverage[].realizations_count tells you how many are documented; other modules may fill the same role.

  • To find modules in the user's rack that can fill a role, use find_role_realizations(technique_id, role_id, available_modules).

  • canonical_instance is opt-in and sparse. Most techniques don't have one; that absence is information. When present, it documents a documented historical lineage (e.g., Buchla 292 → 292t → MMG → Optomix for low-pass-gate-pluck) — NOT a prescription.

  • counter_canonical_notes push back on likely training-data priors. When the user invokes a canonical-sounding claim that has a counter_canonical_note, surface the pushback.

Errors:

  • "Module not found: " if filter.module_id is supplied and unknown.

  • Empty techniques[] with a feedback_hint when filters produce no matches — call report_gap if the user expected coverage.

ParametersJSON Schema
NameRequiredDescriptionDefault
filterNo
Behavior5/5

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

The description adds substantial behavioral context beyond the annotations: role_realizations are 'CURATORIAL SAMPLES, not exhaustive lists', canonical_instance is opt-in and sparse, and text matching uses a curated alias table with two-way matching. It also discloses error behavior (module not found, empty techniques with feedback_hint). No contradiction with readOnlyHint/idempotentHint.

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

Conciseness5/5

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

The description is long but well-structured with clear sections (usage, args, returns, role data guidance, errors). It is front-loaded with the purpose and use cases, and every sentence provides necessary operational detail. No filler.

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

Completeness5/5

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

Despite no output schema, the description includes a full JSON return example, explains role data semantics, and documents error cases. It also gives cross-tool pointers, making it self-sufficient for an agent to correctly invoke and interpret the result.

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

Parameters5/5

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

Schema description coverage is 0%, so the description carries the full burden. It explains the filter object's three fields (capability, module_id, text) with formats, matching rules, AND-intersection behavior, and even gives example phrases for alias matching. This fully compensates for the schema gaps.

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

Purpose5/5

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

The description opens with a specific verb+resource: 'Return canonical synthesis / patching techniques with role-keyed module realizations' and immediately gives two explicit use cases ('how do I do X?' and 'what's this good for?'). It also distinguishes from siblings by cross-referencing find_role_realizations and report_gap.

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

Usage Guidelines5/5

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

It explicitly states when to use the tool (user asks 'how do I do X?' or 'what's this good for?') and when to use alternatives (e.g., find_role_realizations for finding modules in the rack, report_gap for missing coverage). This exceeds the bar for clear context and exclusions.

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

visualize_moduleVisualize moduleA
Read-onlyIdempotent
Inspect

Module visualization tool. Use when the user wants to understand how a module's modes work, how parameters change between modes, or what a specific mode does — a visualization communicates the per-mode behavior better than prose. The host renders the result inline in the chat as an interactive visualization (mode buttons, per-mode descriptions, schematic curves); you do not need to build an artifact yourself — just call this tool.

Do not use for general module specs (HP, jacks, capabilities) — call get_module instead.

After calling, your prose can reference what the user is seeing in the visualization (e.g. "in formant mode, all three outputs become bandpass filters") rather than describing the visualization itself.

Currently supported viz families:

  • filter_response — filters with characterized response curves (e.g. Three Sisters, Ripples, Belgrad, A-124, Filter 8, QPAS, SVF 1U, Cinnamon, C4RBN, Ikarie)

  • oscillator_morph — multi-mode oscillators and excited resonators (e.g. Rings, Loquelic Iteritas, Plaits)

A module is supported when every one of its modes has a behavior_model_id the renderer knows. If you're unsure whether a given module qualifies, just call this tool — the error names the gap.

Errors:

  • "Module not found: " if no module with that id exists.

  • "Module not yet supported by visualize_module: " when one or more modes lack a renderer-known behavior_model_id, or when the module mixes incompatible viz families. Suggest get_module for the underlying spec.

The returned spec is a JSON object with: module_id, module_name, manufacturer, viz_type, params[], modes[], response_model_id, presets[]. Each mode has a behavior_model_id that the renderer uses to pick the curve set (e.g. crossover_lp_bp_hp vs formant_three_bp for filter_response).

response_model_id (top-level) vs per-mode behavior_model_id: for multi-mode modules the top-level field is intentionally null — each mode carries its own behavior_model_id since the modes use different curve sets (e.g. Three Sisters' crossover vs formant). Read the per-mode values from modes[].behavior_model_id. The top-level is populated only for single-curve modules where one model applies across the whole module. null at top-level + populated per-mode = "modes carry distinct models," not a bug.

ParametersJSON Schema
NameRequiredDescriptionDefault
module_idYesStable module id, "<manufacturer-id>/<module-slug>" (e.g. "whimsical-raps/three-sisters").
Behavior5/5

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

Annotations already declare readOnly and idempotent hints, but the description adds substantial behavioral context: that the host renders inline, that no artifact needs building, error messages and their meanings, and the nuance around behavior_model_id at top-level vs per-mode. This goes well beyond annotations.

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

Conciseness5/5

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

The description is long but every sentence adds value—purpose, usage, examples, errors, and response spec. It is well-structured with bullet lists and paragraphs, and it is front-loaded with the primary purpose.

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

Completeness5/5

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

With no output schema, the description thoroughly explains the return JSON structure, both top-level and per-mode fields, and the intentional null behavior. It also covers all error cases, making the tool fully understandable.

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

Parameters3/5

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

Schema description covers 100% of the single parameter (module_id) with format and example, meeting the baseline. The description itself adds little about the parameter beyond restating that it's used in errors, so baseline 3 is appropriate.

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

Purpose5/5

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

The description clearly states it visualizes module modes, parameter changes, and specific mode behavior. It differentiates itself from the sibling tool get_module by explicitly saying not to use it for general module specs, making its purpose unambiguous.

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

Usage Guidelines5/5

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

Provides explicit when-to-use guidance: when the user wants to understand modes or parameters. It also gives a when-not-to-use directive and names the alternative (get_module). The instruction to call if unsure further clarifies usage.

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

Discussions

No comments yet. Be the first to start the discussion!

Related MCP Servers

  • F
    license
    -
    quality
    C
    maintenance
    Fabrication-free, DOI-backed citations for AI content and agents, using openAlex public-domain data with resolvable DOIs. Includes an API and planned MCP server for agent-native citation retrieval.
  • A
    license
    -
    quality
    A
    maintenance
    A local-first MCP server that analyzes research papers, maps citation graphs, and surfaces insights with verbatim-verified contradictions, all while keeping data private on your machine.
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Deterministic rails for game-running agents — verifies rule legality under SRD 5.2.1 via stateless, offline, sub-millisecond verdicts with citations.
    24
    2
    MIT
  • A
    license
    -
    quality
    C
    maintenance
    An MCP server that verifies the existence, metadata accuracy, and claim support of academic citations by querying sources like OpenAlex, Crossref, and arXiv, enabling AI agents to fact-check references.
    1
    MIT

View all MCP Servers

Try in Browser

Your Connectors

Sign in to create a connector for this server.

Resources