Skip to main content
Glama

fcp-midi

MCP server for semantic MIDI composition.

What It Does

fcp-midi lets LLMs compose music by describing musical intent -- notes, chords, dynamics, tempo changes -- and renders it into standard MIDI files. Instead of manipulating raw bytes or MIDI events, the LLM works with operations like note Bass E2 at:1.1 dur:quarter vel:90 and crescendo @track:Lead vel:45-75 @range:3.1-6.4. Built on the FCP framework; a mido.MidiFile is the source of truth throughout, so there's no separate serialization step.

Related MCP server: Vibe Composer MIDI MCP

Quick Example

midi_session('new "Voltage Drop" tempo:140 key:E-minor')

midi([
  'note Drums kick at:1.1 dur:eighth vel:100',
  'note Bass E2 at:1.1 dur:quarter vel:90',
  'chord Pad Em at:1.1 dur:whole vel:70',
  'crescendo @track:Lead vel:45-75 @range:3.1-6.4',
  'tempo 174 at:11.1',
])

midi_session('save as:./voltage_drop.mid')

Available MCP Tools

Tool

Purpose

midi(ops)

Batch mutations -- notes, chords, tracks, tempo, dynamics, copy/transpose

midi_query(q)

Inspect the composition -- map, tracks, events, piano-roll, instruments, find

midi_session(action)

Lifecycle -- new, open, save, checkpoint, undo, redo

midi_help()

Full reference card

Hero Examples

Plumber's Journey -- Classic game theme faithfully recreated: 4 tracks, 288 notes, 16 seconds, 180 BPM.

Voltage Drop -- A drum-and-bass track with tempo acceleration (140 -> 155 -> 174 BPM), 5 tracks, breakbeats, sub-bass, arpeggios, and a signature DROP section. Also used in the FCP vs raw Python agent battle -- FCP produced 1,674 notes across 12 tracks in 87 seconds, compared to 694 notes from ~689 lines of hand-written Python.

See docs/examples/ for MIDI files and the full writeup.

Installation

Requires Python >= 3.11.

pip install fcp-midi

MCP Client Configuration

{
  "mcpServers": {
    "midi": {
      "command": "uv",
      "args": ["run", "python", "-m", "fcp_midi"]
    }
  }
}

Architecture

Mido-native — no parallel semantic model between the op handlers and the file format:

MCP Server (fcp-core create_fcp_server + MidiAdapter)
  Parses op strings, dispatches to verb handlers, session lifecycle
        |
MidiModel (mido.MidiFile is the source of truth)
  Op handlers read/write mido messages directly on the tracks;
  a NoteIndex gives fast selector lookups. Undo/redo and batch
  atomicity are byte snapshots of the file, not event replay.

Key features:

  • Instrument library -- GM instruments by name (acoustic-grand-piano, synth-bass-1, standard-kit)

  • Soundfont support -- Load custom instrument banks

  • Beat addressing -- at:1.1 (bar 1, beat 1), at:3.2.240 (bar 3, beat 2, tick 240)

  • Duration vocabulary -- whole, half, quarter, eighth, sixteenth, triplet

  • Dynamics -- crescendo, diminuendo across ranges

  • Copy/transpose -- Duplicate and shift musical phrases

Development

uv sync
uv run pytest       # 620 tests
uv run pytest -m "not slow"  # skip stress tests (604 tests, ~0.25s)
uv run ruff check   # linting
uv run pyright      # type checking

License

MIT

Available Tools

4 tools
midiA

Execute midi operations. Each op string follows: VERB TARGET [key:value ...] Call midi_help for the full reference card.

MUSIC: note TRACK PITCH at:POS dur:DUR [vel:V] [ch:N] chord TRACK SYMBOL at:POS dur:DUR [vel:V] [ch:N] track add|remove NAME [instrument:INST] [program:N] [ch:N] [bank:MSB[.LSB]] cc TRACK CC_NAME VALUE at:POS [ch:N] bend TRACK VALUE at:POS [ch:N] tracker TRACK import at:POS [res:RES] ... tracker end

STATE: mute TRACK solo TRACK program TRACK INSTRUMENT|program:N [at:POS] [bank:MSB[.LSB]]

META: tempo BPM [at:POS] time-sig N/D [at:POS] key-sig KEY-MODE [at:POS] marker TEXT at:POS title TEXT

EDITING: remove SELECTORS move SELECTORS to:POS copy SELECTORS to:POS transpose SELECTORS SEMITONES velocity SELECTORS DELTA quantize SELECTORS grid:DUR modify SELECTORS [pitch:P] [vel:V] [dur:D] [at:POS] [ch:N] repeat SELECTORS [to:POS] count:N crescendo SELECTORS from:VEL to:VEL decrescendo SELECTORS from:VEL to:VEL

