
drohi-r/grandma2-mcp
Developer toolsMCP server for grandMA2 lighting consoles — 237 MCP tools via Telnet
Overview
MCP server for grandMA2 lighting consoles — 237 MCP tools via Telnet Forked from thisis-romar/ma2-onPC-MCP (originally built by chienchuanw) — hardened and maintained by @drohi-r. 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 237 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.
README
title: grandMA2 MCP description: MCP server for grandMA2 lighting consoles — 237 MCP tools via Telnet version: 1.3.1 created: 2026-04-02T00:00:00Z last_updated: 2026-10-11T20:40:46Z
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.
Quick Start · Architecture · 218 MCP Tools · Resources · Prompts · Skills · Safety System · 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 scripts/run_ui.py # local-operator defaults (tier:5 scope, auth bypass)
# or, with explicit env:
GMA_HOST=192.168.20.179 GMA_PORT=30000 GMA_SCOPE=tier:5 GMA_AUTH_BYPASS=1 uv run python -m src.ui
Then open http://127.0.0.1:8092 (change with GMA_UI_PORT).
The browser UI is an operator console (zero-dependency stdlib server + vanilla JS):
- Dashboard — showfile/version/session tiles, console users, telemetry risk-tier bars, recent agent runs, and a Divergence Watch card (snapshot a baseline, then any desk-side change — loaded show, page change, pool edits — is flagged with the exact changed vars and pool IDs; the header chip flips In sync / Diverged)
- Playback — opens with a tile grid of every assigned executor on the page
(one
List Executor p.1 Thru p.199telnet command — no per-slot scanning), with SEQ/FX badges and cue counts; clicking a tile loads detail + cue list. Manual single-slot probe and direct sequence load are still available - Patch — fixture types collapsed to one row each with fixture-ID ranges and universe tags; expand to compact chips; filter auto-expands matches; DMX-universe distribution card
- Agent — goal composer with plan preview (per-step risk chips), a destructive-run confirm modal, run-trace timeline (status, duration, per-step errors), recent trace explorer, and learned-recipe list with use counts
- Analysis — patch expectation compare + telemetry report
Important behavior notes:
- the executor overview lists only assigned slots; empty slots are simply absent
- direct sequence IDs are more reliable than executor-based sequence resolution
- fixture grouping on the Patch view is parsed from live
list fixtureoutput
[!TIP] Semantic search: Add
GITHUB_MODELS_TOKEN=ghp_...to.env, then runuv run python scripts/rag_ingest.py --provider githubonce to rebuild the index with real embeddings. Thesearch_codebaseMCP 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.py + src/mcp_tools/203 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 203 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, src/mcp_tools/ |
| 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 instance, reply contract, safety gate, env config |
src/mcp_tools/ |
26 domain modules holding the 203 server tools, resources and prompts |
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
GMA_TOOL_PROFILE=full # core (28 tools), standard (104) or full (237, default)
GMA_ELICIT_CONFIRM=1 # 0 = never open confirm dialogs for destructive calls
GMA_MAX_REPLY_CHARS=20000 # cap on raw console text returned per reply
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:readscope 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 |
GMA_TOOL_PROFILE trims what MCP clients see when they load every tool schema up front (about 40k tokens for all 237). run_agent_goal can still use every tool. See doc/tool-surface-tiers.md.
MCP Tools
The server exposes 237 tools to MCP clients, grouped into 15 categories plus an agentic orchestration layer:
MCP Resources
Fourteen read-only resources exposable to any MCP client. Use them for zero-telnet context before calling tools.
| URI | Description |
|---|---|
ma2://console/activity |
Live: recent console-changing tool calls; subscribe to get an update after every change |
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 — all tools clustered by category (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.
MCP Prompts
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 |
Agent Skills
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.
Client Setup
Claude Desktop
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": "uvx",
"args": ["mcp-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/.
VS Code
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.
Codex
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.json
Safety System
grandMA2 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
Layer 1 — OAuth Identity (src/auth.py)
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 |
Layer 2 — Policy Gate (src/rights.py)
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()
Rights are enforced in code via @require_ma2_right; doc/ma2-rights-matrix.json documents the rights model.
Layer 3 — MA2 Native Rights (console enforcement)
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.
Risk Tiers (server-side gate)
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. When the MCP client supports elicitation, a destructive call made without it opens a confirm dialog instead of just failing; only an explicit accept runs it (disable with GMA_ELICIT_CONFIRM=0). run_agent_goal without auto_confirm asks the same way per destructive step.
Raw command lines are classified per ;-separated part, so ClearAll ; Store Group 5 is DESTRUCTIVE, and a bare number (which can answer an open pop-up) is too.
[!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.
Keyword Classification
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 / |
RAG Pipeline
graph LR
A[Crawl] --> B[Chunk] --> C[Embed] --> D[StoreSQLite] --> 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 |
Console Navigation
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
Tree Scanner
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 --resume
Command Builders
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).
Project Structure
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)
Dependencies
| 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.
Development
# 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
Troubleshooting
| 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 |
License
Install
uvx mcp-server-timeConfiguration
{
"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": "uvx",
"args": ["mcp-server-time"]
}
}
}