RoRBridge
by Talladego
README.md
# RoRBridge
Cursor MCP server + companion addon so agents can talk to a live [Return of Reckoning](https://www.returnofreckoning.com/) client: run Lua `/script`, dump bags, send chat, and snapshot StockPiler3 — with structured JSON replies.
Transport is **file IPC** under `<game>/logs` (same family of tricks as LibQuery). There is no socket API from addon Lua, and **`loadstring` is not available** — scripts are executed with `SendChatText("/script …")`.
## What's in this repo
| Piece | Path |
| :--- | :--- |
| Addon | [`addon/`](addon/) → install as `Interface/AddOns/RoRBridge/` |
| MCP server | [`server.py`](server.py) |
| File bridge | [`bridge.py`](bridge.py) |
| Host CLI (SP3 / health) | [`sp3_cli.py`](sp3_cli.py) |
| Cursor MCP snippet | [`mcp.json.example`](mcp.json.example) |
## Requirements
- Return of Reckoning client (logged in)
- Python **3.10+** on the same machine as the game
- [Cursor](https://cursor.com/) (or any MCP client that can spawn a stdio server)
## Setup
### 1. Install the addon
Copy `addon/` into your game AddOns folder so the path is:
```text
<game root>/Interface/AddOns/RoRBridge/RoRBridge.mod
<game root>/Interface/AddOns/RoRBridge/RoRBridge.lua
<game root>/Interface/AddOns/RoRBridge/RoRBridge.xml
```
PowerShell example (adjust both paths):
```powershell
$repo = "C:\Users\<you>\Documents\GitHub\RoRBridge"
$game = "C:\Users\<you>\Games\Return of Reckoning"
New-Item -ItemType Directory -Force -Path "$game\Interface\AddOns\RoRBridge" | Out-Null
Copy-Item -Recurse -Force "$repo\addon\*" "$game\Interface\AddOns\RoRBridge\"
```
Reload the UI (or restart the client). Enable the addon if your UI manager lists it.
### 2. Enable the bridge in-game
Log in, then run:
```text
/rormcp on
```
Disabled by default. Check with `/rormcp status`. Alias: `/rorbridge`.
Leave **`/rormcp off`** when you are not developing — the bridge has full client Lua authority while enabled.
### 3. Install Python deps
From this repo:
```powershell
cd C:\Users\<you>\Documents\GitHub\RoRBridge
python -m pip install -r requirements.txt
```
### 4. Wire Cursor MCP
Merge [`mcp.json.example`](mcp.json.example) into your Cursor MCP config (user or project), and set:
- **`args`**: absolute path to this repo’s `server.py`
- **`ROR_GAME_ROOT`**: absolute path to your RoR install (folder that contains `logs/` and `Interface/`)
- **`PYTHONDONTWRITEBYTECODE`**: keep `"1"` (see below)
Example:
```json
{
"mcpServers": {
"ror-mcp": {
"command": "python",
"args": [
"C:/Users/<you>/Documents/GitHub/RoRBridge/server.py"
],
"env": {
"ROR_GAME_ROOT": "C:/Users/<you>/Games/Return of Reckoning",
"PYTHONDONTWRITEBYTECODE": "1"
}
}
}
}
```
Restart MCP / Cursor so the server reloads. Confirm with the `bridge_health` tool, then `ping` while `/rormcp on`.
### Windows Controlled Folder Access
If the repo lives under `Documents`, Defender CFA may toast when Python writes `__pycache__`. The server sets `PYTHONDONTWRITEBYTECODE=1` / `sys.dont_write_bytecode` to avoid that. Keep the env var in your Cursor `mcp.json`.
## MCP tools
| Tool | Purpose |
| :--- | :--- |
| `bridge_health` | Game root, status log age, whether addon reports enabled |
| `ping` | `bridge.ping` round-trip (no eval) |
| `run_script` | Run Lua via `/script`; capture `pcall` result |
| `dump_bags` | Inventory backpack dump (addon OnUpdate; no `/script`) |
| `chat_send` | Plain `SendChatText` (e.g. `/sp3 dumpall`, `/rormcp status`) |
| `dump_sp3` | Live StockPiler3 snapshot (settings, plan rows, brew, flasks, buy jobs) |
| `force_build_sp3` | `Planner.Build({force=true})` then same snapshot as `dump_sp3` |
Prefer scripts that **`return`** a value:
```lua
return GameData.Player.name
```
For StockPiler3 work prefer **`dump_sp3` / `force_build_sp3`** over long `run_script` bodies (≈1800-char `/script` cap).
Whenever a tool talks to the game, pass **`note`**: a short player-facing sentence. RoRBridge prints `[RoRBridge] MCP: …` in chat (`/rormcp messages off` hides it).
## Host CLI (no Cursor)
With the game up and `/rormcp on`:
```powershell
$env:ROR_GAME_ROOT = "C:\Users\<you>\Games\Return of Reckoning"
python sp3_cli.py health
python sp3_cli.py ping
python sp3_cli.py snapshot
python sp3_cli.py force
```
## Protocol (v1)
| Channel | Path | Direction |
| :--- | :--- | :--- |
| Requests index | `logs/rormcp_requests.csv` | MCP → addon (`BuildTableFromCSV`) |
| Script payload | `logs/rm_<id>.script.csv` | MCP → addon (64-char chunks; deleted after each request) |
| Results | `logs/rormcp_results.log` | Addon → MCP (UTF-16 TextLog) |
| Heartbeat | `logs/rormcp_status.log` | Addon → MCP (UTF-16 TextLog; host uses file mtime) |
Ops: `script.run`, `bridge.ping`, `bags.dump`, `chat.send`, `sp3.snapshot`, `sp3.force_build`.
Slash commands: `/rormcp on|off|status|debug|messages|help` (alias `/rorbridge`).
Debug: `d("[RoRBridge] …")` breadcrumbs are **on by default** (`/rormcp debug off` to silence).
## Limits / safety
- Full client Lua authority while enabled — local stdio MCP only; leave **`/rormcp off`** when not developing.
- Wrapped `/script` length capped (`maxScriptCommandChars`, default 1800). Oversized scripts return `SCRIPT_TOO_LONG`.
- One in-flight request per Cursor tool call (server waits for matching `RequestId`).
## Spike / tests
See [`spike/SPIKE.md`](spike/SPIKE.md). Host-side CSV roundtrip (no client required):
```powershell
cd C:\Users\<you>\Documents\GitHub\RoRBridge
python -m spike.test_csv_roundtrip
```
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues