An MCP server that turns coordinates into agent-ready geospatial context: reverse geocoding, nearby OpenStreetMap features, and a compact sourced location brief.
The current implementation uses public OpenStreetMap infrastructure:
- Nominatim for reverse geocoding.
- Overpass API for nearby features.
Future provider slots can add Google Maps Platform, Google Earth Engine, Census, NOAA, FEMA, USGS, and local datasets without changing the MCP tool contract.
npm install
npm run build
npm test
npm run list-toolsFor local MCP clients after building:
{
"mcpServers": {
"geospatial-context": {
"command": "node",
"args": ["/home/unmodeledtyler/geospatial-context/dist/index.js"],
"env": {
"GEO_CONTEXT_USER_AGENT": "geospatial-context/0.1.0 (you@example.com)"
}
}
}
}Nominatim asks clients to identify themselves. Set GEO_CONTEXT_USER_AGENT to an app/contact string before heavy use.
Generic stdio server settings:
command: node
args:
- /path/to/geospatial-context/dist/index.js
env:
GEO_CONTEXT_USER_AGENT: geospatial-context/0.1.0 (you@example.com)Hermes Agent example:
mcp_servers:
geospatial-context:
command: node
args:
- /path/to/geospatial-context/dist/index.js
connect_timeout: 30
timeout: 180
env:
GEO_CONTEXT_USER_AGENT: geospatial-context/0.1.0 (you@example.com)Resolve exact coordinates to an address-like location identity.
Input:
{
"latitude": 37.8199,
"longitude": -122.4783,
"language": "en"
}Resolve a street address, place name, or location query to coordinates.
Input:
{
"address": "350 5th Ave, New York, NY",
"language": "en"
}Find nearby OSM features grouped into agent-friendly categories such as landmarks, transport, food, lodging, health, education, civic, parks, water, natural, and infrastructure.
Input:
{
"latitude": 37.8199,
"longitude": -122.4783,
"radiusMeters": 1000,
"limit": 40,
"includeInfrastructure": false,
"priorityMode": "human_landmarks"
}Resolve coordinates or an address to timezone, administrative hierarchy, and US Census geographies when available.
Input:
{
"address": "350 5th Ave, New York, NY",
"language": "en"
}Resolve coordinates or an address to physical site context such as elevation and terrain summary.
Input:
{
"latitude": 40.7484405,
"longitude": -73.9856644
}Compose geocoding/reverse geocoding and nearby features into a structured context packet plus a readable markdown brief.
Coordinate input:
{
"latitude": 37.8199,
"longitude": -122.4783,
"radiusMeters": 1000,
"language": "en",
"includeInfrastructure": true,
"priorityMode": "balanced"
}Address input:
{
"address": "Eiffel Tower, Paris",
"radiusMeters": 1000,
"language": "fr",
"includeInfrastructure": false,
"priorityMode": "human_landmarks"
}Provide either address or both latitude and longitude.
This server is intentionally read-only. It calls public geospatial APIs and returns source metadata with each result so agents can reason from evidence instead of inventing local context.
The main context packet now includes:
identity: geocoded or reverse-geocoded place identitynearby: categorized OpenStreetMap featuresboundary: timezone, admin hierarchy, and US Census geographies where availablephysical: elevation and terrain summary where available
nearby feature records include matchedBy:
center_within_radius: the feature point/center is within the requested radiusgeometry_intersects_radius: Overpass matched the feature geometry, but the returned center may sit outside the radius
get_location_context is resilient to sparse data and partial provider failures. The response separates provider health from result richness:
status.providerStatus:complete,partial, orfailedstatus.dataCoverage:rich,limited, oremptyissues: provider failures such as rate limits or unreachable APIsnotices: successful no-result responses, such as no reverse-geocode match
For compatibility, completeness is still included as an alias of status.providerStatus.
Provider calls retry transient HTTP failures, including 429 rate limits, and reverse-geocode results are cached briefly in memory. Tune with:
GEO_CONTEXT_HTTP_RETRIES=2
REVERSE_GEOCODE_CACHE_TTL_MS=300000