mcp-ppsspp
Provides tools to interact with the PPSSPP emulator for PlayStation Portable, enabling memory read/write, button input, screenshot capture, breakpoints, and register inspection via WebSocket debugger.
mcp-ppsspp
An MCP server that exposes PPSSPP — the PlayStation Portable emulator — to any MCP-compatible client (Claude Desktop, Claude Code, etc.) via PPSSPP's built-in WebSocket debugger interface.
Read and write PSP memory, drive games with button input, capture screenshots, set CPU breakpoints, inspect MIPS Allegrex registers — all through a clean tool interface. No bridge plugin needed; PPSSPP's debugger is built into the emulator.
How it works
+------------------+ stdio +------------------+ WebSocket +------------------+
| MCP client | JSON-RPC | mcp-ppsspp | JSON-RPC | PPSSPP |
| (Claude / etc.) | ===========> | (Node.js) | =============> | (debugger) |
+------------------+ +------------------+ +------------------+Unlike the mcp-bizhawk / mcp-mgba bridges (which need a Lua plugin loaded into the emulator), PPSSPP ships with its own debugger WebSocket interface — we just speak JSON to it. No plugin to install.
The connection uses subprotocol debugger.ppsspp.org on PPSSPP's debugger port.
Requirements
PPSSPP (recent version with WebSocket debugger — 1.7+)
Node.js 18+
"Allow remote debugger" enabled in PPSSPP
Install
npm install -g mcp-ppssppOr npx -y mcp-ppsspp.
Set up PPSSPP's debugger
Launch PPSSPP, load any PSP ISO/EBOOT
Settings → Tools → Developer Tools → Allow remote debugger (check the box)
PPSSPP will show the active host:port (e.g.
ws://192.168.1.10:12345/debugger)Note the port number — you'll set it as an environment variable for the MCP server
Register with your MCP client
Claude Code (CLI)
claude mcp add ppsspp --scope user --env PPSSPP_PORT=12345 mcp-ppssppReplace 12345 with your actual port. Verify:
claude mcp list
# ppsspp: mcp-ppsspp - ✓ ConnectedClaude Desktop
Edit claude_desktop_config.json:
{
"mcpServers": {
"ppsspp": {
"command": "mcp-ppsspp",
"env": { "PPSSPP_PORT": "12345" }
}
}
}Restart Claude Desktop after editing.
Configuration
Env var | Default | Purpose |
|
| WebSocket host to dial |
| (required) | WebSocket port — see PPSSPP's debugger settings |
Tools
Tool | Description |
| Verify connectivity (returns version) |
| Title, disc ID, version, run state |
| Read u8 / u16-LE / u32-LE from PSP memory |
| Write to PSP memory |
| Read up to 64 KiB as a byte array |
| Write byte array to memory |
| Read null-terminated UTF-8 string |
| Set persistent PSP button state |
| Press a button for N frames + auto-release |
| Set analog stick position |
| Pause / resume emulation |
| Step one MIPS instruction |
| Soft-reset the loaded game |
| Capture framebuffer as inline PNG |
| Read all MIPS Allegrex registers |
| CPU execution breakpoints |
PSP memory map (cheat sheet)
Range | Region |
| Scratchpad (fast 16 KiB SRAM) |
| VRAM (2 MiB GE video memory) |
| Kernel RAM (8 MiB, low half) |
| User RAM (24 MiB, where most game state lives) |
| Hardware registers |
PSP is little-endian (MIPS Allegrex). Kernel-mode mirrors at 0x88xxxxxx map to the same physical RAM as 0x08xxxxxx.
PSP buttons
cross, circle, triangle, square, up, down, left, right, start, select, ltrigger, rtrigger, home.
Troubleshooting
Symptom | Cause / Fix |
| Set the env var to the port shown in PPSSPP's Developer Tools dialog |
| PPSSPP isn't running, "Allow remote debugger" isn't checked, or you have the wrong port |
Tool calls hang / time out | Check the PPSSPP UI is responding; the WebSocket request requires PPSSPP's main loop to dispatch |
| Address is outside the PSP's mapped regions (user RAM is |
Screenshot returns no data | No game loaded — boot an ISO/EBOOT first |
Buttons don't seem to do anything | PPSSPP's input has the buttons but they may not "feel" right via remote input if the game polls fast; try |
Limitations
No savestate API — PPSSPP's WebSocket debugger doesn't expose
savestate.save/load. Use PPSSPP's keybinds (F1-F8 for slots) via the UI for now. Could be hacked by usinginput.buttons.pressto trigger the keybind, but not native.Frame-advance is instruction-level only (
cpu.stepInto). To advance a whole frame, set a breakpoint at the vblank handler andresume.Analog stick is shared state —
ppsspp_send_analogupdates the persistent stick position; not auto-released.
Development
npm install
npm run dev # tsc --watch — autobuilds on src/ changesLicense
Maintenance
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/dmang-dev/mcp-ppsspp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server