@map-audio/pam-mcp-server 1.18.1 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -77,12 +77,12 @@ Use the same `mcpServers` block in the client's MCP config. Any stdio-compatible
77
77
 
78
78
  ## What's in the box
79
79
 
80
- ~137 tools. The high-value entry points:
80
+ ~145 tools. The high-value entry points:
81
81
 
82
82
  - **Read first**: `design_context` (curated parameter cheat sheet, works offline) and `get_design_overview` (compact live snapshot). Prefer these over full `get_state` dumps or broad `get_parameter_info` sweeps.
83
83
  - **Sound design**: `set_parameters`, `update_pattern`, `add_modulation` / `add_param_seq`, `update_effect_config`, `set_master_effects`, `set_drum_synth`, `randomize` / `randomize_samples` / `randomize_patterns`.
84
84
  - **Samples**: `get_default_locations` → `list_samples` → `load_sample`, plus `trim/reverse/gain/normalize_sample`, `analyze_sample_tempo`, `resample_sample_to_bpm`, `build_sample_chain`.
85
- - **Transport & MIDI**: `start_transport` / `stop_transport` / `full_stop_transport`, `set_bpm`, `trigger_midi` (+ CC / program change), `midi_recording`.
85
+ - **Transport, MIDI & devices**: `start_transport` / `stop_transport` / `full_stop_transport`, `set_bpm`, `trigger_midi` (+ CC / program change), `midi_recording`; `get_audio_device_setup` / `set_audio_device` / `set_midi_io` (standalone).
86
86
  - **Presets, variations & songs**: `load_preset` / `save_preset` / `new_preset`, `save_variation` / `load_variation` / `queue_variation`, `song_mode`, `export_song` (full-track bounce), `export_audio` (incl. per-cell stems).
87
87
  - **Looper**: full 8-track control — arm/record/capture, `load_audio_to_looper_track`, warp, looper variations, `live_resample`.
88
88
  - **Plugin host** (PAM builds with hosting): `scan_plugins` → `get_plugin_scan_status` → `list_plugins` → `load_plugin` → `list_loaded_plugins` → `set_plugin_param` / `set_plugin_bypass`.
@@ -90,7 +90,9 @@ Use the same `mcpServers` block in the client's MCP config. Any stdio-compatible
90
90
  - **Video (VX) & UI** — require PAM's window to be open: `get_video_state`, `add_video_layer`, `bind_video_param`, `video_command`, …, and `capture_ui` (deterministic UI screenshot).
91
91
  - **Offline (manifest-only)**: `get_parameter_info`, `design_context`, `list_presets`, `read_preset`, `get_manifest_summary`.
92
92
 
93
- All three product manifests (PAM / CELL1 / MFX) are bundled; the server auto-selects by the connected instance's product, so one config entry drives all three products.
93
+ - **MFX**: `set_mfx_routing` reads and replaces the cable patch (`input` / `sidechain` → `cellN` → `output`). MFX-only; it errors on PAM and CELL1.
94
+
95
+ All three product manifests (PAM / CELL1 / MFX) are bundled; the server auto-selects by the connected instance's product, so one config entry drives all three products. Preset listing follows that product too — each has its own tree under `MAP Audio`.
94
96
 
95
97
  ## Agent ergonomics
96
98
 
