Map Control × Model Context Protocol — a live, shareable web map that AI agents (and humans) drive from code.
Ask your AI assistant to "draw the burn scar over Los Alamos and fly the camera to it" — and watch it happen live in a browser tab. MapControl is a headless map server with a real-time MapLibre frontend: create maps, add GeoJSON and GeoTIFF overlays, animate the camera, switch basemaps and themes, take screenshots — over a Python SDK, a REST API, or the Model Context Protocol for Claude, Cline, and any other MCP client.
Think of it as the Star Trek computer's map console. You say the words; the map moves.
- 🗺️ Live & shareable — every map is a URL. Open it anywhere; it updates in real time over WebSocket.
- 🤖 Agent-native — a first-class MCP server (Streamable HTTP) mounted at
/mcp. Point Claude Desktop, Claude.ai, Cline, or the OpenAI Agents SDK at it and start talking to your map. - 🐍 Typed Python SDK — the
mapcontrolpackage gives you sessions, assets, styles, screenshots, and camera control in a few lines. - 🌍 Real geospatial data — GeoJSON features, styled polygons/lines/points, glyph markers, arcs, and GeoTIFF rasters rendered server-side with colormaps.
- 🏔️ 3D terrain & globe — MapLibre globe with terrain tiles and sky, or classic 2D. Ballistic zoom animations included.
- 📸 Screenshots — capture the current viewport to PNG, straight from a tool call.
- 🎨 Basemaps & themes — OpenStreetMap, Esri Satellite, and Carto Dark work with zero keys; drop in a MapTiler key for vector streets, hybrid, topo, and dataviz styles. Light/dark themes throughout.
- 🔐 Optional auth — self-issued signed scoped tokens for
/mcp, plus a standalone OAuth-style authorization portal for multi-user deployments.
Claude / Cline / any MCP client Python SDK (`mapcontrol`) curl / your app
│ │ │
▼ ▼ ▼
MCP (/mcp) ────────────────────────► REST API ◄───────────────────────┘
│
FastAPI server (sessions,
assets, events, GeoTIFFs,
screenshots, auth)
│
WebSocket fan-out
│
▼
MapLibre GL frontend (live map,
3D terrain, drawing tools)
| Directory | What it is |
|---|---|
server/ |
FastAPI server — REST API, WebSocket hub, MCP server, GeoTIFF & screenshot services, auth portal |
sdk/ |
mapcontrol — typed Python client SDK |
examples/ |
Runnable demo scripts (shapes, terrain, glyphs, GeoTIFFs) + sample data |
docs/ |
Guides — MCP integration, MCP Apps field guide, map-engine comparison |
docs/vision/ |
Design docs — architecture, specification, roadmap, protocol notes |
deploy/ |
Deployment helpers (local PyPI index for the SDK) |
Docker (fastest):
docker compose up --buildOr from source:
cd server
pip install -e ".[dev]"
uvicorn mapcontrol_server.main:app --reload --port 8000The server is at http://localhost:8000 — interactive API docs at /docs.
cd sdk && pip install -e .from mapcontrol import MapControl
mc = MapControl("http://localhost:8000")
session = mc.create_map(name="demo")
print(session.map_url) # ← open this in a browser; it updates live
session.zoom_to(-122.42, 37.77, zoom=12) # fly to San Francisco
session.add_polygon([[-122.5, 37.7], [-122.4, 37.7], [-122.4, 37.8]])
session.set_basemap("satellite")
session.set_theme("dark")
shot = session.take_screenshot() # PNG of the current viewThe MCP server is mounted in-process at /mcp (Streamable HTTP — the current MCP standard). Add it to any MCP client:
Cline / Claude Desktop (mcpServers config):
{
"mcpServers": {
"mapcontrol": {
"url": "http://localhost:8000/mcp"
}
}
}Then just ask:
"Create a map, add a red polygon around Austin, switch to satellite, and zoom to it."
See docs/mcp-integration.md for full setup guides (Claude Desktop, Cline, Claude.ai web, OpenAI Agents SDK) and transport details.
| Tool | What it does |
|---|---|
create_map |
Create a live map and get its shareable URL |
add_geojson |
Add styled GeoJSON features (polygons, lines, points, glyphs) |
add_arc |
Add a great-circle arc between two points |
add_geotiff |
Upload & render a GeoTIFF raster with a colormap |
zoom |
Fly the camera — to coordinates, bounds, or assets (ballistic animation) |
list_assets |
List everything on a map |
update_style |
Restyle an existing asset |
set_visibility |
Show / hide an asset |
delete_asset |
Remove an asset |
set_basemap |
Switch basemaps (OSM, satellite, dark, MapTiler styles…) |
set_theme |
Light / dark theme |
get_viewport |
Read the current camera position |
take_screenshot |
Capture the current view to PNG |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/maps |
Create a map |
GET |
/api/maps/{id} |
Get map info |
DELETE |
/api/maps/{id} |
Delete a map |
POST |
/api/maps/{id}/sessions |
Create a user session |
POST |
/api/maps/{id}/events |
Send a map command |
GET |
/api/maps/{id}/events |
List events |
GET |
/api/maps/{id}/assets |
List assets |
PATCH |
/api/maps/{id}/assets/{aid} |
Update an asset |
DELETE |
/api/maps/{id}/assets/{aid} |
Delete an asset |
GET |
/map/{id} |
Map frontend (iframe-ready; ?ui=none for a chromeless embed) |
WS |
/ws/{id}/{session} |
WebSocket for real-time events |
Everything lives in server/config.toml — host/port, session TTL, storage paths, default basemap/theme/terrain, and the full basemap catalog. Keyless basemaps (OSM, Esri Satellite, Carto Dark) work out of the box; set MAPTILER_API_KEY to unlock the MapTiler vector styles. Adding a new tile provider is a config-only change.
Optional auth for /mcp is controlled via environment (MAPCONTROL_AUTH_MODE) — see server/mapcontrol_server/portal/ for the standalone authorization portal.
Runnable scripts in examples/ show the SDK end to end (start the server first):
python examples/demo.py # tour: shapes, styles, zoom, basemaps
python examples/demo_terrain_showcase.py # 3D terrain + ballistic camera moves
python examples/demo_glyphs.py # glyph markers & labels
# see also: demo_drawing.py, demo_ballistic_zoom.py, demo_multi_session.pySample GeoTIFFs live in examples/data/.
cd server
pip install -e ".[dev]"
pytest tests/ -vQuestions, ideas, demos to show off? Join us on Discord →
MapControl is developed within the ESIP Federation community. Issues and pull requests are welcome.