US places then: county on a date, PLSS land, GNIS names, old topo maps, post offices.
An MCP server for where things were, then. Records follow the jurisdiction that held a place on the date of the event, not today's: a 1795 deed for a farm now in Greene County, Pennsylvania, is in Washington County's books, because Greene was carved out the next year. This server answers the questions that decide which office to write to:
Nothing here writes anywhere, and nothing here keeps a family tree. It sits well beside nara-catalog-mcp, which can run the archive searches this server builds, familysearch-mcp and snac-archives-mcp.
This is an independent project. It is not affiliated with, endorsed by, or supported by the Newberry Library, OpenHistoricalMap, the Bureau of Land Management, the US Geological Survey, Harvard Dataverse, the dataset's authors or the National Archives.
The server publishes twelve tools, all read-only and annotated so for the client. Five make no network call at all.
Jurisdiction at a date
| Tool | Purpose |
|---|---|
county_at | The county (or counties) that held a point on a date: a day, a month or a year. Returns the holder, its dates, the event and statute that made it, the whole chain of counties for that spot, changes within a year (check those by hand), and whether two governments contested it. |
county_history | Every version of one county: created when, from what, and each later change, with statutes. |
Federal land
| Tool | Purpose |
|---|---|
parse_legal_description | Read a land description, however it is written (E½NE, E2NE, E 1/2 NE 1/4, "the east half of the northeast quarter", GLO's padded 0840N, lots, several tracts), into its parts, with quarter-quarters and warnings for anything guessed. Offline. |
plss_locate | Place a description on the map: centroid, bounding box, acreage and BLM's ids, to the township, section, quarter-quarter or lot. |
plss_from_point | Name the survey tract at a point: township, range, section and quarter-quarter. |
public_land_state | Was this state federal land? If not, who granted first title and where those records are; if so, its meridians and special cases. Offline. |
Vanished places and old maps
| Tool | Purpose |
|---|---|
find_place_name | A named place in GNIS: its point, class, state and county. Searches the live GNIS and, given a state, the archive of August 2021 that keeps the cemeteries, churches, schools, post offices and buildings GNIS dropped that year; says which answered. |
post_offices | Which US post offices existed, 1639-2000: by name, by state and today's county, or around a point, and in a given year. Each with its years, whether it ran continuously, and its point if it was geocoded. |
historical_topo_maps | Every USGS topographic map covering a point, oldest first: date, scale and quadrangle, with GeoPDF, GeoTIFF and JPEG preview links, and a TopoView link for JPEG and KMZ. |
From patent to case file
| Tool | Purpose |
|---|---|
find_land_entry_file | From a patent's Authority: the kind of entry, what its file holds, which National Archives series has it, ready-made arguments for nara-catalog-mcp's search_records_advanced, and how to order the file if it is not online. Offline. |
glo_links | A link to a search, or to one record, on BLM's General Land Office Records site, for you to open. Offline. |
cache_status | This session's live calls and cache hits, and the datasets downloaded so far. Offline. |
You need Python 3.11 or later and uv. There is no key to request.
uvx us-places-mcp
or from a clone:
git clone https://github.com/ianderso/us-places-mcp
cd us-places-mcp
uv sync
uv run us-places-mcp # stdio server, usually launched by the client
{
"mcpServers": {
"places": {
"command": "uvx",
"args": ["us-places-mcp"]
}
}
}
If the server fails to start because uvx cannot be found, give the full path
that which uvx prints as the command.
claude mcp add places -- uvx us-places-mcp
Nothing is required. A .env file in the directory the server starts in
supplies anything the environment does not; only that directory is read.
| Variable | Meaning |
|---|---|
US_PLACES_OVERPASS_URL | OpenHistoricalMap's Overpass endpoint. Default https://overpass-api.openhistoricalmap.org/api/interpreter. |
US_PLACES_PLSS_URL | BLM's national PLSS map service. Default https://gis.blm.gov/arcgis/rest/services/Cadastral/BLM_Natl_PLSS_CadNSDI/MapServer. |
US_PLACES_GNIS_URL | USGS's GNIS map service. Default https://carto.nationalmap.gov/arcgis/rest/services/geonames/MapServer. |
US_PLACES_GNIS_ARCHIVE_URL | The folder of GNIS state files from August 2021. Default https://prd-tnm.s3.amazonaws.com/StagedProducts/GeographicNames/Archive/MainDomestic. |
US_PLACES_TNM_URL | The National Map's TNM Access products API. Default https://tnmaccess.nationalmap.gov/api/v1/products. |
US_PLACES_DATAVERSE_URL | Harvard Dataverse, which holds the post-office dataset. Default https://dataverse.harvard.edu. |
US_PLACES_CACHE_DIR | Response cache directory; downloaded datasets go in its data folder. Default ~/.cache/us-places-mcp. |
US_PLACES_TIMEOUT | HTTP timeout in seconds. Default 60. |
US_PLACES_CONTACT | An email address or URL added to the User-Agent, so the services can reach you. Optional, and courteous. |
Every URL must be https. Their hosts, and Dataverse's file store
(dvn-cloud-iqss.s3.amazonaws.com, where it redirects downloads), are the
only ones the server will contact.
OpenHistoricalMap's Overpass server runs on donated capacity and publishes no
rate limit. The server sends one request at a time to each service, two
seconds apart for OpenHistoricalMap, half a second for BLM and a second for
USGS and Dataverse, joins identical calls in flight, and caches answers on
disk: county answers for 90 days, GNIS and map answers for 30, survey answers
until you pass refresh=true. A 429 or a 5xx is retried three times with
back-off, then reported as rate_limited or upstream_error, which is never
the same as "nothing here".
Two sources are files rather than services, so the server downloads them once and reads them locally. Nothing is downloaded until a tool needs it, and the result that triggered a download says so: what, how big, how it was checked and where it was saved.
| Data | When | Size | Checked against |
|---|---|---|---|
| US Post Offices (Blevins and Helbock, doi:10.7910/DVN/NUKCNA, CC0) | The first post_offices call | 31 MB download, 21 MB on disk | The MD5 Dataverse publishes for the file |
| GNIS state file of 25 August 2021 (USGS, public domain) | The first find_place_name search in that state | Up to 17 MB per state (Pennsylvania 9.8 MB); only the dropped classes are kept, about 6 MB for Pennsylvania | The ETag USGS's bucket reports (an MD5, or the MD5 of the upload's parts) |
Both are stored as SQLite files in data under the cache directory
(~/.cache/us-places-mcp/data by default), never in the repository. A file
that fails its check is deleted and the tool reports download_failed.
cache_status lists what is there; delete the folder to start again.
boundary_change_within_a_year lists changes
close to your date. Laws took effect on stated days, but offices took time to
organise; records from those months can be in either county.county_at reads this from the atlas's event text."status": "contested" means look in both governments' records.parse_legal_description keeps the
original text and says what it guessed: a section number with no "Sec.", a
meridian taken from the state.public_land_state says where
first title was recorded.county_at.topo_quad names the 1:24,000 map each was read from.continuous: false. Moves within a town are not recorded.county_at.gnis_match shows what each was matched to and how closely.find's search text, never inside
a where clause, and local searches use bound parameters.To report a vulnerability, see SECURITY.md.
uv sync --extra dev
uv run pytest # mocked with respx; never touches a service
uv run ruff check .
uv run ruff format --check .
uv run python -m tests.live_check # a few paced calls to every live service
See CONTRIBUTING.md, docs/API-NOTES.md for what was observed of each service and when, and docs/DESIGN.md for why the server is shaped this way.
County boundaries: the Newberry Library's Atlas of Historical County Boundaries (John H. Long, editor), as imported into OpenHistoricalMap and released under CC0. Survey data: the Bureau of Land Management's National PLSS (CadNSDI), a US government work. Place names: the US Geological Survey's Geographic Names Information System, a US government work. Maps: USGS's Historical Topographic Map Collection, through The National Map. Post offices: Cameron Blevins and Richard W. Helbock, US Post Offices, Harvard Dataverse, doi:10.7910/DVN/NUKCNA, released under CC0.
MIT.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
uvx us-places-mcpMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-ianderso-us-places-mcp": {
"command": "uvx",
"args": [
"us-places-mcp"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referenceUS Places, Then works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.