@invarya/maps-mcp
v0.4.0
Published
MCP server for maps.guru — geocoding, map styles, GIS export, and more for AI assistants
Maintainers
Readme
@invarya/maps-mcp
MCP (Model Context Protocol) server for maps.guru — geocoding, map styles, GIS export, and more for AI assistants (Claude Desktop, Cursor, Windsurf, ChatGPT, Gemini).
Setup
Recommended: OAuth 2.1 login
Run once per machine. No secrets land in any config file.
npx @invarya/maps-mcp auth loginThe CLI opens your browser to maps.guru, waits for you to approve the requested scopes, and stores the resulting JWT + refresh token in your OS keychain (macOS Keychain, Windows Credential Manager, or libsecret on Linux).
Credentials are additionally wrapped with an AES-256-GCM envelope keyed off a machine fingerprint (hostname + username + platform + arch) before being written to either the keychain or the file fallback (~/.config/maps-guru/credentials.json). The OS keychain already provides at-rest encryption — the envelope adds a second layer so that an exfiltrated backup, sync export, or copied credential file cannot be decrypted offline on a different host. Legacy unencrypted entries are detected on read, used once with a stderr warning, and re-encrypted on the next write.
After login, point your client at the server with a zero-secret config:
{
"mcpServers": {
"maps-guru": {
"command": "npx",
"args": ["-y", "@invarya/maps-mcp"]
}
}
}Behind the scenes the CLI uses OAuth 2.1 authorization code + PKCE + an ephemeral loopback listener on http://127.0.0.1:<random-port>/callback, as described in RFC 8252 §7.3. Same pattern as gcloud auth login, gh auth login, aws sso login.
Check status or sign out:
npx @invarya/maps-mcp auth status # email, scopes, TTL, backend
npx @invarya/maps-mcp auth logout # clears keychain, deletes per-machine OAuth clientManage active CLI installs across every machine at maps.guru/dashboard/settings/devices.
Legacy: MAPS_GURU_API_KEY env var
For CI, headless containers, or anywhere an OS keychain isn't available, keep using a mapx_ API key:
{
"mcpServers": {
"maps-guru": {
"command": "npx",
"args": ["-y", "@invarya/maps-mcp"],
"env": {
"MAPS_GURU_API_KEY": "mapx_your_api_key_here"
}
}
}
}Get a key at maps.guru/dashboard/tokens. The server forwards it as a Bearer token on every request to maps.guru/api/v1/*.
Credential resolution order
The server checks these sources in priority order on every launch:
MAPS_GURU_BEARER_TOKENenv var (explicit override, rarely needed)- Keychain JWT from
auth login— auto-refreshed 60 seconds before expiry MAPS_GURU_API_KEYenv var — legacy fallback- Exits with an error pointing you at
auth login
Claude Desktop
Config lives at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS (%APPDATA%\Claude\claude_desktop_config.json on Windows). Either of the two setup blocks above works — restart Claude Desktop after saving.
Cursor / Windsurf / Cline / OpenCode
Drop the same config block into .cursor/mcp.json, .windsurf/mcp.json, VS Code Cline MCP settings, or your OpenCode MCP settings. Restart the client.
Testing with MCP Inspector
With a keychain-authenticated install (preferred):
npx @modelcontextprotocol/inspector npx @invarya/maps-mcpOr with an explicit mapx_ key:
MAPS_GURU_API_KEY="mapx_your_key" npx @modelcontextprotocol/inspector npx @invarya/maps-mcpOpens a web UI at http://localhost:6274 — connect, browse all 15 tools, and run them interactively.
Available Tools (15)
Geocoding
| Tool | Description |
| ----------------- | --------------------------------------------------- |
| geocode | Forward geocode — address/place name to coordinates |
| reverse_geocode | Reverse geocode — coordinates to address |
| autocomplete | Address autocomplete with partial input |
| place_lookup | Get place details by Pelias ID |
GIS Export
| Tool | Description |
| --------------------- | ------------------------------------------- |
| get_tile_url | Get tile URL with QGIS-ready connection URI |
| get_style_json | Get full MapLibre GL style JSON |
| get_static_map | Generate static map image (PNG) |
| get_dataset_geojson | Export dataset as GeoJSON |
Styles
| Tool | Description |
| ----------------- | -------------------------------------------------- |
| list_styles | List your map styles |
| create_style | Create a new style from preset |
| modify_style_ai | AI-powered style modification via natural language |
| share_style | Make a style publicly accessible |
| brand_style | Generate a brand-matched map style from a URL |
Data & Account
| Tool | Description |
| --------------- | -------------------------------- |
| list_datasets | List datasets for a style |
| get_usage | Get current API usage and quotas |
Resources
| Resource | Description |
| --------------- | --------------------------- |
| style-presets | Available map style presets |
| service-info | API capabilities and limits |
Environment Variables
| Variable | Required | Default | Description |
| ------------------------ | -------- | ------------------- | -------------------------------------------------------------------- |
| MAPS_GURU_BEARER_TOKEN | No | — | Explicit JWT override (CI, testing). Short-circuits keychain lookup. |
| MAPS_GURU_API_KEY | No | — | Legacy mapx_ fallback. Used when auth login isn't possible. |
| MAPS_GURU_BASE_URL | No | https://maps.guru | API base URL. Point at staging or local dev. |
At least one of auth login (recommended), MAPS_GURU_BEARER_TOKEN, or MAPS_GURU_API_KEY must be available; otherwise the server exits with a pointer to auth login.
QGIS Integration
Two MCP servers cooperate through the AI assistant:
User: "Add my city-streets map to QGIS"
Claude:
1. maps_guru.get_tile_url({ style_slug: "city-streets" })
-> { qgis_uri: "type=xyz&url=...?key=mapx_xxx&zmax=14" }
2. qgis.add_raster_layer({ path: qgis_uri, provider: "wms" })
-> QGIS loads the tile layerRemote MCP (mcp.maps.guru/mcp)
For clients that support HTTP MCP transports (ChatGPT custom connectors, Claude Web Apps, Gemini, Perplexity), maps.guru also exposes a Cloudflare Worker at mcp.maps.guru/mcp. It accepts OAuth 2.1 JWT access tokens only — mapx_ keys are explicitly rejected on that surface. Dynamic client registration (RFC 7591), PKCE, and audience-bound JWTs (RFC 8707) are all handled by the standard OAuth flow on maps.guru/api/v1/auth. No separate setup required beyond what your client does automatically.
License
MIT
