Mingus Chord Suggestion Tool
by sarunabh
README.md
# Mingus Chord Suggestion Tool
An MCP server that takes a chord progression, identifies what's not working, applies a style filter, and returns chord suggestions backed by music theory and Claude's reasoning.
## Architecture
```
┌─────────────────────────────────────────────────┐
│ MCP Client │
│ (Claude Desktop, etc.) │
└────────────────────┬────────────────────────────┘
│ stdio (JSON-RPC)
┌────────────────────▼────────────────────────────┐
│ server.py │
│ MCP tool: suggest_chords │
└──────┬───────────────────────┬──────────────────┘
│ │
┌──────▼──────┐ ┌────────▼────────┐
│music_theory │ │ style.py │
│ .py │ │ │
│ │ │ vibe vocabulary │
│ - parse │ │ - annotate │
│ chords │ │ candidates │
│ - infer key │ │ - extended │
│ - generate │ │ chord gens │
│ diatonic │ │ (jazz/rnb) │
│ + borrowed│ └────────┬────────┘
│ candidates│ │
└──────┬──────┘ │
│ top candidates │
└───────────┬───────────┘
│
┌─────────▼──────────┐
│ claude_advisor.py │
│ │
│ Anthropic API │
│ - final selection │
│ - theory rationale│
│ - vibe rationale │
│ - placement hint │
└────────────────────┘
```
### Three-layer design
**Layer 1 — `music_theory.py` (mingus)**
- Parses chord shorthand to note sets
- Infers the most likely key by scoring all major/minor keys against the note content of the input chords
- Generates diatonic triads, diatonic seventh chords, and common borrowed chords (bVII, bVI, minor iv) as raw candidates
**Layer 2 — `style.py` (rule-based filter)**
- Maps each vibe to a chord vocabulary: preferred chord types, preferred quality suffixes
- Scores and labels each candidate as `strong fit`, `possible`, or `unlikely`
- Generates vibe-specific extended chords (jazz: maj9/m9/dom9/m7b5; R&B: sus4/7sus4/m9)
**Layer 3 — `claude_advisor.py` (Anthropic API)**
- Receives the top-scored candidates, the inferred key, the issue, and the vibe description
- Selects 2-3 final suggestions, writing theory rationale and vibe rationale for each
- Can go outside the candidate list if a better option exists
- Returns structured JSON
## Tool interface
**Tool name:** `suggest_chords`
**Input:**
```json
{
"chords": ["Em", "Gmaj7"],
"issue": "want a third chord that creates tension before resolving back to Em",
"vibe": "jazzy"
}
```
**Output:**
```json
{
"suggestions": [
{
"chord": "Am7",
"theory": "Am7 is the vi7 in G major, a minor subdominant with a 7th. It creates a ii-V-I feel when followed by D7 → Gmaj7, or delivers a deceptive resolution if you return to Em instead.",
"vibe_rationale": "The m7 quality is a jazz staple. The A-C-E-G voicing offers smooth voice leading from Gmaj7 (G-B-D-F#) by dropping B to A and F# to G.",
"placement": "Between Gmaj7 and Em as a passing chord"
}
],
"overall_note": "The progression has a vi-I feel; adding a ii chord turns it into a classic jazz ii-I-vi loop.",
"context": {
"inferred_key": "G major",
"input_progression": ["Em", "Gmaj7"],
"vibe": "jazzy",
"candidate_count": 21
}
}
```
## Setup
### 1. Install dependencies
```bash
cd mingus-chord-tool
pip install -r requirements.txt
```
### 2. Set the API key
```bash
export ANTHROPIC_API_KEY="sk-ant-..."
```
### 3. Register with Claude Desktop
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"mingus-chord-tool": {
"command": "python",
"args": ["/absolute/path/to/mingus-chord-tool/server.py"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-..."
}
}
}
}
```
Restart Claude Desktop. The `suggest_chords` tool will appear in the tools panel.
### 4. Test without Claude Desktop
```bash
python -c "
from music_theory import summarize_theory
from style import annotate_candidates, get_vibe_context
theory = summarize_theory(['Em', 'Gmaj7'])
print('Key:', theory['inferred_key'], theory['inferred_mode'])
scored = annotate_candidates(theory['novel_candidates'], 'jazzy')
for c in scored[:5]:
print(c['chord'], '-', c['vibe_label'])
"
```
## Design decisions
**Why not Spotify?**
Spotify's API exposes audio features (tempo, energy, valence) but not chord data. Chord inference from audio exists but is error-prone and adds a heavy dependency. Mingus computes harmony directly, which is more reliable for this use case.
**Why mingus for theory and Claude for suggestions?**
Mingus is deterministic -- it generates every diatonic and borrowed candidate without hallucinating. Claude's strength is contextual judgment: picking between candidates, balancing tension vs. resolution, and writing coherent rationale. Splitting the work this way means Claude never invents notes that don't belong to a chord, while still applying musical taste.
**Why a scored candidate list rather than asking Claude to reason from scratch?**
Passing scored candidates constrains the search space and gives Claude grounding. It also means the `vibe_label` in the output is independently computed -- you can verify it against the theory layer without trusting Claude's self-report.
**Key inference method**
The server scores every major and minor key by counting how many notes in the input chords belong to that key. This is a weighted note-overlap approach, not a full Roman numeral analysis. It works well for common progressions but will misfire on heavily chromatic or modal music. A more robust approach would add Roman numeral parsing and handle secondary dominants explicitly.
## Extending
- Add `modal` as a vibe (Dorian: ii7, bVII; Lydian: #IV, I; Phrygian: bII)
- Add a `mode` override parameter to skip key inference
- Add a `secondary_dominants` layer that computes V/ii, V/IV, V/V for each candidate
- Persist suggestion history and detect patterns across sessions
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues