| title | grandMA2 MCP |
|---|---|
| description | MCP server for grandMA2 lighting consoles — 218 MCP tools via Telnet |
| version | 1.1.0 |
| created | 2026-04-02 00:00:00 UTC |
| last_updated | 2026-04-04 00:00:00 UTC |
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 Harness | 218 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 Core | Orchestrator, 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 gate | Three risk tiers enforced before any command reaches the console: SAFE_READ (always allowed), SAFE_WRITE (standard mode), DESTRUCTIVE (blocked until confirm_destructive=True). Line-break injection rejected at the transport layer. |
| A closed learning loop | Every tool call recorded to tool_invocations. SkillImprover surfaces repair suggestions from failure patterns and promotion candidates from high-quality sessions. Skills are versioned playbooks with full lineage tracking. |
| RAG-powered knowledge | Three 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 · Architecture · 218 MCP Tools · Resources · Prompts · Skills · Safety System · RAG Pipeline
# 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.uiThen 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.uiThe 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.
graph TD
H["🤖 Agent Core Layer<br/><code>src/server_orchestration_tools.py</code><br/>34 tools (IDs 110–144, excluding 130) · orchestrator · skills"] --> A
A["🎭 MCP Server Layer<br/><code>src/server.py</code><br/>184 server tools · safety gate"] --> B
B["🧭 Navigation Layer<br/><code>src/navigation.py</code><br/>cd · list · scan · set_property"] --> C
C["🔧 Command Builders<br/><code>src/commands/</code><br/>198 pure functions → strings"] --> D
D["📡 Telnet Client<br/><code>src/telnet_client.py</code><br/>async · auth · injection prevention"]
E["📖 Prompt Parser<br/><code>src/prompt_parser.py</code><br/>prompt detection · list parsing"] -.-> B
F["🛡️ Vocabulary & Safety<br/><code>src/vocab.py</code><br/>157 keywords · risk tiers"] -.-> A
G["🔍 RAG Pipeline<br/><code>rag/</code><br/>crawl → chunk → embed → query"] -.-> A
I["🧠 Memory & Planning<br/><code>src/agent_memory.py · src/orchestrator.py</code><br/>WorkingMemory · LTM · TaskDecomposer"] -.-> H
J["📊 OpenSpace<br/><code>src/telemetry.py · src/skill.py · src/skill_improver.py</code><br/>invocation 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.
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 | 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 |
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 dimensionsNote
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 |
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, go_back, goto, fast_forward, fast_back, def_go, def_go_back, 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
| 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 |
| 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 N] |
executor accepts a list |
"def_go" |
defgoforward |
Fires on $SELECTEDEXEC; reads state before firing |
"def_go_back" / "def_goback" |
defgoback |
Same — def_goback is an alias |
"def_pause" |
defgopause |
Same |
All actions return command_sent and raw_response.
def_go, def_go_back, and def_pause additionally return:
| Field | Value |
|---|---|
selected_executor |
Value of $SELECTEDEXEC read before the command was sent (null if unavailable) |
selected_cue_before |
Value of $SELECTEDEXECCUE read before the command (null if unavailable) |
goto additionally returns cue_exists, cue_probe_response, and optionally executor_probe_response.
# Fire next cue on executors 1, 2, and 3 simultaneously
playback_action(action="go", object_type="executor", object_id=[1, 2, 3])
# → go executor 1 + 2 + 3
# Fast-forward executors 2 and 4
playback_action(action="fast_forward", executor=[2, 4])
# → >>> executor 2 + 4
# Go back on the selected executor — response tells you which one fired
playback_action(action="def_go_back")
# → {"command_sent": "defgoback", "selected_executor": "5", "selected_cue_before": "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.
| 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) |
| 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 |
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.
# Select executor 5 and confirm
select_executor(executor_id=5)
# → {"command_sent": "select executor 5", "confirmed_selected_exec": "5"}
# Select executor 5 on page 2
select_executor(executor_id=5, page=2)
# → {"command_sent": "select executor 2.5", "confirmed_selected_exec": "5"}
# Clear the current selection
select_executor(executor_id=1, deselect=True)
# → {"command_sent": "select", "note": "Bare 'select' sent … unverified …"}💾 Programming / Store — 13 tools
| Tool | Description |
|---|---|
create_fixture_group |
Select a range of fixtures and save as a named group |
store_current_cue |
Store programmer state into a cue |
store_new_preset |
Store programmer state as a new preset |
store_object |
Store generic objects — macros, effects, worlds, etc. |
store_cue_with_timing |
Store a cue with explicit fade/delay timing |
update_cue_data |
Update an existing cue with current programmer values |
set_cue_timing |
Edit fade, delay, or trigger timing on an existing cue |
set_sequence_property |
Set a property on a sequence (e.g. looping, autoprepare) |
assign_cue_trigger |
Assign a trigger type (Go, Follow, Time) to a cue |
block_unblock_cue |
Block or Unblock a cue to freeze/restore its tracked values |
clone_object |
Clone (duplicate with data) one or more objects to new IDs |
remove_from_programmer |
Remove specific fixtures or channels from the programmer |
run_macro |
Execute a stored macro by ID |
[!WARNING] Store tools are DESTRUCTIVE — they require
confirm_destructive=True.
⏱️ Timecode & Timer — 3 tools
| Tool | Description |
|---|---|
control_timecode |
Start, stop, or jump a timecode show |
control_timer |
Start, stop, or reset a timer |
store_timecode_event |
Store an event into a timecode show at the current time |
🔗 Assignment & Layout — 9 tools
| Tool | Description |
|---|---|
assign_object |
Assign objects, functions, fades, or layout positions |
assign_executor_property |
Assign any of 22 settable options on an executor (width, priority, autostart, etc.) — page-qualified |
get_executor_state |
Read all 32 fields of one executor via List Executor page.id (SAFE_READ) |
scan_page_executor_layout |
Map executor slot occupancy on a page — required pre-flight before width expansion (SAFE_READ) |
discover_fixture_type_attributes |
Discover fixture type attribute names via EditSetup tree navigation (SAFE_READ) |
label_or_appearance |
Label or set visual appearance of objects |
edit_object |
Edit, cut, or paste objects |
cut_paste_object |
Cut an object to clipboard, or paste clipboard content at a location |
remove_content |
Remove content from objects — fixtures, effects, preset types |
save_recall_view |
Save or recall a screen view configuration |
set_executor_priority |
Set playback priority on an executor (super/high/normal/low/htp/swap) |
set_node_property |
Set a property on any node via dot-separated tree path (DESTRUCTIVE) |
📁 Show Management — 7 tools
| Tool | Description |
|---|---|
save_show |
Save the current show file to disk |
list_shows |
List available show files on the console |
load_show |
Load a show file by name |
new_show |
Create a new empty show |
delete_show |
Delete a show file from disk |
export_objects |
Export show objects (groups, presets, macros, etc.) to a file |
import_objects |
Import objects from a file into the show |
[!CAUTION]
new_showwithoutpreserve_connectivity=Truedisables Telnet, severing the MCP connection.
🔌 Fixture Setup & Patch — 16 tools
| Tool | Description |
|---|---|
list_fixture_types |
List fixture types loaded in the show |
list_layers |
List fixture layers in the patch |
list_universes |
List configured DMX universes |
list_library |
Browse the MA2 fixture library |
list_fixtures |
List fixtures currently patched in the show |
browse_patch_schedule |
Browse the DMX patch schedule |
patch_fixture |
Patch a fixture to a DMX universe and address |
unpatch_fixture |
Remove a fixture's DMX patch assignment |
set_fixture_type_property |
Set a property on a fixture type |
manage_matricks |
Manage MAtricks (fixture matrix) objects |
create_matricks_library |
Generate combinatorial MAtricks pool with 25-color coding |
store_matricks_preset |
Combined set + store + label MAtricks preset workflow |
create_filter_library |
Generate color-coded Filter library with V/VT/E variants |
import_fixture_type |
Import a fixture type from the MA2 library |
import_fixture_layer |
Import a fixture layer XML file into the show patch |
generate_fixture_layer_xml |
Generate a grandMA2 fixture layer XML file for import |
Fixture import workflow
# 1. Generate the XML file
generate_fixture_layer_xml(
filename="my_dimmers",
layer_name="Dimmers",
layer_index=1,
fixtures=[
{"fixture_id": 1, "name": "Dim 1", "fixture_type_no": 2,
"fixture_type_name": "2 Dimmer 00", "dmx_address": 1, "num_channels": 1},
],
showfile="myshow",
)
# 2. Import the fixture type from library
import_fixture_type(
manufacturer="Martin",
fixture="Mac700Profile_Extended",
mode="Extended",
confirm_destructive=True,
)
# 3. Import the layer
import_fixture_layer(filename="my_dimmers", layer_index=1, confirm_destructive=True)MAtricks combinatorial library
Generates every combination of Wings × Groups × Blocks × Interleave (5⁴ = 625 items) with a 25-color scheme embedded directly in the XML:
| Dimension | Controls | Values |
|---|---|---|
| Wings | Hue | Red (0°) · Yellow-Green (72°) · Cyan (144°) · Blue (216°) · Magenta (288°) |
| Groups | Brightness | 100% · 80% · 60% · 45% · 30% |
| Blocks | — | 0–4 |
| Interleave | — | 0–4 |
Colors use <Appearance Color="RRGGBB" /> in the XML — import is instant, no telnet loop required.
# Full library (625 items)
python -m scripts.create_matricks_library --max-value 4
# Quick test (16 items)
python -m scripts.create_matricks_library --max-value 1
# XML only (no telnet import)
python -m scripts.create_matricks_library --xml-only
# Re-apply colors via telnet (if needed)
python -m scripts.create_matricks_library --color-only🔎 Info, Queries & Discovery — 15 tools
| Tool | Description |
|---|---|
get_object_info |
Query info on any object (fixture, group, sequence, etc.) |
query_object_list |
List cues, groups, presets, attributes, or messages |
get_variable |
Get the current value of a console variable |
list_system_variables |
List all 26 built-in system variables ($TIME, $SHOWFILE, etc.) |
list_sequence_cues |
List all cues in a sequence with timing and labels |
discover_object_names |
Discover named objects in a pool via the cd tree |
check_pool_availability |
Check which slots are occupied and free in an object pool |
browse_preset_type |
Browse Feature/Attribute/SubAttribute tree for a PresetType |
list_preset_pool |
List presets in the Global preset pool by type |
browse_effect_library |
Browse the grandMA2 effect library |
browse_macro_library |
Browse the grandMA2 macro library |
browse_plugin_library |
Browse the grandMA2 plugin library |
highlight_fixtures |
Toggle highlight mode for selected fixtures |
list_undo_history |
List recent undo history entries |
discover_filter_attributes |
Discover show-specific filter attributes from patched fixtures |
⚙️ Console & Utilities — 8 tools
| Tool | Description |
|---|---|
send_raw_command |
Send any MA command directly (safety-gated) |
copy_or_move_object |
Copy or move objects between slots (with merge/overwrite) |
delete_object |
Delete any object by type and ID |
manage_variable |
Set or add to console variables (global or user-scoped) |
undo_last_action |
Undo the last console action |
toggle_console_mode |
Toggle console modes: blind, highlight, freeze, solo |
list_fader_modules |
List connected fader modules and their configuration |
list_update_history |
List programming update history |
👤 User Management — 5 tools
| Tool | Description |
|---|---|
list_console_users |
List all user profiles configured on the console |
create_console_user |
Create a new user profile with name and password |
delete_user |
Delete a user profile |
inspect_sessions |
Inspect active Telnet sessions and connected operators |
assign_world_to_user_profile |
Assign a world (visibility scope) to a user profile |
[!NOTE] Requires
GMA_SCOPE=gma2:user:manage(Admin tier). Bootstrap 5 default user accounts withpython scripts/bootstrap_console_users.py.
🤖 ML-Based Tool Discovery — 4 tools
| Tool | Description |
|---|---|
list_tool_categories |
Browse auto-discovered tool categories via K-Means clustering |
recluster_tools |
Re-run the full ML pipeline (extract → embed → cluster → label) |
get_similar_tools |
Find the most similar tools by Euclidean distance in feature space |
suggest_tool_for_task |
Suggest tools for a natural-language task description |
🔍 Codebase Search / RAG — 1 tool
| Tool | Description |
|---|---|
search_codebase |
Semantic search over the indexed codebase and MA2 docs |
🤖 Orchestration & Console State — 34 tools
These tools form the agentic layer (src/server_orchestration_tools.py). They enable
multi-step task execution with memory, risk-tier isolation, and zero-telnet state queries
via a ConsoleStateSnapshot cache that closes 19 show-memory gaps.
For the higher-level agent harness in src/server.py, prefer plan_agent_goal to preview
and run_agent_goal to execute. Use decompose_task / run_task when you specifically
want the lower-level rule-based orchestration surface in src/server_orchestration_tools.py.
| Tool | Description |
|---|---|
decompose_task |
Break a lighting goal into an ordered multi-agent plan (review before execute) |
run_task |
Execute a full task with risk-tier isolation, memory, and state hydration |
list_agent_sessions |
List recent task sessions from long-term memory |
recall_agent_session |
Restore WorkingMemory snapshot from a past session |
agent_token_report |
Report token consumption across agent sessions |
register_decomposition_rule |
Register a custom task-decomposition rule at runtime |
resolve_object_ref |
Resolve a pool object name/ID to a quoted MA2 token (zero telnet) |
list_pool_names |
List all names and IDs for a pool type from the in-memory index |
hydrate_console_state |
Trigger a fresh ConsoleStateSnapshot hydration |
Read from the cached snapshot — no telnet round-trips required.
| Tool | Description |
|---|---|
get_console_state |
Snapshot summary, age, and staleness warning |
get_park_ledger |
All currently parked fixtures |
get_filter_state |
Active filter ID and V/VT/E flag settings |
get_world_state |
Active world and visibility scope |
get_matricks_state |
Write-tracked MAtricks state (interleave, blocks, wings, etc.) |
get_programmer_selection |
$SELECTEDFIXTURESCOUNT, $SELECTEDEXEC, $SELECTEDEXECCUE |
hydrate_sequences |
Deep-hydrate specific sequence cues and parts |
get_sequence_memory |
Sequence properties and CueRecords from the snapshot |
assert_selection_count |
Validate fixture selection count against an expected value |
assert_preset_exists |
Pre-flight check: verify a preset slot is occupied |
get_executor_detail |
Full ExecutorState for a given executor ID |
| Tool | Description |
|---|---|
diff_console_state |
Compare current snapshot against a caller-supplied baseline; returns changed fields |
get_showfile_info |
Return showfile name, version, host status, and active user from snapshot (zero telnet) |
watch_system_var |
Poll a grandMA2 system variable until it changes or a timeout is reached |
confirm_destructive_steps |
Decompose a goal and return only the DESTRUCTIVE steps for human review |
abort_task |
Mark a running session as aborted and return completed/failed step summary |
retry_failed_steps |
Reload a past session from LTM and re-run the original goal |
assert_fixture_exists |
Two-tier fixture patch validation (snapshot index → live telnet fallback) |
| Tool | Scope | Description |
|---|---|---|
get_tool_metrics |
DISCOVER | Latency + error-rate stats for any tool over N days |
list_skills |
DISCOVER | Search the skill registry by name, description, or context |
get_skill |
DISCOVER | Full detail + lineage chain for a single skill |
promote_session_to_skill |
PROGRAMMER_WRITE | Manually promote a completed session to a named, versioned skill |
get_improvement_suggestions |
DISCOVER | Repair suggestions (failing tools) + promotion candidates (successful sessions) |
approve_skill |
SYSTEM_ADMIN | Human-gate: set approved=True on a DESTRUCTIVE-scope skill before agents may use it |
assert_showfile_unchanged |
DISCOVER | Verify open show matches hydration baseline — live ListVar vs cached snapshot |
| Tool | Scope | Description |
|---|---|---|
detect_dmx_address_conflicts |
DISCOVER | Scan all universes for overlapping fixture DMX address assignments |
get_telemetry_report |
DISCOVER | Export tool invocation telemetry as JSON or markdown audit log |
generate_compliance_report |
DISCOVER | SB 132 / safety-audit compliance report from session telemetry |
validate_preset_references |
DISCOVER | Scan cue list for references to deleted or missing preset pool entries |
list_macro_jump_targets |
DISCOVER | Parse macro lines and extract all jump targets for index-shift planning |
check_pool_slot_availability |
DISCOVER | Pre-flight: which pool slots are empty vs. occupied in a range |
remap_fixture_ids |
PROGRAMMER_WRITE | Remap fixture references from one ID to another in groups after PSR import |
[!NOTE] Call
hydrate_console_statebefore using state-query tools. The snapshot caches values that have no direct telnet readback (MAtricks state, park ledger, filter VTE flags, etc.). Check freshness withget_console_state.
🎛️ Busking & Performance — 6 tools
| Tool | Description |
|---|---|
assign_temp_fader |
Set the temp fader level on the currently selected executor |
assign_effect_to_executor |
Bind an effect template to an executor slot (DESTRUCTIVE — requires confirm_destructive=True) |
modulate_effect |
Set rate (EffectRate) or speed (EffectSpeed) on active effects |
clear_effects_on_page |
Release all effect executors on a page range |
normalize_page_faders |
Set all faders on a page to 0 without releasing |
classify_show_mode |
Inspect executor assignments and classify show as busking, sequence, hybrid, or empty |
Thirteen read-only resources exposable to any MCP client. Use them for zero-telnet context before calling tools.
| URI | Description |
|---|---|
ma2://docs/rights-matrix |
OAuth scope → MA2Right mapping matrix (JSON) |
ma2://docs/vocab-summary |
All 157 keywords with RiskTier and category (JSON) |
ma2://docs/tool-taxonomy |
ML-clustered tool taxonomy — 218 tools clustered into 14 categories (JSON) |
ma2://docs/responsibility-map |
Module responsibility map for architectural decisions (Markdown) |
ma2://docs/tool-surface-tiers |
Tier A/B/C classification for every tool (Markdown) |
ma2://docs/volunteer-guide |
Plain-language volunteer operator guide: three-tier access model + Sunday preflight |
ma2://docs/sb132-compliance |
SB 132 / CA Film Tax Credit safety documentation mapped to telemetry fields |
ma2://docs/rdm-workflow |
RDM discovery, autopatch, and device info best practices |
ma2://docs/lua-scripting |
grandMA2 Lua 5.2 scripting reference: gma.* namespace + common patterns |
ma2://skills/{skill_id} |
Skill injection payload by ID — returns formatted user message ready for agent injection |
ma2://busking/patterns |
Best-practice busking patterns: fader model, song macro protocol, live recovery |
ma2://busking/effect-design |
Effect-to-executor assignment patterns, rate vs speed, MAtricks layering |
ma2://busking/color-design |
HSB palette strategy, preset numbering, monochromatic constraint, color lock |
All resources are read-only — no console side-effects.
Ten workflow prompts that orchestrate tools into guided multi-step procedures.
| Prompt | Args | Description |
|---|---|---|
preflight_destructive_change |
operation, target, reason |
Safety pre-flight checklist before any DESTRUCTIVE tool call — checks rights, target existence, blind mode, and executor state |
inspect_console |
focus |
Guided read-only console state inspection — full, playback, fixtures, show, or rights |
plan_cue_store |
sequence_id, cue_number, fixture_selection, preset_or_values |
Plan a cue store operation with pre-flight and verification steps — does not execute |
diagnose_playback_failure |
executor_id, symptom |
Structured playback failure diagnosis — returns fault_class, root_cause, recommended_actions |
load_show_safely |
show_name |
Safe show loading checklist — prevents accidental Telnet disconnection via missing /globalsettings |
bootstrap_rights_users |
(none) | Guided provisioning of the six-tier MA2 rights user accounts |
volunteer_sunday_preflight |
show_name, campus_name |
SAFE_READ preflight for volunteer operators — GREEN/AMBER/RED show verification before service |
generate_busking_template |
target_page, fixture_strategy |
Build a complete busking template from current patch — groups, presets, effects, executor layout |
pre_show_health_check |
sequence_ids, strict |
Full show health audit — showfile, presets, executors, cues, parks, and DMX with scored findings |
adapt_show_to_venue |
source_show_description, new_venue_notes |
Cross-venue show adaptation — patch comparison, group remapping, preset verification |
Forty-five instruction modules in .claude/skills/ are injected as user messages into agent conversations. They teach agents domain-specific workflows without embedding knowledge in tool docstrings.
| Skill | Description |
|---|---|
ma2-command-rules |
MA2 command construction, object resolution, quoting rules, and safety escalation |
telnet-feedback-triage |
Classify and summarise grandMA2 Telnet feedback using the FeedbackClass enum |
feedback-investigator |
Worker playbook: classify and investigate Telnet feedback failures |
cue-list-auditor |
Worker playbook: audit cue list gaps, labels, timing, and health |
operator-recovery-runbook |
On-site incident response for stuck playback, contaminated programmer, wrong world/filter, and similar show emergencies |
busking-lighting-performance |
Live busking — fader-per-effect model, executor layout, effect layering, live recovery |
song-macro-page-design |
Song macro pages — first-button protocol, executor column layout, jump target safety |
constrained-color-design |
Monochromatic HSB palette design — preset numbering, color lock, song-to-palette mapping |
preset-library-architect |
Build full dimmer/position/color/gobo preset pools from raw attribute values |
preset-impact-manager |
Assess preset updates or deletions safely by tracing downstream cue and showfile references |
patch-and-group-builder |
Patch fixtures, build groups by type/position, and verify selection counts |
festival-stage-setup |
End-to-end one-off festival workflow from patched rig to busking-ready showfile |
fixture-swap-surgeon |
Analyze fixture substitutions and plan compatible swap + migration steps |
chaser-builder |
Step-based chasers, running lights via MAtricks, strobes — speed/rate/direction control |
cue-tracking-and-timing |
Tracking vs non-tracking, Block/Unblock, MIB, timing layers, trigger types, Update vs Store |
tracking-debugger |
Diagnose tracking leaks, unexpected blocks, and cue inheritance problems in sequences |
cue-to-cue-rehearsal |
Guided cue-by-cue walkthrough with state summaries and cue diffs during rehearsal |
executor-configuration |
Executor priority, trigger types, fader functions, speed masters, protect options |
show-management-and-psr |
Save/Load/New show (connectivity preservation), PSR workflow, Export/Import XML |
macro-advanced |
SetVar/SetUserVar, conditionals, CmdDelay, jump targets, XML authoring, Store Group timing |
macro-linter-and-refactorer |
Inspect macros for unsafe patterns, broken jumps, and cleanup opportunities |
clone-and-data-transfer |
Clone fixture with /selective, copy/move pool objects, cue-range copy, cross-show PSR |
effect-programmer |
Build effects from scratch, layer rate/speed/phase, assign to executors |
world-filter-designer |
Create worlds, assign fixtures, configure filter objects, control visibility |
timecode-show-programmer |
Build timecode shows, assign events to cues, enable/disable tracks |
color-preset-creator |
Store universal color presets from RGB values — builds the preset pool |
color-palette-sequence-builder |
Build a cue sequence where each cue references a universal color preset |
auto-layout-color-picker |
Preflight and run the installed auto-layout color picker plugin safely — groups, ranges, images, layout, and post-run verification |
hue-palette-creator |
Store 96 universal hue presets (4.101–4.196) using the HSB color model |
hue-sequence-builder |
Build a 16-cue sequence from an adjacent hue pair — 8 saturation variants per hue |
sequence-executor-assigner |
Assign a sequence to a free executor so it appears as a playback fader |
rdm-workflow |
RDM discovery → device info → autopatch workflow via MCP |
lua-and-plugins |
Lua 5.2 scripting with gma.* namespace, plugin invocation, and reload lifecycle |
troubleshoot-no-output |
Systematic no-output diagnostic from Grand Master and worlds down to DMX and fixture-level faults |
companion-integration |
Build Bitfocus Companion button pages that mirror the MA2 executor layout |
showkontrol-bpm-sync |
Sync CDJ tempo from ShowKontrol into MA2 speed masters for live BPM-locked effects |
psr-show-migration |
PSR with pre-flight slot check, fixture ID verification, and post-import diff |
compliance-documentation |
Generate SB 132 / insurance audit reports from session telemetry — SAFE_READ only |
volunteer-operations |
Three-tier access model, Sunday morning preflight, and incident response for non-programmers |
view-and-layout-designer |
Custom console views, executor button placement, image assignment, sheet recall |
show-health-check |
Pre-show audit — showfile, presets, executors, cues, parks, DMX. Returns GREEN/AMBER/RED |
busking-template-generator |
Build a complete busking template from any patched rig — groups, presets, effects, executor page |
cross-venue-adaptation |
Adapt show to a new venue rig — patch comparison, group remapping, preset scope verification |
training-mode |
Annotated SAFE_READ console tour for students, church volunteers, and IATSE training programs |
remote-monitoring |
Continuous SAFE_READ polling — show change detection, alert conditions, broadcast and architectural protocols |
Skills are loaded on demand via ma2://skills/{skill_id} resource or injected by the orchestrator. Use list_skills / get_skill tools to browse and inspect them at runtime.
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"gma2": {
"command": "uv",
"args": ["--directory", "/path/to/grandma2-mcp", "run", "python", "-m", "src.server"],
"env": {
"GMA_HOST": "192.168.1.100",
"GMA_USER": "administrator",
"GMA_PASSWORD": "admin"
}
},
"time": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-time"]
}
}
}The time server provides accurate ISO 8601 timestamps for markdown front matter — required by .claude/rules/markdown-frontmatter.md. It is also registered automatically for Claude Code CLI via .mcp.json and for VS Code via vscode-mcp-provider/.
The vscode-mcp-provider/ directory contains a VS Code extension that registers the grandMA2 MCP server for AI assistant discovery.
cd vscode-mcp-provider
npm install && npm run compile
# Then install in VS Code (F5 to debug, or package with vsce)See vscode-mcp-provider/README.md for full details.
Create a codex.json MCP config file:
{
"mcpServers": {
"gma2": {
"command": "uv",
"args": ["--directory", "/path/to/grandma2-mcp", "run", "python", "-m", "src.server"],
"env": {
"GMA_HOST": "192.168.1.100",
"GMA_USER": "administrator",
"GMA_PASSWORD": "admin"
}
}
}
}Then run Codex with:
codex --mcp-config codex.jsongrandMA2 MCP enforces a 3-layer model where effective permissions are the intersection of all three — no single layer can expand privileges:
scope ∩ policy ∩ ma2_rights = FINAL AUTHORITY
Six scope tiers map to console users created by scripts/bootstrap_console_users.py:
GMA_SCOPE |
Console user | MA2 Rights | Can do |
|---|---|---|---|
tier:0 |
guest |
None (0) | Read-only — list, info, cd |
tier:1 |
operator |
Playback (1) | Go, Flash, Off, timecode |
tier:2 |
presets_editor |
Presets (2) | Set attributes, apply/store presets |
tier:3 |
programmer |
Program (3) | Store cues, groups, sequences, macros |
tier:4 |
tech_director |
Setup (4) | Patch, fixture import, console setup |
tier:5 |
administrator |
Admin (5) | User management, show load/delete |
Every tool is annotated with @require_ma2_right(MA2Right.X) which enforces the OAuth scope requirement before any Telnet command is sent. The check_permission() utility provides a unified gate combining scope and rights checks:
result = check_permission("store_current_cue", granted_scopes, user_right)
# scope ∩ MA2Right — both must pass
if not result.allowed:
return result.as_block_response()All 218 tools are mapped in doc/ma2-rights-matrix.json.
The Telnet session runs as a console user whose native rights are enforced by grandMA2 itself. Commands beyond that user's rights level are rejected with Error #72 — an irrevocable floor that exists regardless of what Layer 1 or 2 permit.
Bootstrap required: On a fresh show, run
python scripts/bootstrap_console_users.pyas Administrator to create the 5 intermediate users. OnlyAdministratorandGuestexist natively.
In addition to the 3-layer model, every keyword is classified into one of three risk tiers enforced by _handle_errors:
| Tier | Description | Examples |
|---|---|---|
SAFE_READ |
Read-only queries | Info, List, CmdHelp, ChangeDest |
SAFE_WRITE |
Reversible state changes | Go, At, Clear, Park, SelFix |
DESTRUCTIVE |
Data mutation or loss | Delete, Store, Copy, Move, Shutdown |
DESTRUCTIVE tools require confirm_destructive=True in addition to OAuth scope.
Important
Command injection prevention: Line breaks (\r, \n) are rejected before any command reaches the console.
The telnet client also strips them as a defense-in-depth measure.
The vocabulary classifies all 157 grandMA2 keywords into categories:
| Category | Count | Description | Examples |
|---|---|---|---|
OBJECT |
56 | Console objects (nouns) | Channel, Fixture, Group, Preset, Executor |
FUNCTION |
90 | Actions (verbs) | Store, Delete, Go, At, Kill, List, Info |
HELPING |
5 | Syntax connectors | And, Thru, Fade, Delay, If |
SPECIAL_CHAR |
6 | Operator symbols | Plus +, Minus -, Dot ., Slash / |
Object Keyword metadata
Object Keywords carry additional metadata from live telnet verification:
| Field | Description |
|---|---|
context_change |
Whether the keyword changes the [default]> prompt context |
canonical |
Console-normalized spelling (e.g., DMX → Dmx) |
notes |
Behavior notes from live telnet testing |
Of the 56 Object Keywords: 53 change the default prompt context and 3 don't (Full, Normal, Zero — these set dimmer values). Channel and Default have context_change=True; their notes describe resetting the default keyword, not the prompt context.
Console aliases:
| Input | Resolves To |
|---|---|
DMX |
Dmx |
DMXUniverse |
DmxUniverse |
Sound |
SoundChannel |
RDM |
RdmFixtureType |
classify_token() example
from src.vocab import build_v39_spec, classify_token
spec = build_v39_spec()
result = classify_token("Delete", spec)
# result.risk == RiskTier.DESTRUCTIVE
# result.canonical == "Delete"
# result.category == KeywordCategory.FUNCTION
result = classify_token("Channel", spec)
# result.risk == RiskTier.SAFE_WRITE
# result.category == KeywordCategory.OBJECT
result = classify_token("DMX", spec)
# result.canonical == "Dmx" (alias resolution)graph LR
A[Crawl] --> B[Chunk] --> C[Embed] --> D[Store<br/>SQLite] --> E[Query] --> F[Rerank]
style A fill:#264653,color:#fff
style B fill:#2a9d8f,color:#fff
style C fill:#e9c46a,color:#000
style D fill:#f4a261,color:#000
style E fill:#e76f51,color:#fff
style F fill:#e63946,color:#fff
# Ingest repository with real embeddings
uv run python scripts/rag_ingest.py --provider github -v
# Semantic search
uv run python scripts/rag_query.py "store cue with fade" -v
# Text-only keyword search (no token needed)
uv run python scripts/rag_query.py "store cue with fade"| Provider | Flag | Requires |
|---|---|---|
| GitHub Models | --provider github |
GITHUB_MODELS_TOKEN |
| Zero-vector stub | --provider zero |
Nothing (for testing) |
| Auto-detect | (no flag) | Uses GitHub if token set, otherwise zero-vector |
Pipeline stages
Ingest
| Stage | Module | Description |
|---|---|---|
| Crawl | rag/ingest/crawl_repo.py |
Walk repo files, respect ignore patterns |
| Chunk | rag/ingest/chunk.py |
Split into overlapping token-bounded chunks |
| Extract | rag/ingest/extract.py |
Extract symbol names (functions, classes, headings) |
| Embed | rag/ingest/embed.py |
Generate vectors via GitHub Models API |
| Store | rag/store/sqlite.py |
Write chunks + vectors to SQLite |
Retrieve
| Stage | Module | Description |
|---|---|---|
| Query | rag/retrieve/query.py |
Embed query, cosine similarity search |
| Rerank | rag/retrieve/rerank.py |
Sort and filter results by relevance |
Chunking strategies
| Language | Strategy | Boundary |
|---|---|---|
| Python | AST-based | Top-level def/class boundaries via ast.parse |
| Markdown | Heading-based | # heading lines |
| Other | Line-based | Fixed-size line windows with overlap |
Defaults: max 1200 tokens/chunk, 20-line overlap. Configured in rag/config.py.
The navigation system combines three layers to discover console state via telnet:
- Command builder (
changedest()) generates cd strings with MA2 dot notation - Telnet client sends the command and captures the raw response
- Prompt parser extracts the current location from the response
Prompt parsing patterns
| Pattern | Example | Parsed |
|---|---|---|
| Bracket prompt | [Group 1]> |
location=Group 1, type=Group, id=1 |
| Dot notation | [Group.1]> |
location=Group.1, type=Group, id=1 |
| Compound ID | [Preset.4.1]> |
location=Preset.4.1, type=Preset, id=4.1 |
| Trailing slash | [Sequence 3]>/ |
location=Sequence 3, type=Sequence, id=3 |
| Angle bracket | Root> |
location=Root, type=Root |
List output parsing
After cd-ing into a destination, list returns tabular output. The parser automatically detects headers and maps columns.
| Field | Description |
|---|---|
object_type |
Type name (e.g. Group, UserImage) |
object_id |
Numeric ID within the parent |
name |
Display name |
columns |
Dict mapping extra header names to values |
raw_line |
Full original line for manual inspection |
scripts/scan_tree.py recursively walks the grandMA2 object tree via Telnet, building a complete JSON map of every node.
# Quick scan (depth 4)
uv run python scripts/scan_tree.py --max-depth 4 --output scan_test.json
# Full scan (depth 20)
uv run python scripts/scan_tree.py --max-depth 20 --output scan_full.json
# Resume an interrupted scan
uv run python scripts/scan_tree.py --max-depth 20 --output scan_full.json --resumeScanner options
| Flag | Default | Description |
|---|---|---|
--host |
from .env |
Console IP address |
--port |
30000 | Telnet port |
--max-depth |
20 | Maximum recursion depth |
--max-nodes |
0 | Stop after N nodes (0 = unlimited) |
--max-index |
60 | Fallback index limit |
--failures |
3 | Stop branch after N consecutive missing indexes |
--output |
scan_output.json |
Output JSON file path |
--delay |
0.08 | Seconds between commands |
--resume |
false | Resume scan from progress file |
Optimizations & resilience
Speed optimizations:
- Known leaf-type shortcutting — skips cd+list for known leaf types
- Smart gap probing — only fills gaps ≤5 between known IDs
- Duplicate detection — compares raw
listsignatures to skip identical subtrees - Consecutive empty leaf early exit — stops after 10 empty slots
Resilience:
- Auto-reconnect with full path recovery
- Progressive save to JSONL after each root branch
- Resume support across sessions
- Heartbeat logging and branch timeouts
The command builder layer (src/commands/) generates grandMA2 command strings as pure functions — no network I/O. 198 exported functions (206 exports including 8 constants) covering navigation, selection, playback, values, store, delete, assign, label, and more.
grandMA2 syntax:
[Function] [Object]— keywords are Function (verbs), Object (nouns), or Helping (prepositions).
Full command builder reference
| Function | Output |
|---|---|
changedest("/") |
cd / |
changedest("..") |
cd .. |
changedest("Group", 1) |
cd Group.1 |
changedest("Preset", "4.1") |
cd Preset.4.1 |
| Function | Output |
|---|---|
fixture(34) |
fixture 34 |
group(3) |
group 3 |
preset("color", 5) |
preset 4.5 |
cue(5) |
cue 5 |
sequence(3) |
sequence 3 |
executor(1) |
executor 1 |
dmx(101, universe=2) |
dmx 2.101 |
attribute("Pan") |
attribute "Pan" |
| Function | Output |
|---|---|
select_fixture(1, 10) |
selfix fixture 1 thru 10 |
select_fixture([1, 3, 5]) |
selfix fixture 1 + 3 + 5 |
clear() |
clear |
clear_all() |
clearall |
| Function | Output |
|---|---|
store("macro", 5) |
store macro 5 |
store_cue(1, merge=True) |
store cue 1 /merge |
store_preset("dimmer", 3) |
store preset 1.3 |
store_group(1) |
store group 1 |
| Function | Output |
|---|---|
go("executor", 3) |
go executor 3 |
go_executor(3) |
go executor 3 |
go_back("executor", 3) |
goback executor 3 |
go_back_executor(3) |
goback executor 3 |
goto(3) |
goto cue 3 |
go_sequence(1) |
go+ sequence 1 |
go_macro(2) |
go macro 2 |
on_executor(3) |
on executor 3 |
off_executor(3) |
off executor 3 |
flash_executor(3) |
flash executor 3 |
swop_executor(3) |
swop executor 3 |
solo_executor(3) |
solo executor 3 |
top_executor(3) |
top executor 3 |
stomp_executor(3) |
stomp executor 3 |
release_executor(3) |
release executor 3 |
goto_cue(1, 5) |
goto cue 5 sequence 1 |
pause_sequence(1) |
pause sequence 1 |
goto_timecode(1, "00:01:30:00") |
goto timecode 1 "00:01:30:00" |
go_fast_forward() |
>>> |
go_fast_forward(executor=[1, 2, 3]) |
>>> executor 1 + 2 + 3 |
go_fast_back() |
<<< |
go_fast_back(executor=[2, 4]) |
<<< executor 2 + 4 |
load_next() |
loadnext |
load_prev() |
loadprev |
def_go_forward() |
defgoforward |
def_go_back() |
defgoback |
def_go_pause() |
defgopause |
solo() |
solo |
blind() |
blind |
freeze() |
freeze |
blackout() |
blackout |
| Function | Output |
|---|---|
at(75) |
at 75 |
at_full() |
at full |
attribute_at("Pan", 20) |
attribute "Pan" at 20 |
fixture_at(2, 50) |
fixture 2 at 50 |
| Function | Output |
|---|---|
copy("group", 1, 5) |
copy group 1 at 5 |
move("group", 5, 9) |
move group 5 at 9 |
delete("cue", 7) |
delete cue 7 |
| Function | Output |
|---|---|
label("group", 3, "All Studiocolors") |
label group 3 "All Studiocolors" |
appearance("preset", "0.1", red=100) |
appearance preset 0.1 /r=100 |
appearance("group", 1, color="FF0000") |
appearance group 1 /color=FF0000 |
[!NOTE] Appearance RGB uses 0–100 percentage scale (not 0–255). HSB: hue 0–360, sat/bright 0–100.
| Function | Output |
|---|---|
export_object("Group", 1, "mygroups") |
export Group 1 "mygroups" |
import_object("mygroups", "Group", 5) |
import "mygroups" at Group 5 |
| Function | Output |
|---|---|
set_var("myvar", 42) |
setvar "myvar" 42 |
set_user_var("speed", 100) |
setuservar "speed" 100 |
grandma2-mcp/
├── src/
│ ├── server.py # FastMCP server (184 interactive tools)
│ ├── server_orchestration_tools.py # Agentic layer (34 tools, IDs 110–144 excluding 130)
│ │
│ │ # Orchestration & Memory
│ ├── orchestrator.py # Multi-agent task runner + session memory
│ ├── task_decomposer.py # NL goal → ordered SubTask plan
│ ├── agent_memory.py # WorkingMemory + LongTermMemory (SQLite)
│ ├── console_state.py # ConsoleStateSnapshot (19-gap hydration)
│ ├── pool_name_index.py # Object name/ID registry (zero-cost resolve)
│ ├── telemetry.py # Per-tool invocation recorder (tool_invocations table)
│ ├── skill.py # Skill dataclass + SkillRegistry (versioned playbooks)
│ ├── skill_improver.py # SkillImprover: repair suggestions + promotion candidates
│ │
│ │ # Security & Auth
│ ├── auth.py # OAuth 2.1 scope enforcement
│ ├── credentials.py # OAuth tier → console credentials
│ ├── rights.py # MA2 native rights + telnet feedback
│ ├── session_manager.py # Telnet session pool (LRU + keepalive)
│ │
│ │ # Core I/O & Parsing
│ ├── telnet_client.py # Async Telnet (telnetlib3, injection prevention)
│ ├── navigation.py # cd + list + scan orchestration
│ ├── prompt_parser.py # Telnet prompt & tabular list parser
│ ├── vocab.py # 157 keywords, risk tiers, functional domains
│ │
│ │ # Command Builders & ML
│ ├── commands/ # 198 exported command-builder functions
│ │ ├── busking.py # Busking/performance builders (6 functions)
│ │ ├── objects/ # Object keywords (9 modules)
│ │ └── functions/ # Function keywords (17 modules)
│ └── categorization/ # ML tool categorization (K-Means)
│
├── rag/ # RAG pipeline
│ ├── ingest/ # crawl → chunk → embed → store
│ ├── retrieve/ # query → rerank
│ └── store/ # SQLite vector store (rag.db)
├── scripts/
│ ├── rag_ingest.py # Ingest repo (zero-vector or real embeddings)
│ ├── rag_ingest_web.py # Crawl MA2 help docs (daily batches)
│ ├── rag_query.py # Query RAG store from CLI
│ ├── bootstrap_console_users.py # Create 5 console user accounts
│ ├── create_matricks_library.py # MAtricks combinatorial library (625 items)
│ ├── create_filter_library.py # Filter library XMLs (168 items with VTE)
│ └── strategic_scan.py # Fast 4-phase console tree scan (~24 min)
├── tests/
├── doc/ # Command builders ref + cd-tree docs
├── vscode-mcp-provider/ # VS Code MCP extension
└── .claude/ # Skills (playbooks) + scoped rules
├── skills/ # 44 agent instruction modules
└── rules/ # 5 scoped rule files (loaded on demand)
| Package | Purpose |
|---|---|
mcp>=1.21.0 |
Model Context Protocol server framework |
python-dotenv>=1.0.0 |
Load .env configuration |
telnetlib3>=2.0.8 |
Async Telnet client |
beautifulsoup4>=4.12.0 |
HTML parsing for RAG web crawler |
numpy>=1.26.0 |
K-Means clustering for tool categorization |
pytest>=9.0.1 |
Testing (dev) |
pytest-asyncio>=1.3.0 |
Async test support (dev) |
Requires Python ≥ 3.12.
# Run all tests
make test # or: uv run python -m pytest -v
# Run a subset
uv run python -m pytest tests/test_vocab.py # single file
uv run python -m pytest tests/test_rag_*.py # RAG tests only
# Start MCP server
uv run python -m src.server
# Login test
uv run python scripts/main.py| Problem | Solution |
|---|---|
| Connection fails | Verify console IP/port, check Telnet is enabled, check firewall |
| Authentication errors | Confirm username/password, check user exists on console |
| Command not working | Verify syntax against MA2 User Manual, ensure objects exist |
| RAG ingest 401 | Verify GITHUB_MODELS_TOKEN has models:read scope |
| RAG query empty | Run scripts/rag_ingest.py first, check rag/store/rag.db exists |