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
ToolRiskSide effectsApproval
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).
readfalseunknown
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).
readfalseunknown
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).
unknownunknownunknown
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.
readfalseunknown
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.
unknownunknownunknown
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.
readfalseunknown
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.
unknownunknownunknown
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).
writetrueunknown
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).
writetrueunknown
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" }
readfalseunknown

02Install & source
npx -y @gradusmusic/notation-mcp
npx

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_statusindex9 unique facts >= 5

06Badge

Add the “as seen on MCPExplorer” badge to your README. Gradus Notation MCP — as seen on mcpexplorer.com

[![Gradus Notation MCP — as seen on mcpexplorer.com](https://mcpexplorer.com/badge/gradus-notation.svg)](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 →