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": <args>,
// 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.