generate_chord_progression
Create chord progressions by specifying a key and musical style such as pop, jazz, or blues.
Instructions
Generate chord progression
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| key | Yes | Key | |
| style | Yes | Style (pop/jazz/blues/etc) |
Implementation Reference
- src/server/tools/generate.ts:197-203 (handler)Handler function that executes 'generate_chord_progression'. Validates inputs (root note + chord style), calls MusicTheory.generateChordProgression() to get the progression string, then calls PatternGenerator.generateChords() to produce the Strudel pattern, and finally appends it to the current pattern.
case 'generate_chord_progression': { InputValidator.validateRootNote(args.key); InputValidator.validateChordStyle(args.style); const progression = ctx.theory.generateChordProgression(args.key, args.style); const chordPattern = ctx.generator.generateChords(progression); await appendOrSet(chordPattern, ctx); return `Generated ${args.style} progression in ${args.key}: ${progression}`; - src/server/tools/generate.ts:84-95 (schema)Tool registration with inputSchema — defines 'generate_chord_progression' requiring 'key' (string) and 'style' (string) parameters.
{ name: 'generate_chord_progression', description: 'Generate chord progression', inputSchema: { type: 'object', properties: { key: { type: 'string', description: 'Key' }, style: { type: 'string', description: 'Style (pop/jazz/blues/etc)' }, }, required: ['key', 'style'], }, }, - src/server/tools/generate.ts:239-240 (registration)Module exports: tools array, toolNames set, and execute function are bundled into generateModule, which is imported by server.ts.
export const generateModule: ToolModule = { tools, toolNames, execute }; - src/services/MusicTheory.ts:62-103 (helper)Core music theory logic: generateChordProgression() maps Roman numeral patterns (from chordProgressions dict) to actual chord names using the given key. Supports styles: pop, jazz, blues, folk, rock, classical, modal, edm.
generateChordProgression(key: string, style: keyof typeof this.chordProgressions): string { const progression = this.chordProgressions[style]; if (!progression) { throw new Error(`Invalid progression style: ${style}`); } const chordMap: Record<string, string> = { 'I': key, 'I7': `${key}7`, 'i': `${key.toLowerCase()}m`, 'ii': `${this.getNote(key, 2)}m`, 'IIM7': `${this.getNote(key, 2)}m7`, 'iii': `${this.getNote(key, 4)}m`, 'III': this.getNote(key, 4), 'IV': this.getNote(key, 5), 'IV7': `${this.getNote(key, 5)}7`, 'V': this.getNote(key, 7), 'V7': `${this.getNote(key, 7)}7`, 'vi': `${this.getNote(key, 9)}m`, 'VI': this.getNote(key, 9), 'VII': this.getNote(key, 11), 'bVII': this.getNote(key, 10), 'IM7': `${key}maj7` }; return progression .map(chord => chordMap[chord] || key) .join(' '); } /** * Calculates a note at a given interval from the root * @param root - Root note name * @param semitones - Number of semitones to transpose * @returns Transposed note name */ getNote(root: string, semitones: number): string { const noteNames = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']; const rootIndex = noteNames.indexOf(root.toUpperCase()); if (rootIndex === -1) return root; return noteNames[(rootIndex + semitones) % 12]; } - PatternGenerator.generateChords() converts the progression string (e.g., 'C G Am F') into a Strudel pattern code with voicing options (triad, seventh, sustained, stab, pad).
generateChords(progression: string, voicing: string = 'triad'): string { const voicings: Record<string, string> = { triad: '.struct("1 ~ ~ ~")', seventh: '.struct("1 ~ ~ ~").add(note("7"))', sustained: '.attack(0.5).release(2)', stab: '.struct("1 ~ 1 ~").release(0.1)', pad: '.attack(2).release(4).room(0.8)' }; return `note("<${progression}>").s("sawtooth")${voicings[voicing] || voicings.triad}`; }