Install
$ agentstack add mcp-drohi-r-grandma2-mcp ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
title: grandMA2 MCP description: MCP server for grandMA2 lighting consoles — 218 MCP tools via Telnet version: 1.1.0 created: 2026-04-02T00:00:00Z last_updated: 2026-04-04T00:00:00Z ---
grandMA2 MCP
> Forked from thisis-romar/ma2-onPC-MCP (originally built by chienchuanw) — hardened and maintained by @drohi-r.
An MCP server for grandMA2 lighting consoles. Exposes 218 grandMA2 operations as Model Context Protocol tools so AI assistants (Claude Desktop, VS Code, etc.) can drive a lighting console via Telnet. Includes a built-in orchestrator, task decomposer, and long-term memory for fully autonomous lighting control.
Built for live production. Pairs with Resolume MCP, MADRIX MCP, Companion MCP, and Beyond MCP for full AI-driven show control.
Agent Harness218 MCP tools covering every grandMA2 operation — playback, programming, user management, show files, busking, and more. Connect any MCP-compatible AI assistant and start controlling the console immediately. Embedded Agent CoreOrchestrator, task decomposer, working + long-term memory, and a skill registry with self-improvement suggestions. Inject a real LLM client and it becomes a fully autonomous lighting agent that plans, executes, remembers, and learns. Layered safety gateThree risk tiers enforced before any command reaches the console: SAFEREAD (always allowed), SAFEWRITE (standard mode), DESTRUCTIVE (blocked until confirmdestructive=True). Line-break injection rejected at the transport layer. A closed learning loopEvery tool call recorded to toolinvocations. SkillImprover surfaces repair suggestions from failure patterns and promotion candidates from high-quality sessions. Skills are versioned playbooks with full lineage tracking. RAG-powered knowledgeThree indexed sources: this repo, ~1,043 grandMA2 help pages, and the MCP SDK. Semantic search via GitHub Models embeddings; falls back to keyword search without an API token.
[Quick Start](#quick-start) · [Architecture](#architecture) · [218 MCP Tools](#mcp-tools) · [Resources](#mcp-resources) · [Prompts](#mcp-prompts) · [Skills](#agent-skills) · [Safety System](#safety-system) · [RAG Pipeline](#rag-pipeline)
Quick start
# 1. Install
git clone https://github.com/drohi-r/grandma2-mcp && cd grandma2-mcp
uv sync
# 2. Configure
cp .env.template .env # then edit with your console IP
# 3. Install git hooks (auto-updates RAG index on every commit)
make install-hooks
# 4. Run
uv run python -m src.server # starts MCP server (stdio transport)
For the local browser UI:
uv run python -m src.ui
Then open http://127.0.0.1:8092.
For a live console target, run the UI with the same connection env vars as the MCP server:
GMA_HOST=192.168.20.179 GMA_PORT=30000 GMA_AUTH_BYPASS=1 uv run python -m src.ui
The browser UI is an operator console for:
- dashboard and console session status
- single-slot executor lookup
- direct sequence inspection
- patch browsing grouped by fixture type
- expectation analysis and agent plan/run flows
Important behavior notes:
- executor lookup is intentionally single-slot only; the UI does not bulk-scan executor ranges by default
- direct sequence IDs are more reliable than executor-based sequence resolution
- empty executor slots can produce normal MA2
NO OBJECTS FOUND FOR LISTwarnings on the console - fixture grouping on the Patch view is parsed from live
list fixtureoutput, not inferred from a full executor scan
> [!TIP] > Semantic search: Add GITHUB_MODELS_TOKEN=ghp_... to .env, then run > uv run python scripts/rag_ingest.py --provider github once to rebuild the index with > real embeddings. The search_codebase MCP tool will automatically use semantic ranking > when the token is present.
Architecture
graph TD
H["🤖 Agent Core Layersrc/server_orchestration_tools.py34 tools (IDs 110–144, excluding 130) · orchestrator · skills"] --> A
A["🎭 MCP Server Layersrc/server.py184 server tools · safety gate"] --> B
B["🧭 Navigation Layersrc/navigation.pycd · list · scan · set_property"] --> C
C["🔧 Command Builderssrc/commands/198 pure functions → strings"] --> D
D["📡 Telnet Clientsrc/telnet_client.pyasync · auth · injection prevention"]
E["📖 Prompt Parsersrc/prompt_parser.pyprompt detection · list parsing"] -.-> B
F["🛡️ Vocabulary & Safetysrc/vocab.py157 keywords · risk tiers"] -.-> A
G["🔍 RAG Pipelinerag/crawl → chunk → embed → query"] -.-> A
I["🧠 Memory & Planningsrc/agent_memory.py · src/orchestrator.pyWorkingMemory · LTM · TaskDecomposer"] -.-> H
J["📊 OpenSpacesrc/telemetry.py · src/skill.py · src/skill_improver.pyinvocation recorder · skill registry · improvement loop"] -.-> H
style H fill:#1a1a2e,stroke:#e94560,color:#fff
style A fill:#1a1a2e,stroke:#e94560,color:#fff
style B fill:#1a1a2e,stroke:#0f3460,color:#fff
style C fill:#1a1a2e,stroke:#16213e,color:#fff
style D fill:#1a1a2e,stroke:#533483,color:#fff
style E fill:#0f3460,stroke:#0f3460,color:#fff
style F fill:#0f3460,stroke:#0f3460,color:#fff
style G fill:#0f3460,stroke:#0f3460,color:#fff
style I fill:#0f3460,stroke:#0f3460,color:#fff
style J fill:#0f3460,stroke:#0f3460,color:#fff
> All network I/O is isolated in telnet_client.py. Command builders are pure functions that return strings. The navigation layer orchestrates cd/list workflows with parsed telnet feedback.
Agent Harness vs. Agent Core
grandMA2 MCP is a layered hybrid — the boundary is explicit in the code:
| Layer | What it is | Key files | |-------|-----------|-----------| | Bottom 184 server tools | Agent Harness — exposes the core MCP tool surface to an external AI; the reasoning loop lives in Claude Desktop, VS Code, etc. | src/server.py | | Top 34 orchestration tools | Embedded Agent Core — orchestrator, task decomposer, long-term memory, skill registry | src/server_orchestration_tools.py, src/orchestrator.py |
The orchestrator accepts a sub_agent_fn injection point. Without it, tool calls run in-process. Wire in a Claude API client and grandMA2 MCP becomes a fully autonomous agent that plans, executes, remembers, and improves itself.
Module Overview
| Module | Role | |--------|------| | src/server.py | FastMCP server, 184 interactive tools, safety gate, env config | | src/server_orchestration_tools.py | 34 agentic tools (IDs 110–144, excluding 130) registered onto FastMCP | | src/orchestrator.py | Multi-agent task runner: hydration, risk-tier isolation, LTM; _showfile_guard(), check_showfile() for dynamic show change detection | | src/task_decomposer.py | Natural-language goal → ordered SubTask plan (rule-based) | | src/agent_memory.py | WorkingMemory (ephemeral) + LongTermMemory (SQLite session log) + showfile baseline tracking (baseline_showfile, showfile_changed()) | | src/console_state.py | ConsoleStateSnapshot: hydrates 19 show-memory gaps; parse_showfile_from_listvar() | | src/pool_name_index.py | In-memory pool name/ID registry — zero-cost object resolution | | src/rights.py | MA2 native rights enforcement + telnet feedback classification | | src/auth.py | OAuth 2.1 scope enforcement (@require_scope, @require_ma2_right) | | src/credentials.py | OAuth tier → console user credential resolver | | src/session_manager.py | Per-operator Telnet session pool (LRU, keepalive, auto-reconnect) | | src/navigation.py | cd + list + scan orchestration | | src/prompt_parser.py | Parse console prompts and list tabular output | | src/vocab.py | 157 keywords, RiskTier, FunctionalDomain, safety classification | | src/commands/ | 198 exported command-builder functions, grouped by keyword type | | src/commands/busking.py | 6 busking/performance builders: effect assign, rate/speed, page release, fader zero | | src/categorization/ | ML tool categorization: K-Means clustering + auto-labeling | | src/telemetry.py | Per-tool invocation recorder: tool_invocations table, latency, risk tier | | src/skill.py | Skill dataclass + SkillRegistry: versioned playbooks with lineage + filesystem skill fallback (_load_filesystem_skill, _list_filesystem_skills) | | src/skill_improver.py | SkillImprover: repair suggestions + promotion candidates (read-only) | | src/tools.py | Global GMA2 telnet client accessor — get_client() used by all tools |
Configuration
Create a .env file (see .env.template):
# grandMA2 Console
GMA_HOST=192.168.1.100 # grandMA2 console IP (required)
GMA_USER=administrator # default: administrator
GMA_PASSWORD=admin # default: admin
GMA_PORT=30000 # default: 30000 (30001 = read-only)
GMA_SAFETY_LEVEL=standard # standard (default), admin, or read-only
LOG_LEVEL=INFO # default: INFO
# RAG Pipeline (optional)
GITHUB_MODELS_TOKEN= # GitHub PAT with models:read scope
RAG_EMBED_MODEL=openai/text-embedding-3-small # embedding model
RAG_EMBED_DIMENSIONS=1536 # vector dimensions
> [!NOTE] > Get a GitHub PAT with the models:read scope at github.com/settings/tokens.
| Level | Behavior | |-------|----------| | read-only | Only SAFE_READ commands allowed (list, info, cd) | | standard | SAFE_READ + SAFE_WRITE allowed; DESTRUCTIVE requires confirm_destructive=True | | admin | All commands allowed without confirmation |
MCP Tools
The server exposes 218 tools to MCP clients, grouped into 15 categories plus an agentic orchestration layer:
🧭 Navigation & Inspection — 4 tools
| Tool | Description | |------|-------------| | navigate_console | Navigate the console object tree via ChangeDest (cd) | | get_console_location | Query the current console destination without navigating | | list_console_destination | List objects at the current destination with parsed entries | | scan_console_indexes | Batch scan numeric indexes at any tree level |
cd / → go to root
cd .. → go up one level
cd Group.1 → navigate to Group 1 (dot notation)
cd 5 → navigate by element index
cd "MySeq" → navigate by name
list → enumerate objects at current destination
Dot notation: MA2 uses [object-type].[object-id] for object references (e.g., Group.1, Preset.4.1, Sequence.3).
💡 Lighting Control — 7 tools
| Tool | Description | |------|-------------| | set_intensity | Set dimmer level on fixtures, groups, or channels | | set_attribute | Set attribute values (Pan, Tilt, Zoom, etc.) on fixtures/groups | | apply_preset | Apply a stored preset (color, position, gobo, beam, etc.) | | clear_programmer | Clear programmer state (all, selection, active, or sequential) | | park_fixture | Park a fixture/channel at its current or a specified value | | unpark_fixture | Release a park lock on a fixture/channel | | fix_locate_fixture | Fix (park) or Locate selected/specified fixtures at their defaults |
🎯 Programmer / Selection — 8 tools
| Tool | Description | |------|-------------| | modify_selection | Select, deselect, or toggle fixtures in the programmer | | adjust_value_relative | Adjust programmer values relatively (+ or –) | | manipulate_selection | Invert or Align the current fixture selection / programmer values | | select_fixtures_by_group | Select all fixtures in a named group | | select_executor | Set the active executor for subsequent operations (single-selection only; use deselect=True to clear) | | select_feature | Set active Feature context (updates $PRESET/$FEATURE/$ATTRIBUTE) | | select_preset_type | Activate a PresetType context (PresetType 1–9 or by name) | | if_filter | Apply an IfOutput / IfActive filter to limit programmer scope |
▶️ Playback & Executor — 9 tools
| Tool | Description | |------|-------------| | execute_sequence | Legacy sequence playback: go, pause, or goto cue | | playback_action | Full playback: go, goback, goto, fastforward, fastback, defgo, defgoback, def_pause | | control_executor | Control an executor (go, pause, stop, flash, etc.) | | load_cue | Pre-load the next or previous cue on an executor without firing it | | get_executor_status | Query status of an executor (current cue, level, state) | | set_executor_level | Set the fader level on an executor | | navigate_page | Navigate to a specific page or page +/– | | release_executor | Release (deactivate) an executor | | blackout_toggle | Toggle grandmaster blackout on/off |
playback_action — parameters & response fields
Parameters
| Parameter | Type | Description | |-----------|------|-------------| | action | str | One of the actions below | | object_type | str \| None | Object type for go/go_back (e.g. "executor", "sequence") | | object_id | int \| list[int] \| None | ID or list of IDs — list produces N + M + … syntax | | cue_id | int \| float \| None | Required for "goto" | | end | int \| None | End of range for go/go_back (builds thru N) | | cue_mode | str \| None | "normal", "assert", "xassert", or "release" | | executor | int \| list[int] \| None | Executor ID(s) for goto/fast_forward/fast_back — list produces N + M + … | | sequence | int \| None | Sequence ID for goto/fast_forward/fast_back |
Actions
| Action | Command sent | Notes | |--------|-------------|-------| | "go" | go [object_type] [id] | Fires next cue; object_id accepts a list | | "go_back" | goback [object_type] [id] | Fires previous cue; object_id accepts a list | | "goto" | goto cue N [executor/sequence] | Pre-flight validates cue exists; returns blocked=True on Error #72 | | "fast_forward" | >>> [executor N] | executor accepts a list | | "fast_back" | `>> executor 2 + 4
Go back on the selected executor — response tells you which one fired
playbackaction(action="defgo_back")
→ {"commandsent": "defgoback", "selectedexecutor": "5", "selectedcuebefore": "3"}
select_executor — parameters & response fields
**Single-selection only.** MA2 telnet `select executor N` accepts exactly one executor number. There is no list syntax — pass a single `executor_id` integer.
#### Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `executor_id` | `int` | required | Executor number (1–999) |
| `page` | `int \| None` | `None` | Page number — produces `select executor page.id` (e.g. `page=2, executor_id=5` → `select executor 2.5`) |
| `deselect` | `bool` | `False` | If `True`, sends bare `select` to clear the current selection (**unverified on grandMA2 telnet** — inspect `raw_response`) |
#### Response fields
| Field | Always present | Description |
|-------|---------------|-------------|
| `command_sent` | ✓ | The exact command sent |
| `raw_response` | ✓ | Raw telnet reply |
| `confirmed_selected_exec` | ✓ | Value of `$SELECTEDEXEC` read after the command (`null` if unavailable) |
| `risk_tier` | ✓ | `"SAFE_WRITE"` |
| `warning` | if mismatch | Present when `confirmed_selected_exec` doesn't match the requested `executor_id` |
| `note` | if deselect | Present when `deselect=True` — warns that bare `select` behaviour is unverified |
#### Page-qualified addressing
When `page` is supplied, MA2 stores `$SELECTEDEXEC` as the executor number only (not the page-qualified form). The confirmation check compares against `executor_id` alone — no spurious warning.
#### Examples
```python
# S
…
## Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [drohi-r](https://github.com/drohi-r)
- **Source:** [drohi-r/grandma2-mcp](https://github.com/drohi-r/grandma2-mcp)
- **License:** Apache-2.0
- **Homepage:** https://ecube-entertainment.com/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.