npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

keyboards-mcp

v2.1.0

Published

MCP server for controlling MIDI keyboards (Nord Electro 5D and more)

Readme

keyboards-mcp

An MCP (Model Context Protocol) server for controlling MIDI keyboards. Supports pluggable keyboard models with auto-detection. Designed to be used with any MCP-compatible AI agent or assistant.

Currently supported: Nord Electro 5D, Roland JUNO-X, Prophet-6

What it does

  • Connect to a keyboard over USB MIDI by port name and model id, with an optional mock-UI shadow port
  • Read and change parameters — piano type/model, organ drawbars, effects, EQ, reverb, delay, and more
  • Load programs by bank and slot number
  • Load set list songs by bank, slot, and part
  • Browse inventory — list programs and songs from extracted backups with name and bank filtering
  • Extract backup files into a structured inventory of all sounds, programs, and set lists
  • Develop without hardware using the companion Sounds and Recreation app — mock keyboards with model-specific web UIs, plus a Song Analysis workbench

Architecture

Model-delegated design. MCP tools are thin wrappers — keyboard models own all business logic.

flowchart TB
    agent([AI Agent])
    mcp["MCP Server"]
    kbd["Keyboard (or Mock)"]
    mcb["MCB (midi-connections-broker)<br/>claims port leases so concurrent<br/>agent sessions don't collide"]
    tools["tools/ (thin delegates)"]
    pool["DevicePool → KeyboardDevice (1..N)"]
    models["keyboard_models/&lt;mfr&gt;/&lt;model&gt;/"]

    agent <-->|MCP| mcp
    mcp <-->|MIDI| kbd
    mcp -- "HTTP / UDS" --> mcb
    mcp --> tools --> pool --> models

A KeyboardModel is a type of keyboard (e.g., "Nord Electro 5D"). It owns shared definitions (parameter map, system prompt, backup parsing) and acts as a factory for device instances.

A KeyboardDevice is a specific physical unit or mock instance. Each device has its own MIDI connection, state, and backup data. Multiple devices of the same model can coexist.

The midi-connections-broker (MCB) is a separate long-running process that owns MIDI port leases. The MCP server claims a lease via MCB on connect_to_keyboard and releases it on disconnect_from_keyboard, so multiple agent sessions can share a host without stepping on each other's ports. MCB also exposes the canonical port list and reaps leases held by dead processes.

Key directories

| Path | Description | |------|-------------| | src/index.ts | MCP server entry point | | src/tools/ | MCP tool registrations (thin wrappers that delegate to device methods) | | src/shared/ | Shared interfaces: KeyboardModel, KeyboardDevice, MidiConnection, MockHandler, mcb-client | | src/keyboard_models/ | Pluggable keyboard models (<manufacturer>/<model>/) | | src/midi/ | MIDI I/O manager (implements MidiConnection) | | src/mcb/ | midi-connections-broker — lease registry, session manager, HTTP-over-UDS API |

The Sounds and Recreation desktop app (and its audio-analysis-client) now live in a separate workspace package, sounds-and-recreation-app, which depends on this package and imports its shared model logic via keyboards-mcp/shared/*.

Adding a new keyboard model

Create a directory under src/keyboard_models/<manufacturer>/<model>/ with:

  • index.ts — Default export implementing the KeyboardModel interface
  • device.ts — Class implementing KeyboardDevice (owns connection, state, all tool logic)
  • midi-map.ts — Parameter definitions with CC mappings and/or SysEx addresses
  • mock-handler.ts — Optional MockHandler implementation for the mock device
  • web/ — Optional mock device web UI (HTML/CSS/JS)

The model is auto-discovered at startup. See src/keyboard_models/nord/electro_5d/ for a CC-based reference implementation, or src/keyboard_models/roland/juno_x/ for a model using both CC and Roland DT1/RQ1 SysEx addressing.

Quick Start (macOS)

Prerequisites: macOS, Node.js 20+, and a supported keyboard connected via USB.

npm install -g keyboards-mcp     # 1. install
keyboards-mcp install            # 2. install + start the broker daemon (launchd)

Then add this to your MCP client config (e.g. .mcp.json / Claude Code settings) and restart the client:

{
  "mcpServers": {
    "keyboards-mcp": {
      "command": "keyboards-mcp"
    }
  }
}

That's it. The midi-connections-broker (MCB) is now a launchd daemon that starts at login and is kept alive automatically — you never run it by hand. Ask your agent to connect_to_keyboard.

  • Check broker status anytime: keyboards-mcp doctor (logs at ~/.mcb/mcb.log).
  • Remove the daemon: keyboards-mcp uninstall.

No hardware? The Sounds and Recreation desktop app (a visual device simulator) is a separate workspace package — see the Sounds and Recreation README. This npm package targets owners of real MIDI hardware.

Development (from source)

This package is one workspace of the keyboards-mcp monorepo. Clone the monorepo, install once at its root (which wires up both workspaces), then build:

npm install                                          # at the monorepo root — both workspaces
npm run build -w keyboards-mcp                        # → packages/keyboards-mcp/dist/
node packages/keyboards-mcp/dist/cli/index.js install # run the BUILT entry so the daemon is node-runnable
                                                      # (or: keyboards-mcp install after a global link)

keyboards-mcp broker runs the broker in the foreground (the daemon's entry point), or npm run mcb -w keyboards-mcp from source. The headless mock and the Electron Sounds and Recreation app live in the sibling sounds-and-recreation-app workspace — npm run sar:headless -w sounds-and-recreation-app / npm run sar -w sounds-and-recreation-app.

Releasing

This package publishes to npm via Changesets from the monorepo — automated by .github/workflows/release.yml with npm OIDC Trusted Publishing, no manual version tags. Ship a changeset on any source PR (npm run changeset). The full flow (Version Packages PR, publishing, trusted-publishing setup) is documented once, in the monorepo README.

Usage

MCP tools

Once connected, the following tools are available:

| Tool | Description | |------|-------------| | list_midi_devices | List available MIDI ports | | connect_to_keyboard | Claim an MCB lease and connect to the keyboard (port + model required, optional with_shadow mock label) | | disconnect_from_keyboard | Disconnect from the keyboard | | is_connected | Check connection status | | set_parameters | Change one or more parameters by name and value | | get_current_state | Read current parameter values from the device. Per-model: Nord and Prophet-6 return "not supported" (one-way MIDI); JUNO-X uses Roland RQ1 to query the device live for scene-effect sections (chorus/delay/reverb/drive). | | list_parameters | List all controllable parameters with ranges and labels | | list_programs | Browse stored programs from backup inventory (filter by name or bank) | | list_songs | Browse set list songs from backup inventory (filter by name or bank) | | load_program | Switch to a program by bank/slot | | load_song | Load a set list song by bank/slot/part | | extract_backup | Parse a backup file into a full inventory (no connection required) | | get_last_backup_location | Get the path of the last extracted backup | | get_system_prompt | Get the keyboard's signal path, capabilities, and sound design guidelines |

Developing without hardware

The Sounds and Recreation desktop app simulates one or more keyboards — a tabbed mock rack with model-specific web UIs, persistent setups, a chat console, and a Song Analysis workbench — so you can drive this MCP server with no MIDI hardware. It's a separate workspace package; see the Sounds and Recreation README for running it (npm run sar -w sounds-and-recreation-app), the headless mock used by tests/CI, and building the standalone .app.

License

Licensed under the GNU General Public License v3.0 (GPL-3.0-or-later). See LICENSE.