Content
# Geospatial Context MCP Server
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.
## Quick Start
```bash
npm install
npm run build
npm test
npm run list-tools
```
For local MCP clients after building:
```json
{
"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:
```yaml
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:
```yaml
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)
```
## Tools
### `reverse_geocode`
Resolve exact coordinates to an address-like location identity.
Input:
```json
{
"latitude": 37.8199,
"longitude": -122.4783,
"language": "en"
}
```
### `geocode_address`
Resolve a street address, place name, or location query to coordinates.
Input:
```json
{
"address": "350 5th Ave, New York, NY",
"language": "en"
}
```
### `nearby_osm_features`
Find nearby OSM features grouped into agent-friendly categories such as landmarks, transport, food, lodging, health, education, civic, parks, water, natural, and infrastructure.
Input:
```json
{
"latitude": 37.8199,
"longitude": -122.4783,
"radiusMeters": 1000,
"limit": 40,
"includeInfrastructure": false,
"priorityMode": "human_landmarks"
}
```
### `get_boundary_context`
Resolve coordinates or an address to timezone, administrative hierarchy, and US Census geographies when available.
Input:
```json
{
"address": "350 5th Ave, New York, NY",
"language": "en"
}
```
### `get_physical_context`
Resolve coordinates or an address to physical site context such as elevation and terrain summary.
Input:
```json
{
"latitude": 40.7484405,
"longitude": -73.9856644
}
```
### `get_location_context`
Compose geocoding/reverse geocoding and nearby features into a structured context packet plus a readable markdown brief.
Coordinate input:
```json
{
"latitude": 37.8199,
"longitude": -122.4783,
"radiusMeters": 1000,
"language": "en",
"includeInfrastructure": true,
"priorityMode": "balanced"
}
```
Address input:
```json
{
"address": "Eiffel Tower, Paris",
"radiusMeters": 1000,
"language": "fr",
"includeInfrastructure": false,
"priorityMode": "human_landmarks"
}
```
Provide either `address` or both `latitude` and `longitude`.
## Notes
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 identity
- `nearby`: categorized OpenStreetMap features
- `boundary`: timezone, admin hierarchy, and US Census geographies where available
- `physical`: elevation and terrain summary where available
`nearby` feature records include `matchedBy`:
- `center_within_radius`: the feature point/center is within the requested radius
- `geometry_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`, or `failed`
- `status.dataCoverage`: `rich`, `limited`, or `empty`
- `issues`: provider failures such as rate limits or unreachable APIs
- `notices`: 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:
```bash
GEO_CONTEXT_HTTP_RETRIES=2
REVERSE_GEOCODE_CACHE_TTL_MS=300000
```