Skip to main content

porymap-mcp

An MCP server that lets Claude, or any MCP client, paint, render and critique Porymap-compatible maps for Pokémon Gen 3 decompilation projects.

CI PyPI Python License: MIT

Iteration 1: first draft Iteration 2: after one critique pass
Iteration 1 render Iteration 2 render
Score 7 / 36 Score 21 / 36

Both images were rendered by the server itself. The agent paints the map, renders it to PNG, gets the image back in the tool response, critiques it against a 12-criterion Gen 3 design rubric, fixes the top issues and renders again. Runnable walkthrough: examples/04_render_loop/.


What it does

  • Reads a pokeemerald-family project: maps, layouts, tilesets, metatiles, events, prefabs.
  • Writes the same files Porymap writes: metatiles, rectangles, flood fills, borders, prefabs, warps, NPCs, signs (with a script stub), triggers, new maps and map-group registration. Writes are atomic.
  • Renders maps, regions and single metatiles to PNG and returns them as MCP image content blocks. Output is pixel-identical to Porymap's own export on a 5-map reference corpus (Littleroot Town, Route 101, Granite Cave 1F, Battle Frontier Outside East, plus a synthetic edge case).

Porymap does not need to be running. Open the project in Porymap whenever you like: your manual workflow is untouched.

It does not edit tilesets (creating new metatiles stays in Porymap), and it does not generate graphics, music or story content.

Compatibility

Built and tested against rh-hideout/pokeemerald-expansion, the base most active hacks use today (ADR-0002). Vanilla pret/pokeemerald uses the same file formats and loads the same way. Bit masks and paths are read from your porymap.project.cfg, so nothing is hard-coded per fork. pokefirered and pokeruby projects are recognised but not covered by the test corpus yet.

Install

pip install "porymap-mcp[render]"

Or run it with no install step via uv:

uvx --from "porymap-mcp[render]" porymap-mcp

The render extra pulls in Pillow and numpy for the three render tools. Without it (pip install porymap-mcp), the 21 read/write tools work on their own.

Requires Python 3.11+.

Register it with your MCP client

Claude Code:

claude mcp add porymap -- uvx --from "porymap-mcp[render]" porymap-mcp

Claude Desktop (claude_desktop_config.json) or any client that takes a JSON server list:

{
  "mcpServers": {
    "porymap": {
      "command": "uvx",
      "args": ["--from", "porymap-mcp[render]", "porymap-mcp"]
    }
  }
}

If you installed with pip, use "command": "porymap-mcp" (or "python" with "args": ["-m", "porymap_mcp"]).

No environment variables are needed: the project path is passed on every tool call, so one server can work on several projects.

First map in 5 minutes

With the server registered, ask your agent:

Open my pokeemerald project at ~/code/pokeemerald-expansion. Create a 20×20 map called LakesideTown in the gMapGroup_TownsAndRoutes group, using gTileset_General + gTileset_Petalburg. Stamp a small house at (3, 4), put a sign next to its door that says "Welcome to Lakeside!", then render the map and critique it.

The agent will typically:

  1. Call get_project_info to confirm the project loads and read its config.
  2. Call list_tilesets to check that both tilesets exist.
  3. Call create_map, which writes data/maps/LakesideTown/map.json, data/layouts/LakesideTown/map.bin and border.bin, and registers the map in data/layouts/layouts.json and data/maps/map_groups.json.
  4. Call paint_prefab with house_small at (3, 4): a 3×3 footprint with its door at (4, 6).
  5. Call add_sign at (3, 7). This appends the event to map.json and generates a script stub (poryscript, or .inc if your project has use_poryscript=0).
  6. Call render_map and look at the PNG it gets back.

Every write tool returns the list of files it modified. Open the project in Porymap, or rebuild your ROM: the map is there.

Tileset labels. Littleroot Town, Oldale Town and Petalburg City all use gTileset_General + gTileset_Petalburg, in both vanilla pokeemerald and pokeemerald-expansion. There is no gTileset_LittlerootTown. If your fork renames or adds tilesets, ask the agent to call list_tilesets first and pick from what it returns.

Tools

24 tools. Each tool's docstring is what your agent reads, and the full contracts are in the ADRs listed below. Every tool takes project_path as its first argument.

