- name
- cheatengine-mcp-bridge
- description
- Connect AI agents to Cheat Engine for automated memory analysis, reverse engineering, and debugging via MCP
- triggers
- ["analyze game memory with cheat engine","automate reverse engineering with AI","scan process memory using natural language","find pointer chains in cheat engine","disassemble functions with AI assistance","create game trainer using cheat engine","debug memory structures with AI","automate pointer scanning and AOB patterns"]
# Cheat Engine MCP Bridge
> Skill by [ara.so](https://ara.so) — MCP Skills collection.
Connect Claude, Cursor, Copilot and other AI agents directly to Cheat Engine via the Model Context Protocol. Automate reverse engineering, memory analysis, pointer scanning, and debugging using natural language queries instead of manual clicking through hex dumps.
## What This Does
The Cheat Engine MCP Bridge exposes ~180 Cheat Engine functions as MCP tools, allowing AI agents to:
- Read/write memory (integers, floats, strings, pointers)
- Follow pointer chains: `[[base+0x10]+0x20]+0x8`
- Scan for values and AOB (Array of Bytes) patterns
- Disassemble and analyze functions
- Set hardware breakpoints and debug invisibly with DBVM (Ring -1 hypervisor)
- Identify C++ objects via RTTI
- Auto-analyze memory structures
- Generate update-resistant AOB signatures
- Inject DLLs and execute shellcode
**Architecture:**
```
AI Agent (Claude/Cursor)
↕ MCP Protocol (JSON-RPC over stdio)
Python MCP Server (mcp_cheatengine.py)
↕ Named Pipe (async)
Cheat Engine Lua Bridge (ce_mcp_bridge.lua)
↕ CE API
Target Process Memory
```
## Installation
### Prerequisites
- **Windows only** (uses Named Pipes via `pywin32`)
- Cheat Engine 7.4+ installed
- Python 3.10+
### Python Dependencies
```bash
cd MCP_Server
pip install -r requirements.txt
```
Or manually:
```bash
pip install mcp pywin32
```
### Load Bridge in Cheat Engine
1. **Enable DBVM** (optional, for advanced debugging):
- Cheat Engine → Settings → Kernel → Enable DBVM
2. **Critical: Disable Memory Query Routines** (prevents BSODs):
- Settings → Extra → **UNCHECK** "Query memory region routines"
3. **Load the Lua bridge**:
- Method A: `File` → `Execute Script` → browse to `MCP_Server/ce_mcp_bridge.lua` → `Execute`
- Method B: `Table` → `Show Cheat Table Lua Script` → paste:
```lua
dofile([[C:\path\to\cheatengine-mcp-bridge\MCP_Server\ce_mcp_bridge.lua]])
```
**Verify:** Console shows `[MCP v12.0.0] MCP Server Listening on: CE_MCP_Bridge_v99`
### Configure MCP Client
Add to your MCP configuration file:
**Claude Desktop** (`~/.config/claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"cheatengine": {
"command": "python",
"args": ["C:/path/to/cheatengine-mcp-bridge/MCP_Server/mcp_cheatengine.py"]
}
}
}
```
**Cursor** (`.cursorrules` or workspace settings):
```json
{
"mcp": {
"servers": {
"cheatengine": {
"command": "python",
"args": ["C:/path/to/cheatengine-mcp-bridge/MCP_Server/mcp_cheatengine.py"]
}
}
}
}
```
**Codex** (`~/.codex/config.toml`):
```toml
[mcp_servers.cheatengine]
command = "python"
args = ['C:\path\to\cheatengine-mcp-bridge\MCP_Server\mcp_cheatengine.py']
```
**Important:** Use forward slashes or escaped backslashes in JSON. Use single quotes in TOML.
Restart your IDE to load the MCP server.
## Core MCP Tools
### Process Management
**Attach to a process:**
```
User: "Attach to notepad.exe"
Agent uses: open_process
Args: {"process_name": "notepad.exe"}
```
**List running processes:**
```
Tool: get_process_list
Returns: [{"pid": 1234, "name": "game.exe"}, ...]
```
**Launch a new process:**
```
Tool: create_process
Args: {"path": "C:\\Games\\game.exe"}
```
**Get current process info:**
```
Tool: get_process_info
Returns: {"pid": 5678, "name": "game.exe", "base_address": "0x400000"}
```
### Memory Reading
**Read integer (4 bytes):**
```
Tool: read_integer
Args: {"address": "0x12345678"}
Returns: {"value": 15000}
```
**Read float:**
```
Tool: read_float
Args: {"address": "game.exe+0x1234", "is_double": false}
Returns: {"value": 100.5}
```
**Read string:**
```
Tool: read_string
Args: {"address": "0x400000", "length": 64}
Returns: {"value": "PlayerName"}
```
**Read pointer chain:**
```
Tool: read_pointer_chain
Args: {"base": "game.exe+0x1000", "offsets": [0x10, 0x20, 0x8]}
Returns: {"final_address": "0x789ABC", "value": 42}
```
**Read bytes:**
```
Tool: read_memory
Args: {"address": "0x400000", "size": 16}
Returns: {"hex": "4D5A90000300000004000000FFFF0000", "bytes": [77, 90, ...]}
```
### Memory Scanning
**Scan for value:**
```
Tool: scan_all
Args: {
"value_type": "4byte",
"scan_type": "exact",
"value": "15000",
"writable": true,
"executable": false
}
Returns: {"count": 47, "addresses": ["0x123000", "0x456000", ...]}
```
**Next scan (filter results):**
```
Tool: next_scan
Args: {"value": "15100"}
Returns: {"count": 3, "addresses": ["0x123000", ...]}
```
**AOB (Array of Bytes) scan:**
```
Tool: aob_scan
Args: {
"pattern": "48 8B 05 ?? ?? ?? ?? 48 85 C0",
"writable": false,
"executable": true
}
Returns: {"addresses": ["0x401000", "0x402500"]}
```
**Pointer scan:**
```
Tool: pointer_scan
Args: {
"address": "0x789000",
"max_level": 5,
"max_offset": 4096
}
Returns: {"count": 12, "results": [{"base": "game.exe+0x1000", "offsets": [0x10, 0x8]}]}
```
### Code Analysis
**Disassemble:**
```
Tool: disassemble
Args: {"address": "0x401000", "count": 10}
Returns: {
"instructions": [
{"address": "0x401000", "bytes": "55", "disassembly": "push rbp"},
{"address": "0x401001", "bytes": "4889E5", "disassembly": "mov rbp,rsp"}
]
}
```
**Analyze function:**
```
Tool: analyze_function
Args: {"address": "0x401000"}
Returns: {
"prologue": "push rbp; mov rbp,rsp",
"calls_count": 3,
"references": ["0x402000", "0x403000"]
}
```
**Get RTTI class name:**
```
Tool: get_rtti_classname
Args: {"address": "0x500000"}
Returns: {"classname": "CPlayerInventory"}
```
**Find references to address:**
```
Tool: find_references
Args: {"address": "0x600000"}
Returns: {"count": 5, "references": ["0x401234", "0x402567"]}
```
### Structure Analysis
**Dissect structure:**
```
Tool: dissect_structure
Args: {"address": "0x500000", "size": 256}
Returns: {
"fields": [
{"offset": "0x00", "type": "vtable", "value": "0x401000"},
{"offset": "0x08", "type": "int32", "value": 15},
{"offset": "0x10", "type": "pointer", "value": "0x600000"}
]
}
```
### Debugging
**Set breakpoint:**
```
Tool: set_breakpoint
Args: {
"address": "0x401000",
"type": "hardware",
"condition": "rax==5"
}
```
**Set data breakpoint (watch memory writes):**
```
Tool: set_data_breakpoint
Args: {"address": "0x789000", "size": 4, "type": "write"}
```
**Start DBVM watch (invisible debugging):**
```
Tool: start_dbvm_watch
Args: {"address": "0x401000"}
```
**What writes to address:**
```
Tool: what_writes
Args: {"address": "0x789000"}
```
**What accesses address:**
```
Tool: what_accesses
Args: {"address": "0x789000", "type": "read"}
```
### Memory Writing
**Write integer:**
```
Tool: write_integer
Args: {"address": "0x123000", "value": 9999, "size": 4}
```
**Write bytes:**
```
Tool: write_memory
Args: {"address": "0x401000", "bytes": [0x90, 0x90, 0x90]}
```
**Freeze value:**
```
Tool: freeze_address
Args: {"address": "0x123000", "value": 1000, "description": "Player Health"}
```
### Code Injection
**Inject DLL:**
```
Tool: inject_dll
Args: {"dll_path": "C:\\mods\\trainer.dll"}
```
**Execute shellcode:**
```
Tool: execute_code
Args: {
"code": "mov rax, 1; ret",
"address": "0x500000"
}
```
**Auto-assembler:**
```
Tool: auto_assemble
Args: {
"script": "[ENABLE]\nalloc(hook,128)\nhook:\n mov [health],#999\n ret"
}
```
### Symbol Management
**Register symbol:**
```
Tool: register_symbol
Args: {"name": "PlayerHealth", "address": "0x789000"}
```
**Get symbol info:**
```
Tool: get_symbol_info
Args: {"symbol": "PlayerHealth"}
Returns: {"address": "0x789000", "type": "int32"}
```
**Enable Windows symbols (PDB):**
```
Tool: enable_windows_symbols
Args: {"enable": true}
GitHubで見る