tmw-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., "@tmw-mcp Log in and tell me what's happening around my character."
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.
tmw-mcp
A Python client for The Mana World (a tmwAthena-based MMORPG) exposed as an MCP server. Point any MCP-capable AI agent at it and the agent can log in, walk around, fight, trade, and talk to NPCs.
The bot also runs as an interactive CLI for humans, and ships with an optional browser dashboard.
Please follow the server rules
The Mana World's game rules explicitly forbid AFK botting. Treat this MCP server as an attended assistant: stay at the keyboard while your character is logged in, prompt the bot to respond to chat and GMs in a timely way, and disconnect before stepping away. Running it unattended may get your account banned.
Related MCP server: GrokHack MCP Server
Install
pip install tmw-mcpThe only third-party dependency is mcp. Game data (maps, items, monsters, sprites) is fetched on first login from the server's update host and cached under ~/.cache/tmw-mcp/; nothing to clone or unpack.
Register an account
tmw-mcp-register --user MyAccount --char-name MyCharacterThis writes a credentials.json (chmod 600, owner read/write only) in the current directory. Treat it like any other secret. tmw-mcp looks for it in its own current working directory by default, so the simplest setup is to run the host from this same directory; otherwise point at the file explicitly with TMW_CREDENTIALS_FILE (covered below).
Using an existing account
If you already have a TMW account and character, you can skip tmw-mcp-register and write credentials.json by hand. The full shape is:
{
"server": "server.themanaworld.org",
"port": 6901,
"username": "MyAccount",
"password": "hunter2",
"char_name": "MyCharacter"
}Only username and password are required; the rest fall back to the defaults shown above. char_name picks which character on the account to log in as; omit it to use the account's first character. Remember to chmod 600 credentials.json so it's owner-only, and keep it out of git.
Use it from an MCP client
Recommended: Claude Code
Claude Code is the only MCP host today that wakes the agent on notifications/claude/channel messages, which is how the bot surfaces chat, NPC dialog, combat damage, death, map changes, and the ferry-bell effect in real time. Without that, the bot only acts when you prompt it, which is fine for short tasks but turns the game into "ask the bot what's happening" instead of "the bot tells you." If you have a choice, use this one.
claude mcp add tmw -- tmw-mcp # writes .mcp.json in the current project
# (or add -s user for ~/.claude.json)Equivalent in JSON, drop into .mcp.json at your project root by hand:
{
"mcpServers": {
"tmw": {
"command": "tmw-mcp"
}
}
}Verify with claude mcp list; remove with claude mcp remove tmw.
The reactive-wakeup channel is gated behind a Claude Code dev flag. Launch claude with --dangerously-load-development-channels server:tmw so the host actually subscribes to notifications/claude/channel from this server; without the flag every other tool still works, you just don't get the wake-up on in-game events.
Other hosts (no wake-ups)
The tool surface is identical across hosts; what you lose without Claude Code is just the wake-up channel, every tmw tool itself works the same. Pick whichever fits your workflow.
Claude Desktop, Cursor, Cline. Same mcpServers shape as Claude Code, just in a different config file:
{ "mcpServers": { "tmw": { "command": "tmw-mcp" } } }Host | Config path |
Claude Desktop |
|
Cursor |
|
Cline |
|
VS Code Copilot extension. Different schema (servers not mcpServers, explicit type: "stdio"). Drop into .vscode/mcp.json at the workspace root (or use "MCP: Open User Configuration"):
{ "servers": { "tmw": { "type": "stdio", "command": "tmw-mcp" } } }Switch Copilot Chat from "Ask" to "Agent" mode; MCP tools only show up there.
Copilot CLI and Codex CLI. Same mcp add shape as Claude Code's:
copilot mcp add tmw -- tmw-mcp # writes ~/.copilot/mcp-config.json
codex mcp add tmw -- tmw-mcp # writes a block into ~/.codex/config.tomlVerify with <host> mcp list; remove with <host> mcp remove tmw. If tmw-mcp isn't on PATH (e.g. it's only in a specific venv), use the absolute path after the --.
When credentials.json isn't in the host's cwd
Claude Code, Cursor, Cline, and VS Code Copilot launch tmw-mcp with the workspace as cwd, so a credentials.json at the workspace root is found automatically. The CLI hosts (Claude Code CLI, Copilot CLI, Codex CLI) inherit your terminal's cwd. If neither lines up with where credentials.json lives (Claude Desktop on macOS, for instance), pass an absolute path via TMW_CREDENTIALS_FILE:
{
"mcpServers": {
"tmw": {
"command": "tmw-mcp",
"env": {
"TMW_CREDENTIALS_FILE": "/home/you/credentials.json"
}
}
}
}For the CLI hosts: claude mcp add -e TMW_CREDENTIALS_FILE=/home/you/credentials.json tmw -- tmw-mcp (and --env instead of -e for copilot / codex).
Without a credentials file
If you'd rather not have a credentials.json on disk at all, pass TMW_USERNAME, TMW_PASSWORD, and TMW_CHAR_NAME in the host's env block directly. Mind that those secrets then live inside each host's config file, which is usually plaintext and sometimes inside a workspace dir that's easy to commit by accident.
Self-restart via restart
tmw-mcp is fronted by a thin stdio shim that owns the actual game-client daemon as a subprocess. Calling the restart tool sends a clean quit to the map server, waits for the server's account-online entry to clear, and respawns the daemon, all without dropping the MCP session. The standard MCP tools/listChanged notification fires after the restart so any host re-syncs. It pairs especially well with Claude Code, where the conversation context survives the restart and you get a tight "fix bug, restart, verify" loop in one session.
Configuration
Variable | Meaning |
| Account name |
| Account password |
| Character name. If omitted, the account's first character is used. |
| Login server. Accepts |
| Override port only. Default |
| World name (blank for default). |
| Bind the browser dashboard on |
| Skip the update-host download and read game data from this directory instead. Dev-only convenience for iterating on local TMX / item XML edits. |
| Absolute path to a |
Precedence: explicit CLI flags > env vars > credentials.json > built-in defaults. TMW_CREDENTIALS_FILE, if set, picks which credentials.json gets read; per-field env vars (TMW_USERNAME etc.) still override whatever's in the file.
Browser dashboard
Set TMW_DASHBOARD_PORT=8765 (or pass --dashboard-port 8765 to any CLI entry) and open http://127.0.0.1:8765/. The dashboard shows a live tile map (collision grid, beings, floor items, walk path, hunt zone, aggro discs), HP/SP/EXP bars, hunt status, NPC dialog state, inventory, and a chat tail. Localhost-only, no auth, no extra dependencies (stdlib HTTP + SSE + vanilla JS).
Where things live
Kind | Path |
Downloaded game data |
|
Logs and session state |
|
Credentials file |
|
Console scripts
pip install creates four entry points:
Command | What it runs |
| Self-restartable MCP stdio entry point. This is what MCP clients should call. |
| The daemon itself, useful for standalone testing. |
| Interactive REPL for humans. |
| Create an account on the server. |
The same modules also work via python -m tmw_mcp.mcp_shim etc, so you don't need to install to try them.
Running from source
git clone https://github.com/bjorn/tmw-mcp.git
cd tmw-mcp
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/python -m unittest discover # from repo root; 66 testsGame data (maps, items, monsters) is fetched from the server's update host on first login and cached under ~/.cache/tmw-mcp/, so a checkout is all you need to run the tests and the CLI. If you want to iterate on local TMX or item XML changes, point TMW_CLIENT_DATA at a directory that mirrors the same layout and the downloader is bypassed.
How it works
The TMW protocol is binary, little-endian, over TCP. Three servers in sequence: login (default 6901), character (6122), map (5122). After a successful login the server emits a SMSG_UPDATE_HOST (0x0063) packet pointing at a small resources.xml manifest of ZIP files; the client downloads, hash-verifies (adler32), and presents them as a read-only overlay used for map collision, item names, and monster names.
The active code path is tmw_mcp.mcp_shim (the console-script tmw-mcp), a thin stdio proxy that owns a daemon subprocess running tmw_mcp.mcp_server. The shim survives daemon restarts; the daemon owns the actual game connection. Inside the daemon, a single GameClient (tmw_mcp.game) walks the login handshake and dispatches packets, while a thin MCP layer exposes every action as an MCP tool under the tmw namespace.
Game data layout, packet definitions, and the NPC dialog state machine are documented in CLAUDE.md.
License
MIT. See LICENSE.
The Mana World itself is GPL'd content maintained by its community; this client is independent original work that speaks the same wire protocol.
Available Tools
46 toolsattackB
Attack a being by ID (starts continuous attack).
Inputs: target_id (required).
attack_rangeA
Override weapon attack range (normally auto-detected from server). 1=melee, 2=scythe/polearm.
Inputs: range.
buyC
Buy items from shop. Must open buy list first with tmw_shop_buy.
Inputs: name_id (required), count.
close_storageA
Send CMSG_CLOSE_STORAGE (0x00f7) to the server. Required after clicking a storage NPC; without it, the server leaves sd->state.storage_open set and silently drops walks and item-use packets.
Inputs: no named parameters.
dropC
Drop an item on the ground. Amount 0 = drop entire stack.
Inputs: index (required), amount.
emoteC
Send an emote.
Inputs: emote_id (required).
equipC
Equip an item by inventory index.
Inputs: index (required).
faceB
Change facing direction (0=south, 2=west, 4=north, 6=east).
Inputs: direction (required).
ferry_exitA
Auto-exit the ferry after N bell rings. E.g. bells=1 exits at next stop, bells=2 skips one stop then exits.
Inputs: bells.
followB
Follow a player by name or ID. Pass empty string to stop.
Inputs: target (required).
huntA
Continuously hunt monster(s) by name. Comma-separated for multiple types. Pass empty string to stop.
Inputs: monster_name (required).
inventoryB
List inventory items.
Inputs: no named parameters.
mapB
Show ASCII minimap around current position.
Inputs: radius.
npcC
Click on an NPC to start dialog.
Inputs: npc_id (required).
npc_chooseC
Choose an NPC menu option (1-based index).
Inputs: choice (required).
npc_closeA
Close NPC dialog. If npc_id is 0 (default), closes the NPC tracked by the client; pass an explicit id to close a specific NPC when the client state is stale (e.g., after clicking a storage NPC that never sent a dialog packet).
Inputs: npc_id.
npc_input_intC
Submit integer input to an NPC dialog.
Inputs: value (required).
npc_input_strC
Submit text input to an NPC dialog.
Inputs: text (required).
npc_nextA
Continue NPC dialog (click Next).
Inputs: no named parameters.
onlineA
Get list of all players currently online.
Inputs: no named parameters.
party_chatB
Send a message to party members.
Inputs: message (required).
party_leaveB
Leave the current party.
Inputs: no named parameters.
party_replyC
Accept or reject a party invitation.
Inputs: account_id (required), accept.
pickupC
Pick up a floor item by ID.
Inputs: item_id (required).
respawnB
Respawn after death.
Inputs: no named parameters.
restartA
Hard-restart the TMW bot daemon. Sends a clean quit to the map server so re-login succeeds immediately. Useful when the bot is wedged or after a code change.
Inputs: no named parameters.
sayC
Send a public chat message in-game.
Inputs: message (required).
sellB
Sell items to shop. Must open sell list first with tmw_shop_sell.
Inputs: index (required), count.
shop_buyB
Open a shop NPC's buy list. Use after clicking a shop NPC (0x00c4 event). The buy list will appear in game state.
Inputs: npc_id (required).
shop_sellB
Open a shop NPC's sell list. Use after clicking a shop NPC (0x00c4 event).
Inputs: npc_id (required).
sitC
Sit down.
Inputs: no named parameters.
standC
Stand up.
Inputs: no named parameters.
statB
Increase a stat: str, agi, vit, int, dex, or luk.
Inputs: stat_name (required).
stateA
Get current game state: character info, position, HP/SP, nearby beings, floor items.
Inputs: no named parameters.
stop_attackA
Stop auto-attack and hunting.
Inputs: no named parameters.
trade_acceptB
Accept an incoming trade request.
Inputs: no named parameters.
trade_add_itemC
Add an inventory item to the trade offer (amount=0 means entire stack).
Inputs: index (required), amount.
trade_add_zenyC
Add zeny (GP) to the trade offer.
Inputs: amount (required).
trade_cancelB
Cancel the current trade.
Inputs: no named parameters.
trade_commitA
Commit the trade after both sides have locked.
Inputs: no named parameters.
trade_lockB
Lock your side of the trade (indicate readiness to commit).
Inputs: no named parameters.
trade_rejectB
Reject an incoming trade request.
Inputs: no named parameters.
trade_requestC
Request a player-to-player trade with the given player name.
Inputs: target (required).
useC
Use an item by inventory index.
Inputs: index (required).
walkB
Walk to coordinates (x, y) using A* pathfinding. Sends a channel notification on arrival or failure.
Inputs: x (required), y (required).
whisperC
Send a private message to a player.
Inputs: target (required), message (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 46 tools
Most tools target clearly distinct game actions, with descriptions that clarify sequencing and context. Some potential confusion exists between pairs like npc_close/close_storage, shop_buy/buy, and attack/hunt, but these are mitigated by explicit instructions in the descriptions.
All tools use snake_case, but the naming pattern is mixed: many are single verbs (walk, attack), several are nouns (state, inventory), and others are verb_noun (trade_commit, npc_next). This inconsistency reduces predictability, though names remain readable.
46 tools is well above the typical 3-15 range and exceeds the 25+ threshold for 'too many'. While the domain is complex, many tools could be consolidated or grouped (e.g., trade operations, NPC dialog steps) to reduce surface area.
The surface covers core gameplay: state, movement, combat, chat, party, trade, shop, inventory, NPC dialog, and stats. Minor gaps include no party_invite tool and no explicit skill/ability management, but the core lifecycle is well covered.
Maintenance
Related MCP Connectors
Make games with AI: one MCP server that connects your agent to Unity, Unreal and Godot editors.
Trading MCP server for AI agents, with live market data, account reads and controlled execution.
One connector for 15,000+ MCP servers plus your team's private MCPs, from any AI client.
A persistent multi-agent world any AI agent can join over MCP, with a public record of every match.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI agents to play Pokémon games by providing a functional interface for game interaction. It allows for seamless integration with AI clients to execute gameplay tasks and manage game states.3-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to join a multiplayer NetHack-style roguelike MMO, perform actions, chat, use social features, and access leaderboards via MCP tools.MIT
- AlicenseAqualityBmaintenanceMCP server for Project CPU, a blockchain game on EVM. It lets an AI agent play on your behalf: read the world map, reveal cells, build and mine, craft, move resources, trade at marketplaces, and cash out to on-chain $CPU.7133 npm1MIT
- FlicenseNot gradedqualityDmaintenanceEnables MCP-capable agents to connect to a persistent shared-world service, discover people and worlds, and participate via natural-language actions.9 npm-