@@ -0,0 +1,96 @@
1
+ export type DrumDispKind = "freq" | "time" | "note" | "st" | "ratio" | "pct" | "num";
2
+ export interface DrumParamDisplay {
3
+ kind: DrumDispKind;
4
+ lo?: number;
5
+ hi?: number;
6
+ /** Exact engine-unit anchor at norm 0.5; each half maps separately. */
7
+ center?: number;
8
+ curve?: "exp" | "lin";
9
+ digits?: number;
10
+ suffix?: string;
11
+ direction?: "pitchSweep";
12
+ }
13
+ export interface DrumRegistrySlot extends DrumParamDisplay {
14
+ label: string;
15
+ default: number;
16
+ bipolar?: boolean;
17
+ rand?: [number, number];
18
+ group: "pitch" | "gen" | "amp";
19
+ groupOrder: number;
20
+ }
21
+ export interface DrumSynthRegistry {
22
+ engines: Record<string, {
23
+ name: string;
24
+ slots: DrumRegistrySlot[];
25
+ }>;
26
+ }
27
+ export interface DrumSynthEngineDescriptor {
28
+ /** Engine enum value (1..N); 0 is Off and has no descriptor. */
29
+ id: number;
30
+ name: string;
31
+ params: {
32
+ label: string;
33
+ default: number;
34
+ bipolar?: boolean;
35
+ rand?: [number, number];
36
+ }[];
37
+ }
38
+ /** Breakpoint shape of cell{N}_synthAmpCurve — structurally the UI's CurvePoint. */
39
+ export interface DrumCurvePoint {
40
+ t: number;
41
+ v: number;
42
+ tension: number;
43
+ }
44
+ export type DrumSynthDelta = Record<string, number | DrumCurvePoint[]>;
45
+ export declare const DRUM_SYNTH_PARAMS_PER_CELL = 8;
46
+ /**
47
+ * Half the 0.001 manifest step for cell{N}_synth_pN, which also absorbs the
48
+ * float32 round-trip a normalized value takes through the host parameter. A slot
49
+ * within this of its engine's curated default was never touched, so an engine
50
+ * switch reseeds it instead of carrying it.
51
+ */
52
+ export declare const DRUM_SLOT_EDIT_EPSILON = 0.0005;
53
+ /** Must match DrumSynthCore::prepare (0.25 s) and the UI selector fallback. */
54
+ export declare const DEFAULT_DRUM_AMP_TIME_MS = 250;
55
+ /** Flat-at-unity: the no-op gain contour the C++ default seed renders. */
56
+ export declare const DEFAULT_DRUM_AMP_CURVE: DrumCurvePoint[];
57
+ /** normalized 0..1 → real engine-unit value (mirrors mapParamValue in C++). */
58
+ export declare function drumParamToReal(d: DrumParamDisplay, x: number): number;
59
+ /** real engine-unit value → normalized 0..1 (the inverse). */
60
+ export declare function drumParamFromReal(d: DrumParamDisplay, v: number): number;
61
+ export declare const isDrumSlotEdited: (value: unknown, curatedDefault: number) => boolean;
62
+ /**
63
+ * Move an edited value from one engine's slot to another's. `pct` slots carry the
64
+ * knob POSITION because their display IS the position; every unit-bearing family
65
+ * carries the engine value, re-normalized through the destination's own map and
66
+ * clamped into its range. Returns undefined when the two slots are not the same
67
+ * quantity.
68
+ */
69
+ export declare const carryDrumSlotValue: (src: DrumParamDisplay | undefined, dst: DrumParamDisplay | undefined, value: number) => number | undefined;
70
+ /**
71
+ * A drawn amp envelope shapes EVERY engine and its C++ latch is one-way, so an
72
+ * untouched (absent, or flat-at-unity over the default window) contour is cleared
73
+ * when the engine changes. Anything the user actually drew survives.
74
+ */
75
+ export declare const isDrumAmpEnvUntouched: (curve: unknown, timeMs: unknown) => boolean;
76
+ /**
77
+ * Empty array, not the flat curve: sampler.ts omits the ampEnvCurveLUT prop for an
78
+ * empty array and emits ampEnvActive: 0, which clears the node's one-way latch on
79
+ * the rebuild an engine change always triggers.
80
+ */
81
+ export declare const drumAmpEnvResetDelta: (cellId: number) => DrumSynthDelta;
82
+ export declare const drumSynthParamKey: (cellId: number | string, slot: number) => string;
83
+ export interface DrumSynthCatalog {
84
+ /** Index matches drumsynth::Engine — element 0 is 'Off'. */
85
+ engineNames: readonly string[];
86
+ engines: DrumSynthEngineDescriptor[];
87
+ getEngine(engineId: number): DrumSynthEngineDescriptor | undefined;
88
+ getDisplay(engineId: number, slot: number): DrumParamDisplay | undefined;
89
+ buildEngineSwitchDelta(cellId: number, nextEngineId: number, state: Record<string, unknown>): DrumSynthDelta;
90
+ }
91
+ /**
92
+ * Project the registry into the roster + switch rule. Taking the parsed JSON as an
93
+ * argument (rather than importing it) is what lets the published package read the
94
+ * copy vendored into dist/ while the repo checkout reads shared/.
95
+ */
96
+ export declare function createDrumSynthCatalog(registry: DrumSynthRegistry): DrumSynthCatalog;
@@ -0,0 +1,193 @@
1
+ // Drum-synth engine roster + engine-switch delta, built from
2
+ // shared/drumSynthEngines.json.
3
+ //
4
+ // The server used to carry its own copy of the roster (labels + normalized
5
+ // defaults) and its own engine-switch rule. Both drifted: Kick, Cowbell and 808
6
+ // kept their pre-anchor Tune defaults after the registry re-centred them, and
7
+ // the switch rule carried knob positions where the plugin carries engine units.
8
+ // A call over the bridge therefore landed somewhere the same call in the plugin
9
+ // does not (issue #999).
10
+ //
11
+ // Everything here mirrors interface/src/dsp/modules/drumSynth.ts, which is the
12
+ // implementation the UI hook and the in-plugin assistant executor both call.
13
+ // The published package cannot import across workspaces, so this is a vendored
14
+ // twin — interface/test/mcpDrumSynthParity.test.ts drives both over the same
15
+ // inputs and fails on any divergence.
16
+ export const DRUM_SYNTH_PARAMS_PER_CELL = 8;
17
+ /**
18
+ * Half the 0.001 manifest step for cell{N}_synth_pN, which also absorbs the
19
+ * float32 round-trip a normalized value takes through the host parameter. A slot
20
+ * within this of its engine's curated default was never touched, so an engine
21
+ * switch reseeds it instead of carrying it.
22
+ */
23
+ export const DRUM_SLOT_EDIT_EPSILON = 5e-4;
24
+ /** Must match DrumSynthCore::prepare (0.25 s) and the UI selector fallback. */
25
+ export const DEFAULT_DRUM_AMP_TIME_MS = 250;
26
+ /** Flat-at-unity: the no-op gain contour the C++ default seed renders. */
27
+ export const DEFAULT_DRUM_AMP_CURVE = [
28
+ { t: 0, v: 1, tension: 0 },
29
+ { t: 1, v: 1, tension: 0 },
30
+ ];
31
+ /**
32
+ * Unit families for the engine-switch carry. `kind` is display-only and is never
33
+ * read by the cook, so 'note' and 'freq' are the same physical quantity in Hz and
34
+ * share a family — they differ only in whether the UI renders "A1" or "55 Hz".
35
+ */
36
+ const DRUM_CARRY_FAMILY = {
37
+ note: "hz",
38
+ freq: "hz",
39
+ time: "s",
40
+ st: "st",
41
+ ratio: "ratio",
42
+ num: "num",
43
+ pct: "pct",
44
+ };
45
+ const clamp01 = (x) => (x < 0 ? 0 : x > 1 ? 1 : x);
46
+ /** normalized 0..1 → real engine-unit value (mirrors mapParamValue in C++). */
47
+ export function drumParamToReal(d, x) {
48
+ const lo = d.lo ?? 0;
49
+ const hi = d.hi ?? 1;
50
+ const t = clamp01(x);
51
+ const mapSegment = (segmentLo, segmentHi, segmentT) => d.curve === "exp"
52
+ ? segmentLo * Math.pow(segmentHi / segmentLo, segmentT)
53
+ : segmentLo + (segmentHi - segmentLo) * segmentT;
54
+ if (d.center === undefined)
55
+ return mapSegment(lo, hi, t);
56
+ if (t === 0.5)
57
+ return d.center;
58
+ return t < 0.5 ? mapSegment(lo, d.center, t * 2) : mapSegment(d.center, hi, (t - 0.5) * 2);
59
+ }
60
+ /** real engine-unit value → normalized 0..1 (the inverse). */
61
+ export function drumParamFromReal(d, v) {
62
+ const lo = d.lo ?? 0;
63
+ const hi = d.hi ?? 1;
64
+ const unmapSegment = (segmentLo, segmentHi) => {
65
+ if (d.curve === "exp") {
66
+ return clamp01(Math.log(Math.max(v, 1e-9) / segmentLo) / Math.log(segmentHi / segmentLo));
67
+ }
68
+ return segmentHi === segmentLo ? 0 : clamp01((v - segmentLo) / (segmentHi - segmentLo));
69
+ };
70
+ if (d.center === undefined)
71
+ return unmapSegment(lo, hi);
72
+ if (v === d.center)
73
+ return 0.5;
74
+ return v < d.center ? unmapSegment(lo, d.center) * 0.5 : 0.5 + unmapSegment(d.center, hi) * 0.5;
75
+ }
76
+ export const isDrumSlotEdited = (value, curatedDefault) => {
77
+ const numeric = Number(value);
78
+ if (!Number.isFinite(numeric))
79
+ return false;
80
+ return Math.abs(numeric - curatedDefault) > DRUM_SLOT_EDIT_EPSILON;
81
+ };
82
+ /**
83
+ * Move an edited value from one engine's slot to another's. `pct` slots carry the
84
+ * knob POSITION because their display IS the position; every unit-bearing family
85
+ * carries the engine value, re-normalized through the destination's own map and
86
+ * clamped into its range. Returns undefined when the two slots are not the same
87
+ * quantity.
88
+ */
89
+ export const carryDrumSlotValue = (src, dst, value) => {
90
+ if (!src || !dst)
91
+ return undefined;
92
+ const family = DRUM_CARRY_FAMILY[src.kind];
93
+ if (family === undefined || family !== DRUM_CARRY_FAMILY[dst.kind])
94
+ return undefined;
95
+ if (family === "pct")
96
+ return clamp01(value);
97
+ const real = drumParamToReal(src, value);
98
+ const lo = dst.lo ?? 0;
99
+ const hi = dst.hi ?? 1;
100
+ const bounded = Math.min(Math.max(real, Math.min(lo, hi)), Math.max(lo, hi));
101
+ return clamp01(drumParamFromReal(dst, bounded));
102
+ };
103
+ /**
104
+ * A drawn amp envelope shapes EVERY engine and its C++ latch is one-way, so an
105
+ * untouched (absent, or flat-at-unity over the default window) contour is cleared
106
+ * when the engine changes. Anything the user actually drew survives.
107
+ */
108
+ export const isDrumAmpEnvUntouched = (curve, timeMs) => {
109
+ const time = Number(timeMs ?? DEFAULT_DRUM_AMP_TIME_MS);
110
+ if (Number.isFinite(time) && Math.abs(time - DEFAULT_DRUM_AMP_TIME_MS) > 1e-6)
111
+ return false;
112
+ if (!Array.isArray(curve) || curve.length === 0)
113
+ return true;
114
+ if (curve.length !== DEFAULT_DRUM_AMP_CURVE.length)
115
+ return false;
116
+ return curve.every((point, i) => {
117
+ const ref = DEFAULT_DRUM_AMP_CURVE[i];
118
+ return (Math.abs(Number(point?.t) - ref.t) < 1e-6
119
+ && Math.abs(Number(point?.v) - ref.v) < 1e-6
120
+ && Math.abs(Number(point?.tension ?? 0) - (ref.tension ?? 0)) < 1e-6);
121
+ });
122
+ };
123
+ /**
124
+ * Empty array, not the flat curve: sampler.ts omits the ampEnvCurveLUT prop for an
125
+ * empty array and emits ampEnvActive: 0, which clears the node's one-way latch on
126
+ * the rebuild an engine change always triggers.
127
+ */
128
+ export const drumAmpEnvResetDelta = (cellId) => ({
129
+ [`cell${cellId}_synthAmpCurve`]: [],
130
+ [`cell${cellId}_synthAmpTime`]: DEFAULT_DRUM_AMP_TIME_MS,
131
+ });
132
+ export const drumSynthParamKey = (cellId, slot) => `cell${cellId}_synth_p${slot}`; // slot is 1-based
133
+ /**
134
+ * Project the registry into the roster + switch rule. Taking the parsed JSON as an
135
+ * argument (rather than importing it) is what lets the published package read the
136
+ * copy vendored into dist/ while the repo checkout reads shared/.
137
+ */
138
+ export function createDrumSynthCatalog(registry) {
139
+ const bySlot = registry.engines;
140
+ const ids = Object.keys(bySlot)
141
+ .map(Number)
142
+ .sort((a, b) => a - b);
143
+ const engineNames = ["Off", ...ids.map((id) => bySlot[String(id)].name)];
144
+ const engines = ids.map((id) => ({
145
+ id,
146
+ name: bySlot[String(id)].name,
147
+ params: bySlot[String(id)].slots.map((s) => ({
148
+ label: s.label,
149
+ default: s.default,
150
+ ...(s.bipolar ? { bipolar: true } : {}),
151
+ ...(s.rand ? { rand: s.rand } : {}),
152
+ })),
153
+ }));
154
+ const display = Object.fromEntries(ids.map((id) => [id, bySlot[String(id)].slots]));
155
+ const getEngine = (engineId) => engines.find((e) => e.id === engineId);
156
+ const getDisplay = (engineId, slot) => display[engineId]?.[slot - 1];
157
+ const buildEngineSwitchDelta = (cellId, nextEngineId, state) => {
158
+ const delta = { [`cell${cellId}_synthEngine`]: nextEngineId };
159
+ const nextEngine = getEngine(nextEngineId);
160
+ if (!nextEngine)
161
+ return delta;
162
+ const currentEngineId = Math.round(Number(state[`cell${cellId}_synthEngine`] ?? 0));
163
+ const currentEngine = getEngine(currentEngineId);
164
+ // Only slots the user MOVED off their curated default travel. An untouched
165
+ // cell therefore lands on the destination's factory voice exactly.
166
+ const editedByLabel = new Map();
167
+ currentEngine?.params.forEach((param, index) => {
168
+ const value = Number(state[drumSynthParamKey(cellId, index + 1)]);
169
+ if (isDrumSlotEdited(value, param.default)) {
170
+ editedByLabel.set(param.label, { slot: index + 1, value });
171
+ }
172
+ });
173
+ for (let i = 0; i < DRUM_SYNTH_PARAMS_PER_CELL; i++) {
174
+ const nextParam = nextEngine.params[i];
175
+ const paramId = drumSynthParamKey(cellId, i + 1);
176
+ if (!nextParam) {
177
+ delta[paramId] = 0.5; // manifest default for an unused slot
178
+ continue;
179
+ }
180
+ const edited = editedByLabel.get(nextParam.label);
181
+ const carried = edited
182
+ ? carryDrumSlotValue(getDisplay(currentEngineId, edited.slot), getDisplay(nextEngineId, i + 1), edited.value)
183
+ : undefined;
184
+ delta[paramId] = carried ?? nextParam.default;
185
+ }
186
+ if (isDrumAmpEnvUntouched(state[`cell${cellId}_synthAmpCurve`], state[`cell${cellId}_synthAmpTime`])) {
187
+ Object.assign(delta, drumAmpEnvResetDelta(cellId));
188
+ }
189
+ return delta;
190
+ };
191
+ return { engineNames, engines, getEngine, getDisplay, buildEngineSwitchDelta };
192
+ }
193
+ //# sourceMappingURL=drumSynth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drumSynth.js","sourceRoot":"","sources":["../src/drumSynth.ts"],"names":[],"mappings":"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"}