# Boundary Atlas: full guide for agents

> Free MCP server of US and Canadian boundaries (cities, ZIP codes, counties, districts, precincts, ridings).
> MCP endpoint: https://atlas-production-d344.up.railway.app/mcp (streamable HTTP, no key).
> Home: https://atlas-production-d344.up.railway.app/ · Map demo: https://atlas-production-d344.up.railway.app/demo

## Connect

- **Claude Code:** `claude mcp add --transport http boundary-atlas https://atlas-production-d344.up.railway.app/mcp`
- **Cursor (~/.cursor/mcp.json):** `{"mcpServers": {"boundary-atlas": {"url": "https://atlas-production-d344.up.railway.app/mcp"}}}`
- **Codex (~/.codex/config.toml):**
  ```
  [mcp_servers.boundary-atlas]
  url = "https://atlas-production-d344.up.railway.app/mcp"
  ```
- **Claude app (claude.ai or desktop):** `Settings → Connectors → Add custom connector → https://atlas-production-d344.up.railway.app/mcp`
- **ChatGPT (developer mode):** `Add a custom connector: URL https://atlas-production-d344.up.railway.app/mcp, no authentication`

Limits per IP address: 60 requests a minute, 3,000 a day, 4 at once (429 with `Retry-After` past
them). Large boundary results come back as a signed `download_url` that works for an hour.

## Server instructions

Boundary Atlas: US and Canadian boundaries and lookups. Cities and towns (Census places), ZIP codes
(Census ZCTAs), counties, towns and townships, congressional and state legislative districts (the maps in force for the
Nov 3, 2026 election), voting precincts, and Canadian provinces, ridings and polling divisions.
IDs look like '<cc>:<level>:<code>': 'us:state:34', 'us:county:34013' (FIPS), 'us:place:1714000' (Chicago),
'us:zcta:07102', 'us:congressional_district:3410', 'us:precinct:...' (the current precinct where a state publishes
one, else the 2020 Census VTD; check `vintage`), 'us:vtd_2020:...' (2020 VTDs kept for historical joins),
'ca:province:35', 'ca:federal_electoral_district:35001'.
What contains an address or point: geocode it, then locate_point. Find IDs by name with search_geographies.
Cross between units with related_geographies (population shares: a ZIP's cities, counties and districts; a city's
districts; level='zcta' lists the ZIPs in a city, county or district). Walk the hierarchy with list_children.
Polygons: get_boundaries (GeoJSON; big sets come back as a download link, not inline). Every record carries its
source, vintage and updated_at; call data_freshness before relying on precincts, which change between elections.
lat/lon are internal points (inside the shape). Districts are not nested inside counties; their parent is the state.
ZCTAs approximate USPS ZIP Codes.

## How to use the tools well

1. Find IDs with `search_geographies` (filter by `country`, `level`, `region`). IDs are `<cc>:<level>:<code>`:
   `us:place:1714000` (Chicago), `us:county:34013`, `us:zcta:07102`, `us:congressional_district:3410`,
   `us:precinct:34013030504`, `ca:federal_electoral_district:35110`. Cities and towns are level `place`: incorporated
   places plus Census-designated places (named unincorporated communities; `extra.incorporated` is false).
2. Walk down with `list_children` (state → counties/districts, county → precincts/towns, riding → polling divisions),
   or across with `list_geographies` (all districts of one kind in a state/province).
3. Cross between units with `related_geographies`: a precinct's, town's, city's or county's congressional and
   legislative districts (a city also lists its counties); every precinct in a district (`level='precinct'`); the ZIP
   codes in a city, county or district (`level='zcta'`). `weight` is the population share; 'overlaps' means split.
4. Check a precinct's `vintage` and `source_id` before relying on it. Current official precincts (2022–2026) cover
   about 92% of the US population: statewide files in 34 states + DC, county/town files elsewhere. Counties without
   one keep 2020 Census VTDs (`data_freshness` lists every source and licence). Replaced 2020 VTDs remain as level
   `vtd_2020`. Oregon counties without a current file have no precinct rows. Canada has federal polling divisions
   (2025), provincial ridings and, for most provinces, provincial polling divisions.
5. To find what contains an address, geocode it, then call `locate_point` (true point-in-polygon; results flagged
   `approximate` were snapped to the nearest shape within ~1 km). `nearest_geographies` is only a nearest-centroid
   approximation. For a ZIP code, use `us:zcta:<zip>` (2020 Census ZIP Code Tabulation Areas): `related_geographies`
   gives its cities, counties, towns, precincts and districts with each one's share of the ZIP's population (use the
   shares to split ZIP-level data across counties or cities), and `get_boundaries`
   with `children_level='precinct'` draws its precincts. Tell users ZCTAs only approximate USPS ZIP Codes
   (PO-box-only ZIPs have none).
