Loenn Mcp — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Loenn Mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Celeste map editor for AI agents — a Model Context Protocol (MCP) server that lets GitHub Copilot, Claude, and other MCP clients read, edit, analyze, procedurally generate, and preview Celeste .bin map files without ever opening Lönn.
Built for use with Everest mods. Works with maps created by Lönn or Ahorn.
Map Reading
| Tool | Description |
|---|---|
list_maps | List all .bin files in the project |
read_map_overview | Summary of rooms, entities, triggers, and stylegrounds |
read_room | Full detail for a single room: tiles, entities, triggers, decals |
get_room_tiles | Raw tile grid (foreground or background) for a room |
Map Reading Extensions (NEW in v5)
| Tool | Description |
|---|---|
read_map_metadata | Quick metadata (package, room count, world bounds) without full read |
search_entities | Search entities across rooms by type, position, and room |
search_triggers | Search triggers across rooms by type |
compare_rooms | Side-by-side comparison of two rooms (size, difficulty, entities) |
Map Editing
| Tool | Description |
|---|---|
add_entity | Place an entity in a room (auto-assigns ID) |
remove_entity | Delete an entity by ID |
add_trigger | Place a trigger (rectangular region) in a room, with optional path nodes |
remove_trigger | Delete a trigger by ID |
set_room_tiles | Replace the tile grid for a room |
add_room | Create a new room with custom position/size |
remove_room | Delete a room from the map |
create_map | Create a new empty .bin map file |
Map Editing Extensions (NEW in v5)
| Tool | Description |
|---|---|
update_entity | Update properties of an existing entity by ID |
move_entity | Move an entity to a new position |
update_room | Update room-level properties (music, dark, wind, etc.) |
clone_room | Clone a room to a new name and position |
batch_add_entities | Add multiple entities in one call (JSON array) |
resize_room | Change room dimensions |
Decals (NEW in v5)
| Tool | Description |
|---|---|
list_decals | List all decals in a room (FG or BG) |
add_decal | Add a decal with texture, position, and scale |
remove_decal | Remove a decal by index |
Stylegrounds
| Tool | Description |
|---|---|
list_stylegrounds | List foreground + background effects (with indices) |
add_styleground | Add an effect (parallax, custom Lua effect, apply group, etc.) to FG or BG |
remove_styleground | Remove an effect by index |
update_styleground | Merge property changes into an existing effect |
Entity / Trigger Catalog
| Tool | Description |
|---|---|
list_entity_definitions | Browse Lönn entity .lua files in the project |
get_entity_definition | Read the full source of a single entity definition |
list_trigger_definitions | Browse Lönn trigger .lua files |
list_effect_definitions | Browse Lönn effect .lua files |
Catalog Extensions (NEW in v5)
| Tool | Description |
|---|---|
get_trigger_definition | Read the source of a trigger .lua file by name |
get_effect_definition | Read the source of an effect .lua file by name |
Analysis
| Tool | Description |
|---|---|
analyze_map | Statistics: entity counts, type breakdown, world bounds |
visualize_map_layout | ASCII mini-map of room positions |
preview_map_section | Detailed ASCII preview of a map region |
Advanced Analysis — gdep-inspired (NEW in v5)
| Tool | Description |
|---|---|
analyze_entity_usage | Entity usage stats across the entire map |
analyze_difficulty | Estimate room/map difficulty from hazards, nav aids, tile coverage |
find_entity_references | Find all occurrences of an entity type across rooms |
detect_map_patterns | Detect design archetypes (linear, hub, collectible-rich, etc.) |
analyze_room_connectivity | Adjacency graph: isolated rooms, dead ends, hubs |
Suggestions — gdep-inspired (NEW in v5)
| Tool | Description |
|---|---|
suggest_improvements | Actionable suggestions for a room (spawns, floors, balance) |
compare_maps | Structural diff between two map files |
Wiki / Cache — gdep-inspired (NEW in v5)
| Tool | Description |
|---|---|
wiki_save | Persist analysis results locally for instant repeated queries |
wiki_search | Search cached wiki entries by key, content, or tags |
wiki_list | List all wiki entries |
wiki_get | Retrieve a specific wiki entry |
Mod Project (NEW in v5)
| Tool | Description |
|---|---|
get_mod_info | Project info: everest.yaml, map count, PCG library, wiki |
validate_map | Whole-map playability validation with optional auto-fix |
Import / Export (NEW in v5)
| Tool | Description |
|---|---|
export_room_json | Export a room as JSON for external editing or sharing |
import_room_json | Import a room from JSON into a map |
Diff & Fix — gdep-inspired (NEW in v5)
| Tool | Description |
|---|---|
summarize_map_diff | Snapshot-based structural diffing for tracking map evolution |
batch_validate_and_fix | Batch playability checks with optional auto-fix |
Rendering
| Tool | Description |
|---|---|
render_map_html | Interactive HTML preview (zoom, pan, room details, minimap, search) |
Procedural Generation
| Tool | Description |
|---|---|
build_pattern_library | Scan local .bin maps and extract room patterns into a reusable JSON library |
generate_room_from_pattern | Generate a new room using patterns + a strategy + seed |
validate_room | Check a room for playability issues (spawn, floor, bounds) |
ingest_external_map | Download maps from external URLs (GameBanana etc.) and extract patterns |
Image-to-Map & Terrain Generation (v4)
| Tool | Description |
|---|---|
generate_map_from_image | Convert a color-mapped image (PNG/JPG/BMP) into a full playable Celeste map |
generate_terrain_map | Procedural map using seeded Perlin noise + Voronoi biomes |
preview_terrain_biomes | ASCII preview of biome layout before generating |
pip install loenn-mcpOr clone and install from source:
git clone https://github.com/Maggy-Studio/loenn-mcp
cd loenn-mcp
pip install -e .Add to your project's .vscode/mcp.json:
{
"servers": {
"loenn-mcp": {
"type": "stdio",
"command": "python",
"args": ["-m", "loenn_mcp.server"],
"env": {
"LOENN_MCP_WORKSPACE": "${workspaceFolder}"
}
}
}
}Then ask Copilot things like:
Add to claude_desktop_config.json:
{
"mcpServers": {
"loenn-mcp": {
"command": "python",
"args": ["-m", "loenn_mcp.server"],
"env": {
"LOENN_MCP_WORKSPACE": "/absolute/path/to/your/mod"
}
}
}
}python -m loenn_mcp.preview_map Maps/Maggy/Main/01_City_A.bin
python -m loenn_mcp.preview_map Maps/Maggy/Main/01_City_A.bin g- # filter rooms by prefixThe HTML preview opens in your browser and supports:
F to focus)+ / - zoom, 0 fit, Esc deselect| Strategy | Description |
|---|---|
balanced | Mix of exploration and challenge — good default |
exploration | Open spaces, gentle platforming, few hazards |
challenge | Dense tiles, many hazards, tight jumps |
speedrun | Linear path, minimal platforms, fast flow |
| Profile | Seed behaviour | Best for |
|---|---|---|
creative | Random seed each call | Maximum room variety |
deterministic | Stable seed from strategy name | CI pipelines, reproducible layouts |
architect | Random seed | Emphasis on room shape and connectivity |
1. Build pattern library from existing maps
2. (Optional) ingest community maps from GameBanana
3. Create a blank map
4. Generate rooms with a chosen strategy and seed
5. Validate each room
6. Render HTML previewExample agent prompts:
# Step 1 — build pattern library
build_pattern_library()
# Step 2 — ingest a GameBanana mod for richer pattern data
ingest_external_map(
source_url="https://gamebanana.com/mods/53774",
attribution="Spring Collab 2020 (various authors)",
confirm_download=True,
tags="community,collab"
)
# Step 3 — create map and generate rooms
create_map("Maps/PCG/MyAIMap.bin", "PCG/MyAIMap")
generate_room_from_pattern(
map_path="Maps/PCG/MyAIMap.bin",
room_name="a-01",
strategy="exploration",
seed=42,
model_profile="deterministic"
)
generate_room_from_pattern(
map_path="Maps/PCG/MyAIMap.bin",
room_name="a-02",
strategy="challenge",
x=320
)
# Step 4 — validate
validate_room("Maps/PCG/MyAIMap.bin", "a-01")
# Step 5 — preview
render_map_html("Maps/PCG/MyAIMap.bin")Pass seed=<integer> and model_profile="deterministic" to get the exact same room every time:
# These two calls produce identical output:
generate_room_from_pattern(map_path="...", room_name="r1", strategy="challenge", seed=1234, model_profile="deterministic")
generate_room_from_pattern(map_path="...", room_name="r2", strategy="challenge", seed=1234, model_profile="deterministic")ingest_external_map can fetch maps directly from GameBanana:
# Dry-run (no download) — shows what would happen
ingest_external_map(
source_url="https://gamebanana.com/mods/53774",
attribution="Spring Collab 2020",
confirm_download=False
)
# Actual download + pattern extraction
ingest_external_map(
source_url="https://gamebanana.com/mods/53774",
attribution="Spring Collab 2020 (various authors, see mod page)",
confirm_download=True,
tags="expert,collab"
)Downloaded files are saved to PCG/Datasets/ with an attribution.json file. Always verify the mod's licence permits derivative use before building on its patterns.
Convert any color-mapped image directly into a playable Celeste map. Each pixel becomes one 8×8 tile, with colors mapped to tile types and entities.
| Color | Hex | Maps to |
|---|---|---|
| Black | #000000 | Solid tile (foreground) |
| White | #FFFFFF | Air (empty space) |
| Red | #FF0000 | Spike hazard |
| Green | #00FF00 | Player spawn |
| Blue | #0000FF | Jump-through platform |
| Yellow | #FFFF00 | Strawberry collectible |
| Magenta | #FF00FF | Spring (bounce pad) |
| Cyan | #00FFFF | Refill crystal |
| Orange | #FF8000 | Crumble block |
| Grey | #808080 | Background solid (decorative) |
# Basic — converts image using default color mapping
generate_map_from_image(image_path="Assets/my_level.png")
# Custom colors and scale
generate_map_from_image(
image_path="Assets/large_map.png",
output_path="Maps/Custom/level.bin",
scale=4, # 4×4 pixel blocks → 1 tile
color_map_json='{"#FF0000":"solid","#00FF00":"spawn","#0000FF":"air"}'
)scale factor.bin fileRequires Pillow — install with: pip install loenn-mcp[image]
Generate complete maps procedurally using Perlin noise and Voronoi diagrams, inspired by AliShazly/map-generator.
| Biome | Character | Terrain |
|---|---|---|
mountain | Dense tiles | Tight platforms, spikes |
forest | Moderate density | Many platforms, springs |
plains | Open spaces | Gentle platforms, collectibles |
lake | Sparse tiles | Jump-throughs, refills |
cave | Enclosed | Crumble blocks, dark rooms |
summit | Sparse platforms | Wind effects |
generate_terrain_map(seed=42, difficulty=3)
preview_terrain_biomes(seed=42, width_rooms=4, height_rooms=3)
### Generation algorithm
1. **Perlin noise** creates organic heightmap terrain — controls where solid tiles, platforms, and gaps appear
2. **Voronoi diagrams** partition the map into biome regions — each room inherits the biome of its Voronoi region
3. **Seeded RNG** ensures the same `seed` + parameters always produce the exact same output
4. **Difficulty scaling** (1-5) adjusts hazard density, tile coverage, and platform frequency
5. Biome properties control tile characters, entity types, room flags (dark, underwater, wind)
### Parameters
| Parameter | Default | Description |
|---|---|---|
| `seed` | -1 (random) | Integer seed for reproducible output |
| `width_rooms` | 4 | Rooms horizontally |
| `height_rooms` | 3 | Rooms vertically |
| `frequency` | 8.0 | Perlin noise frequency (lower = smoother) |
| `voronoi_points` | 12 | Number of biome region centres |
| `biome_set` | all | Comma-separated biome names |
| `difficulty` | 3 | 1-5 scale for hazard density |
---
## Game Analysis & Wiki (NEW in v5 — gdep-inspired)
Advanced analysis tools adapted from game design analysis patterns.
### Usage examples
analyze_difficulty(map_path="Maps/MyMod/1-City.bin")
detect_map_patterns(map_path="Maps/MyMod/1-City.bin")
suggest_improvements(map_path="Maps/MyMod/1-City.bin", room_name="lvl_a-01")
summarize_map_diff(map_path="Maps/MyMod/1-City.bin") # saves snapshot
summarize_map_diff(map_path="Maps/MyMod/1-City.bin") # shows diff
wiki_save(key="city_difficulty", content="Avg difficulty 4.2/10, 3 hard rooms", tags="analysis") wiki_search(query="difficulty")
batch_validate_and_fix(map_path="Maps/MyMod/1-City.bin", auto_fix=True)
search_entities(map_path="Maps/MyMod/1-City.bin", entity_type="strawberry")
clone_room(map_path="Maps/MyMod/1-City.bin", source_room="lvl_a-01", new_name="lvl_a-01-copy")
export_room_json(map_path="Maps/MyMod/1-City.bin", room_name="lvl_a-01") import_room_json(map_path="Maps/MyMod/2-Resort.bin", json_path="Export/lvl_a-01.json")
### Wiki cache
The wiki stores analysis results in `.loenn_mcp_wiki/` as JSON files.
Results persist across sessions so repeated queries return instantly.
---
## AI-Powered Analysis (NEW — Claude API)
Leverage Anthropic's Claude AI for intelligent map design feedback, narrative generation, and entity placement suggestions.
**Setup:**pip install loenn-mcp
$env:ANTHROPIC_API_KEY="sk-ant-api03-..."
**Available Tools:**
| Tool | Description |
|---|---|
| `ai_analyze_map` | Claude-powered design feedback (general/difficulty/visual/flow analysis) |
| `ai_describe_room` | Generate narrative descriptions of rooms in various styles |
| `ai_suggest_entities` | Get specific entity placement recommendations with coordinates |
**Example prompts:**
ai_analyze_map(map_path="Maps/MyMod/1-City.bin", analysis_type="general")
ai_describe_room(map_path="Maps/MyMod/1-City.bin", room_name="lvl_a-03", style="atmospheric")
ai_suggest_entities(map_path="Maps/MyMod/1-City.bin", room_name="lvl_a-03", goal="add_challenge")
**Analysis Types:**
- `general` — Overall design assessment with improvement suggestions
- `difficulty` — Difficulty curve and balancing analysis
- `visual` — Visual variety and theme consistency feedback
- `flow` — Player movement flow and navigation clarity
**Description Styles:**
- `atmospheric` — Evocative, mood-focused descriptions
- `technical` — Gameplay-focused descriptions
- `story` — Narrative/story snippets
- `brief` — Concise 1-2 sentence summaries
**Suggestion Goals:**
- `improve_flow` — Better player guidance and navigation
- `add_challenge` — Skill-testing elements
- `reduce_difficulty` — Accessibility improvements
- `add_secrets` — Exploration rewards
The AI tools gracefully degrade if `ANTHROPIC_API_KEY` is not set, returning helpful error messages.
---
## Environment Variables
| Variable | Default | Description |
|---|---|---|
| `LOENN_MCP_WORKSPACE` | Current working directory | Root of your Celeste mod project. The server resolves all map paths relative to this. Path traversal outside the workspace is blocked. |
---
## How It Works
### `celeste_bin.py` — standalone binary parser
A pure-Python implementation of the Celeste `.bin` map format (no Everest or Lönn required):
- Full read/write round-trip with no data loss
- Handles all 7 value types: `bool`, `uint8`, `int16`, `int32`, `float32`, lookup string, raw string, RLE-encoded string
- Recursive element tree matching the internal Lönn/Maple format
### `pcg.py` — procedural generation module
Provides:
- **Pattern extraction** — converts `.bin` rooms into reusable pattern records (size class, entity density, tile motifs, trigger usage, gameplay tags)
- **Pattern library** — JSON-based store with deduplication by content hash
- **Strategy-based generation** — `balanced`, `exploration`, `challenge`, `speedrun` modes
- **Seeded randomness** — `random.Random(seed)` for reproducible outputs; seed exposed via MCP tool parameters
- **Model profiles** — `deterministic` / `creative` / `architect` profiles control how seeds are resolved
### `image_map.py` — image-to-map conversion (NEW in v4)
Converts color-mapped images into playable Celeste maps:
- **Color-to-role mapping** — configurable palette mapping colors to tiles and entities
- **Automatic room splitting** — large images are divided into room-sized chunks
- **Entity placement** — spawns, hazards, collectibles extracted directly from pixel colors
- **Scale support** — large images can be downscaled (N×N pixel blocks → 1 tile)
- **Tolerance matching** — fuzzy color matching for hand-drawn or anti-aliased images
### `terrain_gen.py` — seeded terrain generator (NEW in v4)
Procedural map generation inspired by [AliShazly/map-generator](https://github.com/AliShazly/map-generator):
- **Perlin noise** — pure-Python implementation with fractal octaves for organic terrain
- **Voronoi biomes** — map partitioned into distinct biome regions (mountain, forest, plains, lake, cave, summit)
- **Fully seeded** — same seed + parameters = identical output every time
- **Difficulty scaling** — 1-5 scale controls hazard density, tile coverage, and platform frequency
- **Biome-aware entities** — each biome has appropriate hazards, collectibles, and room flags
### `gdep_tools.py` — game analysis tools (NEW in v5)
Integrates game analysis concepts from [pirua-game/ai_game_base_analysis_cli_mcp_tool](https://github.com/pirua-game/ai_game_base_analysis_cli_mcp_tool) (gdep):
- **Wiki caching** — persist analysis results locally so repeated queries are instant (`.loenn_mcp_wiki/`)
- **Pattern detection** — detect gameplay design archetypes (linear progression, hub layouts, collectible-rich, wind corridors)
- **Difficulty analysis** — estimate room/map difficulty from hazard density, navigation aids, tile coverage (1-10 scale)
- **Room connectivity** — adjacency graph analysis showing isolated rooms, dead ends, and hubs
- **Map diffing** — snapshot-based structural diffing for tracking map evolution over time
- **Batch validation** — whole-map playability checks (spawns, floors, bounds) with optional auto-fix
- **Suggestions** — actionable improvement suggestions based on room analysis
### `ai_analyzer.py` — AI-powered analysis (NEW)
Integrates Anthropic's Claude API for intelligent map design assistance:
- **Map analysis** — AI-powered feedback on design, difficulty, visuals, and flow
- **Room descriptions** — Generate narrative descriptions in atmospheric, technical, story, or brief styles
- **Entity suggestions** — Get specific entity placement recommendations with coordinates
- **Graceful degradation** — Helpful error messages when `ANTHROPIC_API_KEY` is not configured
### `server.py` — MCP server
Built with [FastMCP](https://github.com/jlowin/fastmcp). All file paths are resolved relative to `LOENN_MCP_WORKSPACE` with path-traversal protection. Map writes are atomic (parse → mutate → write). External downloads require explicit `confirm_download=True`.
---
## Requirements
- Python 3.9+
- `fastmcp >= 3.0.0`
- `anthropic >= 0.40.0` (optional — only needed for AI-powered tools)
- `Pillow >= 9.0` (optional — only needed for `generate_map_from_image`)
Install with all optional features: `pip install loenn-mcp[image]`
No Celeste installation required to parse, generate, or preview maps.
---
## License
MIT — see [LICENSE](LICENSE).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.