pitch-mcp
MCP server for real-time pitch detection and score alignment. Listens to a singer via microphone and reports their current position in a score and whether they are singing in tune.
What it does
Covers three goals:
- Goal 4 — Show the current measure/beat position while singing
- Goal 5 — Report pitch accuracy (too high / too low / on pitch)
- Goal 6 — Identify where in the score a singer is based on a hummed or sung phrase
Supports both offline analysis of pre-recorded audio and real-time microphone input.
Tools
| Tool | Description |
|---|---|
analyze_recording |
Offline: analyse a WAV file against a reference MusicXML score |
load_score |
Load a MusicXML score into a named session; returns a session_id |
start_monitoring |
Open the microphone and begin real-time pitch detection |
get_current_position |
Poll the current score position and pitch accuracy |
stop_monitoring |
Stop the microphone and return a session summary |
list_capabilities |
Return server metadata: pitch backend, microphone availability |
health_check |
Check that runtime dependencies (librosa, sounddevice/portaudio) are available |
Installation
cd pitch-mcp
uv sync
For real-time monitoring (start_monitoring), PortAudio is required:
# Ubuntu / Debian
sudo apt install libportaudio2
Quick install: on Ubuntu/Debian/Linux Mint, bash install.sh handles uv and the optional
libportaudio2 install for you — see SETUP.md for the full non-technical walkthrough.
Ready-made client configs (Claude Desktop, Cursor, Windsurf, Continue, Zed) are in
examples/. If something goes wrong, check TROUBLESHOOTING.md.
Running
uv run pitch-mcp
Configuration
| Variable | Default | Description |
|---|---|---|
PITCH_BACKEND |
librosa |
Pitch detection algorithm: librosa or crepe |
crepe requires a manual TensorFlow install (~500 MB) and downloads ~50 MB of model weights on first use. The default librosa backend (pYIN algorithm) works well for singing voice with no extra setup.
Usage examples
// Offline analysis of a recording
{
"tool": "analyze_recording",
"arguments": {
"wav_path": "/path/to/recording.wav",
"musicxml_path": "/path/to/score.mxl",
"part_name": "Soprano"
}
}
// Real-time session
{"tool": "load_score", "arguments": {"musicxml_path": "/path/to/score.mxl", "part_name": "Alto"}}
// → returns {"session_id": "abc123"}
{"tool": "start_monitoring", "arguments": {"session_id": "abc123"}}
{"tool": "get_current_position", "arguments": {"session_id": "abc123"}}
// → returns measure, beat, expected pitch, detected pitch, accuracy
{"tool": "stop_monitoring", "arguments": {"session_id": "abc123"}}
Audio must be 16-bit PCM WAV. MP3 and FLAC are not supported.
Testing
# Unit tests (no microphone or audio required)
VIRTUAL_ENV= .venv/bin/pytest tests/ -v
All 100 current tests are unit tests, run against mocks and synthetic (in-memory) WAV data — none require real audio hardware or pre-recorded fixtures.
The integration and manual pytest markers are registered in pyproject.toml and reserved for
future Phase B work (fixture-based offline analysis and real-microphone tests, respectively), but
no tests are marked with them yet, so -m integration / -m manual currently select nothing.
Dependencies
- librosa — pYIN pitch detection (primary backend, pure Python)
- music21 — score parsing and pitch calculations
- sounddevice — real-time microphone input
- numpy, scipy — numerics
- mcp — MCP protocol
System requirements
- Python 3.12+
libportaudio2— required for real-time microphone input (start_monitoring)- No system libraries required for offline analysis
Phase status
| Phase | Status |
|---|---|
| Phase A — offline analysis | Complete. DTW-based alignment (dtaidistance); 112 unit tests plus 4 -m integration tests against a committed fixture pair (tests/fixtures/) |
| Phase B — real-time monitoring | Complete. Position tracking is audio-driven (matches detected pitch, not just elapsed time); tempo_bpm override supported. Covered by unit tests with mocked sounddevice; full-lifecycle -m manual tests exist for real-microphone verification but require real hardware to run |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pitch_mcp-0.2.0.tar.gz.
File metadata
- Download URL: pitch_mcp-0.2.0.tar.gz
- Upload date:
- Size: 603.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c9cd24db59f8c27bb56522b187b6fd4aadab8b91f92f69277fd53754ae634523
|
|
| MD5 |
b5cc59bf56ad03dcfa7e730098fb0772
|
|
| BLAKE2b-256 |
717594f8f4761bf40d50b0d97c41645f2a803222578fb1aec04b96b9e7491d40
|
Provenance
The following attestation bundles were made for pitch_mcp-0.2.0.tar.gz:
Publisher:
publish.yml on raulkivi/music-assistant
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pitch_mcp-0.2.0.tar.gz -
Subject digest:
c9cd24db59f8c27bb56522b187b6fd4aadab8b91f92f69277fd53754ae634523 - Sigstore transparency entry: 2485427466
- Sigstore integration time:
-
Permalink:
raulkivi/music-assistant@45cd0b49d14509ebe09650866d077245edd6f945 -
Branch / Tag:
refs/tags/pitch-mcp/v0.2.0 - Owner: https://github.com/raulkivi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@45cd0b49d14509ebe09650866d077245edd6f945 -
Trigger Event:
push
-
Statement type:
File details
Details for the file pitch_mcp-0.2.0-py3-none-any.whl.
File metadata
- Download URL: pitch_mcp-0.2.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84dbfce4b1d4136c87add2e73351b22956ed1682eb81311f775b4a6e9f29a2fa
|
|
| MD5 |
d532ab9d9cb7240309830f127d022931
|
|
| BLAKE2b-256 |
189323f4de5e58b82285edf1d4101ea7ea88a332d7ae41d1ac6a50028366fc06
|
Provenance
The following attestation bundles were made for pitch_mcp-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on raulkivi/music-assistant
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pitch_mcp-0.2.0-py3-none-any.whl -
Subject digest:
84dbfce4b1d4136c87add2e73351b22956ed1682eb81311f775b4a6e9f29a2fa - Sigstore transparency entry: 2485427545
- Sigstore integration time:
-
Permalink:
raulkivi/music-assistant@45cd0b49d14509ebe09650866d077245edd6f945 -
Branch / Tag:
refs/tags/pitch-mcp/v0.2.0 - Owner: https://github.com/raulkivi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@45cd0b49d14509ebe09650866d077245edd6f945 -
Trigger Event:
push
-
Statement type: