mgba_read_range
Read a contiguous range of bytes from emulated memory and return them as an integer array. Supports up to 4096 bytes per request.
Instructions
Read a contiguous range of bytes from emulated memory and return them as an array of integers. Maximum 4096 bytes per call.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| address | Yes | Start address | |
| length | Yes | Number of bytes to read |
Implementation Reference
- src/tools.ts:325-335 (handler)Handler for the mgba_read_range tool. Calls the mGBA bridge's 'read_range' method with the address and length parameters, then formats the returned byte array as a hex string.
case "mgba_read_range": { const bytes = await mgba.call<number[]>("read_range", { address: p.address, length: p.length, }); const hex = bytes .map((b) => b.toString(16).padStart(2, "0").toUpperCase()) .join(" "); const addr = (p.address as number).toString(16).toUpperCase(); return ok(`0x${addr} [${bytes.length} bytes]:\n${hex}`); } - src/tools.ts:126-137 (schema)Schema definition for mgba_read_range. Defines the tool name, description, and input schema requiring 'address' (integer) and 'length' (integer, 1-4096).
{ name: "mgba_read_range", description: "Read a contiguous range of bytes from emulated memory and return them as an array of integers. Maximum 4096 bytes per call.", inputSchema: { type: "object", required: ["address", "length"], properties: { address: { type: "integer", description: "Start address" }, length: { type: "integer", minimum: 1, maximum: 4096, description: "Number of bytes to read" }, }, }, }, - src/tools.ts:258-411 (registration)Registration function that binds the TOOLS list (including mgba_read_range) to the MCP server via ListToolsRequestSchema and CallToolRequestSchema handlers.
export function registerTools(server: Server, mgba: MgbaClient): void { server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS })); server.setRequestHandler(CallToolRequestSchema, async (req) => { const { name, arguments: args = {} } = req.params; const p = args as Record<string, unknown>; switch (name) { case "mgba_ping": { const r = await mgba.call<string>("ping"); return ok(r); } case "mgba_get_info": { const r = await mgba.call<{ title?: string; code?: string; frame?: number; platform?: number | string; capabilities?: Record<string, boolean>; }>("get_info"); const lines = [ `Title: ${r.title ?? "(unavailable)"}`, `Code: ${r.code ?? "(unavailable)"}`, `Platform: ${r.platform ?? "(unavailable)"}`, `Frame: ${r.frame ?? "(unavailable)"}`, ]; if (r.capabilities) { const present = Object.entries(r.capabilities).filter(([, v]) => v).map(([k]) => k); const missing = Object.entries(r.capabilities).filter(([, v]) => !v).map(([k]) => k); lines.push(""); lines.push(`Capabilities present: ${present.length ? present.join(", ") : "(none)"}`); if (missing.length) lines.push(`Missing on this build: ${missing.join(", ")}`); } return ok(lines.join("\n")); } case "mgba_read8": { const v = await mgba.call<number>("read8", { address: p.address }); return ok(`0x${(p.address as number).toString(16).toUpperCase()}: ${formatHex(v)}`); } case "mgba_read16": { const v = await mgba.call<number>("read16", { address: p.address }); return ok(`0x${(p.address as number).toString(16).toUpperCase()}: ${formatHex(v)}`); } case "mgba_read32": { const v = await mgba.call<number>("read32", { address: p.address }); return ok(`0x${(p.address as number).toString(16).toUpperCase()}: ${formatHex(v)}`); } case "mgba_write8": { await mgba.call("write8", { address: p.address, value: p.value }); return ok(`Wrote ${formatHex(p.value)} → 0x${(p.address as number).toString(16).toUpperCase()}`); } case "mgba_write16": { await mgba.call("write16", { address: p.address, value: p.value }); return ok(`Wrote ${formatHex(p.value)} → 0x${(p.address as number).toString(16).toUpperCase()}`); } case "mgba_write32": { await mgba.call("write32", { address: p.address, value: p.value }); return ok(`Wrote ${formatHex(p.value)} → 0x${(p.address as number).toString(16).toUpperCase()}`); } case "mgba_read_range": { const bytes = await mgba.call<number[]>("read_range", { address: p.address, length: p.length, }); const hex = bytes .map((b) => b.toString(16).padStart(2, "0").toUpperCase()) .join(" "); const addr = (p.address as number).toString(16).toUpperCase(); return ok(`0x${addr} [${bytes.length} bytes]:\n${hex}`); } case "mgba_write_range": { const r = await mgba.call<{ written: number }>("write_range", { address: p.address, bytes: p.bytes, }); const addr = (p.address as number).toString(16).toUpperCase(); return ok(`Wrote ${r.written} bytes → 0x${addr}`); } case "mgba_press_buttons": { const r = await mgba.call<{ queued: boolean; queue_size: number }>("press_buttons", { buttons: p.buttons, frames: p.frames ?? 1, release_frames: p.release_frames ?? 1, }); const keys = (p.buttons as string[]).join("+"); return ok( `Queued press: ${keys} ` + `(hold ${p.frames ?? 1}f, release ${p.release_frames ?? 1}f). ` + `Queue size: ${r.queue_size}`, ); } case "mgba_advance_frames": { const frame = await mgba.call<number>("advance_frames", { count: p.count ?? 1 }); return ok(`Advanced ${p.count ?? 1} frame(s). Current frame: ${frame}`); } case "mgba_pause": { await mgba.call("pause"); return ok("Emulation paused"); } case "mgba_unpause": { await mgba.call("unpause"); return ok("Emulation resumed"); } case "mgba_reset": { await mgba.call("reset"); return ok("ROM reset"); } case "mgba_screenshot": { const path = await mgba.call<string>("screenshot", p.path ? { path: p.path } : {}); return ok(`Screenshot saved: ${path}`); } case "mgba_save_state": { if (p.slot === undefined && p.path === undefined) { throw new Error("provide either `slot` (0-9) or `path`"); } const r = await mgba.call<{ slot?: number; path?: string }>("save_state", { ...(p.slot !== undefined ? { slot: p.slot } : {}), ...(p.path !== undefined ? { path: p.path } : {}), }); return ok(r.path ? `Saved state to ${r.path}` : `Saved state to slot ${r.slot}`); } case "mgba_load_state": { if (p.slot === undefined && p.path === undefined) { throw new Error("provide either `slot` (0-9) or `path`"); } const r = await mgba.call<{ slot?: number; path?: string }>("load_state", { ...(p.slot !== undefined ? { slot: p.slot } : {}), ...(p.path !== undefined ? { path: p.path } : {}), }); return ok(r.path ? `Loaded state from ${r.path}` : `Loaded state from slot ${r.slot}`); } default: throw new Error(`Unknown tool: ${name}`); } }); }