doricomcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Dorico MCP server: read and write a live Dorico 6 score by conversation.
Positions: every tool takes either bar (1-based) + beat (offset in crotchets from the bar start, e.g. "0",
"1", "3/2") or an absolute pos in crotchets from the flow start. Voices are voice-stream ids from
get_score_overview (e.g. piano: 2 = right hand, 4 = left hand). Event ids come from read_music/read_markings.
Every write is one undo step, verified by reading the score back; a failed check is undone automatically.
Start with get_score_overview, then get_bar_map and read_music. Write with add_notes and the add_*/set_* tools. Use screenshot to look at the result. list_capabilities shows what is confirmed live and what is experimental. Dorico's API cannot read: lyrics, fp and sffz (sffz reads as sfz), tonic/mode of keys (only the signature), title/composer; and per-note properties in voices that contain trills, ornaments, arpeggios, techniques or glissandi. Tempo values are read by selecting the tempo marking; undo skips those selection steps. Undo works any time; redo only directly after undo (any read clears Dorico's redo stack).
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| dorico_statusB | Live Dorico status (mode, selection, note input, undo availability) from Remote Control. [READ-ONLY: not yet confirmed by the live harness] |
| list_capabilitiesB | The confirmation matrix: every capability, its mechanism and whether the live harness confirmed it. [READ-ONLY: not yet confirmed by the live harness] |
| describe_commandsC | Search Dorico's 1,200 commands (regex on name/display name) with their parameters and enum values. [READ-ONLY: not yet confirmed by the live harness] |
| describe_enumsB | Exact accepted values of a Dorico enum type (or regex over enum type names). [READ-ONLY: not yet confirmed by the live harness] |
| describe_propertyB | Type, display name and enum values of an event property (e.g. kNoteVelocity, kEventColour). [READ-ONLY: not yet confirmed by the live harness] |
| list_libraryC | Library entities (ids + names), live from Dorico: kInstrumentCollection, kClefCollection, kPlayingTechniqueAppearanceCollection, kOrnamentCollection, kTempoPresetCollection, kParagraphStyleCollection... [READ-ONLY: not yet confirmed by the live harness] |
| run_commandA | Escape hatch: run any catalogued Dorico command ("Namespace.Command?Param=value&..."), validated against the catalogue. With select_event_id the event is selected first in the same undo step. |
| screenshotB | A picture of Dorico's score window, to check engraving by eye. bar: scroll there first; zoom: view zoom in percent for the picture (e.g. 200 to read dynamics and small markings), restored afterwards. |
| list_dialogsA | Dorico's open dialogs (every window other than a project window): title, modal, the texts shown and the controls (role, title or label, value, enabled, path). A modal dialog blocks all commands until it is answered with dialog_click / dialog_set. Needs Accessibility permission for the app running this server. |
| dialog_clickB | Press a control in a Dorico dialog: a button ("OK", "Cancel", "Apply", "Close"), checkbox, radio button or tab, by its title, the label before it, or its path from list_dialogs. dialog: its title, if several are open. |
| dialog_setB | Set a control in a Dorico dialog: a checkbox or radio button to true/false, a text field to text, a pop-up or combo box to one of its items (by name). control: its title, the label before it, or its path. |
| refreshA | Forget cached reads (time signatures, dynamics, keys, structure); use after editing in Dorico by hand. [READ-ONLY: not yet confirmed by the live harness] |
| get_score_overviewB | Players, instruments, layouts and flows; per flow its streams and voices (voice-stream id -> instrument, staff index, voice index). Use the voice ids for read_music/add_notes. |
| get_bar_mapB | Bar numbers <-> positions, time signatures (read by Dorico's own equality API, cached) and optionally key signatures (include_keys: a letter-entry probe into an empty span; it plays 7 audition notes). |
| read_musicB | Notes, chords, rests (explicit and implicit), grace notes, tuplets, slurs and articulations per voice, with exact positions, durations, spelled pitches, MIDI numbers and event ids. Range: bars (inclusive) or positions [from_pos, to_pos). detail="compact": per voice and bar the notes in add_notes syntax plus their ids (about a tenth of the size; use it for long ranges or many voices). detail="grid": one row per onset of any voice (or every grid_step crotchets, e.g. "1/2") with what each voice sounds, for checking verticals. |
| read_markingsC | Dynamics (levels incl. sfz/rfz/fz, hairpins), slurs, clefs, ottavas, text, tempo (text, bpm), holds, rehearsal marks, repeats, breaks, playing techniques (name), ornaments, time/key signatures in a range. Each row says whether its content is readable. A dynamic group lists its parts in order, each with its own position (bar, beat): a level (p, f...) or a hairpin (cresc/dim, length, end); "sub" identifies a hairpin part for set_property. |
| read_context_atC | What is in force at a point: time signature, key signature, clef, dynamic level (and a hairpin running through the point), ottava, the last tempo marking (text, bpm), and the notes sounding in the voice. |
| check_voice_leadingA | Voice-leading check of the score: parallel and contrary fifths/octaves/unisons, hidden fifths/octaves in the outer voices, crossings, spacing over an octave between upper voices, leaps over max_leap semitones and tritone leaps. voices: from highest to lowest (default: ordered by average pitch). chords (optional harmonic plan, "bar[:beat] symbol, ...", e.g. "28 D, 28:2 A7, 29 Bm/F#") adds doubled thirds (major chords), doubled sevenths, doubled leading tone (needs key, e.g. "D" or "Bm"), missing thirds, non-chord tones and wrong bass notes. A voice holding a chord counts by its top note. |
| score_changesA | What changed in a flow: without since, take a snapshot and return its token; with since=, list the events added, removed and changed since then, each marked by "server" (written through these tools) or "Dorico" (edited in Dorico by hand), and a new token. Changes inside dynamic groups (levels) are not seen. |
| get_selectionB | The current selection in Dorico (event type and, if available, its properties). [READ-ONLY: not yet confirmed by the live harness] |
| get_optionsC | House-style options: kind kEngraving (per score), kNotation (per flow: flow_id), kLayout (per layout: layout_id). [READ-ONLY: not yet confirmed by the live harness] |
| add_notesA | Write notes, chords and rests one after another from a position. notes: space-separated items "PITCHES:DURATION"; chords join pitches with "+"; "r" is a rest; a missing duration repeats the previous one. Durations: crotchets (1, 3/2, 1/2) or w h q e s t (+ dots, e.g. "q."). Pitches: C4 = middle C, F#5, Bb3. Example: "Eb4+G4+C5:h. G4:e Eb5:q. C5:s r:q". replace=True first clears the notes and rests of the span (slurs, text and other markings there stay); otherwise notes are added (chords merge with existing notes). |
| delete_rangeB | Delete the notes, rests, grace notes and tuplets of a voice in a range (bars inclusive, or positions [from_pos, to_pos)); slurs, text and other markings in the voice stay unless include_markings=True. |
| delete_eventsB | Delete events by id: notes, rests or markings (dynamics, hairpins, slurs, text, clefs, octave lines...). Ids come from read_music / read_markings. |
| set_pitchA | Change one note's pitch and spelling (e.g. "F#4", "Ebb5") in place: it keeps its id, rhythm, slurs and articulations. |
| set_durationC | Change a note's or rest's duration (crotchets or w h q e s t with dots). |
| edit_notesC | Apply an edit to notes: pitch_up/pitch_down (diatonic steps x count), chromatic_up/down, octave_up/down, respell_above/below, double_duration, halve_duration, tie (to the next note of the same pitch), delete; remove_rests on rest ids (Dorico's Remove Rests: the voice shows a gap there, e.g. a divisi line that pauses). |
| add_intervalB | Add a note at an interval to each given note, making a chord: "3" (third above), "-3", "maj3", "min6 below", "p5", "octave". |
| add_grace_noteC | Add a grace note before the note at the given position (value: notated length, default quaver). |
| copy_rangeC | Copy (or move) notes and rests of a range to another place or voice/staff (markings are not copied). |
| add_tupletB | A tuplet typed with Dorico's note input, overwriting what is there: ratio "3:2", "5:4"; unit = the tuplet's note value (e, q, s, h); notes in add_notes syntax with notated values, e.g. "C5:e D5 E5" or "Eb4+G4:q B4 D5". Accidentals are always explicit (C#5, Ab4); plain letters mean naturals. |
| swap_voicesB | Exchange the notes and rests of two voices in a range (e.g. divisi lines trading places), one undo step. Notes are re-created with their pitch and rhythm (new ids); slurs, text and markings stay in their voice. |
| add_voiceB | Start a new voice on the same staff as |
| add_articulationC | staccato, staccatissimo, tenuto, accent, marcato, stress, unstress, staccato_tenuto on notes. |
| add_spanA | A line from one note to another in the same voice: slur, cresc, dim, messa_di_voce (hairpins), 8va, 8vb, 15ma, 15mb (octave lines), glissando. Only that voice gets it, even with other voices on the staff. spans: several [start_event_id, end_event_id] pairs in one call (slurs: one undo step), e.g. a slur over every pair of quavers. Hairpins end at the end of the end note; for exact positions use add_hairpin. |
| add_hairpinA | A hairpin (cresc, dim, messa_di_voce) from one position to another, e.g. bar 33 beat 0 to bar 33 beat 3/2, wherever notes start (also inside a held note). voices: put the same hairpin on several instruments (one voice each), e.g. the whole string section. A hairpin starting at a dynamic joins its group (p<), reported as merged_into. Returns the direction, positions and drawn length. |
| add_dynamicA | An immediate dynamic (p, pp, mp, mf, f, ff, sfz, fp, ...) on the voice's instrument at a position, also where no note starts (inside a held note) or where a hairpin ends. voices: the same on several instruments. at: more dynamics in the same call, e.g. [{"value": "f", "bar": 34}, {"value": "p", "bar": 36, "beat": "2"}] (each takes bar + beat or pos). One undo step; returns only the dynamics created. |
| add_note_markingC | kind=ornament (value tr, mordent, inv, turn), hold (fermata, breath, caesura...), playing_technique (value: a name like pizz., arco, con sord., sul pont., ord., or a library id like pta.pizzText), tie, articulation (value staccato...). |
| add_textC | Staff text (e.g. "dolce", "espress.") attached to a voice at a position. |
| add_clefD | A clef change on the voice's staff: clef.treble, clef.bass, clef.alto, clef.tenor, clef.treble8ba ... |
| set_tempoD | A tempo marking: "q=120", "Allegro q=132", "h.=60", "rit.", "a tempo". |
| set_time_signatureC | Time signature from a bar on: 3/4, 6/8, 2+3/8, c, cut. Single n/d values are read back to confirm. |
| set_key_signatureC | Key signature from a bar on: "2#", "3b", "0", or names like "Eb", "F#m", "c minor". |
| add_barlineC | Barline at the start of a bar: "||" double, "|:" start repeat, ":|" end repeat, ":|:", "|||" final, ":" dashed. |
| add_repeat_markerD | segno, coda, fine, "to coda", "D.C.", "D.C. al Fine", "D.C. al Coda", "D.S. al Fine", "D.S. al Coda". |
| add_rehearsal_markC | A rehearsal mark (next letter in sequence) at the start of a bar. |
| add_breakC | Force a system or frame (page) break before a bar. |
| set_propertyB | Set any event property (all layouts), e.g. kNoteVelocity=100, kEventColour=#ffff0000, kEventScale=kCue, kNoteForcedVoiceDirection... Omit value to reset to default. See describe_property. kDynamicGradualChangeDuration (hairpin length in crotchets) also works on a hairpin joined to a dynamic (p<); part: the hairpin's "sub" from read_markings when its group holds several hairpins (> <). |
| set_optionA | Set a house-style option (paths and values from get_options). kind: kEngraving, kNotation (flow_ids), kLayout (layout_ids). Written via Dorico's own commands (the setoptions message ignores layout ids). |
| add_playerB | Add a solo (or section) player holding an instrument from the library, e.g. instrument.strings.violin, instrument.wind.flute (list_library kInstrumentCollection). |
| add_instrumentB | Give an existing player (index in get_score_overview players) an extra instrument (doubling). |
| rename_playerC | Rename a player (index in get_score_overview players). |
| add_flowA | Add a new flow (movement) at the end of the project, with all players. |
| rename_flowB | Rename a flow (ids from get_score_overview flows). |
| delete_flowA | Delete a flow and all its music (one undo step; undo restores it). Dorico's "all music ... will also be deleted" confirmation is answered OK. The last flow cannot be deleted. |
| remove_instrumentA | Remove an instrument and all its music (one undo step; undo restores it). Instrument ids are in get_score_overview players. Dorico's "will also delete all its music" confirmation is answered OK. |
| add_layoutA | Add a custom score layout (optionally named). Part layouts are created automatically with players. |
| rename_layoutB | Rename a layout (ids from get_score_overview layouts). |
| layout_flowsB | Include or exclude flows in a layout (Dorico does not expose a layout's flows for read-back). |
| set_score_orderC | Instrument order template, e.g. instrumentscoreorder.orchestral, instrumentscoreorder.windband, instrumentscoreorder.choral (list_library kInstrumentScoreOrderCollection). |
| go_toC | Scroll Dorico's view to a bar. |
| select_eventsB | Select an event in Dorico (e.g. to show the user). Note: selection changes are undo steps in Dorico. |
| playC | Start playback (from a bar, or from the playhead). |
| stopA | Stop playback. |
| undoA | Undo the last |
| redoA | Redo |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| status_resource | |
| score_resource |
TDQS
Scored across 66 tools
Most tools have a clear verb+object purpose (add_notes, read_markings, set_tempo), but several overlap: add_span vs add_hairpin both create hairpins, add_articulation vs add_note_marking (kind=articulation) both add articulations, and delete_range vs delete_events both remove content. set_property and run_command are generic catch-alls that could do almost anything, though the descriptions do explicitly point to the specialised tool ('for exact positions use add_hairpin'), which keeps misselection recoverable rather than fatal.
The dominant pattern is verb_noun (add_player, get_score_overview, read_music, delete_flow, set_pitch), applied consistently across the large write surface. Deviations are limited to a few noun_verb tools (dialog_click, dialog_set, layout_flows, score_changes) and bare-verb transport tools (play, stop, undo, redo, refresh, screenshot), which are conventional enough not to break predictability.
66 tools is far beyond what an agent can comfortably scan and choose from in one surface, even for a rich domain like score engraving. The set is really several servers in one (transport/undo, accessors, music reading, note writing, markings, dialogs, house style), and should have been grouped or narrowed.
Coverage is unusually thorough: status/diagnostics, structure (players, flows, layouts), reads (music, markings, context, bar map, changes), note and marking writes, options, dialogs and an escape hatch, plus undo/redo. Minor gaps remain — no remove_player or delete_layout (removal exists for instruments and flows only), no transpose/bulk pitch-shift beyond edit_notes, and no way to read back a layout's flows (layout_flows is write-only).