Dorico MCP Server
Enables natural language control of Steinberg Dorico music notation software, allowing creation of scores, note input, notation, harmony analysis, orchestration checks, and more via the Dorico Remote Control API.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Dorico MCP Server Create a string quartet in G major, 3/4 time, tempo 120"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Dorico MCP Server
π΅ Control Dorico via Claude Desktop or ChatGPT - A gift for composition majors
This MCP (Model Context Protocol) server enables natural language control of Steinberg Dorico music notation software through Claude Desktop or ChatGPT Desktop.
Features
πΉ Core Score Tools
Create new scores with custom instruments
Save and export scores (PDF, MusicXML)
Navigate through the score
πΌ Note Input
Add notes with pitch, duration, and articulation
Create chords
Add rests and ties
π Notation
Set key signatures (all major and minor keys)
Set time signatures
Add dynamics (pp, p, mp, mf, f, ff, etc.)
Add tempo markings
Add slurs and articulations
π΅ Harmony Tools (νμ±ν)
Analyze chord quality and Roman numerals
Suggest next chords based on context
Generate chord progressions
Check voice leading rules (parallel 5ths/8ves)
π» Orchestration Tools (μ€μΌμ€νΈλ μ΄μ )
Complete instrument database with ranges
Check playability (instrument range validation)
Transposition for transposing instruments
Get detailed instrument information
π Query Tools
Get flows, layouts, and selection properties
Access engraving, layout, and notation options
π Guided Workflows (Prompts)
Harmonize a melody
Orchestrate piano scores
Species counterpoint exercises
Related MCP server: fl-studio-mcp
Installation
Prerequisites
Python 3.11+
Steinberg Dorico (with Remote Control enabled)
Claude Desktop or ChatGPT Desktop
Install from PyPI (Recommended)
pip install dorico-mcp-serverInstall from Source (Development)
git clone https://github.com/happycastle114/dorico-mcp-server.git
cd dorico-mcp-server
pip install -e ".[dev]"Enable Dorico Remote Control
Open Dorico
Go to Preferences β General
Enable Allow remote control
Note the port number (usually 4560)
Configuration
Claude Desktop
Add to your Claude Desktop configuration:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
Linux: ~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"dorico": {
"command": "python",
"args": ["-m", "dorico_mcp.server", "--stdio"]
}
}
}ChatGPT Desktop
Add to your ChatGPT Desktop configuration:
macOS: ~/Library/Application Support/com.openai.chat/mcp.json
Windows: %LOCALAPPDATA%\com.openai.chat\mcp.json
Linux: ~/.config/com.openai.chat/mcp.json
{
"mcpServers": {
"dorico": {
"command": "python",
"args": ["-m", "dorico_mcp.server", "--stdio"]
}
}
}Note: Restart the app after updating the configuration.
Usage Examples
Creating a Score
"Create a new score for string quartet in G major, 3/4 time, tempo 120"Adding Notes
"Add a C major chord (C4, E4, G4) as quarter notes"
"Add a melody: C4, D4, E4, F4, G4 as eighth notes"Harmony Analysis
"What chord would work well after I-IV-V?"
"Generate a 8-bar chord progression in A minor with an authentic cadence"Orchestration Help
"Is F2 playable on the violin?"
"What's the comfortable range for French horn?"
"What transposition does the Bb clarinet use?"Counterpoint
"Check if this counterpoint follows first species rules:
Cantus: C4, D4, E4, F4, E4, D4, C4
Counterpoint: G4, A4, B4, C5, B4, A4, G4"
"Generate a counterpoint melody above this cantus firmus: D4, E4, F4, G4, F4, E4, D4"Voice Leading Validation
"Check this four-part harmony for parallel fifths:
Soprano: C5, D5, E5
Alto: E4, F4, G4
Tenor: G3, A3, B3
Bass: C3, D3, E3"Available Tools (51)
Category | Tools |
Connection |
|
Score |
|
Notes |
|
Notation |
|
Navigation |
|
Transpose |
|
Playback |
|
Harmony |
|
Orchestration |
|
Counterpoint |
|
Analysis |
|
Validation |
|
Proofreading |
|
Query |
|
Development
Run tests
pytestType checking
mypy src/dorico_mcpLinting
ruff check src/dorico_mcpArchitecture
dorico-mcp-server/
βββ src/dorico_mcp/
β βββ __init__.py # Package exports
β βββ server.py # FastMCP server with tools/resources/prompts
β βββ client.py # Dorico WebSocket client
β βββ commands.py # Dorico command builders (pure functions)
β βββ models.py # Pydantic models
β βββ tools/
β βββ __init__.py # Harmony analysis
β βββ instruments.py # Instrument database
βββ tests/ # Pytest tests
βββ docs/ # Documentation
βββ examples/ # Usage examplesDorico Remote Control API
This server communicates with Dorico via its WebSocket-based Remote Control API:
Protocol: WebSocket (JSON messages)
Port: Dynamic (usually 4560-4565)
Authentication: Session token (stored locally after first approval)
Key Limitations
Read access is limited: Can only read currently selected items
Write-focused: Best for sending commands/input
Full score reading: Requires MusicXML export
Contributing
Contributions are welcome! Please:
Fork the repository
Create a feature branch
Add tests for new functionality
Submit a pull request
License
MIT License
Acknowledgments
AbletonMCP - Inspiration for MCP structure
MuseScore-MCP - Notation MCP reference
Dorico.Net - Dorico API documentation
music21 - Music theory analysis
Made with β€οΈ for composition majors everywhere
Available Tools
54 toolsadd_articulationB
Add an articulation to the current selection.
Args: articulation: Articulation type (staccato, accent, tenuto, marcato, staccatissimo, fermata)
Returns: Success status
Inputs: articulation (required). Returns: object
add_dynamicsA
Add a dynamic marking to the selection.
Args: dynamic: Dynamic marking. Options: - pppp, ppp, pp, p (soft) - mp, mf (medium) - f, ff, fff, ffff (loud) - fp, sf, sfz, fz, rf, rfz (accented)
Returns: Success status
Examples: - Piano: add_dynamics("p") - Forte: add_dynamics("f") - Sforzando: add_dynamics("sfz")
Inputs: dynamic (required). Returns: object
add_instrumentB
Add an instrument to the score.
Args: instrument_name: Name of the instrument to add. Common names: Piano, Violin, Viola, Cello, Double Bass, Flute, Oboe, Clarinet, Bassoon, Horn, Trumpet, Trombone, Tuba, Timpani, Harp, Voice
Returns: Success status
Inputs: instrument_name (required). Returns: object
add_notesA
Add notes to the score at the current position.
Args: notes: List of notes to add (e.g., ["C4", "E4", "G4"]) Format: Note name + octave, with optional # or b Examples: "C4", "F#5", "Bb3", "G#4" duration: Note duration - one of: "whole", "half", "quarter", "eighth", "sixteenth", "32nd", "64th" as_chord: If True, add all notes simultaneously as a chord. If False, add notes sequentially.
Returns: Success status and notes added
Examples: - Single note: add_notes(["C4"]) - Melody: add_notes(["C4", "D4", "E4", "F4", "G4"]) - C major chord: add_notes(["C4", "E4", "G4"], as_chord=True) - Half notes: add_notes(["C4", "E4"], duration="half")
Inputs: notes (required), duration, as_chord. Returns: object
add_restB
Add a rest at the current position.
Args: duration: Rest duration (whole, half, quarter, eighth, sixteenth, 32nd, 64th)
Returns: Success status
Inputs: duration. Returns: object
add_slurA
Add a slur to the current selection.
Select the notes you want to slur first, then call this tool.
Returns: Success status
Inputs: no named parameters. Returns: object
add_tempoA
Add a tempo marking.
Args: bpm: Beats per minute (20-400) text: Optional tempo text (e.g., "Allegro", "Andante", "Presto")
Returns: Success status
Examples: - add_tempo(120) # Just BPM - add_tempo(120, "Allegro") # BPM with text - add_tempo(60, "Adagio")
Inputs: bpm (required), text. Returns: object
add_textB
Add text to the score at the current position.
Args: text: Text content to add text_type: Type of text (expression, technique, tempo, staff)
Returns: Success status
Inputs: text (required), text_type. Returns: object
analyze_chordA
Analyze a chord and get its Roman numeral analysis.
Args: pitches: List of pitch names (e.g., ["C4", "E4", "G4"]) key: Key for Roman numeral analysis (e.g., "C major", "A minor")
Returns: Chord analysis with root, quality, and Roman numeral
Inputs: pitches (required), key. Returns: object
analyze_intervalsA
Analyze intervals between consecutive pitches.
Args: pitches: List of pitches (e.g., ["C4", "E4", "G4", "C5"])
Returns: List of intervals with names, semitones, and consonance info
Inputs: pitches (required). Returns: object
balance_dynamicsA
Suggest dynamic adjustments for ensemble balance.
Args: instruments: List of instruments in the ensemble target_dynamic: Target overall dynamic level (pp, p, mp, mf, f, ff) melody_instrument: Instrument carrying the melody (should project)
Returns: Dynamic suggestions for each instrument
Inputs: instruments (required), target_dynamic, melody_instrument. Returns: object
check_beamingA
Check if beaming follows standard notation rules.
Args: time_signature: Time signature (e.g., "4/4", "6/8") note_values: List of note values in a bar (e.g., ["8th", "8th", "8th", "8th"])
Returns: Beaming analysis with suggestions
Inputs: time_signature (required), note_values (required). Returns: object
check_enharmonicA
Check for potentially incorrect enharmonic spellings.
Suggests alternative spellings based on key context.
Args: pitches: List of pitches to check (e.g., ["C#4", "Db4", "F#4"]) key: Key context (e.g., "Db major" - suggests Db instead of C#)
Returns: List of spelling suggestions
Examples: - check_enharmonic(["C#4", "F#4"], key="Db major") -> Suggests using Db and Gb instead
Inputs: pitches (required), key. Returns: object
check_instrument_rangeA
Check if a pitch is playable on an instrument.
Args: instrument: Instrument name (e.g., "violin", "flute", "clarinet") pitch: Pitch to check (e.g., "C4", "G3")
Returns: Playability status and range information
Inputs: instrument (required), pitch (required). Returns: object
check_playabilityA
Check if a passage is playable on an instrument.
Args: instrument: Instrument name (e.g., "violin", "flute") pitches: List of pitches to check
Returns: Playability analysis with range and technique issues
Inputs: instrument (required), pitches (required). Returns: object
check_spacingA
Check if note spacing is appropriate for readability.
Args: note_count: Number of notes in the bar bar_width_mm: Width of the bar in millimeters shortest_note: Shortest note value in the bar
Returns: Spacing analysis with recommendations
Inputs: note_count (required), bar_width_mm, shortest_note. Returns: object
check_species_rulesA
Check species counterpoint rules.
Analyzes a counterpoint line against a cantus firmus for rule violations.
Args: cantus_firmus: List of pitches for the cantus firmus (e.g., ["C4", "D4", "E4"]) counterpoint: List of pitches for the counterpoint line species: Species number (1-5): 1 = Note against note 2 = Two notes against one 3 = Four notes against one 4 = Syncopation/suspensions 5 = Florid (free)
Returns: Analysis with intervals and rule violations
Examples: - First species: check_species_rules(["C4", "D4", "E4"], ["G4", "A4", "C5"], species=1)
Inputs: cantus_firmus (required), counterpoint (required), species. Returns: object
check_voice_leadingC
Check for voice leading issues between two voice parts.
Detects parallel fifths, parallel octaves, voice crossing, etc.
Args: voice1: List of pitches for first voice (e.g., ["C4", "D4", "E4"]) voice2: List of pitches for second voice (e.g., ["G3", "A3", "B3"])
Returns: List of voice leading issues found
Inputs: voice1 (required), voice2 (required). Returns: object
connect_to_doricoA
Connect to Dorico.
Establishes a WebSocket connection to Dorico's Remote Control API. Must be called before using other Dorico tools.
Returns: Connection status and Dorico information
Inputs: no named parameters. Returns: object
create_scoreA
Create a new score in Dorico.
Creates a new score with the specified settings. This is the starting point for any new composition.
Args: title: Score title (shown on first page) composer: Composer name instruments: List of instruments to add (e.g., ["Piano", "Violin", "Cello"]) time_signature: Time signature (e.g., "4/4", "3/4", "6/8") key_signature: Key signature (e.g., "C major", "G minor", "Bb major") tempo_bpm: Tempo in beats per minute (20-400)
Returns: Success status and score information
Examples: - Simple piano piece: create_score(title="Prelude", instruments=["Piano"]) - String quartet: create_score(instruments=["Violin", "Violin", "Viola", "Cello"]) - Orchestra: create_score(instruments=["Flute", "Oboe", "Clarinet", "Horn", "Violin", "Viola", "Cello", "Double Bass"])
Inputs: title, composer, instruments, time_signature, +2 more. Returns: object
delete_notesA
Delete the currently selected notes.
Select the notes to delete first, then call this tool.
Returns: Success status
Inputs: no named parameters. Returns: object
detect_parallel_motionB
Detect parallel fifths and octaves between two voices.
Args: voice1: List of pitches for first voice voice2: List of pitches for second voice
Returns: Detection results with parallel motion instances
Inputs: voice1 (required), voice2 (required). Returns: object
export_scoreA
Export the score to PDF or MusicXML.
Args: path: Export file path format: Export format ("pdf" or "musicxml")
Returns: Success status and export path
Inputs: path (required), format. Returns: object
find_dissonancesA
Find dissonant intervals in a collection of pitches.
Args: pitches: List of pitches sounding together (e.g., ["C4", "E4", "G4", "B4"]) context: Context for analysis ("counterpoint", "harmony", "any")
Returns: List of dissonances found with resolution advice
Inputs: pitches (required), context. Returns: object
generate_chord_progressionB
Generate a chord progression.
Args: key: Key for the progression (e.g., "C major", "A minor") length: Number of chords (default 4) style: Style (classical, pop, jazz) ending: Cadence type (authentic, half, plagal, deceptive)
Returns: Generated chord progression with Roman numerals
Inputs: key, length, style, ending. Returns: object
generate_counterpointA
Generate a counterpoint line for a cantus firmus.
Creates a counterpoint melody following species rules.
Args: cantus_firmus: List of pitches (e.g., ["C4", "D4", "E4", "F4", "E4", "D4", "C4"]) species: Species number (1-5) above: If True, generate counterpoint above CF; if False, below
Returns: Generated counterpoint with validation results
Examples: - Above CF: generate_counterpoint(["C4", "D4", "E4", "D4", "C4"], species=1, above=True) - Below CF: generate_counterpoint(["C4", "D4", "E4", "D4", "C4"], species=1, above=False)
Inputs: cantus_firmus (required), species, above. Returns: object
get_dorico_statusA
Get current Dorico status.
Returns information about the current score, selection, and application state.
Inputs: no named parameters. Returns: object
get_engraving_optionsA
Get current engraving options.
Engraving options control the visual appearance of notation.
Returns: Current engraving options
Inputs: no named parameters. Returns: object
get_flowsA
Get list of flows in the current project.
Flows are separate musical sections within a Dorico project.
Returns: List of flows with IDs and names
Inputs: no named parameters. Returns: object
get_instrument_infoA
Get detailed information about an instrument.
Args: instrument: Instrument name (e.g., "violin", "horn", "clarinet")
Returns: Instrument details including range, transposition, family
Inputs: instrument (required). Returns: object
get_layout_optionsA
Get layout options for a specific layout.
Args: layout_id: ID of the layout (get from get_layouts())
Returns: Layout options for the specified layout
Inputs: layout_id (required). Returns: object
get_layoutsA
Get list of layouts in the current project.
Layouts define how music is presented (full score, parts, etc.).
Returns: List of layouts with IDs and names
Inputs: no named parameters. Returns: object
get_notation_optionsA
Get notation options for a specific flow.
Args: flow_id: ID of the flow (get from get_flows())
Returns: Notation options for the specified flow
Inputs: flow_id (required). Returns: object
get_selection_propertiesA
Get properties of the current selection.
Returns detailed information about whatever is currently selected in Dorico. NOTE: This is selection-based only - cannot query arbitrary score positions.
Returns: Properties of current selection
Inputs: no named parameters. Returns: object
go_to_barB
Navigate to a specific bar in the score.
Args: bar_number: Bar number to go to (1-based)
Returns: Success status
Inputs: bar_number (required). Returns: object
open_scoreA
Open an existing score file.
Args: path: File path to the Dorico project file (.dorico)
Returns: Success status
Inputs: path (required). Returns: object
playback_controlC
Control playback.
Args: action: One of "play", "stop", "rewind"
Returns: Success status
Inputs: action (required). Returns: object
realize_figured_bassA
Realize figured bass notation into chord pitches.
Args: bass_pitch: Bass note (e.g., "C3", "G2") figures: Figured bass notation (e.g., "6", "64", "7", "65", "43", "42") key: Key context for accidentals
Returns: Realized chord with all pitches
Inputs: bass_pitch (required), figures, key. Returns: object
remove_instrumentB
Remove an instrument from the score.
Args: instrument_name: Name of the instrument to remove
Returns: Success status
Inputs: instrument_name (required). Returns: object
save_scoreB
Save the current score.
Args: path: File path to save to. If None, saves to current location.
Returns: Success status
Inputs: path. Returns: object
set_engraving_optionsC
Set engraving options for the document.
Engraving options control the visual appearance of notation elements.
Args: options: Dictionary of option names and values to set
Returns: Success status
Inputs: options (required). Returns: object
set_key_signatureA
Set the key signature.
Args: root: Root note of the key (C, D, E, F, G, A, B with optional # or b) Examples: "C", "G", "F#", "Bb", "Eb" mode: "major" or "minor" bar: Bar number to insert at. None = current position.
Returns: Success status
Examples: - C major: set_key_signature("C", "major") - G major: set_key_signature("G", "major") - A minor: set_key_signature("A", "minor") - Bb major: set_key_signature("Bb", "major") - F# minor: set_key_signature("F#", "minor")
Inputs: root (required), mode, bar. Returns: object
set_layout_optionsC
Set layout options for a specific layout.
Args: layout_id: ID of the layout (get from get_layouts()) options: Dictionary of option names and values to set
Returns: Success status
Inputs: layout_id (required), options (required). Returns: object
set_notation_optionsA
Set notation options for a specific flow.
Args: flow_id: ID of the flow (get from get_flows()) options: Dictionary of option names and values to set
Returns: Success status
Inputs: flow_id (required), options (required). Returns: object
set_time_signatureA
Set the time signature.
Args: numerator: Top number (beats per measure). Range: 1-32 denominator: Bottom number (beat unit). Common values: 2, 4, 8, 16 bar: Bar number to insert at. None = current position.
Returns: Success status
Examples: - Common time: set_time_signature(4, 4) - Waltz: set_time_signature(3, 4) - Compound duple: set_time_signature(6, 8) - Cut time: set_time_signature(2, 2)
Inputs: numerator (required), denominator (required), bar. Returns: object
suggest_cadenceA
Suggest appropriate cadence types based on context.
Args: current_chord: Current chord (e.g., "V", "IV", "I") key: Key context (e.g., "C major", "A minor") phrase_position: Position in phrase ("end", "middle", "beginning")
Returns: Cadence suggestions with explanations
Inputs: current_chord (required), key, phrase_position. Returns: object
suggest_doublingA
Suggest instruments for doubling a given instrument.
Args: instrument: Primary instrument to double (e.g., "violin", "flute") purpose: Purpose (reinforcement, octave_above, octave_below, color) register: Register of the passage (low, middle, high)
Returns: Doubling suggestions with rationale
Inputs: instrument (required), purpose, register. Returns: object
suggest_instrumentationB
Suggest instrumental ensembles based on style and requirements.
Args: style: Musical style (classical, romantic, modern, baroque, jazz) size: Ensemble size (solo, small, medium, large, orchestra) character: Character of piece (lyrical, dramatic, light, powerful, intimate)
Returns: Suggested ensembles with rationale
Inputs: style, size, character. Returns: object
suggest_next_chordA
Suggest possible next chords based on harmonic context.
Args: previous_chords: List of previous chord Roman numerals (e.g., ["I", "IV"]) key: Current key (e.g., "C major") style: Style of suggestions (classical, pop, jazz)
Returns: List of suggested chords with explanations
Inputs: previous_chords (required), key, style. Returns: object
transposeA
Transpose the current selection by semitones.
Args: semitones: Number of semitones to transpose. Positive = up, Negative = down. Examples: 12 = up one octave, -12 = down one octave, 7 = up a perfect fifth, -5 = down a perfect fourth
Returns: Success status and transposition amount
Inputs: semitones (required). Returns: object
transpose_for_instrumentA
Transpose a pitch for a transposing instrument.
Args: pitch: Pitch to transpose (e.g., "C4") instrument: Instrument name (e.g., "clarinet", "horn", "trumpet") to_concert: If True, written to concert pitch; if False, concert to written
Returns: Transposed pitch with interval info
Inputs: pitch (required), instrument (required), to_concert. Returns: object
transpose_octaveB
Transpose the current selection by one octave.
Args: direction: "up" or "down"
Returns: Success status
Inputs: direction. Returns: object
validate_scoreA
Comprehensive score validation.
Checks voice leading, ranges, parallel motion, and more.
Args: voices: Dictionary mapping voice names to pitch lists key: Key for analysis
Returns: Complete validation report with score and issues
Inputs: voices (required), key. Returns: object
validate_voice_leadingB
Validate voice leading in a multi-voice passage.
Checks for parallel fifths/octaves, voice crossing, and range issues.
Args: voices: Dictionary mapping voice names to pitch lists Example: {"soprano": ["C5", "D5"], "alto": ["E4", "F4"], "tenor": ["G3", "A3"], "bass": ["C3", "D3"]} key: Key for analysis (e.g., "C major", "A minor")
Returns: Validation results with errors and warnings
Examples: - Four-part: validate_voice_leading({ "soprano": ["C5", "D5", "E5"], "alto": ["E4", "F4", "G4"], "tenor": ["G3", "A3", "B3"], "bass": ["C3", "D3", "E3"] })
Inputs: voices (required), key. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogβ¦
TDQS
Scored across 54 tools
Many tools have distinct purposes, but there is significant overlap among analysis tools (e.g., check_voice_leading, validate_voice_leading, detect_parallel_motion) and suggestion tools (suggest_cadence, suggest_next_chord). This can confuse an agent about which tool to use.
Most tool names follow a verb_noun pattern, but there are inconsistencies like check_voice_leading vs. validate_voice_leading, and generate_counterpoint vs. realize_figured_bass. The pattern is mostly predictable but not fully uniform.
With 54 tools, the count is far above the typical well-scoped range. While music notation is a complex domain, this many tools risk redundancy and cognitive load. The server could be streamlined by merging overlapping functions.
The tool set covers an impressively broad scope: score creation, note entry, expressive markings, playback, layout, engraving, analysis, voice leading, counterpoint, figured bass, and export. Almost no obvious gaps exist for the domain.
Maintenance
Related MCP Connectors
ScoreStarling is an all-in-one AI sheet music assistant. Ask for anything to do with sheet music: transcribe a song from audio, video or a link, read a PDF or photo, add chords, change the key, make it easier, turn it into guitar TAB or jianpu, or arrange it for another instrument. Every change lands on a real score you can hear, fix and download (PDF, MIDI, MusicXML, guitar TAB, jianpu, audio). Hosted remote server with OAuth sign-in. Free accounts get monthly credits and free previews; prices are at scorestarling.com/pricing. Setup: https://scorestarling.com/mcp
Generate AI music via the Lacuna Music API from MCP clients like Claude Desktop & Code.
MCP server for Producer/Riffusion AI music generation
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI assistants like Claude to interact with FL Studio's piano roll, allowing users to create melodies, chord progressions, and musical patterns through natural language with automatic, real-time updates.49MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that connects Claude to FL Studio, enabling natural language control of transport, mixer, channel rack, and piano roll operations.2MIT
- FlicenseNot gradedqualityDmaintenanceMCP server that lets AI agents compose real music through a persistent server-side score, supporting planning, voice writing, verification, and MIDI export.-
- AlicenseAqualityBmaintenanceAn AI composition partner that remote-controls Steinberg Dorico through the Model Context Protocol, enabling composers to create, edit, play back, and refine musical scores using natural language.307AGPL 3.0