Ultimaps

com.ultimapsPublished by ultimaps.comOfficial publisherv0.2.0Updated Oct 24, 2026

Create choropleth, category and pin maps of countries, states, counties and ZIP codes as images.

VerifiedStreamable HTTPWeb executableData & AnalyticsMedia & Design

Overview

AI-generated overview

Ultimaps renders choropleth, category and pin maps of countries, states, counties and ZIP codes as images from data the assistant supplies.

What you can do
  • Render maps as PNG or SVG images from numbers, categories or explicit colors, with pins, title, legend, theme and region labels
  • Preview region matching and the color plan without rendering
  • List the available map catalog, searchable by query
  • Look up one map's region keys and titles, 200 per page, searchable by key, title or alias
When to use it
Useful when you want a map image inside the conversation from pasted figures or a list of places, such as coloring US states by population, EU members by currency, or pinning office locations. It saves building a charting pipeline for one-off geographic visuals.
Requirements
Either the hosted endpoint at api.ultimaps.com or the local npm package, which needs Node.js 20 or newer. No account is required; an optional API key can be supplied as ULTIMAPS_API_KEY locally or as an Authorization bearer header on the hosted server. Network access to the Ultimaps API is required.
Before you install
Render requests, including region values, pins, title and styling, are sent to Ultimaps and logged with your IP address; request content is kept 30 days and IP and user agent 90 days. An API key is sent with render requests only, and an invalid key is an error rather than a fallback. Renders count against hourly, daily or monthly quotas, and embeddable links for small keyless renders contain the full map request, readable by anyone with the link. Rendered images are written to a temp directory…

Installation

In SourceWeft

  1. Open Ultimaps in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/com.ultimaps%2Fmcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config.

{
  "mcpServers": {
    "ultimaps": {
      "type": "http",
      "url": "https://api.ultimaps.com/mcp"
    }
  }
}

README

@ultimaps/mcp

An MCP server for Ultimaps. Ask Claude, Codex or any MCP client for a map and get the image back in the conversation. It covers choropleths from pasted numbers, category maps and pinned locations, for countries, states, provinces, counties, continents and the world.

"Map US states by population." · "Color the EU members by currency." · "Show France's regions with these unemployment rates: …" · "Pin our five offices on a map of Europe."

No account needed. Without an API key the server uses the keyless tier. Set ULTIMAPS_API_KEY for plan quotas and larger or unbranded output.

Can't run a local command? In ChatGPT (developer mode), claude.ai or any client that connects to remote MCP servers, add the hosted server instead: https://api.ultimaps.com/mcp. In ChatGPT, turn it on in each conversation where you want maps. It has the same three tools and nothing to install. See Hosted server. This package is the local version: requests come from your own IP address with your own key, and every image is saved to a file on your computer.

Tools

ToolWhat it does
render_mapRenders a map as an image (PNG, or SVG with a Pro key), shown inline when it is small enough. Choropleth (numbers), categories (labels) or explicit colors, plus pins, title, a legend with its own heading, theme, region labels (names, values or both) and extra layers. Region names are matched fuzzily, and every correction or miss is reported with suggestions. dryRun: true previews matching and the color plan without rendering.
list_mapsThe map catalog: {id, title, regionType, layers, regionCount, labels}, searchable with query.
get_map_regionsOne map's region keys and titles, 200 per page, searchable by key, title or alias.

All three are read-only. Agents rarely need the discovery tools: render_map accepts region names, codes and aliases directly.

Install

Requires Node.js 20 or newer.

Claude Code

sh
claude mcp add ultimaps -- npx -y @ultimaps/mcp# with a key:claude mcp add ultimaps --env ULTIMAPS_API_KEY=um_live_… -- npx -y @ultimaps/mcp

Codex

sh
codex mcp add ultimaps -- npx -y @ultimaps/mcp# with a key:codex mcp add ultimaps --env ULTIMAPS_API_KEY=um_live_… -- npx -y @ultimaps/mcp

Codex writes TOML, not the JSON below. The equivalent entry in ~/.codex/config.toml (or .codex/config.toml in a trusted project):

toml
[mcp_servers.ultimaps]command = "npx"args = ["-y", "@ultimaps/mcp"]

Claude Desktop

Download ultimaps-<version>.mcpb from the latest release and open it: Claude Desktop installs it in one click and asks for the optional API key. Or add this to claude_desktop_config.json:

json
{  "mcpServers": {    "ultimaps": {      "command": "npx",      "args": ["-y", "@ultimaps/mcp"],      "env": { "ULTIMAPS_API_KEY": "" }    }  }}

Cursor

~/.cursor/mcp.json (or .cursor/mcp.json in a project):

json
{  "mcpServers": {    "ultimaps": { "command": "npx", "args": ["-y", "@ultimaps/mcp"] }  }}

VS Code

.vscode/mcp.json:

json
{  "servers": {    "ultimaps": { "type": "stdio", "command": "npx", "args": ["-y", "@ultimaps/mcp"] }  }}

Hosted server

You don't need this package to use the hosted server. Add the URL to your client:

sh
claude mcp add --transport http ultimaps https://api.ultimaps.com/mcp# with a key:claude mcp add --transport http ultimaps https://api.ultimaps.com/mcp \  --header "Authorization: Bearer um_live_…"

Clients with a config file take the URL alone, for example ~/.cursor/mcp.json:

json
{  "mcpServers": {    "ultimaps": { "url": "https://api.ultimaps.com/mcp" }  }}

The hosted server sends a key as an Authorization header, not as ULTIMAPS_API_KEY. In ChatGPT and claude.ai you can't set headers, so renders there use the anonymous tier: PNG up to 1600 px with attribution, up to 30 per hour per conversation. Every render also comes back as an image link that expires after 30 days. Images too large for the conversation, and all SVGs, come back only as the link. ChatGPT doesn't show images returned by tools, so the link is how you see the map there.

Configuration

VariableDefaultPurpose
ULTIMAPS_API_KEYnone (keyless)API key from Studio → Workspace → API. An invalid key is an error and never falls back to keyless.
ULTIMAPS_API_URLhttps://api.ultimaps.comPoint at a local API during development (http://localhost:3001). Plain http is only accepted for localhost.

Limits

KeylessFree keyPro key
Renders30/hour, 5/minute500/month, 50/day, 10/minute5,000/month, 1,000/day, 30/minute
OutputPNG up to 1600 px, attributionPNG up to 1600 px at scale 2 (a 3200 px raster), attributionPNG up to 4000 px at scale 4, SVG, no attribution

All keys in a workspace share the monthly quota. The daily and per-minute caps are per key, so a free key stops at 50 renders a day long before the month runs out.

Dry runs skip the monthly quota but still count against rate limits. When five or fewer keyless renders remain in the hour, the result says so.

What a render returns

  • The image, inline, when it is small enough (781 KB for PNG, 98 KB for SVG). The default 1200 px width usually fits. Every render is also written to <tmpdir>/ultimaps-mcp/ and the path is in the result, so in a terminal client the file is the thing you can actually open. Nothing is re-rendered or resampled on your behalf.
  • A text report: auto-corrected and unmatched region keys with suggestions, the resolved choropleth plan, warnings (such as layer_unavailable or labels_overlap), a link to open the map in Ultimaps Studio for editing, and the render id for support.
  • An embeddable image URL for keyless PNG renders whose whole spec fits a ~2,000-character URL, so small datasets only. The URL carries the spec, not the image, and renders keyless, so it is not offered when a key is set.
  • structuredContent with the same report as data, described by the tool's outputSchema.

Privacy Policy