6. For maps, call `get_boundaries` with `children_level` (every `place` in a state, every `precinct` in a county) and
   `include_districts=true` if the dashboard joins results by district. Big sets come back as a `download_url`
   (hosted: `curl -o` it into the project within the hour) or a `file` (local: copy it in). Features carry `id`,
   `code`, `name`, `vintage` and `source_id`; join results on `code` within the county, and check `source_id` to tell
   current precincts from 2020 Census VTDs. Use detail `low` for a whole state, `medium` for a county.
7. Keep the `source` attribution from `get_geography` in anything you publish (Census: "Source: U.S. Census Bureau";
   Elections Canada: OGL-Canada notice; Statistics Canada: the "Adapted from Statistics Canada…" line).

When matching an election-night results feed (e.g. Clarity ENR precinct names) to precinct IDs, list the county's
precincts once and match names locally; precinct names in results feeds rarely match Census names exactly.

The hosted server is free and needs no key. It is rate-limited per IP address (60 requests a minute, 3,000 a day,
4 at once); on a 429, wait for the `Retry-After` seconds. Batch where you can: one `get_boundaries` call with
`children_level` beats hundreds of single-shape calls.

## Coverage

- cities and towns: 32,350
- ZIP codes (ZCTAs): 33,774
- counties: 3,222
- towns and townships: 36,297
- congressional districts: 437
- state senate districts: 1,958
- state house districts: 4,873
- voting precincts: 182,778
- Canadian federal ridings: 343
- federal polling divisions: 71,217
- provincial districts: 761

## Tools

### search_geographies(query: str, country: str | None = None, level: str | None = None, region: str | None = None, limit: int = 20)

Find geographies by name, e.g. 'Essex County', 'Newark ward 5', 'Toronto Centre'.

country: 'US' or 'CA'. level: one of the levels from coverage_summary (e.g. 'county', 'precinct',
'congressional_district', 'federal_electoral_district'). region: USPS state or province code ('NJ', 'ON').

### get_geography(id: str)

Full record for one geography: attributes, parent chain up to the country, child counts by level,
and the source it came from (licence, vintage, last fetched).

### list_children(id: str, level: str | None = None, limit: int = 200, offset: int = 0)

Geographies directly under `id` (state -> counties and districts, county -> precincts and towns,
province -> ridings). Filter with `level`; page with limit/offset (max 1000).

### list_geographies(country: str, level: str, region: str | None = None, limit: int = 500, offset: int = 0)

Every geography at one level, optionally within one state/province, e.g. all congressional districts
in 'NJ' or all federal ridings in 'ON'. Page with limit/offset (max 1000).

### related_geographies(id: str, level: str | None = None, min_weight: float = 0.0, limit: int = 500, offset: int = 0)

Links between geographies that overlap without nesting, with population shares.

Districts: for a precinct, county, town, city (place) or ZIP, the congressional, state senate and state house
districts it falls in; for a district, the precincts, counties, towns, cities or ZIPs inside it (filter with
`level`, e.g. 'precinct'). A city ('us:place:1714000') also lists its counties. A ZIP ('us:zcta:07102') lists the
cities, counties, towns, precincts and districts it overlaps. Ask for `level='zcta'` on a city, county, town or
district to list the ZIP codes in it.
`weight` is the share of the smaller unit's 2020 population inside the other (for a ZIP, the share of the ZIP's
residents in each unit; 0 for parts with land but no residents). relation 'within' means wholly inside (1.0),
'overlaps' means split, 'approximate' means the unit was too small to contain any 2020 block's internal point and
was placed by the nearest block. Use min_weight to drop slivers. ZCTAs approximate USPS ZIP Codes.

### locate_point(lat: float, lon: float, levels: list[str] | None = None)

Which geographies contain a point: precinct, county, town, congressional and state legislative districts in
the US; province, census division and subdivision, federal riding, polling divisions and provincial districts in
Canada. Point-in-polygon on stored boundaries (simplified to ~10 m, so a point within ~10 m of a line can land on
either side). Geocode an address to lat/lon first.

levels: restrict to some levels (default: all except 'vtd_2020'). If a point is just outside every shape of a
level that its state/province has (a pier, a beach, a gap between precinct files), it is matched to the nearest
shape of that level in the same state/province within ~1 km and flagged approximate=true with distance_m.
not_found lists levels the state/province has data for but no shape here; no_data lists levels with no
boundaries there at all (e.g. Nebraska has no state house; Ontario has no provincial polling divisions here).

### get_boundaries(id: str, children_level: str | None = None, detail: str = 'medium', include_districts: bool = False, clip_to_land: bool = True, offset: int = 0, limit: int = 2000, inline_max_kb: int = 100)

Polygon boundaries as a GeoJSON FeatureCollection (EPSG:4326, RFC 7946 winding), for drawing dashboard maps.