Tool Group What it does
get_project_info Discovery Project snapshot: base game, map, layout and tileset counts.
list_maps Discovery Every map registered in map_groups.json.
get_map_info Discovery Full metadata for one map: layout, tilesets, size, header.
list_tilesets Discovery Every primary and secondary tileset found on disk.
list_metatiles Discovery The metatiles of one tileset, with attributes.
list_prefabs Discovery Named multi-metatile stamps available to paint_prefab.
list_events Discovery Every event on a map, grouped by class.
paint_metatile Mutation Set one tile (metatile, collision, elevation). Idempotent.
paint_rectangle Mutation Fill an inclusive rectangle with one metatile.
flood_fill Mutation Replace a 4-connected region of identical metatiles.
set_border Mutation Replace the map's repeating border tiles.
paint_prefab Mutation Stamp a named prefab, top-left anchored.
create_map Mutation Create a new map: writes its files and registers it everywhere.
resize_map Mutation Resize a layout from its top-left corner, keeping the overlapping content.
register_map Project Add an existing map directory to map_groups.json.
unregister_map Project Remove a map from map_groups.json (files are kept).
add_warp Events Add a warp to another map.
add_object_event Events Add an NPC, item ball or other object event.
add_sign Events Add a sign with inline text and generate its script stub.
add_trigger Events Add a coordinate-based script trigger.
remove_event Events Remove any event by its id.
render_map Render Render a full map to PNG, optionally with its border frame.
render_map_region Render Render a rectangular slice of a large map.
render_metatile Render Preview a single metatile from a tileset.

The three render tools accept overlays (collision, elevation, grid, events) and a scale factor. All seven map-mutation tools and all five event tools accept return_render=True, which adds the post-edit render to the same response and saves a round trip.

Design records

Every decision that is hard to reverse is written up as an ADR in docs/decisions/:

  • ADR-0001: FastMCP as the MCP framework
  • ADR-0002: pokeemerald-expansion as the primary target
  • ADR-0003: a single Project entry point, config-driven formats
  • ADR-0004: where tileset metadata comes from
  • ADR-0005, ADR-0006, ADR-0007: discovery, mutation and event tool contracts
  • ADR-0008: prefab library and paint_prefab
  • ADR-0009: why live Porymap hot-reload was dropped
  • ADR-0010: renderer design, including the four corrections found while validating against Porymap

The project's vision document is MCP_PORYMAP.md (in French).

Prefabs

paint_prefab ships with three stamps: single_tree, flower_patch and house_small. Their metatile IDs follow vanilla gTileset_General conventions. If your fork uses custom tilesets, register your own prefabs in porymap_mcp.prefabs.LIBRARY (a plain dict). See ADR-0008.

Develop

git clone https://github.com/hugomrts/porymap-mcp
cd porymap-mcp
uv sync --all-extras        # or: pip install -e ".[dev]"
pre-commit install
pytest

CI blocks on ruff check, ruff format --check, mypy --strict and the full test suite (Linux and macOS, Python 3.11 to 3.13). CLAUDE.md describes the conventions used to develop this repo with Claude Code, including the sub-agents in .claude/agents/, which anyone can reuse.

Acknowledgements

  • Porymap by Marcus Huderle: the editor whose files this server writes.
  • pret: the decompilation projects that make all of this possible.
  • rh-hideout: the pokeemerald-expansion fork.
  • FastMCP: the Python MCP framework used here.

License

MIT

Metadata

Release files for porymap-mcp 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for porymap-mcp 1.0.0
File Size Uploaded Provenance Actions
porymap_mcp-1.0.0.tar.gz 689.7 kB With provenance Details for porymap_mcp-1.0.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for porymap-mcp 1.0.0
File Interpreter ABI Platform Actions
porymap_mcp-1.0.0-py3-none-any.whl Python 3 none any Details for porymap_mcp-1.0.0-py3-none-any.whl

Total release size: 780.7 kB

Release files / porymap_mcp-1.0.0.tar.gz

Download URL porymap_mcp-1.0.0.tar.gz
Size 689.7 kB
Tags Source
SHA-256 checksum
How to use checksums
93fbc60d8cb589caf4afd51f49b566dce3c474bc7957d19e67ba92d3a1de5c9b
BLAKE2b-256 checksum
How to use checksums
02f34b7e06f224324737bbfe408e46af20bb6fc178ecd3c80f805fb22fa88916
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Release files / porymap_mcp-1.0.0-py3-none-any.whl

Download URL porymap_mcp-1.0.0-py3-none-any.whl
Size 91.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3d5b55ee2ab7ea1e6915cfa2b3fc41fd20bf978e1376563a22b985fd250aadf2
BLAKE2b-256 checksum
How to use checksums
1080afdd894d5bbd779805eb9bb243ca776bb5e2e69df699bd4b146cb2c3d0ad
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

Security for porymap-mcp 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for porymap_mcp-1.0.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page