This server runs on your machine, has no telemetry of its own and talks only to the Ultimaps API (https://api.ultimaps.com, or the ULTIMAPS_API_URL you set). The full Ultimaps privacy policy is at ultimaps.com/privacy-policy.

What is sent to Ultimaps. Tool calls are ordinary HTTPS requests to the Ultimaps API, so they arrive from your IP address with an ultimaps-mcp/<version> user agent. render_map sends the whole map request: region keys and values, pins, title and styling. If you set ULTIMAPS_API_KEY, it is sent with render requests only.

What Ultimaps keeps. Each render request is logged: the request content, the map and outcome, timing, your IP address and user agent, and for keyed requests which key and workspace made it. This lets support look up a render id, lets the "Open in Studio" link rebuild your map, and counts usage. The request content is kept for 30 days and the IP address and user agent for 90 days. What remains is a usage record, tied to your workspace when a key was used. Ultimaps uses a third-party error-monitoring service that may receive details of a failed request. Ultimaps does not sell this data or use it for advertising.

What stays on your machine. Every rendered image is written to <tmpdir>/ultimaps-mcp/ and this server never deletes it. What your MCP client keeps, including tool results in your conversation, is governed by its own privacy policy.

Shareable links. The embeddable image URL offered for small keyless renders contains the full map request. Anyone with the link can read it.

The hosted server. The server at https://api.ultimaps.com/mcp runs on Ultimaps' servers, not yours, so the section above about your machine doesn't apply to it. The full privacy policy covers it.

Questions or deletion requests: [email protected], quoting the render id.

Development

sh
npm installnpm run typechecknpm test           # unit + in-process protocol testsnpm run build      # → dist/

End-to-end over stdio against a real API (spends render units from your tier):

sh
npm run buildnode scripts/smoke.mjs

src/generated/render-request.schema.json is generated from the Ultimaps API contract; do not edit it by hand. Tool and property descriptions live in src/descriptions.ts. Arguments are never validated locally: the API is additive-only, and its 400 responses carry suggestions.

Issues and pull requests are welcome. Releases are cut by the Ultimaps team, and accepted changes ship with the next release.

The package publishes a bin and nothing else. import '@ultimaps/mcp' is not supported and fails by name, because dist/index.js starts a stdio server when it loads.

License

MIT © Ultimaps. See LICENSE.

Source: README.md at commit 8804579

Tools

3

list_maps

List maps

List the maps Ultimaps can render: the world, continents, countries subdivided into states, provinces, counties or departments, and US ZIP code areas. Each row is {id, title, regionType, layers, regionCount, labels}. `id` is the mapId for render_map and get_map_regions; it is the map's slug on ultimaps.com (the last path segment, not the whole URL) and always means the current edition. `regionCount` is how many region keys a complete dataset needs. `labels: false` means the map has no region labels, so `style.labels` does nothing there. `layers` are the ids render_map's `layers` can turn on. Pass `query` to search ids, titles, region types and categories (e.g. "counties", "germany", "africa"). Only call this when you don't know the id: common ids such as `world`, `united-states` and `europe` just work, and an unknown id usually comes back with the closest ids.

Parametersquery

get_map_regions

Get map regions

Look up one map: title, regionType, regionCount, labels, layers, and its regions as {key, title}, 200 per page. You rarely need this before rendering. render_map accepts region names, codes and common aliases and auto-corrects typos, reporting what it matched. Use it to build a dataset covering every region of a map, to see how a map names its regions, or to resolve a key render_map could not match. `query` searches keys, titles and aliases, so no hits means the map really has no such region. Use `offset` for further pages.

ParametersmapIdrequiredqueryoffset

render_map

Render map

Draws a map of real places as an image: countries, states, counties or ZIP codes colored by data (a choropleth or heat map) or by category, with a legend, a title and pins. Borders come from real geographic data, not from an image model, and region names are matched for you. It draws only real places, never fictional or invented ones. The map is returned as an image in the conversation. Maps cover the world, continents, countries, their states, provinces and counties, and US ZIP code areas. Color regions with ONE of these (choropleth and categories are mutually exclusive): - `choropleth`: a number per region, e.g. {"values": {"California": 39.5, "Texas": 30.5}}. Classes, breaks and palette are picked from the data unless you set them. Say what the numbers are with `kind` (and `midpoint` when they have a meaningful center, `unit` for a short label unit): that is what gets percents, currencies, years and diverging scales right. When the data does not cover every region of the map, add `noData: true` so the legend explains the uncolored ones. - `categories`: a label per region, e.g. {"values": {"France": "Euro", "Poland": "Złoty"}}. Colors are assigned automatically unless you set `colors`. - `regions`: explicit hex colors, e.g. {"Texas": "#1D4ED8"}. Also works on top of either mode as an override. Region keys can be names, ISO/FIPS-style codes or common aliases. Typos are auto-corrected, and every correction or unmatched key is reported with suggestions, so there is no need to call get_map_regions first. Get `mapId` from list_maps if you don't know it. Also available: pins (`locations` with lat/lon), `title`, `legend` (position, `title`, `subtitle`), `style` (theme, borders, region labels; `style.labels.content: "value"` prints each region's value instead of its name and `"name_value"` stacks the name above the value, both needing `choropleth` or `categories`; `style.labels.fit` (default "auto") shortens labels that don't fit or overlap and never hides one; any still

ParametersmapIdrequiredstyletitledryRunlayerslegendoutputregionslocationscategorieschoroplethonUnmatched

Version history

3
  1. v0.2.0LatestOct 20, 2026
  2. v0.1.1Sep 16, 2026
  3. v0.1.0Sep 16, 2026

Score

100% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts