Use ModalJazz with an agent
ModalJazz has a built-in MCP server, mj-mcp. With it, an AI agent such as Claude Code reads and changes your scores. You ask in plain words, and the agent does the work.
The agent starts mj-mcp and talks to it over standard input and output. There is no network port. With the app closed, the tools change the score files. With the app open, they can change the scores in its windows, and you see each change at once.
Add mj-mcp to your agent
The app has mj-mcp in it, at this path:
/Applications/ModalJazz.app/Contents/MacOS/mj-mcp
The server takes no arguments. If the app is in another folder, change the path.
Claude Code
Run this command once in Terminal:
claude mcp add --scope user modaljazz -- /Applications/ModalJazz.app/Contents/MacOS/mj-mcp
--scope user gives the server to all your projects. Without it, only the current project gets it. claude mcp list shows the server, and /mcp in Claude Code shows its tools.
Claude Desktop
- In Claude Desktop, open Settings > Developer, and click Edit Config. This opens
claude_desktop_config.json. - Add the server under
mcpServers:{ "mcpServers": { "modaljazz": { "command": "/Applications/ModalJazz.app/Contents/MacOS/mj-mcp" } } } - Quit Claude Desktop and open it again.
Other agents
Any MCP client that starts a local server over standard input and output (the stdio transport) can use mj-mcp. Give the path above as the command, with no arguments.
Work in the open app
Type :set agent on in the app once. The app keeps this setting. Then a tool call on a score that is open in the app changes the score in its window:
- The agent names the score by its path, its file name (
prelude.mj), or its window title (Untitledfor a new score). - While an agent is connected, the windows show a small "Agent connected" banner.
- Cmd-Z (or u) removes the changes of one agent request.
- The
savetool saves the score in the app. A new score needs a path. - A score that is not open in the app changes in its file.
The app listens on a Unix socket in ~/Library/Application Support/ModalJazz/agent.sock. Only your user can use it. :set agent off closes it.
Ask for changes
Give the path of the score in your request. For example:
- "Start a new jazz band score in ~/Scores/blues.mj."
- "Show me measures 1-8 of ~/Scores/prelude.mj."
- "In ~/Scores/prelude.mj, put measures 5-8 up an octave and save."
- "Write a C major scale in quarter notes in measures 1-2 of the right hand."
- "Add a D.C. al Fine at the end of measure 16, and Fine at measure 8."
The changes stay in memory until the agent calls save. Each tool call that changes the score is one undo step.
Example: enter a score from a PDF
This example enters Twinkle, Twinkle, Little Star (a traditional tune) from a PDF with Claude Code. Agents that can read a PDF, or an image of a page, can do this.
You ask:
> Make a piano score ~/Scores/twinkle.mj from ~/Downloads/twinkle.pdf.The agent makes the file with
new_score, and reads the PDF. Then it callstext_formatto learn the score text.The agent writes the music with
write_measures, measures 1-4:m1: time=4/4 tempo="Moderato",q=96 m1 P1.1: C4:q C4:q G4:q G4:q m1 P1.2: C3:h E3+G3:h m2 P1.1: A4:q A4:q G4:h m2 P1.2: F3+A3:h E3+G3:h m3 P1.1: F4:q F4:q E4:q E4:q m3 P1.2: D3+F3:h C3+E3:h m4 P1.1: D4:q D4:q C4:h m4 P1.2: G2+G3:h C3:hThe agent runs
:commands withrun_command::title Twinkle, Twinkle, Little Star,:4 barline |., and:5-8 bars delete(the new score has eight measures).The agent calls
read_measuresand compares the result with the PDF. Then it callssave.
With :set agent on and a new score open in the app, you can ask for the same work in the Untitled window, and see each step.
A long score works best a page or a system at a time: write, read back, and compare. The transcribe-pdf recipe gives the agent all the steps.
The tools
The agent sees these tools and their descriptions. Arguments in bold are required.
Each tool on a score takes file: The path of the score file: .mj, .musicxml, .xml, or .mxl. If the score is open in the ModalJazz app (with :set agent on), the tools change it in its window: there the file name or the window title (Untitled for a new score) also works.
score_summary
Shows the title, the composer, the parts and their staves, the number of measures, the key, the time, and the selection. It also shows each text (title block, copyright, credits, cover) and each page setting as the : command that sets it (| for a new line, {italic} for a style), to change and run with run_command.
file- The score. See
file.
read_measures
Shows measures as compact score text: one line for each measure and staff, for example m5 P1.1: C5:q D5:q E5:h. Call text_format for the form of the text.
file- The score. See
file. measuresoptional- 5 or 5-8, counted from 1. The default is all measures.
stavesoptional- Staff labels with commas: P1,P2.1. P2 is part 2; P1.2 is staff 2 of part 1. score_summary shows the parts.
write_measures
Writes compact score text over measures, as one undo step. Each line of the text must be in the measures. A staff with no line in the text does not change. Call text_format for the form of the text. The selection ends.
file- The score. See
file. measures- 5 or 5-8, counted from 1.
text- The compact score text.
run_command
Runs one : command, as one undo step. A measure range can come first: :5-8 transpose +P8. A staff label of score_summary can come before it, for a command on that part or staff (:instrument acts on one part): :P5 instrument brace off, :P1.2 4 clef bass. With no label, the command acts on the staff of the cursor (P1 at the start). With no range, the command acts on the selection (see select), or on the measure of the cursor (measure 1 at the start; :5 moves it to measure 5). The commands: time, pickup, key, clef, bars, barline, repeat, volta, segno, coda, tocoda, fine, dc, ds, rehearsal, section, break, pagebreak, numbers, hide, show, transpose, tempo, title, subtitle, composer, lyricist, arranger, copyright, credits, cover, new, instrument, set, notation, notehead, slur, artic, bow, ornament, tuplet, cue, tremolo, hairpin, text. :set takes the settings of the score (firstpage, font, staffsize, staffdistance, systemdistance, hairpin, fingering, names, chords, keynaturals, copyright, paper, mmrest, octavecourtesy, brackets, hideempty, repeatwings, concert). Commands only for the app window (run_command refuses them): w, e, q, wq, x, export, part, score, speed, solo, mute, unmute, loop, chords, lyrics, tutor, map, keys. Call list_commands for what each command and setting does.
file- The score. See
file. command- The command, for example
:key Eb.
select
Selects measures. The commands of run_command with no measure range then act on the selection. With staves, the selection is a time range on those staves (and the staves between them); with no staves, it is whole measures on all staves.
file- The score. See
file. measures- 5 or 5-8, counted from 1, or none to end the selection.
stavesoptional- Staff labels with commas: P1,P2.1. P2 is part 2; P1.2 is staff 2 of part 1. score_summary shows the parts.
check_collisions
Lists the marks that overlap notes or other marks on the pages, one line for each: the page, the measure, and the two objects with their staves, for example p1 m2: dynamic p (P4) / tempo mark (P5.1). The layout moves staves apart and breaks hairpins to keep marks clear, so the list shows what is left. Call it after the music and the marks are in, and fix what it lists with run_command or write_measures (for example another side or time for a mark).
file- The score. See
file.
layout
Lists the systems of each page, one line for each page: the measures of each system, with (break) or (page break) after a break set with :break or :pagebreak, for example p3: m37-40 (break), m41-44. The other system ends come from the layout. A measure line of read_measures shows a set break as break or pagebreak, and write_measures sets and clears them.
file- The score. See
file.
save
Writes the score to its file. The changes of the other tools stay in memory until a save. With to, it writes a copy in the format of the extension (.mj, .musicxml, .xml, .mxl, .svg, or .pdf) and does not change the file of the score: a later save with no to still writes file. A score in the app with no file yet saves to a .mj path in to.
file- The score. See
file. tooptional- A path for a copy. The default is file.
new_score
Writes a new score from a template to a new file, with eight empty measures. The file must not exist yet. The extension gives the format. The other tools can then change the score. The templates: piano, string-orchestra, full-orchestra, concert-band, jazz-band, choir, choir-piano, woodwind-quintet.
file- The score. See
file. templateoptional- The template. The default is piano.
list_commands
Lists the : commands of run_command, with what each one does.
text_format
Describes the compact score text of read_measures and write_measures.
guide
Gives the recipes for jobs with more than one step, for example the copy of a PDF score. With no name, it lists the recipes. With a name, it gives the steps of that recipe, and tells which programs of the recipe are installed.
nameoptional- The name of a recipe, for example transcribe-pdf.
Limits
- The tools take no key commands. They use
:commands and the score text. - The
:commands that need the app (files, windows, playback, and entry modes) do not work inmj-mcp. Thelist_commandstool shows the commands that work. - A file with no unsaved changes in the app opens again when it changes on disk, for example after
mj write.