lilypond-mcp
v0.2.2
Published
MCP server that engraves GNU LilyPond sources into cropped EPS, PDF, SVG, and PNG assets
Maintainers
Readme
lilypond-mcp
MCP server that engraves GNU LilyPond sources into placeable assets: cropped PDF, EPS, SVG, and PNG, sized to the music rather than a full page — ready to drop into page-layout software such as InDesign.
Nothing to install beyond Node: the server fetches a WebAssembly build of LilyPond on first use and engraves with that — the same engine on every machine.
Quick start
Claude Code — .mcp.json in your project:
{
"mcpServers": {
"lilypond": {
"command": "npx",
"args": ["-y", "lilypond-mcp@latest"]
}
}
}Claude Desktop — claude_desktop_config.json, same entry under
mcpServers. Or skip the config entirely: grab the .mcpb file from
the latest release
and open it with Claude Desktop — a desktop extension with the engine
bundled in, so it works offline from the first engrave.
That's the whole setup. On the first engrave, the server downloads the
engine (~35 MB, checksum-verified, cached under
~/.cache/lilypond-mcp — safe to delete at any time).
Tools
engrave_file— engrave a.lyfile. Defaults to cropped PDF — the format to place in InDesign (fonts embedded and subsetted, all PDF boxes defined). Also returns a preview PNG, both as a file and inline as an image in the tool result, so the agent sees what it engraved.engrave_code— engrave LilyPond code passed inline, for iterating on a musical idea without touching disk.lilypond_version— the LilyPond version the server engraves with, for picking the right\versionheader.
Both engrave tools accept formats (pdf/eps/svg/png), crop,
include_dirs (for shared \include libraries), output_dir, and
preview (default on; turn off to skip the inline image on batch runs). Paths
are resolved against the working directory the server is launched in — for
an .mcp.json entry, that is the project root. On failure the result
carries LilyPond's diagnostics, line numbers included, so an agent can fix
the source and retry.
What you get
This snippet, sent to engrave_code:
\version "2.26.0"
\header { tagline = ##f }
\score {
<<
\new ChordNames \chordmode { g2. | c | d | g }
\new Staff \new Voice = "m" \relative c'' {
\key g \major
\time 3/4
\tempo "Waltz" 4 = 132
g4 b d | e4.( d8) c4 | a4 fis d | g2 r4 \bar "|."
}
\new Lyrics \lyricsto "m" { Round and round the waltz goes, old and slow. }
>>
\layout { indent = 0 }
}comes back cropped to the music, as PDF, EPS, SVG or PNG — this is the SVG:
(Source in docs/example.ly.)
Engine
Engraving runs a WebAssembly build of LilyPond from
lilypond-wasi releases,
pinned in engine.json and executed in a child Node process via
node:wasi. Node 22 or newer: the engine uses WebAssembly exception
handling that V8 first shipped in Node 22. (The node:wasi fast-call
regression in Node 22.21.1+ —
nodejs/node#59600 — is
sidestepped automatically with --no-turbo-fast-api-calls.)
The engine trails lilypond-wasi's stable releases: a weekly workflow
re-pins engine.json to the newest release, engraves with it as a real
consumer, and opens a PR.
Development
npm install
npm run build # tsc → dist/
npm test # engraves real snippets with the wasm engine** The tests need an engine dir and skip without one. Either download the
pinned release into the cache — node scripts/assemble-engine-dir.mjs
prints the dir — or build one from a lilypond-wasi checkout:
./test/assemble-engine-dir.sh /tmp/engine-dir ../lilypond-wasi stable.
Then LILYPOND_MCP_ENGINE_DIR=<dir> npm test.
Releases: conventional commits → Knope bot release PR → merge → npm publish via OIDC trusted publishing (no tokens).
Privacy Policy
Everything happens on your machine. LilyPond sources are engraved locally by the bundled WebAssembly engine; neither your sources nor the generated assets ever leave your computer, and the server collects no data — no telemetry, no analytics, no accounts.
The npm package makes exactly one kind of network request: downloading
the pinned engine release from GitHub on first use (verified against
checksums, cached under ~/.cache/lilypond-mcp). The desktop extension
(.mcpb) ships the engine inside the bundle and makes no network
requests at all.
Generated assets are written to the output_dir you choose and stay
under your control; the server retains nothing else. Questions:
[email protected] or the
issue tracker.
Licence
MIT. The server runs a GPL-licensed engraver (the lilypond-wasi
WebAssembly build of GNU LilyPond) as a separate program, and the npm
package contains none of its bytes — see
LICENSING.md for the analysis and the design rules that keep that
boundary clean.
