# dmang-dev/mcp-pine [Health: Active]

**Category:** 🎮 Gaming  
**Repository:** https://github.com/dmang-dev/mcp-pine  
**GitHub Stars:** 2  
**npm Downloads (last month):** 93  
**Views:** 4  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/dmang-dev-mcp-pine

## Description
Memory inspection and savestate control for PCSX2 and other emulators speaking the PINE protocol. Read/write 8/16/32/64-bit memory, save/load state slots, query game metadata. TCP on Windows, Unix sockets on Linux/macOS.

## Tools
Capabilities this server exposes over MCP:

- **pine_ping** — PURPOSE: Verify the PINE server (PCSX2) is reachable and responding. USAGE: Call once at session start before other tool calls. Issues PINE Version opcode (0x08) — doubles as liveness probe and emulator-version sniff. BEHAVIOR: No side effects. Bridge connects on demand — Unix socket at $XDG_RUNTIME_DIR/pcsx2.sock.<slot> (Linux/macOS, with $TMPDIR/$/tmp fallback) or TCP to 127.0.0.1:<slot> (Windows, default slot 28011). 10-second timeout if the emulator isn't running, PINE isn't enabled (For PCSX2: Settings > Advanced > Enable PINE Server (default port 28011).), or slot/port mismatches. RETURNS: 'OK — emulator: VERSION_STRING', e.g. 'OK — emulator: PCSX2 <version>'.
- **pine_get_info** — PURPOSE: Get the loaded game's metadata — title, serial code, disc CRC, in-game version string — plus the current emulator run state in one call. USAGE: Call after pine_ping to confirm what game is loaded (don't poke memory blindly — the same address means different things across games). For just the run state without the metadata round-trips use pine_get_status (1 PINE call vs 5 here). The serial (e.g. 'SLUS-21274' for PS2, 'SLUS-00067' for PS1) uniquely identifies the disc release region; combine with disc CRC to identify a specific revision. BEHAVIOR: No side effects — pure read of emulator metadata. Issues five PINE opcodes in parallel (Title, ID, UUID, GameVersion, Status). Any individual field that the emulator doesn't expose or that fails is replaced with the literal string '(unavailable)' and the rest still come back. If the entire connection fails the call propagates an error. RETURNS: Multi-line text with Title, Serial, Disc CRC, Game version, and Status — one field per line.
- **pine_get_status** — PURPOSE: Get the emulator run state — 'running', 'paused', 'shutdown', or 'unknown'. USAGE: Cheap (1 PINE round-trip) check before timing-sensitive sequences — writes work while paused but only take visible effect after unpause. For game metadata (title, serial, CRC) use pine_get_info (batches Status with Title/ID/UUID/GameVersion). PINE has no pause/resume opcode; this tool only reports state. BEHAVIOR: No side effects. Issues PINE Status opcode (0x0F), decodes the 32-bit response (0=running, 1=paused, 2=shutdown). Errors on connection failure or PINE FAIL. RETURNS: 'Status: STATE' where STATE ∈ {running, paused, shutdown, unknown}.
- **pine_read8** — PURPOSE: Read an unsigned 8-bit byte from the emulator's EE main address space at the given absolute address. USAGE: Use for single-byte fields — status flags, counters, 8-bit enums, character bytes. For 16/32/64-bit values use pine_read16/read32/read64 (one call instead of multi-byte assembly); for spans of more than ~4 bytes use pine_read_range (one batched call instead of N round-trips). BEHAVIOR: No side effects — pure read. Reads work whether the emulator is running or paused. No alignment requirement (byte access is naturally aligned). Returns an error if the address is unmapped, the connection drops, or PINE returns its FAIL response (0xFF). The 10-second per-call timeout fires if the emulator drops the reply (PCSX2 has been observed to do this under heavy pipeline load — see pine_read_range for the wider context).

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'ADDR_HEX: VAL_DEC (0xVAL_HEX)', e.g. '0x00200000: 99 (0x63)'.
- **pine_read16** — PURPOSE: Read an unsigned 16-bit little-endian value from the emulator's EE main address space at the given absolute address. USAGE: Use for 16-bit fields (HP, score, coordinates on many PlayStation 2 titles). For single bytes use pine_read8; for 32/64-bit use pine_read32/read64; for unaligned reads or big-endian fields, use pine_read_range and decode the bytes yourself (this tool always interprets bytes as little-endian, which matches MIPS byte order on PS1/PS2). BEHAVIOR: No side effects — pure read. Reads two consecutive bytes (low byte at `address`, high byte at `address+1`) and combines them as little-endian. Address MUST be 2-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. Returns a PINE FAIL response on unmapped addresses; times out after ~10s if the reply is dropped.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'ADDR_HEX: VAL_DEC (0xVAL_HEX)'.
- **pine_read32** — PURPOSE: Read an unsigned 32-bit little-endian value from the emulator's EE main address space at the given absolute address. USAGE: Use for 32-bit fields — timestamps, large counters, RGBA colors, and the lower half of 64-bit pointers. For single byte / 16-bit / 64-bit values use pine_read8/read16/read64; for big-endian or unaligned multi-word reads use pine_read_range and decode yourself. BEHAVIOR: No side effects — pure read. Reads four consecutive bytes starting at `address` and combines them as little-endian (LSB at `address`, MSB at `address+3`). Address MUST be 4-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. Returns a PINE FAIL response on unmapped addresses; times out after ~10s if the reply is dropped.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'ADDR_HEX: VAL_DEC (0xVAL_HEX)'.
- **pine_read64** — PURPOSE: Read an unsigned 64-bit little-endian value from the emulator's EE main address space at the given absolute address. USAGE: Use for true 64-bit fields — full pointers, large IDs, packed double-word state. The PS2 EE is a 128-bit MIPS where 64-bit slots are common; PS1 and PS3 use 64-bit less heavily but the opcode still works. Reach for this rather than chaining two pine_read32 calls when you want atomicity. For 8/16/32-bit values use the corresponding sibling; for byte spans use pine_read_range. BEHAVIOR: No side effects — pure read. Reads eight consecutive bytes starting at `address` and combines them as little-endian. Address MUST be 8-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. The result is returned as a decimal STRING (not a JSON number) to preserve precision past 2^53 (JavaScript number limit) — parse with BigInt if you need to do arithmetic. Returns a PINE FAIL response on unmapped addresses; times out after ~10s if the reply is dropped.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'ADDR_HEX: VAL_DEC (0xVAL_HEX)' — VAL_DEC is a decimal string that may exceed 2^53.
- **pine_read_range** — PURPOSE: Read a contiguous range of bytes from EE main address space memory as a hex dump. USAGE: For >4 bytes — far cheaper than looping pine_read8. Max 4096 bytes/call; chunk larger reads in 4 KiB. Powers snapshot-diff RAM hunts (snapshot before/after a known change, diff for matching deltas), unknown-struct inspection, and region capture/restore. BEHAVIOR: No side effects. PINE has no native bulk-read opcode; the tool synthesizes the range from read64/32/16/8 calls (largest aligned load at each step) and assembles client-side. Issued FULLY SERIALLY by default because PCSX2's PINE queue silently drops replies past ~7 in-flight requests, desyncing the bridge until emulator restart. Loopback serial is fast enough (~52 ms for 4096 bytes on PCSX2 v2.6.3); other targets are typically similar or faster. Override via PINE_PIPELINE_BATCH env var at your own risk. Errors on length out of 1-4096, any underlying FAIL, or reply timeout.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: 'ADDR_HEX [N bytes]:' header + space-separated 2-digit uppercase hex bytes.
- **pine_write8** — PURPOSE: Write a single unsigned byte (0-255) to the emulator's EE main address space at the given absolute address. USAGE: Use for single-byte cheats, debug pokes, and game-state mutations (give a player N lives, unlock a flag, set a counter). For 16/32/64-bit values prefer pine_write16/write32/write64 (single call instead of byte-at-a-time, and atomic from the emulator's perspective). For seeding many bytes there is no native bulk write — loop pine_write8 yourself or batch via pine_write64 on aligned regions. To roll back later use pine_save_state BEFORE the write and pine_load_state to restore. BEHAVIOR: DESTRUCTIVE: overwrites whatever was at `address` with no undo. The write is direct memory access — bypasses TLB protection and any DMA semantics — so writes to read-only regions (BIOS, etc.) are silently dropped by the emulator with no error. The write takes effect immediately, but visible game-state effects only appear when the emulator next ticks (so writing while paused shows changes only after unpause or frame-step). No alignment requirement for byte access. Returns an error if the connection drops or PINE returns FAIL on a wholly invalid address.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX'.
- **pine_write16** — PURPOSE: Write an unsigned 16-bit little-endian value to EE main address space. USAGE: For 16-bit cheats/pokes (HP, score, coordinates). For single bytes use pine_write8; for 32/64-bit use pine_write32/write64; for big-endian fields byteswap first (this tool always writes little-endian). Snapshot via pine_save_state for rollback. BEHAVIOR: DESTRUCTIVE: overwrites two bytes (low at `address`, high at `address+1`) with no undo. Direct write — bypasses TLB; writes to read-only regions (BIOS) are silently dropped. Address MUST be 2-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. Errors on connection drop or PINE FAIL.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX'.
- **pine_write32** — PURPOSE: Write an unsigned 32-bit little-endian value to the emulator's EE main address space at the given absolute address. USAGE: Use for 32-bit cheats and pokes — timestamps, large counters, RGBA colors, the lower half of pointers. For single byte / 16-bit values use pine_write8/write16; for true 64-bit fields use pine_write64 — chaining two pine_write32 calls is non-atomic and can be observed mid-update by the running game. For big-endian layouts, byteswap into a little-endian value yourself first. BEHAVIOR: DESTRUCTIVE: overwrites four bytes starting at `address` with no undo. Direct memory write — bypasses TLB protection and DMA mediation; writes to read-only regions (BIOS) are silently dropped with no error. Address MUST be 4-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. Values are NOT truncated by this tool: the schema rejects anything outside 0-4294967295 (0x00000000-0xFFFFFFFF) before the call ever reaches PINE. Returns an error if the connection drops or PINE returns FAIL on a wholly invalid address.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: Single line 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX'.
- **pine_write64** — PURPOSE: Write an unsigned 64-bit little-endian value to EE main address space. USAGE: For true 64-bit writes — full pointers, large IDs, packed doubleword state. Atomic from the emulator's perspective; preferred over chaining two pine_write32 calls (a running game can observe the in-between state). For 8/16/32-bit values use the corresponding sibling. BEHAVIOR: DESTRUCTIVE: overwrites eight bytes from `address` with no undo. Direct write — bypasses TLB; writes to read-only regions silently dropped. Address MUST be 8-byte aligned. PINE on PCSX2 does NOT enforce alignment — unaligned access typically returns whatever bytes are at the aligned address below, silently corrupting the value. If you need an unaligned multi-byte read, use pine_read_range and assemble the bytes yourself. `value` is a DECIMAL STRING (0 through 18446744073709551615) to preserve precision past JS's 2^53 number limit. Errors on connection drop or PINE FAIL.

PlayStation 2 main address space landmarks (PCSX2):
  0x00100000-0x01FFFFFF  EE main RAM (32 MiB) — game code & data; the most common target
  0x10000000             Hardware registers (DMA, GIF, VIF, etc.)
  0x11000000             VU0 / VU1 memory
  0x12000000             GS privileged registers
  0x1C000000-0x1C1FFFFF  IOP RAM (2 MiB)
  0x1F800000             IOP scratchpad
  0x70000000             EE scratchpad (16 KiB)
PINE memory operations target the EE address space.

RETURNS: 'Wrote VAL_DEC (0xVAL_HEX) → ADDR_HEX' — VAL_DEC may exceed 2^53.
- **pine_save_state** — PURPOSE: Trigger the emulator to save complete state (RAM, registers, GPU, audio, timing) to a numbered slot. USAGE: Rollback point before risky writes, bookmarks, repro sharing. Companion pine_load_state restores from the same slot. PINE savestates are SLOT-BASED (0-255), not file-path-based — PCSX2 picks the disk location. BEHAVIOR: DESTRUCTIVE TO TARGET SLOT: silently overwrites prior contents — no prompt, no backup, no recovery. Bound to the exact game disc and PCSX2 version; loading mismatched usually crashes the core. The call returns when PCSX2 schedules the save, NOT when the file is on disk — brief half-written window possible. Errors on no game loaded, unwritable folder, or PINE FAIL.