SELECTORS: @track:NAME @channel:N @range:M.B-M.B @pitch:PITCH @velocity:N-M @all @recent @recent:N @not:TYPE:VALUE Combine to intersect: @track:Piano @range:1.1-4.4

POSITION: M.B (1.1 = start) M.B.T (tick offset) tick:N +DUR -DUR end

DURATION: whole, half, quarter, eighth, sixteenth, 32nd 1n, 2n, 4n, 8n, 16n, 32n dotted-quarter, triplet-eighth, ticks:N

PITCH: C4, D#5, Bb3 (note+accidental+octave) midi:60 (raw MIDI number)

CHORDS: Cmaj, Am, Dm7, G7, Bdim, Faug, Csus4, Asus2 Cmaj7, Am7, Dm7b5, G9, Cm6, Cadd9, Dm/F (slash)

VELOCITY: 0-127 (numeric) ppp, pp, p, mp, mf, f, ff, fff (dynamic names)

CC NAMES: volume, pan, modulation, expression, sustain, reverb, chorus, brightness, portamento, breath

GM INSTRUMENTS (EXAMPLES): acoustic-grand-piano, electric-piano-1, vibraphone acoustic-guitar-nylon, electric-bass-finger, violin trumpet, alto-sax, flute, string-ensemble-1 program:N (raw 0-127) bank:MSB[.LSB]

RESPONSE PREFIXES:

  • note/chord added ~ event modified

  • track modified - event removed ! meta event @ bulk operation

CONVENTIONS:

  • Positions are 1-based: measure 1, beat 1 = 1.1

    • Channels are 1-indexed user-facing (ch:1 through ch:16)

    • Channel 10 is drums (GM standard)

    • Track names are unique identifiers

    • Batch multiple ops in one call for efficiency

    • Call midi_help after context truncation for full reference

ParametersJSON Schema
NameRequiredDescriptionDefault
opsYes

TDQS

A4.2/5.0
Behavior4/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It does well by documenting response prefixes, 1-based positions, 1-indexed channels, and GM conventions. It stops short of explaining failure modes, transactionality of batched ops, or persistence behavior, which are relevant for an execution tool.

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 long but meticulously organized into labeled sections (MUSIC, STATE, META, EDITING, SELECTORS, etc.) with a monospaced format for readability. The front-loaded instruction 'Each op string follows: VERB TARGET [key:value ...]' and the pointer to midi_help ensure efficiency. Every section provides essential syntax for a complex DSL, so no space is wasted.

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

Completeness5/5

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

Given the tool's complexity, the absence of an output schema, and zero annotations, this description is remarkably complete. It covers all major operation types, selectors, notational conventions, and response prefixes. It also references midi_help for deeper coverage, making it sufficient for correct tool invocation.

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

Parameters5/5

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

The schema has a single undocumented parameter 'ops' (an array of strings), and the description fully compensates by defining the exact op syntax, selectors, positions, durations, pitches, chords, velocities, and more. This is a comprehensive semantic specification that makes parameter usage unambiguous.

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

Purpose4/5

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

The description opens with 'Execute midi operations,' a clear verb+resource statement that identifies the tool's core purpose. It also differentiates from midi_help by instructing users to call it for the full reference card. However, it does not explicitly contrast with midi_query or midi_session, so it doesn't fully distinguish among all sibling tools.

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 description offers some usage guidance, such as batching multiple ops for efficiency and calling midi_help when context is truncated. However, it does not explicitly state when to use this tool instead of midi_query or midi_session, and the guidance is mostly implied through the operation list.

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

midi_helpA

Returns the midi reference card with all syntax.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral transparency. It only states that a reference card is returned, without detailing the format, whether it is read-only, or any other operational aspects. For a help tool this is minimal but lacks depth.

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 a single 8-word sentence with no extraneous detail, front-loading the key action and outcome.

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?

For a zero-parameter help tool with no output schema, the description sufficiently explains the return value (the reference card) and its scope (all syntax). It lacks some specifics about the card's content, but overall is complete for its simplicity.

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 tool has zero parameters and the schema covers 100% of the interface, so description-level parameter semantics are unnecessary. Baseline score of 4 applies.

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 clearly states the tool returns a reference card for MIDI syntax, using the specific verb 'Returns' and a concrete resource. This differentiates it from siblings like midi_query or midi_session.

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 description implies this tool is used to obtain reference information, but it does not explicitly state when to use it or provide alternatives. There is no mention of situations where other sibling tools would be more appropriate.

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

