mgba_run_lua
Execute custom Lua scripts in mGBA emulator to automate testing, analyze game data, read/write memory, capture screenshots, and generate structured output for Game Boy, GBC, and GBA ROMs.
Instructions
Run a custom Lua script in the emulator. The script can use emu:read8(), emu:write8(), emu:screenshot(), callbacks:add(), etc.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| rom_path | Yes | Path to the ROM file | |
| script | Yes | Lua script to execute. Use emu:quit() to exit. Write JSON to 'output.json' for structured data. | |
| savestate_path | No | Optional savestate to load | |
| timeout | No | Timeout in seconds (default: 30) |
Implementation Reference
- src/mgba_mcp/emulator.py:31-97 (handler)Core handler implementation: writes Lua script to temp file, executes mgba-qt subprocess with --script flag, captures stdout/stderr, screenshot.png, and parses output.json.def _run_with_lua( self, rom_path: str, lua_script: str, savestate_path: Optional[str] = None, timeout: int = 30, ) -> EmulatorResult: """Run mGBA with a Lua script and return results.""" # Write Lua script to temp file lua_file = self.temp_dir / "script.lua" lua_file.write_text(lua_script) # Build command cmd = [] if self.use_xvfb: cmd.extend(["xvfb-run", "-a"]) cmd.extend([self.mgba_path, rom_path]) if savestate_path: cmd.extend(["-t", savestate_path]) cmd.extend(["--script", str(lua_file), "-l", "0"]) try: result = subprocess.run( cmd, capture_output=True, text=True, timeout=timeout, cwd=str(self.temp_dir), ) # Check for output files screenshot_path = self.temp_dir / "screenshot.png" output_path = self.temp_dir / "output.json" screenshot = None if screenshot_path.exists(): screenshot = screenshot_path.read_bytes() output_data = None if output_path.exists(): try: output_data = json.loads(output_path.read_text()) except json.JSONDecodeError: pass return EmulatorResult( success=result.returncode == 0, screenshot=screenshot, output=result.stdout, error=result.stderr if result.returncode != 0 else None, data=output_data, ) except subprocess.TimeoutExpired: return EmulatorResult( success=False, error=f"Emulator timed out after {timeout}s", ) except Exception as e: return EmulatorResult( success=False, error=str(e), )
- src/mgba_mcp/emulator.py:266-275 (handler)Direct handler method called from server.py; thin wrapper invoking the core _run_with_lua.def run_lua_script( self, rom_path: str, script: str, savestate_path: Optional[str] = None, timeout: int = 30, ) -> EmulatorResult: """Run a custom Lua script.""" return self._run_with_lua(rom_path, script, savestate_path, timeout)
- src/mgba_mcp/server.py:340-365 (handler)MCP server dispatch handler: calls emulator.run_lua_script with parsed arguments, formats and returns text/image results.elif name == "mgba_run_lua": result = emu.run_lua_script( rom_path=arguments["rom_path"], script=arguments["script"], savestate_path=arguments.get("savestate_path"), timeout=arguments.get("timeout", 30), ) lines = [] if result.success: lines.append("Lua script executed successfully") if result.data: lines.append(f"Output data: {json.dumps(result.data, indent=2)}") if result.output: lines.append(f"Stdout: {result.output}") else: lines.append(f"Error: {result.error}") result_content.append(TextContent(type="text", text="\n".join(lines))) if result.screenshot: result_content.append(ImageContent( type="image", data=base64.b64encode(result.screenshot).decode(), mimeType="image/png", ))
- src/mgba_mcp/server.py:177-203 (registration)Tool registration including name, description, and input schema (part of @server.list_tools()).Tool( name="mgba_run_lua", description="Run a custom Lua script in the emulator. The script can use emu:read8(), emu:write8(), emu:screenshot(), callbacks:add(), etc.", inputSchema={ "type": "object", "properties": { "rom_path": { "type": "string", "description": "Path to the ROM file", }, "script": { "type": "string", "description": "Lua script to execute. Use emu:quit() to exit. Write JSON to 'output.json' for structured data.", }, "savestate_path": { "type": "string", "description": "Optional savestate to load", }, "timeout": { "type": "integer", "description": "Timeout in seconds (default: 30)", "default": 30, }, }, "required": ["rom_path", "script"], }, ),