@williamzujkowski/live-coding-music-mcp 4.0.0 → 4.1.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.
Files changed (53) hide show
  1. package/README.md +202 -705
  2. package/dist/AudioAnalyzer.js +1294 -91
  3. package/dist/PatternStore.js +276 -23
  4. package/dist/StrudelController.js +388 -56
  5. package/dist/server/resources.js +27 -20
  6. package/dist/server/server.js +384 -76
  7. package/dist/server/tools/ai.js +124 -91
  8. package/dist/server/tools/analysis.js +168 -59
  9. package/dist/server/tools/capture.js +135 -24
  10. package/dist/server/tools/compose.js +26 -26
  11. package/dist/server/tools/diagnostics.js +20 -3
  12. package/dist/server/tools/editor.js +60 -6
  13. package/dist/server/tools/generate.js +38 -15
  14. package/dist/server/tools/history.js +30 -8
  15. package/dist/server/tools/playback.js +2 -1
  16. package/dist/server/tools/session.js +38 -6
  17. package/dist/server/tools/storage.js +179 -8
  18. package/dist/server/tools/transform.js +127 -43
  19. package/dist/server/tools/types.js +209 -14
  20. package/dist/services/AudioCaptureService.js +302 -33
  21. package/dist/services/AudioExportService.js +318 -0
  22. package/dist/services/BrowserOnlyFunctions.js +149 -0
  23. package/dist/services/EventDensityProbe.js +324 -0
  24. package/dist/services/GeminiService.js +221 -36
  25. package/dist/services/IsolatedEngineRunner.js +308 -0
  26. package/dist/services/IsolatedStrudelEngine.js +135 -0
  27. package/dist/services/LocalPatternEngine.js +16 -0
  28. package/dist/services/MIDIExportService.js +765 -71
  29. package/dist/services/MIDIImportService.js +474 -0
  30. package/dist/services/MusicTheory.js +85 -13
  31. package/dist/services/PatternGenerator.js +168 -85
  32. package/dist/services/PatternSandbox.js +359 -0
  33. package/dist/services/SessionManager.js +338 -65
  34. package/dist/services/StrudelEngine.js +218 -12
  35. package/dist/services/StrudelEngineHelpers.js +24 -8
  36. package/dist/services/StyleRegistry.js +204 -0
  37. package/dist/services/Transferable.js +114 -0
  38. package/dist/services/ai/AiTransport.js +56 -0
  39. package/dist/services/ai/AudioMeasurements.js +155 -0
  40. package/dist/services/ai/CliTransport.js +256 -0
  41. package/dist/services/engineChild.js +83 -0
  42. package/dist/services/engineChildPath.js +28 -0
  43. package/dist/utils/CategorisedError.js +59 -0
  44. package/dist/utils/ErrorRecovery.js +130 -110
  45. package/dist/utils/InputValidator.js +55 -7
  46. package/dist/utils/PatternValidator.js +136 -17
  47. package/dist/utils/SafePath.js +112 -0
  48. package/dist/utils/ServerConfig.js +248 -0
  49. package/dist/utils/TableLookup.js +41 -0
  50. package/dist/utils/Tempo.js +143 -0
  51. package/package.json +17 -5
  52. package/dist/services/__mocks__/StrudelEngine.js +0 -157
  53. package/dist/types/index.js +0 -1
@@ -31,6 +31,7 @@ import { sessionModule } from './tools/session.js';
31
31
  import { captureModule } from './tools/capture.js';
32
32
  import { aiModule } from './tools/ai.js';
33
33
  import { composeModule } from './tools/compose.js';
34
+ import { TEMPO_BY_STYLE } from '../services/StyleRegistry.js';
34
35
  export const resources = [
35
36
  {
36
37
  uri: 'strudel://examples',
@@ -41,7 +42,7 @@ export const resources = [
41
42
  {
42
43
  uri: 'strudel://patterns',
43
44
  name: 'Saved patterns',
44
- description: 'Patterns saved by the user via the `save` tool, with tags and timestamps',
45
+ description: 'Patterns saved by the user via the `pattern_store` tool, with tags and timestamps',
45
46
  mimeType: 'application/json',
46
47
  },
47
48
  {
@@ -66,23 +67,16 @@ export function isResourceUri(uri) {
66
67
  * compose.ts:TEMPO_BY_STYLE — both grow together when a new genre
67
68
  * lands. Future cleanup (#120 aftermath): single source of truth.
68
69
  */
69
- const STYLE_DEFAULTS = {
70
- techno: 130,
71
- house: 125,
72
- dnb: 174,
73
- ambient: 80,
74
- trap: 140,
75
- jungle: 160,
76
- jazz: 110,
77
- experimental: 120,
78
- dubstep: 140,
79
- trance: 138,
80
- breakbeat: 130,
81
- garage: 130,
82
- electro: 128,
83
- downtempo: 90,
84
- idm: 115,
85
- };
70
+ // The style list is no longer duplicated here.
71
+ //
72
+ // This was a hand-maintained copy, and it had drifted: it omitted
73
+ // intelligent_dnb, trip_hop and boom_bap — the only three genres with
74
+ // BOTH dedicated drums and a dedicated bassline — plus acid, dub and
75
+ // funk. An agent using this resource to discover what the generator
76
+ // accepts would never find trip_hop. The comment above it claimed it
77
+ // was "kept in sync with compose.ts:TEMPO_BY_STYLE", but that table
78
+ // moved to StyleRegistry and nothing guarded the copy (#341).
79
+ const STYLE_DEFAULTS = TEMPO_BY_STYLE;
86
80
  const TOOL_MODULES = [
87
81
  editorModule,
88
82
  playbackModule,
@@ -128,14 +122,27 @@ async function readExamples(examplesDir) {
128
122
  return { count: items.length, examples: items };
129
123
  }
130
124
  async function readSavedPatterns(store) {
131
- const patterns = await store.list();
125
+ // `listDetailed`, not `list`.
126
+ //
127
+ // #426 made the store keep going past a file it cannot read and report
128
+ // how many it skipped, because one truncated `.json` used to make
129
+ // every saved pattern list as zero. The `pattern_store` tool got that
130
+ // count; this resource did not, so it still reported `count: N` with
131
+ // unreadable files dropped in silence (#442).
132
+ const { patterns, skipped } = await store.listDetailed();
132
133
  const items = patterns.map(p => ({
133
134
  name: p.name,
134
135
  tags: p.tags,
135
136
  timestamp: p.timestamp,
136
137
  contentPreview: p.content.length > 200 ? p.content.slice(0, 200) + '...' : p.content,
137
138
  }));
138
- return { count: items.length, patterns: items };
139
+ return {
140
+ count: items.length,
141
+ patterns: items,
142
+ // Only when there is something to say, so the common shape is
143
+ // unchanged for callers already parsing this.
144
+ ...(skipped > 0 ? { skipped, note: `${String(skipped)} file(s) could not be read and were skipped.` } : {}),
145
+ };
139
146
  }
140
147
  function readStyles() {
141
148
  const items = Object.entries(STYLE_DEFAULTS)