fmg-mcp
fmg-mcp
An MCP (Model Context Protocol) server that drives Azgaar's Fantasy Map Generator in a real browser via Playwright, so Claude (or any MCP client) can generate maps, inspect them, and export screenshots / SVG / JSON.
FMG is a client-side web app with no public API, so this server works by puppeting an actual instance of the page — clicking buttons, filling inputs, and reading its in-memory JS state — rather than reimplementing its generation algorithms.
There are two ways to run this: locally over stdio (for Claude Desktop/Code) or remotely over HTTP (to use as a "custom connector" URL in claude.ai). Pick one.
Option A: Local, stdio (Claude Desktop / Claude Code)
cd fmg-mcp
npm install
npx playwright install chromium # downloads a headless Chromium build
npm run buildRegister it:
{
"mcpServers": {
"fmg": {
"command": "node",
"args": ["/absolute/path/to/fmg-mcp/dist/stdio.js"],
"env": {
"FMG_HEADLESS": "true",
"FMG_OUTPUT_DIR": "/absolute/path/to/fmg-output"
}
}
}
}Environment variables (all optional):
FMG_URL— override the FMG URL (defaults to the GitHub Pages instance).FMG_HEADLESS—"false"to watch the browser while it works. Defaults to headless.FMG_OUTPUT_DIR— where screenshots/exports are written. Defaults to./fmg-output.
Option B: Remote, HTTP (claude.ai "Add custom connector")
This runs the same tools over Streamable HTTP at /mcp, so you can host it
somewhere and give claude.ai the URL. It needs a real browser, so it must
run on a container/VM host, not a serverless/edge platform.
Deploy on Render.com (free/starter tier, easiest)
Push this folder to a GitHub repo.
In Render: New > Blueprint, point it at the repo — it will pick up
render.yamlandDockerfileautomatically and build the image.Render auto-generates an
AUTH_TOKENenv var for you (see the service's Environment tab) — copy it.Once deployed, your MCP URL is
https://<your-service>.onrender.com/mcp.
Deploy anywhere else that runs Docker (Fly.io, Railway, a VPS, etc.)
docker build -t fmg-mcp .
docker run -p 8787:8787 -e AUTH_TOKEN=$(openssl rand -hex 24) fmg-mcpPut whatever host/domain that ends up behind at https://your-host/mcp.
Add it to claude.ai
Settings → Connectors → Add custom connector, then:
URL:
https://your-host/mcpIf you set
AUTH_TOKEN, choose the auth option that lets you supply a bearer token, and paste the token value in.
⚠️ Security note: anyone with the URL and token can drive a real
browser through your server. Always set AUTH_TOKEN on anything reachable
from the public internet — don't leave it unset outside of local testing.
Notes on the HTTP deployment
Playwright's official Docker base image (
mcr.microsoft.com/playwright) is used so Chromium and its OS dependencies are already present — no extraapt-get/playwright installstep needed in the container.The server keeps one browser page per MCP session (keyed by the
Mcp-Session-Idheader the SDK manages automatically), so map state persists across tool calls within a conversation, same as the stdio version.Free hosting tiers that spin containers down when idle will lose in-memory map state between calls — fine for occasional use, but if you want state to reliably survive idle periods, use a plan that keeps the container warm.
Tools
Tool | What it does |
| Launches/reuses the browser session and waits for FMG to load. Call first. |
| Generates a new map, optionally with a specific seed and/or heightmap template. |
| Reads seed, dimensions, and counts of cultures/states/burgs/religions from the page state. |
| Saves a PNG of the map (or full page) to the output directory. |
| Saves the live map SVG to a |
| Best-effort dump of FMG's internal |
| Clicks any element by CSS selector — for UI FMG doesn't have a dedicated tool for. |
| Lists map-related |
| Evaluates arbitrary JS in the page (e.g. calling FMG's own save/generate functions directly). |
| Closes the browser session. |
A note on fragility
FMG doesn't publish a stable API, and its internal function/variable names
and UI selectors have changed across versions over the project's history.
The tools above use the most common/longstanding selectors and globals
(#regenerateMap, window.pack, window.seed, etc.), but if the deployed
version has drifted:
Use
inspect_globalsandrun_jsto poke around and find the current equivalents (e.g.run_jswith"Object.keys(window).filter(k => /gener/i.test(k))").Use
clickwith browser devtools-inspected selectors as a fallback for any UI action not covered by a dedicated tool.
Example session
open_map
new_map { "seed": "123456789", "template": "Continents" }
get_map_info
screenshot { "fileName": "continents.png" }
export_svg { "fileName": "continents.svg" }Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/rashestbread691/fmg-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server