Skip to main content
Glama
tubone24
by tubone24

MIDI MCP Server

A Model Context Protocol (MCP) server for AI-driven MIDI composition. Generate MIDI files from structured JSON data, with chord name support, an interactive piano-roll preview UI, and multiple deployment modes.

demo

Looking for the Agent Skills approach? It composes better songs with less context: tubone24/midi-agent-skill


Features

  • Two MCP tools: create_midi (with interactive preview UI) and parse_chord

  • Rich pitch input: MIDI numbers, note name strings ("C4"), pitch arrays, or chord names ("Cmaj7")

  • Chord library: 25+ chord qualities — major, minor, dim, aug, 7th, maj7, m7, sus2, sus4, power, and more

  • Flexible durations: numeric beats, standard strings ('4', '8'), dotted ('d4'), triplet ('T8')

  • Music theory resources: 7 built-in reference documents accessible as MCP resources

  • Three transport modes: stdio, HTTP, or Cloudflare Workers (remote)

  • MCP App UI: Piano-roll visualization and audio playback rendered directly in the conversation


Related MCP server: CHUK Music MCP Server

Deployment Options

Option A — Remote (Cloudflare Workers)

A pre-deployed remote server is available:

https://midi-mcp-server.tubone24.workers.dev/mcp

Add it to any MCP client that supports Streamable HTTP (e.g., Claude.ai):

{
  "mcpServers": {
    "midi": {
      "type": "http",
      "url": "https://midi-mcp-server.tubone24.workers.dev/mcp"
    }
  }
}

Build and configure as a local stdio server:

npm install
npm run build
{
  "mcpServers": {
    "musicComposer": {
      "command": "node",
      "args": ["/path/to/midi-mcp-server/build/index.js"]
    }
  }
}

Option C — Local HTTP

Run as a local Streamable HTTP server:

node build/index.js --http
# or with a custom port:
node build/index.js --http --port=8080

The server exposes:

  • POST /mcp — MCP Streamable HTTP endpoint

  • GET /health — Health check ({"status":"ok","version":"0.2.0"})


Tools

create_midi

Generate a MIDI file from structured composition data. Returns base64-encoded MIDI and renders an interactive piano-roll preview with audio playback in supported MCP clients (MCP App).

mid

Input

Field

Type

Required

Description

title

string

Title of the composition

composition

object

Composition data (see schema below)

Output (structured content)

Field

Type

Description

midiBase64

string

Base64-encoded MIDI file data

title

string

Composition title

bpm

number

Tempo used

trackCount

number

Number of tracks generated


parse_chord

Parse a chord name and return its component MIDI pitches and note names. Useful for understanding voicings before composing.

Input

Field

Type

Required

Description

chord

string

Chord name, e.g. "Cmaj7", "F#m7", "G7sus4"

octave

number

Root octave (default: 4)

Output example

{
  "chord": "Cmaj7",
  "octave": 4,
  "midiNumbers": [60, 64, 67, 71],
  "noteNames": ["C4", "E4", "G4", "B4"]
}

Composition Schema

{
  "bpm": 120,                              // tempo (also accepted: "tempo")
  "timeSignature": { "numerator": 4, "denominator": 4 },  // optional, default 4/4
  "tracks": [
    {
      "name": "Piano",                     // optional
      "instrument": 0,                     // GM program number 0–127 (optional)
      "notes": [
        {
          "pitch": 60,                     // MIDI number, note name "C4", or array [60, 64, 67]
          "chord": "Cmaj7",                // OR use chord name (overrides pitch)
          "beat": 1,                       // beat position (1-based); OR use startTime
          "startTime": 0,                  // tick offset (alias: "time")
          "duration": "4",                 // see Duration Reference below
          "velocity": 100,                 // 0–127 (optional, default 100)
          "channel": 0                     // MIDI channel 0–15 (optional)
        }
      ]
    }
  ]
}

Pitch Input Formats

Format

Example

Description

MIDI number

60