RETURNS: 'Save state triggered for slot N'.
- **pine_load_state** — PURPOSE: Trigger the emulator to load a previously-saved state from the given numbered savestate slot, replacing all live state. USAGE: Counterpart to pine_save_state. Use to undo a sequence of writes/inputs (the snapshot/experiment/restore workflow), to jump to a bookmarked game state, or to start each tool-call sequence from a known baseline. There is no PINE 'reset' opcode — to start fresh from boot you must use the emulator's GUI or pre-prepare a slot containing a freshly booted state. BEHAVIOR: DESTRUCTIVE TO LIVE STATE: replaces ALL current emulator state (RAM, registers, GPU, audio, etc.) with the contents of the slot's file. Anything not previously snapshotted is lost permanently. The state file MUST come from the same game disc and same PCSX2 version that produced it; loading an incompatible state typically crashes the core (no recovery without restarting PCSX2). The PINE call returns immediately after PCSX2 schedules the load, NOT after the load is fully visible — there can be a brief window where state is partially loaded. Returns an error if the slot file doesn't exist, the file is corrupt or for the wrong game, or PINE returns FAIL.

RETURNS: Single line 'Load state triggered for slot N'.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "mcp-pine": {
    "command": "npx",
    "args": ["-y","mcp-pine"]
  }
}
```

## Documentation

## What dmang-dev/mcp-pine MCP server does

The dmang-dev/mcp-pine MCP server exposes PINE-compatible emulator operations through standard MCP over stdio. Its primary documented targets are PCSX2 for PlayStation 2 and RPCS3 for PlayStation 3, with the target selection controlling socket discovery and the memory-map context shown in tool descriptions.

The tool set starts with connectivity and identification. `pine_ping` checks that the emulator answers and reports its version. `pine_get_info` returns the loaded title, serial, disc CRC, game version, and current run state, while `pine_get_status` provides only the emulator state. These checks are useful before reading an address whose meaning depends on the loaded game.

Memory tools read or write unsigned 8-, 16-, 32-, and 64-bit values, plus contiguous ranges of up to 4096 bytes. Writes are direct and destructive. Save and load tools operate on numbered slots from 0 through 255, making it possible to save a baseline before an experiment and restore it later.

## How it works

An MCP client starts the Node.js process and communicates with it over stdio. The process opens a loopback TCP connection on Windows or a Unix-domain socket on Linux and macOS, then converts each MCP request into a binary PINE request for the emulator.

For PCSX2, memory operations target the EE address space. Multi-byte operations use little-endian interpretation and require the corresponding 2-, 4-, or 8-byte alignment. Range reads are assembled from smaller PINE reads rather than a native bulk-read operation. They are intentionally serialized by default because aggressive concurrency can cause PCSX2 to lose replies.

`PINE_TARGET` changes both the target-specific socket naming and the descriptions supplied to the agent. The default target is PCSX2. RPCS3 support is documented as compatible in concept but not thoroughly verified at the wire level.

## Setup and configuration

To run dmang-dev/mcp-pine MCP server, use Node.js 22 or newer and install the npm package globally, or launch it directly with `npx -y mcp-pine`. The direct command can be registered as a stdio server in Claude Desktop. The emulator must be running, have its PINE or compatible IPC service enabled, and have a game loaded for most meaningful operations.

Supported configuration variables include:

- `PINE_TARGET`: selects `pcsx2` or `rpcs3`; defaults to `pcsx2`.
- `PINE_SLOT`: selects the PINE slot or TCP port. The documented defaults are 28011 for PCSX2 and 28012 for RPCS3.
- `PINE_HOST`: changes the TCP host from `127.0.0.1`.
- `PINE_SOCKET_PATH`: supplies a complete Unix socket path and bypasses automatic discovery.

In PCSX2, enable the PINE server in the advanced settings and adjust `PINE_SLOT` if the default port is changed. On Linux and macOS, automatic socket resolution uses the runtime directory with temporary-directory fallbacks.

## Tools and capabilities

- Check emulator reachability and identify its version.
- Retrieve title, serial, disc CRC, game version, and run state.
- Read typed values or byte ranges from emulator memory.
- Write typed values for memory experiments and game-state changes.
- Save or load complete emulator state using numbered slots.

The 64-bit read and write interfaces use decimal strings where needed to avoid JavaScript precision loss. Range reads accept 1 through 4096 bytes. Savestate calls affect the selected slot or live emulator state and return after the emulator schedules the operation, not necessarily after disk I/O or restoration is fully complete.

## Limitations and notes

The dmang-dev/mcp-pine MCP server does not provide controller input, screenshots, frame stepping, pause, or reset operations because those capabilities are not exposed by PINE. It is therefore intended for memory-oriented workflows, not for general game control.

Unaligned multi-byte accesses can produce incorrect results even though PCSX2 may not reject them. ROM or other read-only writes may be silently ignored. Loading a state from a different game disc or PCSX2 version can crash the emulator, and saving overwrites the selected slot without a recovery prompt. A failed connection, unmapped address, missing game, or fragile emulator request queue can also produce errors or timeouts.

_Full upstream README: https://allmcps.com/mcp/dmang-dev-mcp-pine/readme_

