servers / gradus-notation
Gradus Notation MCP server
communitystdiolocalwrite capablehealthy
Render music notation (SVG/MusicXML/MIDI), analyze, search music theory. Free, no auth, no GUI.
01Tools · 10
| Tool | Risk | Side effects | Approval |
|---|---|---|---|
| knowledge_search Search the Gradus music-theory knowledge base for authoritative source material. The corpus includes hand-authored curriculum prose, Bach chorale analysis (408 chorales), score commentaries on 50+ orchestral works, and primary historical sources from Fux (1725) through Boulanger.
WHEN TO USE: before generating notation if you need to look up a specific theory fact — typical voice leading for a Neapolitan-to-V resolution, idiomatic figured-bass realizations of a particular cadence, what makes a chromatic mediant feel like one composer's style versus another. Hitting this first prevents the agent from inventing chord progressions that are stylistically wrong.
WHEN NOT TO USE: for generic music vocabulary ("what is a chord?") that any LLM already knows; for non-theory queries like composer biographies, performance recommendations, or history dates — those are out of scope; for fetching actual score notation (use notation_render or notation_examples instead).
INPUT: provide EITHER `topics` (kebab-case tags) OR `step` (curriculum step 1-49). Topics are stronger; step is the fallback when you do not know the canonical topic tag. Both empty returns a MISSING_QUERY error.
OUTPUT (JSON): { ok: true, requestId, chunks: [{ id, sourceType, sourceId, title, content, composer?, era?, topics: string[], curriculumSteps: number[], tokenEstimate }], meta: { query, returnedCount, totalTokens, responseTimeMs }, attribution }. `sourceType` is one of: kg_concept, score_analysis, score_commentary, bach_chorale_analysis, composer, dictionary, curriculum, lesson_content, practicum, voice_leading, fugue, chorale_exercise, etc. Empty `chunks: []` when nothing matched the topics — agent should fall back to its own knowledge or try a different topic tag.
EXAMPLE INPUT: { "topics": ["voice-leading", "deceptive-cadence"], "limit": 3 }
TYPICAL LATENCY: 200-700 ms (one Voyage 3 embedding call + Supabase pgvector RPC). | read | false | unknown |
| notation_render Render music notation from a JSON score into three output formats in a single call: inline SVG (engraved through Verovio with the Bravura SMuFL font — same engine as IMSLP and the Music Encoding Initiative), round-trippable MusicXML (opens cleanly in Sibelius, Finale, MuseScore, Dorico), and base64-encoded SMF Type-1 MIDI.
WHEN TO USE: when the agent needs to surface engraved notation to its user (composer demoing an idea, teacher making a worksheet, content creator embedding a notation example), or when converting a JSON score to file formats other agents/tools can consume (MusicXML for desktop notation software, MIDI for sequencers).
WHEN NOT TO USE: if you are not sure the input is well-formed → call notation_validate first (much cheaper, no rendering); if you do not yet know the input format → call notation_examples or notation_schema; if you need theory facts before composing → call knowledge_search first.
INPUT: requires `instruments` (non-empty array). Each instrument has `name` (required; clef is inferred from the name — "Cello" → bass, "Viola" → alto, "Timpani" → percussion — overridable via `clef`) and either `notes` (single-voice shortcut) or `voices` (multi-voice). Pitches use scientific notation ("C4", "F#5", "Bb3"); durations use letter codes ("w" "h" "q" "8" "16" "32" "64" with optional "." for dotted, ".." for double-dotted). Bar lines are inferred from `timeSignature` (default [4,4]); notes that cross a bar line are split and tied automatically — agents do not count beats.
OUTPUT (JSON, success): { ok: true, requestId, outputs: { svg: string, musicxml: string, midiBase64: string }, meta: { measureCount, instrumentCount, voiceCount, durationBeats, renderTimeMs }, warnings?: ValidationIssue[], attribution }. ValidationIssue = { path, code, message, fix?, severity: "error"|"warning" }. SVG is typically 60-100 KB with Bravura font embedded; MusicXML is a few KB; MIDI is sub-1 KB.
OUTPUT (JSON, validation failure): { ok: false, requestId, errors: ValidationIssue[], attribution }. Each error includes a concrete `fix` field — surface that to your end user or use it to repair the input automatically.
EXAMPLE INPUT: { "title": "C major scale", "tempo": 100, "timeSignature": [4,4], "keySignature": "C major", "instruments": [{ "name": "Violin", "notes": ["C4/q","D4/q","E4/q","F4/q","G4/h","rest/h"] }] }
TYPICAL LATENCY: 100 ms (single-line melody) to 1.5 s (string quartet, 16+ measures). | read | false | unknown |
| notation_validate Pre-flight validate a notation_render input without rendering. Returns errors with concrete `fix` field that tells the agent exactly how to repair malformed input. Substantially cheaper than notation_render because it skips the Verovio engraving step entirely.
WHEN TO USE: when iterating on input shape and uncertain whether it is well-formed; when input came from user-supplied or LLM-generated data that may be malformed; when surfacing precise validation errors to your end user before committing to a full render; when learning the input format (combine with notation_examples to see canonical inputs).
WHEN NOT TO USE: if input is known to be valid (just call notation_render directly — it validates internally too); if you have not learned the schema yet (call notation_schema or notation_examples first to see the format).
INPUT: identical shape to notation_render. `instruments` array required (each with `name` and `notes` or `voices`).
OUTPUT (JSON, valid): { ok: true, requestId, valid: true, warnings: ValidationIssue[], meta: { measureCount, instrumentCount, voiceCount, durationBeats }, attribution }. Warnings are non-blocking notices (e.g. unusual time signature handling).
OUTPUT (JSON, invalid): { ok: false, requestId, valid: false, errors: ValidationIssue[], warnings, attribution }. Each ValidationIssue: { path: "instruments[0].voices[0].notes[3]", code: "BAD_PITCH"|"BAD_DURATION"|"MISSING_FIELD"|"BAD_KEY_SIG"|..., message, fix: "Use scientific notation: letter A-G + optional # or b + octave number, e.g. C4, F#5, Bb3.", severity: "error"|"warning" }. Surface the `fix` to your user or use it to auto-repair.
EXAMPLE INPUT: { "instruments": [{ "name": "Violin", "notes": ["C5/q","D5/q","E5/q","F5/q"] }] }
TYPICAL LATENCY: 30-100 ms (no Verovio render; pure JSON-to-Score conversion + bar-line arithmetic). | unknown | unknown | unknown |
| notation_examples Fetch six canonical example inputs covering the most common notation_render use cases: single-line melody, two-voice counterpoint (cantus firmus + counterpoint), block-chord progression (cadence), mixed rhythms with dynamics + articulations, four-instrument string quartet, and notes tied across a bar line.
WHEN TO USE: first encounter with this MCP — fetch examples to learn the input format with concrete worked patterns; before a notation_render call when uncertain how to express a particular musical structure (a chord, a multi-voice staff, a tied note); to show your end user what kinds of notation are possible.
WHEN NOT TO USE: after caching the response (the examples are stable across the v1 API; fetch once and reuse forever); when you only need formal type definitions (use notation_schema for JSON Schema instead).
INPUT: none. Pass an empty object `{}`.
OUTPUT (JSON): { ok: true, examples: [{ id, title, description, use_when, input: NotationInput }], docs: { schema, render, validate }, attribution }. Six examples with stable ids: single-melody, two-voice-counterpoint, chord-progression, mixed-rhythms, string-quartet-snippet, tied-across-bar. Each `input` is a complete payload that can be passed directly to notation_render.
EXAMPLE INPUT: {} (no parameters)
TYPICAL LATENCY: 30-200 ms. Response is cached at CDN with long TTL — subsequent calls are essentially free. | read | false | unknown |
| theory_parse_xml Parse a MusicXML string into a maestroAnalyst Score object. The Score is the input type for theory_validate_ranges and can be passed to any maestroAnalyst analysis function.
WHEN TO USE: when you have a MusicXML file (e.g., exported from Sibelius, Finale, MuseScore, Dorico, or produced by notation_render) and want to analyse it — detect key, check ranges, respell accidentals. This is the entry point for the native analysis pipeline that replaces music21.
LIMITATIONS: accepts plain MusicXML text (score-partwise format). Does NOT accept .mxl ZIP archives — decompress first if needed. Score-timewise and other non-partwise formats are not supported.
INPUT: { xml: string } — the full MusicXML document text.
OUTPUT: { ok, requestId, score: Score, meta: { partCount, noteCount, measureCount }, attribution }. The Score JSON can then be passed to theory_validate_ranges or any other theory tool.
TYPICAL SIZE: a Bach chorale (4 parts, 32 measures) produces a Score with ~512 notes. A Beethoven symphony movement (12 parts, 400 measures) may produce 8,000+ notes. Fit within your context budget or process in chunks. | unknown | unknown | unknown |
| notation_schema Fetch the JSON Schema (Draft 2020-12) describing the notation_render input shape. Includes every field, its type, defaults, validation rules (including the shorthand-string regex pattern), and `$defs` for Instrument, VoiceLine, Note, and NoteObject.
WHEN TO USE: first encounter with this MCP and you want machine-readable type definitions; building a client that validates input client-side before calling notation_render; generating code (TypeScript types, Zod schemas, etc.) that consumes the format.
WHEN NOT TO USE: after caching the response (stable across the v1 API); when you want learning-by-example (use notation_examples instead — worked payloads are easier to read than schema definitions).
INPUT: none. Pass an empty object `{}`.
OUTPUT (JSON): { ok: true, schema: { $schema: "https://json-schema.org/draft/2020-12/schema", $id, title, type: "object", required: ["instruments"], properties, $defs: { Instrument, VoiceLine, Note, NoteObject } }, docs: { examples, render, validate }, attribution }. The `schema` field is a complete JSON Schema document.
EXAMPLE INPUT: {} (no parameters)
TYPICAL LATENCY: 30-200 ms. Response is cached at CDN with long TTL — subsequent calls are essentially free. | read | false | unknown |
| theory_validate_ranges Check every note in a Score JSON against its instrument's standard practical range. Returns warnings for out-of-range pitches with measure, beat, MIDI number, and severity.
WHEN TO USE: after parsing a MusicXML file with theory_parse_xml and before analysis — catch unplayable or extreme notes early; when generating or editing a score programmatically and want to verify instrument idiomatic range; when a student submits a composition for critique and range errors should be flagged.
SEVERITY LEVELS: "error" = note is > 1 semitone outside the practical range; "warn" = note is at the boundary (within 1 semitone).
SUPPORTED INSTRUMENTS (partial name match, case-insensitive): Violin, Viola, Cello, Double Bass, Harp, Flute, Piccolo, Oboe, English Horn, Clarinet, Bass Clarinet, Bassoon, Contrabassoon, Soprano/Alto/Tenor/Baritone Sax, Horn, Trumpet, Trombone, Tuba, Piano, Organ, Marimba, Xylophone, Vibraphone, Glockenspiel, Timpani, Soprano/Mezzo/Alto/Tenor/Baritone/Bass (voice).
INPUT: a maestroAnalyst Score object — obtain one by calling theory_parse_xml with MusicXML text.
OUTPUT: { ok, requestId, warnings: [{ measure, beat, pitch, midi, partId, instrumentName, min, max, severity }], attribution }. Empty `warnings` array means all notes are in range.
EXAMPLE: pass a Score with a Violin part containing a note at A7 (MIDI 105) — it will return severity "error" since violin tops out around B7/MIDI 107 but A7 is beyond practical range. | unknown | unknown | unknown |
| theory_respell Suggest the preferred enharmonic spelling for one or more pitches in a given key context. Picks the spelling that is diatonic to the key (e.g. F# in G major, Gb in F major). Uses the key's accidental preference (sharps/flats) as a tiebreaker for chromatic passing tones.
WHEN TO USE: after OMR (optical music recognition) to correct mis-spelled accidentals; when generating notation and unsure whether to write F# or Gb; when transposing — respell after the semitone shift to maintain diatonic spelling; before calling notation_render to clean up accidentals.
INPUT: { keyContext: string, pitches: string[] } OR { keyContext: string, pitch: string }. Pitch strings use scientific notation: "F#4", "Bb3", "C5", "Eb4".
OUTPUT: { ok, requestId, keyContext, results: [{ input, output, changed }], attribution }. `changed` is true when the spelling was adjusted.
EXAMPLES:
{ keyContext: "F major", pitches: ["F#4", "Bb4", "E4"] }
→ F#4→Gb4 (Gb is diatonic in F major), Bb4 unchanged, E4 unchanged.
{ keyContext: "G major", pitch: "Gb4" } → Gb4→F#4 (F# is diatonic in G major). | write | true | unknown |
| theory_analyze_score One-shot endpoint: parse MusicXML → run the full MaestroAnalyzer harmonic analysis pipeline → query the Gradus Knowledge Base (GKB) for curated theory chunks matched to the score's detected features. Returns both the algorithmic analysis and relevant hand-authored knowledge in a single call.
WHEN TO USE: when an agent has a MusicXML score and wants to know what's harmonically interesting about it — key, local-key trajectory, chord analyses with Roman numerals, cadences, phrase structure, style period, AND relevant theory context from the GKB (voice-leading rules, harmonic vocabulary, orchestration notes, historical context). This is the richest single-call analysis available.
WHEN NOT TO USE: if you only need range checking (theory_validate_ranges); if you only need re-spelling (theory_respell); if you want raw GKB search without score analysis (knowledge_search).
INPUT: { xml: string, maxKnowledgeTokens?: number (default 1500), includeKnowledge?: boolean (default true) }
OUTPUT: {
meta: { partCount, noteCount, measureCount },
analysis: {
overallKey: { key, mode, confidence },
localKeys: [{ measure, key, confidence }],
chordAnalyses: [{ measure, beat, primary, readings: [{ rn, rnAscii, inversion, localKey, confidence }], tendencyTones }],
cadences: [{ type: "PAC"|"IAC"|"HC"|"DC"|"Plagal"|"Phrygian"|"unclear", ... }],
phrases: [{ index, measureStart, measureEnd, fermataMeasures }],
},
submissionHints: { stylePeriod, focusAreas, rationale }, // inferred style heuristic
knowledge: {
topics: string[], // GKB tags derived from the analysis
chunks: [{ title, content, sourceType, era, composer, curriculumSteps }],
totalTokens: number,
},
}
TYPICAL LATENCY: 200-600 ms (analysis is pure JS; GKB adds one Voyage embedding call ~100-200 ms). | write | true | unknown |
| theory_pitch_utils A collection of fast, pure pitch-utility operations that replace the most-used music21 pitch functions with zero network round-trip.
OPERATIONS:
midi_to_pitch — MIDI number → pitch string. midi=60 → "C4". preferFlats=true → "Db" spellings.
pitch_to_midi — pitch string → MIDI number. "C4"→60, "F#5"→78, "Bb3"→46. Returns null for rests.
interval_name — semitone count → interval quality string. 0→"P1" 3→"m3" 4→"M3" 7→"P5" 12→"P8". Compound intervals: 14→"M2+8".
transpose_pitch — shift a pitch by semitones. "C4"+7→"G4", "E5"+-2→"D5". preferFlats controls black-key spelling.
WHEN TO USE: fast arithmetic during score generation or analysis without invoking a full analysis pipeline; populating MIDI output tables; labeling intervals in educational contexts; transposing individual notes while composing.
INPUT: { op: string, ...params } where op is one of the operations above.
EXAMPLES:
{ op: "midi_to_pitch", midi: 60 } → { pitch: "C4" }
{ op: "pitch_to_midi", pitch: "F#5" } → { midi: 78 }
{ op: "interval_name", semitones: 7 } → { interval: "P5" }
{ op: "transpose_pitch", pitch: "C4", semitones: 7 } → { pitch: "G4" }
{ op: "transpose_pitch", pitch: "E4", semitones: 1, preferFlats: true } → { pitch: "F4" } | read | false | unknown |
02Install & source
npx -y @gradusmusic/notation-mcp
npx- repohttps://github.com/delmas41/gradusnotation
- licenseMIT
- adoption2 stars · 0 forks
03Access granted
Vector & semantic search · write
The access this server can exercise, inferred from its verified tools — not a declared OAuth scope.
05Provenance & freshness
sourcesOfficial MCP Registry [p1]
last_checked2026-07-07 08:51Z
next_check2026-07-09 08:42Z
cadenceevery 48h
verifiedtools_list:passed handshake:passed metadata:passed
index_statusindex — 9 unique facts >= 5
06Badge
Add the “as seen on MCPExplorer” badge to your README.
[](https://mcpexplorer.com/servers/gradus-notation)
Next step
This is one server. A loadout combines the right servers, governance, and proven plays for a whole job — assembled deliberately, not tool-dumped.
Explore loadouts →