Standard MIDI note number (0–127)

Note name

"C4"

Letter + optional accidental + octave

Pitch array

[60, 64, 67]

Multiple pitches played simultaneously

Chord field

chord: "Cmaj7"

Chord name expanded automatically

Supported accidentals: # (sharp), b (flat). Examples: "F#5", "Bb3".

Duration Reference

Value

Description

'1'

Whole note

'2'

Half note

'4'

Quarter note

'8'

Eighth note

'16'

Sixteenth note

'32'

Thirty-second note

'd1' 'd2' 'd4' 'd8' 'd16'

Dotted variants

'dd4'

Double-dotted quarter

'T4' 'T8'

Triplet variants

4 (number)

Beat-based: 1=quarter, 2=half, 4=whole, 0.5=eighth

Supported Chord Qualities

Quality

Example

Description

(none) / maj

C, Cmaj

Major

m / min

Dm

Minor

dim

Bdim

Diminished

aug

Eaug

Augmented

7

G7

Dominant 7th

maj7 / M7

Cmaj7

Major 7th

m7 / min7

Am7

Minor 7th

dim7

Bdim7

Diminished 7th

m7b5

Bm7b5

Half-diminished

aug7

Eaug7

Augmented 7th

6 / m6

C6, Am6

6th

9 / maj9 / m9

G9

9th variants

add9

Cadd9

Add 9th

11 / 13

C11

Extended

sus2 / sus4

Gsus4

Suspended

7sus4 / 7sus2

G7sus4

7th suspended

power / 5

G5

Power chord


MCP Resources

The server exposes 7 music theory reference documents as MCP resources:

URI

Description

music-theory://harmony

Intervals, chord types, diatonic chords, cadences, voice leading

music-theory://chord-progressions

Common progressions by mood/genre, substitutions, modulation

music-theory://counterpoint

Species counterpoint rules, consonance/dissonance, motion types

music-theory://modes-scales

Diatonic modes, minor scale variants, pentatonic/blues, genre guide

music-theory://orchestration

Instrument ranges, GM program numbers, texture types

music-theory://rhythm-patterns

Time signatures, MIDI duration reference, genre grooves

music-theory://voice-leading

Forbidden parallels, voicing strategies, non-chord tones

MCP clients that support resource reading can pass these to the AI as context, enabling theory-aware composition.


Example Composition

const composition = {
  bpm: 120,
  timeSignature: { numerator: 4, denominator: 4 },
  tracks: [
    {
      name: "Piano",
      instrument: 0,
      notes: [
        { chord: "Cmaj7", beat: 1, duration: "2", velocity: 90 },
        { chord: "Am7",   beat: 3, duration: "2", velocity: 90 },
        { chord: "Fmaj7", beat: 5, duration: "2", velocity: 90 },
        { chord: "G7",    beat: 7, duration: "2", velocity: 90 }
      ]
    },
    {
      name: "Melody",
      instrument: 0,
      notes: [
        { pitch: "E4", beat: 1, duration: "4", velocity: 100 },
        { pitch: "G4", beat: 2, duration: "4", velocity: 100 },
        { pitch: "A4", beat: 3, duration: "2", velocity: 110 }
      ]
    }
  ]
};

Demo

The prompt below generates an 8-bar melodic minor choral piece:

Create an 8-bar choral piece in a slightly minor, melodic scale.

https://github.com/user-attachments/assets/e20ebef0-fdbf-4e72-910d-41b94183f9d9

melodic_minor_chorus.mid


Build & Development

npm install

# Full build (UI + server)
npm run build

# Build steps individually
npm run build:ui     # Vite — builds the MCP App preview HTML
npm run build:server # tsc — compiles TypeScript server

# Deploy to Cloudflare Workers
npm run deploy

# Run tests
npm test
npm run test:coverage

Dependencies

Package

Purpose

@modelcontextprotocol/sdk

MCP server implementation (stdio & HTTP transports)

@modelcontextprotocol/ext-apps

