pyularn-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., "@pyularn-mcpstart a new game as a wizard and move east a few steps"
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.
py-ularn
A Python port of Ularn 1.6.3a, the classic roguelike by Julian Olds (based on Larn by Noah Morgan), plus an MCP server so AI agents can play it.
Ported from the C source at R0x7/ularn-1.6.3a. The port follows the original UNIX terminal build function by function. Formulas, messages, monsters, items, shops and level layouts match the C code, including its known quirks. See PORTING.md for the conventions used.
Pure Python 3.10+, standard library only (plus windows-curses on Windows
for the terminal front end).
Play
pip install .
pyularn # or: python -m pyularnIt needs a terminal of at least 80x24. The original command-line options
are kept (pyularn -h). Scores and save games are stored in ~/.pyularn;
set PYULARN_HOME to use another folder.
Press ? in the game for help. Move with hjklyubn (or the arrow keys).
Capital letters run. Your daughter is dying of dianthroritis: find the potion
that cures her and bring it home before time runs out.
With graphics
pyularn --web # opens http://localhost:8765/ in your browserThis plays the same game in a web page, drawn with the original 32x32 sprite tiles from the X11/Windows versions of Ularn. A terminal cannot show sprites. The keyboard works as in the terminal. Arrow keys and Home/PgUp/End/PgDn move, and Ctrl+letter works too. Tiles / Text switches between the sprite map and the classic character screen. Zoom sets the tile size: when the map does not fit, it scrolls with the player, as in the X11 version.
Options: --web PORT (0 picks a free port), --web-host 0.0.0.0 to play
from another machine, and --no-browser. The usual Ularn options (-d,
-n, ...) still work. Saves and scores are shared with the terminal
version. The program ends when the game does, or press Ctrl+C in the
terminal.
Related MCP server: GrokHack MCP Server
MCP server
pyularn-mcp (or python -m pyularn.mcp_server) runs a Model Context
Protocol server over stdio. It has no dependencies: it implements the
JSON-RPC protocol directly.
Claude Code:
claude mcp add pyularn -- python -m pyularn.mcp_serverClaude Desktop / other clients (mcpServers config):
{
"mcpServers": {
"pyularn": { "command": "python", "args": ["-m", "pyularn.mcp_server"] }
}
}Tools
Tool | What it does |
| Start a game. Options: |
| Send keystrokes, e.g. |
| Step or run in a compass direction ( |
| The current 80x24 screen. |
| JSON: HP, stats, gold, AC/WC, dungeon level, position, turns, inventory, active effects, known spells. |
| Command list, map legend and goal. |
| Stop the current game. |
Watching an agent play live
Start the server with --watch (or set PYULARN_WATCH=8765) and open
http://localhost:8765/ in a browser:
claude mcp add pyularn -- python -m pyularn.mcp_server --watch 8765The page redraws the game, with the same sprite tiles as pyularn --web
(or as text), each time the agent's input is handled. It also shows HP, spells, stats, inventory, active effects, known
spells and the agent's recent keys. Playback can be Live, Smooth
(10 frames/s) or Slow (4 frames/s), and you can pause it. The page is
view-only, and new_game includes the address in its result. Use
--watch 0 to pick a free port and --watch-host 0.0.0.0 to allow
viewers from other machines. If the server runs in WSL2, a Windows browser
can open localhost too.
To see it without an AI client, python examples/random_agent.py starts the
server with the page on and wanders the character around at random.
How it works
The unmodified game engine runs in a background thread on an in-memory
terminal (pyularn.term_virtual.VirtualTerminal). Each tool call feeds keys,
then waits until the game is blocked on input again before it returns.
Because the engine keeps its state in module globals, as the C original does,
one server process runs one game at a time. new_game resets the engine
(pyularn.engine.reset()).
Saving with S writes the save file. The next game started with the same
user name resumes it, as in the original.
Embedding
import threading
from pyularn import engine, header, term_virtual, ularn
engine.reset()
header.set_seed(1234) # optional: reproducible game
term = term_virtual.VirtualTerminal()
threading.Thread(target=ularn.run_game, args=(term,), daemon=True).start()
term.wait_for_input(5)
term.feed("e\r") # pick Rogue, skip the intro
term.wait_for_input(5)
print(term.text(ascii_walls=True))Tests
python -m unittest discover -s tests -t .
python tests/fuzz.py 20 2000 # random-key fuzzing in town
python tests/fuzz.py deep 20 300 # fuzz every dungeon and volcano levelLayout
Module | From C | Contents |
| ularn.c, ularn_game.c, ularn_ask.c | main loop, options, prompts |
| ularn_win.h, ularn_wintty.c | screen layout, input, with pluggable |
| dungeon.c, dungeon_obj.c | level generation, map objects |
| monster.c, sphere.c | monsters, combat, spheres of annihilation |
| player.c, object.c, itm.c | the player, inventory, items |
| potion.c, scroll.c, spell.c | magic |
| action.c, show.c | player commands, inventory display |
| store.c, scores.c, savegame.c, saveutils.c | shops, the bank and college, scoreboard, save/restore |
| help.c, fortune.c, diag.c | help pages, fortunes, diagnostics |
| ularn_winx11.c | sprite tile numbers for the map (the X11 |
| (new) | MCP server, the web page (watching and |
The sprite sheet pyularn/data/ularn_gfx.png is made from the original
data/ularn_gfx.xpm by tools/make_tiles.py. That script also bakes in
the transparency masks for the cursor and sparkle tiles, which the X11 code
built at start-up. data/gfx_guide.txt lists what each tile is.
License
GPL-2.0, like Ularn itself; see LICENSE and COPYRIGHT. Original game © Julian Olds and the Larn/Ularn authors.
Available Tools
7 toolsend_gameA
Stop the game in progress without saving.
Inputs: no named parameters.
get_screenA
Return the current 80x24 game screen without sending input.
Inputs: no named parameters.
get_stateA
Return structured player state as JSON: stats, HP, gold, dungeon level, position, inventory, active effects and known spells.
Inputs: no named parameters.
key_referenceA
Return the list of Ularn commands, map symbols and the goal of the game.
Inputs: no named parameters.
moveB
Move the player one or more steps in a compass direction (or run until something interesting).
Inputs: direction (required), run, count, include_state.
new_gameA
Start a new game of Ularn (ends any game in progress). Returns the screen and player state.
Inputs: seed, skip_intro, player_name, character_class.
send_keysA
Send keystrokes to the game and return the resulting screen. Plain characters are sent literally; use , , , , ///, for special keys. Call key_reference for the command list.
Inputs: keys (required), include_state.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 7 tools
Most tools have clearly distinct purposes: get_screen vs. get_state vs. key_reference vs. new_game/end_game are unambiguous. The main overlap is move versus send_keys, since movement could also be done by sending direction keys; the descriptions clarify the intended split, but an agent may still hesitate between them.
Most names follow a verb_noun pattern (get_screen, get_state, send_keys, new_game, end_game), which is predictable and readable. The bare verb 'move' and the noun-phrase 'key_reference' are minor deviations, not enough to cause confusion.
Seven tools is well-scoped for an interactive game server: screen/state inspection, input, movement, lifecycle control, and a reference tool. Each tool earns its place without redundant surface area.
The surface covers the core game lifecycle: start, inspect screen/state, send input, move, get help, and end. send_keys acts as a general escape hatch for unmodeled actions, though there is no explicit save/resume or wait/rest operation.
Maintenance
Related MCP Connectors
Make games with AI: one MCP server that connects your agent to Unity, Unreal and Godot editors.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal E…
The game engine built for AI. Any agent makes a multiplayer game and publishes it.
Create, test and play AI-native games through server-authoritative contracts.
Related MCP Servers
- FlicenseNot gradedqualityAmaintenanceEnables AI agents to play Slay the Spire 2 by exposing game state and actions through an MCP server, supporting combat, rewards, and run management.357-
- 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
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to play local Windows games through low-level keyboard/mouse input, screen capture, OCR, and per-game profiles for semantic actions.-
- AlicenseNot gradedqualityCmaintenanceEnables an AI agent to inspect and control a real Minecraft Java client through the Model Context Protocol, exposing world data, screenshots, inventories, chat, and normal player actions under the player's permissions.1MIT