Playbykey Music Theory

An MCP server exposing @playbykey/theory as AI-callable, computed music theory tools, includes chords, scales, progressions, transpositions, and MIDI/frequency conversions.

Документация

@playbykey/theory-mcp

An MCP server that exposes @playbykey/theory as AI-callable music theory tools.

MCP lets an AI assistant call the theory engine directly as tools instead of reasoning about scales, modes, and key relationships from training data. Music theory relationships, resolved deterministically through fixed interval and scale-degree relationships.

See the @playbykey/mcp page for the same setup instructions and full tool reference.

Installation

No global install needed - npx fetches and runs the package on demand. Requires Node.js (for npx).

Claude Desktop

Edit the MCP config file (claude_desktop_config.json) via Claude Desktop's settings.

{
  "mcpServers": {
    "theory": {
      "command": "npx",
      "args": ["-y", "@playbykey/theory-mcp"]
    }
  }
}

Restart Claude Desktop after saving, then check its settings to confirm theory shows as connected.

Cursor

Config file location:

  • Global (all projects): ~/.cursor/mcp.json
  • Project only: .cursor/mcp.json in your project root
{
  "mcpServers": {
    "theory": {
      "command": "npx",
      "args": ["-y", "@playbykey/theory-mcp"]
    }
  }
}

Restart Cursor after saving, then check its MCP settings to confirm theory shows as connected.

Claude Code

Project scope (recommended) - commit an .mcp.json at your repo root so the server is available to every contributor after git clone:

{
  "mcpServers": {
    "theory": {
      "command": "npx",
      "args": ["-y", "@playbykey/theory-mcp"]
    }
  }
}

Local scope - register the server for yourself in this project only, without committing anything:

claude mcp add theory npx -y @playbykey/theory-mcp

Global scope - register the server for yourself across every project on this machine:

claude mcp add theory npx -y @playbykey/theory-mcp --scope user

Run claude mcp list to confirm theory shows as connected.

Tools

Modes

get_mode_notes - Returns the 7 notes of a diatonic mode.
Input: root (note), mode (mode name)
Example: get_mode_notes("D", "dorian") → D, E, F, G, A, B, C

get_parent_scale_modes - Returns all 7 modal rotations of the parent key.
Input: root (note), mode (mode name)
Example: get_parent_scale_modes("D", "dorian") → C ionian, D dorian, E phrygian, F lydian, G mixolydian, A aeolian, B locrian

get_modal_root - Returns the root note of a mode within a parent (major) key.
Input: parent_key (note), mode (mode name)
Example: get_modal_root("C", "dorian") → D

get_relative_minor - Returns the relative minor root for a major key.
Input: major_key (note)
Example: get_relative_minor("C") → A

get_relative_major - Returns the relative major root for a minor key.
Input: minor_key (note)
Example: get_relative_major("A") → C

get_mode_info - Returns display metadata for a mode: name, scale degree, and characteristic description.
Input: mode (mode name)
Example: get_mode_info("dorian") → Dorian, degree 2, "Minor with a raised 6th"

Circle of Fifths

get_circle_of_fifths - Returns all 12 chromatic notes in ascending-fifths order starting from C.
Input: none
Example → C, G, D, A, E, B, F#, C#, G#, D#, A#, F

Key Signatures

get_key_signature - Returns the sharp or flat count for a given key, treated as a major-key tonic (minor-key signatures are not exposed by this tool).
Input: key (note)
Example: get_key_signature("D") → 2 sharps

Scales

get_scale_notes - Returns the notes of a scale by type.
Input: root (note), scale_type (one of: major, blues, pentatonic-major, pentatonic-minor, harmonic-minor, melodic-minor, chromatic)
Example: get_scale_notes("A", "blues") → A, C, D, D#, E, G

build_note_map - Returns structured per-note data: note name, scale degree (1-based), and semitone offset from root.
Input: root (note), scale_type
Example: build_note_map("C", "major")[{note:"C", scaleDegree:1, semitoneOffset:0}, {note:"D", scaleDegree:2, semitoneOffset:2}, ...]

get_scale_degree - Returns the 1-based scale degree of a note within a scale, or null if the note is not in the scale.
Input: root (note), scale_type, note (note)
Example: get_scale_degree("C", "major", "E") → 3

is_note_in_scale - Returns whether a note belongs to a given scale.
Input: root (note), scale_type, note (note)
Example: is_note_in_scale("C", "major", "F#") → false

get_melodic_minor_notes - Returns the seven notes of the ascending melodic minor scale.
Input: root (note)
Example: get_melodic_minor_notes("C") → C, D, D#, F, G, A, B