midi_queryD

Query midi state.

ParametersJSON Schema
NameRequiredDescriptionDefault
qYes

TDQS

D1.6/5.0
Behavior1/5

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

No annotations are provided, so the description carries the full burden for behavioral disclosure. 'Query' implies a read operation, but there is no explicit mention of safety, side effects, permissions, or output behavior, making the tool behaviorally opaque.

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

Conciseness2/5

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

The description is a single short sentence, which is concise, but it is under-specified rather than efficiently informative. It lacks essential details and does not earn its brevity, similar to the 'Process' example where minimalism harms usability.

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

Completeness1/5

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

Given the lack of annotations, an opaque parameter, no output schema, and no usage context, the description is grossly incomplete. The agent has no information about query syntax, return values, or operational constraints, making the tool nearly unusable for reliable invocation.

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

Parameters1/5

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

The input schema only defines a required string 'q' with 0% description coverage. The description adds no meaning for the parameter—it does not explain what 'q' should contain, the query syntax, or expected format. The parameter is completely underdocumented.

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

Purpose3/5

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

The description 'Query midi state' provides a verb and a resource, but 'midi state' is vague and does not specify what aspect of MIDI state is being queried. It does not distinguish itself from sibling tools like 'midi' or 'midi_session', and the purpose remains ambiguous.

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

Usage Guidelines1/5

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

No guidance is given for when to use this tool versus alternatives. The description does not mention any context, prerequisites, or comparisons to sibling tools, leaving the agent without direction for tool selection.

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

midi_sessionC

Session: 'new "Title"', 'open ./file', 'save', 'checkpoint v1', 'undo', 'redo'

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYes

TDQS

C2.6/5.0
Behavior2/5

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

With no annotations, the description carries full responsibility for behavioral disclosure. It lists commands like 'undo' and 'redo' which imply state changes, but it does not explain side effects, persistence semantics, error behavior, or any side effects beyond naming the actions. The behavior is largely opaque.

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

Conciseness4/5

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

The description is very short and to the point, listing commands in a compact format. It is front-loaded with 'Session:' which sets the context. The structure is somewhat unstructured as a free-form string, but it contains no fluff and every word contributes to the set of examples.

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

Completeness2/5

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

Despite having only one parameter and no output schema, the description is still too minimal. It does not explain what the tool returns, whether commands are executed sequentially, what 'checkpoint' does, or what constitutes valid input. For a session management tool, the description lacks essential operational context.

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?

The single 'action' parameter has no schema description and no enum, but the description partially compensates by providing concrete example values (e.g., 'new "Title"', 'open ./file'). This gives the agent some sense of expected syntax, though the format is ambiguous (mixing quotes, spaces, and version strings) and not all actions are equally explained.

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

Purpose3/5

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

The description implies session management through a list of example commands ('new', 'open', 'save', etc.), but it never explicitly states the tool's purpose as a verb+resource (e.g., 'Manage MIDI sessions'). It is more of a usage hint than a clear functional definition, and it does not explicitly distinguish itself from sibling tools like 'midi' or 'midi_query'.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives. The sibling tools are not mentioned, and there is no description of scenarios suitable for session operations. The examples imply actions, but no context or exclusion criteria are given.

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. Dates show when Glama detected each change.

  1. 4 tool updatesv0.2.0
    • First observedmidi
    • First observedmidi_help
    • First observedmidi_query
    • First observedmidi_session

TDQS

B3.3/5.0
Disambiguation5/5

Each tool has a clearly distinct role: midi for editing/creating music, midi_query for reading state, midi_session for session/file management, and midi_help for documentation. There is no overlap in their primary purposes.

Naming Consistency5/5

All tools follow a consistent 'midi[_suffix]' pattern using snake_case. The base 'midi' denotes the core operation, while suffixes like '_query', '_session', and '_help' clearly indicate auxiliary functions. This is a predictable and uniform convention.

Tool Count5/5

With exactly 4 tools, the set is well-scoped and right-sized. The main tool centralizes a rich DSL for MIDI operations, while the supporting tools handle query, session, and help functions. No redundancy or excessive splitting.

Completeness5/5

The tool set provides full lifecycle coverage for MIDI work: creating/editing via midi, reading state via midi_query, session control (new/open/save/undo/redo) via midi_session, and reference via midi_help. There are no obvious missing operations within the domain.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/os-tack/fcp-midi'

If you have feedback or need assistance with the MCP directory API, please join our Discord server