id: the geography to draw, e.g. 'us:county:34013'. children_level: draw everything at that level inside it
instead, e.g. every 'precinct' in a county or state, every 'county' in a state, every 'polling_division' in a
riding, or every 'precinct' overlapping a congressional district (any share; use related_geographies for shares).
detail: 'high' (~10 m), 'medium' (~50 m, default) or 'low' (~200 m). Neighbouring shapes from the same source
share identical edges at every detail level. clip_to_land: trim open water (ocean, bays, Great Lakes) using
the state/province shoreline outline (default true; inland lakes are not trimmed; shorelines are generalized
to ~1:500k, widened ~200 m so land isn't cut); false gives legal extents. include_districts: add each feature's
congressional / state senate / state house district holding the largest share of its population.
Feature properties: id, level, code, name, parent_id, region, population (2020 Census for precincts and towns,
latest estimate for counties and states), vintage and source_id (2020 Census VTDs have source_id
'us-census-vtd-2020'; current precincts don't), shape_source.

Small results come back inline as `geojson`. Larger ones are not returned inline (they'd flood the
conversation): the hosted service returns a short-lived `download_url` (fetch it with curl into your project);
a local server writes the file to its own export folder and returns `file` (copy it into your project). Page
big selections with offset/limit (max 5000 features).

### nearest_geographies(lat: float, lon: float, level: str, limit: int = 5)

Geographies at `level` whose internal point is closest to (lat, lon). This is a nearest-point
approximation, not point-in-polygon. To find the geography containing a point, use locate_point.

### data_freshness()

When each upstream dataset was last fetched and checked, what period it describes (vintage),
how often it is re-checked, and whether it is overdue. Includes the recent refresh history.

### coverage_summary()

What's in the atlas: row counts by country and level, with the vintage of each layer.

## FAQ

**Is there an MCP server for US boundaries like cities, ZIP codes, counties and districts?**
Yes. Boundary Atlas is a free MCP server of US and Canadian boundaries: cities and towns, ZIP codes, counties, towns and townships, congressional and state legislative districts, and voting precincts, plus Canadian provinces, ridings and polling divisions. Add https://atlas-production-d344.up.railway.app/mcp to Claude, ChatGPT, Cursor or Codex; no key or sign-up.

**What city, county and congressional district is an address in?**
Geocode the address to latitude and longitude, then call locate_point: a point-in-polygon lookup that returns the city, county, town, ZIP code, congressional and state legislative districts and voting precinct containing it. The map demo does this for any US address with the free Census Geocoder.

**What county or city is a ZIP code in?**
Often more than one: ZIP codes cross county lines and city limits (90210 is mostly Beverly Hills and partly Los Angeles). related_geographies on a ZIP (for example us:zcta:90210) returns every city, county and town it overlaps with each one's share of the ZIP's 2020 population, so you can split ZIP-level data correctly.

**How do I find which congressional district a ZIP code is in?**
Many ZIP codes span more than one district, so a single answer is often wrong. Ask Boundary Atlas for the ZIP: related_geographies returns every congressional, state senate and state house district it overlaps with each one's share of the ZIP's residents, and get_boundaries draws them.

**Which ZIP codes are in a city, county or district?**
Call related_geographies on the city, county or district with level='zcta'. Each ZIP comes with the share of its residents inside, so ZIPs that only clip the edge are easy to drop.

**Where can I get GeoJSON boundaries for cities, counties, districts or precincts?**
get_boundaries returns GeoJSON for any single area, or everything at one level inside another: every city in a state, every precinct in a county or district, every county in a state. Three detail levels; water can be trimmed. Large sets come back as a download link.

**How current are the precincts and district maps?**
Precincts are current official files for about 92% of the US population (statewide files in 34 states and DC, plus 437 county, town and municipio sources), with 2020 Census voting districts elsewhere. Districts are the maps in force for the November 3, 2026 election, including the 2025–26 mid-decade redraws.

**Are ZIP codes the same as ZCTAs?**
Not quite. ZIP Code Tabulation Areas are the Census Bureau's approximation of USPS ZIP Codes, built from 2020 blocks. PO-box-only and single-building ZIPs have none, and a mailing address's ZIP can differ from the ZCTA its location falls in. Boundary Atlas uses ZCTAs and says so.

**Does it cover Canada?**
Yes: provinces, census divisions and subdivisions, the 343 federal ridings (2023 Representation Order), federal polling divisions from the 2025 general election, provincial electoral districts, and provincial polling divisions for most provinces.

**Where does the data come from?**
Every record carries its source, licence, vintage and last update, and data_freshness lists each source with its refresh history. Sources include the U.S. Census Bureau (TIGER/Line and the 2020 Census; public domain), state and county election offices, Elections Canada and Statistics Canada. Keep their attribution in anything you publish.

**Is it free?**
Yes. The hosted server needs no key. It is rate-limited per IP address (60 requests a minute, 3,000 a day) so it stays fast for everyone.

## Attribution

Sources include the U.S. Census Bureau (TIGER/Line, 2020 Census; public domain), state and county election offices,
Elections Canada (Open Government Licence – Canada) and Statistics Canada ("Adapted from Statistics Canada…").
`data_freshness` lists every source with its licence and refresh history. Keep the attribution in anything you
publish.
