Skip to main content
Glama

eurorack

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 Definition Quality

Score is being calculated. Check back soon.

Available Tools

15 tools
draw_patch_diagramPatch Diagram
Read-onlyIdempotent
Inspect

Patch diagram tool. Use whenever the user describes routing across multiple Eurorack corpus modules — a graph almost always communicates the routing better than prose, and offering one is cheap. 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.

Lean toward offering it. When the user has been describing a multi-module patch over recent turns, default to offering the diagram: "Want me to render this patch?" Don't wait to be asked. The cost of offering is one sentence the user can wave off; the cost of not offering is invisible (prose-when-diagram-would-help). When in doubt, offer.

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. Utility modules (mixers, attenuators, mults, switches) collapse into processor. 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
find_compatible_withFind Compatible Modules
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?".

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 relationship is required and typed — no fuzzy matching. 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, required): one of the values above

  • limit (number): default 50, max 200

Returns: { "module": { id, name }, "relationship": , "matches": [{ id, name, manufacturer, notes, source_id, direction }] }

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
relationshipYes
find_role_realizationsFind Role Realizations
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.

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.

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.

Errors:

  • "Technique not found: "

  • "Role not defined for technique: <role_id> in <technique_id>"

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

ParametersJSON Schema
NameRequiredDescriptionDefault
role_idYes
technique_idYes
available_modulesNo
get_manual_chunkFetch Manual Chunk
Read-onlyIdempotent
Inspect

Return the full text of one manual chunk by id — the drill-in partner to get_module's manual_outline. Use this whenever your answer would benefit from the manufacturer's exact words backing a claim.

After calling this, quote one sentence (or short passage) from text verbatim in your answer to the user. That's the whole point — get_module's typed fields tell the user what a field does, this tool gives them the manual's actual sentence to verify against. If you call get_manual_chunk and don't end up quoting from it, you've spent a tool call for nothing.

When to call:

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

  • You're about to write a multi-sentence answer with specific technical claims (voltage ranges, behavior, calibration steps) and want one verbatim quote to ground it.

  • The user asked a prose-shaped question ("what does the manual say about X?") — quote the relevant chunk directly.

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, // full chunk text — quote one sentence verbatim "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.
get_moduleLook up module
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.

How to answer with this data — quote the manual, don't just paraphrase it

Default pattern for spec-shaped questions with specific technical claims (voltage ranges, jack polarities, mode behavior, calibration steps, anything numeric or behavioral the user might verify): scan manual_outline for the relevant heading, call get_manual_chunk(chunk_id) for the full text, and include ONE verbatim quote from the chunk in your answer alongside the typed data. Treat manual_outline → get_manual_chunk as a default two-step, not an optional drill-in. The typed data tells the user what the field does; the quote gives them the manual's actual sentence to verify against — that's the whole point of the citation-anchored design.

Skip the quote ONLY for routine 1-2 sentence factual answers (HP, manufacturer name, capability tag presence). A quote on "Maths is 20 HP" is padding.

Anti-pattern to avoid: tagging "(from the X manual)" after every clause in a multi-claim answer. Name the source once; ground the substantive claim in a verbatim quote from get_manual_chunk. If you've called get_module and are about to write a multi-paragraph answer with no get_manual_chunk call, that's the signal to drill in — your answer needs a quote.

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, 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: { <field_name>: { 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, 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.

  • 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
idYesStable module id, "<manufacturer-id>/<module-slug>" (e.g. "alm-busy-circuits/pamelas-new-workout").
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, _field_absent, panel_sections, character, common_problems, role_fitness, firmware_versions, reference_url, audit_url, production_status, replaced_by, manual_outline, manual_outline_total.
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.
get_modulesLook up modules
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:

  • 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
idsYes
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.
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.
get_sourceGet Source Metadata
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
list_capabilitiesList Capabilities
Read-onlyIdempotent
Inspect

Return the Eurorack capability taxonomy — either globally or scoped to one module.

Use this before search_modules to discover the right capability ids to filter by, or pass a module_id to see which capabilities a specific module exhibits (with per-module realization notes from module_capabilities).

Two modes by argument:

  1. Without module_id: global taxonomy, sorted alphabetically, with module_count per capability so you can see which capabilities have data behind them.

  2. With module_id: capabilities the named module exhibits.

Capability ids are kebab-case strings drawn from a fixed vocabulary populated as the corpus is ingested. Examples: envelope-generator, clock-source, clock-divider, clock-multiplier, modulation-source, lfo, random-source, quantizer, logic, vco, vcf, vca, euclidean-rhythm-generator, sample-and-hold, slew-limiter, attenuverter, cv-mixer, function-generator, lowpass-gate, oscillator, complex-oscillator, hard-sync, pulse-width-modulation, exponential-fm, phase-modulation, wavefolder, stepped-voltage-generator.

Args:

  • module_id (string, optional): module id (e.g. "alm-busy-circuits/pamelas-new-workout")

Returns: { "capabilities": [ { id, label, description: string|null, module_count?: number } ] }

module_count is populated only in the global listing.

ParametersJSON Schema
NameRequiredDescriptionDefault
module_idNo
list_referencesList Module References
Read-onlyIdempotent
Inspect

Return the source documents associated with one module — manuals, firmware notes, product pages, errata, and (in v2) field notes.

Args:

  • module_id (string, required): "/"

Returns: { "module_id": string, "references": [ { id, source_type, title, canonical_url, archived_url, format, last_verified } ] }

Each reference's id can be passed to get_source for full metadata (content_hash, fetched_date, canonical-change detection, audit_url).

Returns module_id with references=[] if the module has no sources recorded. Errors if the module id is unknown.

ParametersJSON Schema
NameRequiredDescriptionDefault
module_idYes
list_techniquesList Patch Techniques
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 list_capabilities). 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
lookup_conceptLook Up Concept
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", "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 suggestions are provided, present 2–3 closest suggestions 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
report_gapReport a Data or Tool GapInspect

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
search_manualSearch Module Manuals
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 quoted prose, not typed facts. When you cite them, frame them as quotes from the manual and include the source title or heading_path, never as authoritative behavior claims.

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, "results": [{ "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, // full chunk text (use for direct quotation) "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 results=[] 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
search_modulesSearch Eurorack Modules
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'. Use list_capabilities to see the full 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"). 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 list_capabilities; 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: { "results": [{ id, name, manufacturer, hp, capabilities: [string], description, production_status }], "total": number, // total matches (across all pages) "_meta": { "query": } }

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 results array (and total=0) if nothing matches. Not an error.

  • 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
visualize_moduleVisualize module
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)

  • delay_impulse_response — delays with tap patterns on a time axis

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
idYesStable module id, "<manufacturer-id>/<module-slug>" (e.g. "whimsical-raps/three-sisters").

Discussions

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

Try in Browser

Your Connectors

Sign in to create a connector for this server.

Resources