ro-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ro-mcp Log in, create a character, and walk to Prontera to talk to the NPC test quest."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ro-mcp
An MCP server that drives a real Ragnarok Online client session against a local rAthena server, so an agent can log in, walk around, talk to NPCs and fight — and therefore test server content end to end instead of reading log files.
The client is OpenKore, driven through
a small control plugin (openkore-plugin/mcpbridge.pl) that exposes a
line-oriented JSON socket.
Claude ⇄ MCP server (stdio)
⇄ JSON over TCP :24390
OpenKore + mcpbridge plugin
⇄ RO protocol (plaintext)
rAthena login:6900 char:6121 map:5121Why OpenKore rather than a hand-rolled client
OpenKore ships an exact match for the packet version this server speaks —
RagexeRE_2021_11_03 exists in its Send and Receive trees plus a matching
recvpackets table — and it already handles pathfinding, reconnects, map
changes and inventory. Reimplementing that was the alternative; reusing it
was not close.
Packet obfuscation is a non-issue here: rAthena resolves PACKETVER > 20180307
to zero obfuscation keys, which makes the XOR an identity operation. The
server confirms this at boot with
Packet Obfuscation: Enabled. Keys: 0x00000000, 0x00000000, 0x00000000.
Related MCP server: Roblox Executor MCP Server
Requirements
Requirement | Notes |
Perl 5.34+ | macOS system Perl is fine |
GNU readline |
|
Xcode Command Line Tools | Perl's C headers live inside the SDK on modern macOS |
Python 3 | only to run OpenKore's bundled SCons |
Node.js 18+ | the MCP server itself |
Setup
./setup.sh # clone OpenKore, patch, build XSTools, install config + pluginsetup.sh is idempotent. It does four things the stock OpenKore build cannot
do unattended on Apple Silicon:
Points SConstruct at the
/opt/homebrewreadline prefix (it only knows the Intel/usr/localone).Points it at Perl's headers inside the macOS SDK, since
Config.pmreports a bare/System/Librarypath that no longer holds them.Shims
python→python3for the bundled SCons.Installs our server entry, config overrides and the
mcpbridgeplugin — including addingmcpbridgetoloadPlugins_list, without which the control socket never opens.
Server-side prerequisites
The rAthena instance needs three settings for unattended login:
File | Setting | Why |
|
| lets |
|
| the PIN prompt blocks OpenKore's main loop, which stalls the control socket |
|
| character creation |
The bridge protocol
Newline-delimited JSON, both directions, on 127.0.0.1:24390 (loopback only —
this grants full control of a game session).
// requests
{"id": 1, "op": "ping"}
{"id": 2, "op": "state"}
{"id": 3, "op": "run", "cmd": "move 155 180"}
// responses
{"id": 1, "ok": true, "pong": 1}
{"id": 3, "ok": false, "error": "unknown or rejected command: ..."}
// events, pushed as they happen
{"event": "npc_talk", "name": "TS Lab", "msg": "Welcome to the V8 smoke test."}
{"event": "npc_talk_responses", "responses": ["Mob spawn", "Reputation", "Cancel"]}
{"event": "map_changed", "map": "prontera"}op: run forwards to OpenKore's own command layer rather than reimplementing
movement or NPC logic — OpenKore already knows how to path, retry and recover,
and duplicating that here would only rot.
Usage
npm install && npm run build
node scripts/smoke.mjs # end-to-end check against a running serverRegister with an MCP client by pointing it at dist/index.js:
{ "mcpServers": { "ro": { "command": "node", "args": ["/path/to/ro-mcp/dist/index.js"] } } }RO_MCP_KORE_DIR and RO_MCP_PORT override the OpenKore location and bridge port.
Tools
Tool | Purpose |
| launch / shut down the session |
| map, position, HP/SP, level, zeny, nearby NPCs and monsters |
| inspect and answer OpenKore's interactive questions |
| character creation and selection |
| move within a map / travel to another map |
| talk to an NPC, returning its dialog text and menu options |
| drive a conversation |
| attack a nearby monster |
| read console output / escape hatch |
A note on prompts
OpenKore asks some questions on stdin — character creation, character
selection, password retry. Those are blocking reads inside its main loop,
so while one is pending the loop is stopped and the control socket cannot
answer. The MCP server therefore owns the child process's stdin as well as
the socket; ro_prompt surfaces a pending question and ro_answer replies
to it. If a tool ever times out, check ro_prompt first.
Status
Verified end to end against a live server (scripts/smoke.mjs):
account auto-creation, login, character creation and selection
ro_statereporting map, position, HP/SP, level, zeny and nearby actorsro_walkmoving the character and confirming arrivalunreachable destinations rejected in ~30ms with the reason, rather than burning the full timeout — OpenKore reports these only on the console, so the arrival poll is raced against that message
a full NPC conversation against TypeScript-scripted content (
scripts/npc-test.mjs): reading dialog, parsing menu options, choosing a branch and reading the reply
Not yet exercised: ro_attack.
Two async traps worth knowing
Actor lists populate after map entry. A ro_state taken immediately
after login legitimately reports no nearby NPCs; poll until they appear.
A dialog's last message arrives as it closes. Scripts commonly answer
and then close in one go, so treat npc_talk_done as "mark closed", never
as "discard the buffer" — otherwise the end of a conversation, usually the
part being asserted on, is exactly the part lost.
Available Tools
17 toolsro_answerA
Answer OpenKore's pending interactive question by writing a line to its stdin.
Inputs: answer (required).
ro_attackB
Attack a nearby monster by its binID from ro_state.nearbyMonsters.
Inputs: binID (required), waitMs.
ro_close_dialogB
Close the currently open NPC dialog.
Inputs: no named parameters.
ro_commandA
Escape hatch: run an arbitrary OpenKore console command. Prefer the specific tools; use this for anything they do not cover.
Inputs: cmd (required).
ro_consoleA
Read recent OpenKore console output. Useful when something did not behave as expected.
Inputs: lines.
ro_create_charB
Create a character in the given slot. Only valid while OpenKore is asking for character properties — call ro_prompt first to confirm.
Inputs: name (required), job, sex, slot, +2 more.
ro_dialog_nextC
Advance an NPC dialog that is waiting on a 'next' click.
Inputs: timeoutMs.
ro_gm_warpA
Teleport instantly to a map using the @warp GM command. Requires the account to have a GM group with @warp permission. Unlike ro_warp this needs no walkable route, which matters because some maps (the tutorial grounds, instances) have no path out.
Inputs: map (required), x, y, timeoutMs.
ro_promptA
Check whether OpenKore is blocked on an interactive question (character creation, character selection, password retry). While a prompt is pending its main loop is stopped, so every other tool will time out until it is answered with ro_answer.
Inputs: no named parameters.
ro_select_charC
Select a character by its slot number and enter the world.
Inputs: slot.
ro_startA
Launch OpenKore and connect to the local rAthena server. Must be called before any other tool. Returns the resulting game state, or the pending prompt if login needs an answer.
Inputs: no named parameters.
ro_stateA
Read the live game state: connection, map, character stats and position, and nearby NPCs/monsters.
Inputs: no named parameters.
ro_stopB
Shut down the OpenKore session.
Inputs: no named parameters.
ro_talk_npcB
Talk to an NPC and return its dialog text plus any menu options. Identify the NPC either by its binID from ro_state, or by map coordinates.
Inputs: x, y, binID, timeoutMs.
ro_walkC
Walk to coordinates on the current map and wait until the character arrives.
Inputs: x (required), y (required), timeoutMs, tolerance.
ro_warpC
Move to another map by name (uses OpenKore's route planner; the path must exist).
Inputs: map (required), x, y, timeoutMs.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 17 tools
Most tools have clearly distinct purposes (start/stop/state/console, character creation/selection, movement, dialog steps, attack). Minor overlap exists between movement tools (ro_walk vs ro_warp vs ro_gm_warp) and dialog tools (ro_talk_npc, ro_menu_select, ro_dialog_next, ro_close_dialog), but the descriptions clarify when each is appropriate.
All tools follow the `ro_` prefix with a consistent snake_case verb_noun pattern (e.g., ro_create_char, ro_menu_select, ro_gm_warp). Variations like ro_close_dialog or ro_dialog_next still adhere to the same convention, making the naming predictable and easy to infer.
At 17 tools, the server is on the higher end but appropriate for a game automation bot that needs to cover startup, character management, movement, NPC interaction, and combat. The count feels justified given the domain, with only slight overlap (e.g., two warp tools) that could be consolidated.
The toolset covers the core lifecycle (start/stop/state), character setup, movement, NPC dialogs, and basic combat, with an escape hatch (ro_command) for anything else. Minor gaps exist (e.g., inventory or skill handling) but these are outside the apparent scope and can be addressed via the command tool.
Maintenance
Related MCP Connectors
Launch and verify high-fidelity mobile simulations from an AI agent.
Plan, run and inspect AI-agent drills with synthetic users, hosted tools and cloud worlds.
Drive real devices from your AI Coding tool. Embed a client SDK (Unity, Godot, Flutter, iOS/macOS, Android, React Native, Web) in your app, then capture screenshots, traverse the UI tree, inject taps and key events, and run automated test tasks on the physical device over a secure relay.
Trading MCP server for AI agents, with live market data, account reads and controlled execution.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to interact with a running Roblox game client to execute Lua code, inspect scripts, spy on remotes, and more.129 npm216MIT
- AlicenseAqualityBmaintenanceEnables AI agents to execute Lua code, inspect scripts, spy on remotes, and interact with a running Roblox game client through an MCP interface.1822129 npm1MIT
- AlicenseCqualityCmaintenanceEnables MCP-capable AI agents to play The Mana World by logging in, moving around, fighting, trading, and talking to NPCs in real time.46MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to interact with a running Roblox game client, including executing Lua code, inspecting scripts, searching instances, intercepting remote events via Sigma Spy, and controlling the GUI.129 npm1MIT