MrJ-JMRI-MCP
This server lets you control a DCC model railroad layout via JMRI through any MCP client (voice, chat, etc.).
Power Management
list_systems— Discover all DCC power systems and their current statesget_power— Read the current power state (ON/OFF/UNKNOWN/IDLE) of a specific systemset_power— Turn a DCC system's power ON or OFFsystem_status— Diagnostic check of JMRI reachability, version, and all power system states
Roster & Locomotive Discovery
list_roster— List every locomotive in JMRI's roster (name, DCC address, road, model)find_locomotive— Resolve a spoken/typed name to a DCC address via fuzzy, accent-insensitive matchingget_locomotive_functions— List a locomotive's named decoder functions (e.g. "F2": "Rear lights")
Throttle & Movement Control
acquire_throttle/release_throttle— Acquire or release control of a locomotive by DCC addressset_speed— Set speed as a percentage (0–100%) of maximumset_direction— Set direction to forward or reversestop— Controlled, smooth stop (speed 0%)emergency_stop— Immediate e-stop for safety-critical situations
Decoder Functions & Lights
set_function— Turn any decoder function (F0–F28) on or offlights_on/lights_off— Shortcuts to toggle a locomotive's headlights (F0)
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MrJ-JMRI-MCPturn on track power"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MrJ JMRI AI Assistant
License & attribution — please read before reusing this work. This project is © HO44 PROJECT (MrJ) and licensed under AGPL-3.0-or-later (see LICENSE). If you redistribute, modify, or republish any part of this project —
jmri-core,jmri-cli,jmri-mcp, the.mcpb/.codex.zipbundles, or the documentation — on this repository or anywhere else (a fork, another platform, a package registry, a video, a write-up), you must:
keep the original author credit (MrJ / HO44 PROJECT) and a link back to this repository, and
keep the same AGPL-3.0-or-later license on any redistributed or modified version.
Removing or hiding this attribution is not just bad etiquette — under AGPL-3.0 it is a license violation, and it will be treated as one. See NOTICE.md for details.
Questions or general discussion: use GitHub Discussions. Bug reports and feature requests: use Issues.
Talk to your model railroad.
Bring AI to your JMRI powered layout. Connect your favorite AI assistant and control your DCC model railroad using natural language through voice or chat.
Drive locomotives, control turnouts, operate signals, manage layout accessories, and more — just by asking.
Compatible with MCP clients such as Claude Desktop, Claude Code, xiaozhi, and other MCP-compatible AI assistants.
Features
MrJ JMRI AI Assistant provides:
Ready-to-use package for easy installation
Full documentation with setup guides and usage examples
A complete MCP (Model Context Protocol) server for JMRI integration
A command-line interface (
jmri-cli) for direct control, scripting, and automation50 MCP tools exposing the main JMRI capabilities:
Power management
Locomotive throttles and functions
Roster management
Turnouts
Sensors
Layout lights
Signals
Blocks
Operating modes
Layout-wide meta tools (status overview, secure/night/day mode)
See the complete MCP tools reference in mcp-tools.md.
The goal is simple: make advanced JMRI control accessible to every model railroader, from casual operators to automation enthusiasts.
Built on real hardware, not just the JMRI docs
This project was developed against a real DCC++ layout with multiple command stations, and several of its behaviors exist specifically because live hardware doesn't always behave the way the JMRI API documentation implies:
Self-healing UNKNOWN power states. Re-sending a command station's current power state (a naive "set power ON" when it's already ON) is a known JMRI/DCC++ trap: it knocks the system into an UNKNOWN state instead of being a safe no-op. Every power command re-reads current state first and skips redundant POSTs — and if a genuine ON request still lands in UNKNOWN, it automatically recovers with an OFF → wait → ON retry sequence, rather than leaving the layout stuck.
Per-locomotive command station affinity. On a layout with more than one DCC connection, sending a locomotive's throttle commands to the wrong command station doesn't raise an error — it's just silently inaudible to the decoder. Roster entries can declare which connection they normally run on via a
DccSystemcustom attribute (set in JMRI's own Roster Entry → Edit → Attributes tab, e.g.DccSystem=T), and throttle acquisition reads it automatically to target the right station.DCC connection and hardware address surfaced on every turnout, light, and signal. Listing a turnout, light, or signal reports which DCC connection actually drives it (resolved from its JMRI system name, e.g.
OT23→ohara (turnouts)) alongside its raw hardware address where JMRI exposes one (turnouts and lights; signal masts don't expose theirs via any JMRI API today, so that field is honestly reported as unknown rather than guessed).Every write is confirmed by re-reading real state, never by trusting the response. Power, turnout, light, and signal commands all re-read JMRI's actual state after acting, and report exactly what was observed — including when that doesn't match what was asked for — instead of assuming a 200 response means the layout did what was requested.
Throttle state stays live even when driven from elsewhere. JMRI broadcasts every throttle change (speed, direction, functions) to all clients holding that locomotive — including other JMRI panels or a second MCP session — and this project's throttle cache is kept continuously in sync with that stream, not just with its own commands, so it never reports stale state after someone else drives the train.
Related MCP server: nas-mcp-server
What can I say?
Pick the page that matches what you want to do — each links to the next. Available in English and French:
🚂 Conductor — just want to drive trains? Start here. English · Français
🔧 Tinkerer — managing power, turnouts, signals, and the whole layout. English · Français
🛠️ Engineer — full tool reference, CLI, scripting, and JMRI internals. English · Français
The conductor/tinkerer/engineer split is borrowed from DCC-EX, who came up with this framing first.
Installation
Getting started is designed to be simple.
See the installation guide for every install combination (CLI, Claude Desktop .mcpb, Kira bridge), configuration, and first commands.
Prefer a step-by-step walkthrough with screenshots? See the community Instructable: Control Your JMRI Railroad by Chatting With Claude.
AI Assistant Setup
Command Line Interface
jmri-cli is a full-featured command-line client for your layout, talking to JMRI
directly with no AI assistant or MCP client required — everything the MCP tools can do,
a human can do too, from a terminal.
Run it bare with no arguments to open an interactive shell: a single persistent
connection that keeps locomotives moving, lit, and acquired between commands (unlike a
one-shot invocation, which releases every throttle the instant it exits). The shell
adds real command-line ergonomics on top: up/down arrow command history persisted
across sessions (~/.jmri-cli/shell_history), TAB completion across the entire
command tree, ;-separated multi-command lines, a wait command to sequence a
--hold and a following command, and a friendlier natural-language-ish sentence
syntax for speed/direction (speed Autorail at 30 for 30 up 5 down 6 forward)
alongside the regular flag-based form. Exiting always leaves the layout safe: any
locomotive still in motion gets a ramp-down-and-release prompt, and active functions
(lights) are turned off before the connection closes, rather than being abandoned.
Every command also works one-shot from a plain terminal for scripting, automation, and quick manual checks or troubleshooting against a real layout.
See the CLI reference.
MCP Tools
The MCP server currently exposes 50 tools covering the main JMRI capabilities.
See the complete reference:
Status
v1.0
The project is fully functional and actively maintained.
Future improvements, feature requests, and roadmap items are tracked in the project board and the issues.
Requirements
Python ≥ 3.10 (developed on 3.12)
A running JMRI Web Server (tested with JMRI 5.4)
See docs/install.md for installation details.
Documentation
Getting started
Installation guide — every install combination (CLI, Claude Desktop
.mcpb, Kira bridge), configuration, and first commandsDeveloping on this repo — editable installs from a cloned copy, for working on the code itself
AI assistants
Claude Desktop / Claude Code setup — connect your AI assistant to JMRI
Codex (ChatGPT) setup — register the MCP server with OpenAI Codex
xiaozhi / Kira setup — expose JMRI control to voice assistants
Advanced users
CLI reference —
jmri-clicommand referenceExhibition mode — restricted-safety mode for public demos
Architecture — module design, JMRI clients, WebSocket implementation
Testing — mocked and live test suites, hardware safety configuration
Resources — references for JMRI, MCP, and xiaozhi/Kira
Project
ACKNOWLEDGMENTS.md — thanks to the open-source projects this depends on
CONTRIBUTING.md — contribution guidelines and project conventions
Configuration
Variable | Default | Description |
|
| Base URL of the JMRI Web Server |
|
| Password required to exit exhibition mode. See Exhibition mode. |
| (none) | Comma-separated DCC addresses locomotives are restricted to while exhibition mode is on. |
| (off) | If set to |
Credits
Built and maintained by MrJ.
Questions, bugs, and feature requests are welcome via issues.
License
Chosen deliberately over a permissive license (MIT/Apache) so that anyone who modifies this project and offers it as a network service (not just redistributes the code) must also publish their modified source.
See the license text for the exact terms, and NOTICE.md for what attribution is required when reusing this project.
Third-party code
xiaozhi_wrapper (part of the jmri-mcp package) is adapted from the MCP pipe example in xiaozhi-esp32 (MIT License, Copyright (c) 2025 Shenzhen Xinzhi Future Technology Co., Ltd. and Project Contributors).
See the package documentation:
packages/jmri-mcp/src/xiaozhi_wrapper/__init__.py
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/HO44-PROJECT/MrJ-JMRI-MCP'
If you have feedback or need assistance with the MCP directory API, please join our Discord server