get_melodic_minor_mode_notes - Returns the seven notes of a melodic minor mode.
Input: root (note), mode (one of: melodic-minor, dorian-b2, lydian-augmented, lydian-dominant, mixolydian-b6, locrian-nat2, altered)
Example: get_melodic_minor_mode_notes("C", "altered") → C, C#, D#, E, F#, G#, A#

get_harmonic_minor_mode_notes - Returns the seven notes of a harmonic minor mode.
Input: root (note), mode (one of: harmonic-minor, phrygian-dominant)
Example: get_harmonic_minor_mode_notes("C", "phrygian-dominant") → C, C#, E, F, G, G#, A#

get_bebop_scale_notes - Returns the eight notes of a bebop scale variant - a diatonic scale plus one chromatic passing tone.
Input: root (note), type (one of: bebop-dominant, bebop-major, bebop-dorian)
Example: get_bebop_scale_notes("C", "bebop-dominant") → C, D, E, F, G, A, A#, B

Intervals

resolve_interval - Returns the from-note and to-note for a named interval within a root context.
Input: root (note), interval (interval ID, e.g. major_3rd, perfect_5th)
Example: resolve_interval("C", "major_3rd") → C to E (4 semitones)

get_semitone_distance - Returns the ascending semitone distance between two notes (0-11).
Input: from (note), to (note)
Example: get_semitone_distance("C", "E") → 4

Note Spelling

get_sharps - Respells a list of notes to canonical sharp spelling. Most tools accept flat-spelled input directly, but get_flats and get_enharmonic_labels require sharp-spelled input - use this to normalize flat-spelled notes before calling those two.
Input: notes (sharp or flat)
Example: get_sharps(["Db", "C#", "D"]) → C#, C#, D

get_flats - Respells a list of sharp-spelled notes as flats. Natural notes are unaffected.
Input: notes (must be sharp-spelled)
Example: get_flats(["C#", "D"]) → Db, D

get_enharmonic_labels - Returns combined sharp/flat display labels for a list of sharp-spelled notes. Natural notes are unaffected.
Input: notes (must be sharp-spelled)
Example: get_enharmonic_labels(["C#", "D"]) → Db/C#, D

Chords

get_chord_notes - Returns the notes of a chord given a root and chord type.
Input: root (note), chord_type (one of the 11 chord types, e.g. major-triad, dominant-7th, major-9th)
Example: get_chord_notes("C", "major-triad") → C, E, G

get_diatonic_chords - Returns the 7 diatonic triads for a key/mode, one per scale degree, in degree order.
Input: root (note), mode (mode name, optional - defaults to ionian)
Example: get_diatonic_chords("C", "ionian") → C major-triad, D minor-triad, E minor-triad, F major-triad, G major-triad, A minor-triad, B diminished-triad

get_chord_by_degree - Returns the diatonic chord at a specific scale degree (1-7) for a key/mode.
Input: degree (integer 1-7), root (note), mode (mode name, optional - defaults to ionian)
Example: get_chord_by_degree(5, "C", "ionian") → G major-triad

get_available_inversions - Returns the valid inversion numbers for a chord type, based on its note count.
Input: chord_type
Example: get_available_inversions("major-9th") → 0, 1, 2, 3, 4

get_chord_inversion - Reorders a chord's notes so the given inversion's chord tone is lowest.
Input: root (note), chord_type, inversion (integer, valid range depends on chord type)
Example: get_chord_inversion("C", "major-triad", 1) → E, G, C

Progressions

get_progression_in_key - Renders a named catalog progression as chords in a given key, in order.
Input: progression_id (one of I-V-vi-IV, ii-V-I, I-IV-V, vi-IV-I-V, 12-bar-blues), root (note)
Example: get_progression_in_key("I-V-vi-IV", "C") → C major-triad, G major-triad, A minor-triad, F major-triad

get_roman_numeral - Returns the roman numeral for a scale degree in a mode - case and suffix reflect diatonic triad quality.
Input: degree (integer 1-7), mode (mode name, optional - defaults to ionian)
Example: get_roman_numeral(7, "ionian") → vii°

Transposition

transpose - Transposes a set of notes from one key to another by the semitone distance between the two roots.
Input: notes (array of notes), from_root (note), to_root (note)
Example: transpose(["C", "E", "G"], "C", "D") → D, F#, A

MIDI & Frequency

note_to_midi - Returns the MIDI note number for a note at a given octave, using scientific pitch notation (C4 = middle C = MIDI 60).
Input: note (note), octave (integer)
Example: note_to_midi("C", 4) → 60

midi_to_note - Returns the note and octave for a given MIDI note number - the inverse of note_to_midi.
Input: midi_number (integer 0-127)
Example: midi_to_note(69) → A4

note_to_frequency - Returns the frequency in Hz for a note at a given octave, equal temperament, A4 = 440Hz.
Input: note (note), octave (integer)
Example: note_to_frequency("A", 4) → 440 Hz

License

MIT