MCP Apps extension — interactive UI in conversation

midi-writer-js

MIDI file generation

@tonejs/midi

MIDI parsing (preview UI)

soundfont-player

Audio playback in preview UI

zod

Input schema validation

Available Tools

2 tools
create_midiCreate MIDIA

Generate a MIDI file from structured composition data with chord support. Supports single notes, note arrays (chords), and chord names (5, 6, 7, 9, 11, 13, maj, m, min, dim, etc.). Returns base64-encoded MIDI data and displays an interactive preview with piano-roll notation and playback.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesTitle of the composition
compositionNoComposition object with bpm (number), optional timeSignature ({numerator, denominator}), and tracks (array of {name?, instrument?, notes: [{pitch, chord?, beat?, startTime?, duration, velocity?, channel?}]})

Output Schema

ParametersJSON Schema
NameRequiredDescription
bpmYes
titleYes
midiBase64Yes
trackCountYes

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses that the tool returns base64-encoded MIDI data and shows an interactive preview, which is useful. However, it does not mention any side effects, limitations, or prerequisites beyond the input schema, leaving some behavioral ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured, with two sentences that front-load the main purpose and then provide key details about output and preview. There is no redundant information or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 parameters, output schema present), the description covers the essential aspects: what it does, the output format, and the interactive preview. It does not mention the behavior when composition is omitted (since title is the only required parameter), but this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds value beyond the input schema by elaborating on the chord support feature, listing specific chord types (5, 6, 7, 9, 11, 13, maj, m, min, dim, etc.). It also clarifies that the composition data must be structured, reinforcing the schema's meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Generate') and resource ('MIDI file'), clearly stating the tool's function. It also mentions chord support, which distinguishes it from the sibling parse_chord tool, even though it does not explicitly name it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly indicates the tool should be used when generating a MIDI file from structured composition data. However, it does not explicitly mention when not to use it or provide alternatives, such as referencing the sibling parse_chord tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parse_chordA

Parse a chord name and return its component MIDI pitches. Useful for understanding chord voicings.

ParametersJSON Schema
NameRequiredDescriptionDefault
chordYesChord name (e.g., "Cmaj7", "Dm", "F#m7", "G7sus4")
octaveNoOctave for the root note (default: 4)

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden. It states the output (MIDI pitches) but does not mention read-only nature, error handling for invalid chord names, whether pitches are sorted, or how octave affects non-root notes. Behavior is partly transparent but gaps remain.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences, front-loaded with the action, and contains no filler. Every word contributes meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with 2 parameters and no output schema, the description is adequate but incomplete. It does not specify the exact return format (e.g., array of integers, sorted order) or how octave interacts with chord voicing internals. More detail would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: both chord and octave have descriptions. The tool description adds no further parameter meaning, so it does not exceed the baseline provided by the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the verb (parse) and resource (chord name) and the result (component MIDI pitches). This differentiates it from the sibling create_midi, which generates MIDI rather than parsing chords.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Useful for understanding chord voicings' implies a use case but does not explicitly state when to use this tool versus create_midi, nor does it provide exclusions or prerequisites. It gives context but lacks clear when-to-use/when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.2.0
    • First observedcreate_midi
    • First observedparse_chord

TDQS

A4.1/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have clearly distinct purposes: create_midi generates MIDI files from composition data, while parse_chord analyzes chord names into pitches. No overlap or ambiguity exists.

Naming Consistency5/5

Both tool names follow a consistent verb_noun pattern (create_midi, parse_chord), making the naming predictable and intuitive.

Tool Count4/5

With only 2 tools, the server is minimal but appropriately scoped for a niche MIDI/chord utility. The low count is justified by the focused domain, though it is on the thin side.

Completeness4/5

The server covers generation of MIDI files and chord parsing, addressing its core purpose. Minor gaps like MIDI file reading or conversion exist, but they are not obvious omissions for the stated functionality.

Maintenance

ActivityInactive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers