Skip to main content

ZenMap developer tools

A client for ZenMap's developer API, the zenmap command, and an MCP server (zenmap mcp) for Claude Code and other local MCP clients. They publish data to a ZenMap app (a public, published map with its own keys) and query that map's published version.

The client and the command line use the Python standard library only (Python 3.10+). Only zenmap mcp needs one more package, the MCP SDK.

pip install zenmap            # the client and the command line
pip install 'zenmap[mcp]'     # and the MCP server
zenmap --version              # zenmap 0.1.1

The Python import is zenmap_dev:

import os
from zenmap_dev.client import Client

client = Client(os.environ["ZENMAP_SECRET_KEY"])
print(client.status())

The key

Each app has a secret key (zm_sk_…), shown once when it is made in ZenMap (Settings → Developer). It can publish, so keep it off web pages and out of your code:

  • zenmap login keeps it in the macOS Keychain or the Linux Secret Service keyring (--profile NAME for more than one app);
  • or set ZENMAP_SECRET_KEY (CI, containers, the MCP server's environment).

The tools send it only in the Authorization header and require HTTPS. HTTP is allowed for local development on localhost, 127.0.0.1 and ::1. Redirects are refused, so a redirected request cannot leak your key. A secret key sent in a web address is turned off by ZenMap at once.

The default service address is https://zenmap.ai; ZENMAP_URL or --url overrides it. The same transport rules apply to all configured addresses and upload URLs.

Your whole workspace, with a personal key

A personal key (zm_ak_…, Settings → Developer → Personal keys) reaches every project, layer and data folder in your workspace, with what you ticked when you made it: read and write, and separately share and delete. It lasts 90 days unless you choose up to a year, and stops when you sign out everywhere. It is kept and sent exactly like a secret key.

zenmap push splices.geojson cabinets.geojson poles.geojson --project Dallas
zenmap push drops.gpkg --folder Fiber/2026        # a missing folder is made
zenmap push sites.shp --project Dallas --below splices
zenmap update sites new-sites.geojson --key site_id
zenmap update sites more.geojson --append
zenmap update sites all-sites.geojson --replace
zenmap undo sites
zenmap versions sites                    # kept 30 days, and the newest always
zenmap restore sites --version 3         # put version 3 back (the data now is kept first)
zenmap style parcels parcels.qml         # on the one map it is on (--project P on several)
zenmap style parcels parcels.qml --library       # what every map it is added to starts with
zenmap view Dallas --lng -96.80 --lat 32.78 --zoom 11 --basemap voyager
zenmap move sites --folder Fiber
zenmap find splices --project Dallas

A layer is named by its name or its id. A name that several layers share is refused, and the ids of the ones that match are listed.

Each command prints a short summary of what happened. --json prints ZenMap's whole answer instead:

$ zenmap update units units-october.geojson --key unit_id
Updated units: 1 added, 1 changed, 54 unchanged
Changed on 1 map: DFW expansion
Undo with: zenmap undo units

A QGIS style saved beside a file (splices.qml or .sld, "Save as default" in QGIS) styles its layer on the project's map; so does a GeoPackage's own saved style. The answer lists anything that did not carry over. --no-style skips them. Uploading never shares anything.

Publishing

zenmap status                         # the app, its map link and its layers
zenmap push data.gpkg --name "Sites"  # a new layer (a shapefile's sidecars go with it)
zenmap style Sites style.json         # style, labels, popup: zenmap.map/1
zenmap fields Sites name score        # the columns the query API may return
zenmap publish                        # a new public version
zenmap update Sites new-data.gpkg --replace   # new rows; the old rows kept as a version
zenmap undo Sites

The public map changes only on publish.

Querying the published map

zenmap query nearest LAYER --lng LNG --lat LAT --k 5
zenmap query within LAYER --lng LNG --lat LAT --distance 2 --unit km --all
zenmap query contains LAYER --lng LNG --lat LAT
zenmap query filter LAYER --where "COLUMN > 10" --fields COLUMN OTHER
zenmap query summarize LAYER --group-by COLUMN --metric count --metric COLUMN:mean

Only the fields the app publishes are answered. Queries use the service address followed by /api/v1/maps by default. ZENMAP_QUERY_URL overrides that query base address.

MCP

zenmap login                         # the key goes to the keychain
claude mcp add zenmap -- zenmap mcp  # the server reads it from there

(--env ZENMAP_SECRET_KEY=… works too, but writes the key into Claude Code's own settings file.)

Tools with an app key: status, push, replace, undo_replace, set_style, set_published_fields, publish, job_status, query.

Tools with a personal key: workspace, find_layers, push_layers, move_to_folder, update_layer, undo_update, layer_versions, restore_version, style_layer, set_view, set_map_order, job_status, and only when the key has the scope, share_project and stop_sharing (share) or delete_layer and delete_project (delete). "Push these three layers into my Dallas project with my QGIS styles" and "put this in my Fiber folder" are each one push_layers call.

Uploads and style files come only from the folder the server was started in (or ZENMAP_MCP_ROOT), and only files ZenMap reads.

Metadata

Release files for zenmap 0.1.1

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

Source distribution (sdist)

Source distribution for zenmap 0.1.1
File Size Uploaded Provenance
zenmap-0.1.1.tar.gz 59.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for zenmap 0.1.1
File Interpreter ABI Platform
zenmap-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 120.3 kB

Release files / zenmap-0.1.1.tar.gz

Download URL zenmap-0.1.1.tar.gz
Size 59.5 kB
Tags Source
SHA-256 checksum
How to use checksums
60b1ecab34487362d2c4eceb75bf8d7b245684e0596924eafa0795710dd6a86e
BLAKE2b-256 checksum
How to use checksums
ca9b3a9d3eae704da81e10b2959bca7b74773fe65c2c2b7170d6cad621be301e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.8

Release files / zenmap-0.1.1-py3-none-any.whl

Download URL zenmap-0.1.1-py3-none-any.whl
Size 60.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a7c8269a5cbef2d878602923c88d81b0c8a70afb54c5839243f83a0fb251942e
BLAKE2b-256 checksum
How to use checksums
28dceed02e6c64e0947c0d43a312d4be478ee1d2849bb74591ccbed8e26c7eb9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.8

Security for zenmap 0.1.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

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

0.1.1 This release

2 release files No 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