geotap-mcp-server 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/package.json +2 -2
- package/src/index.js +24 -19
- package/src/sources.js +2 -0
- package/src/tools.js +33 -8
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# GeoTap Developer
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/geotap-mcp-server)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
3
6
|
**One API for 28+ US federal environmental and infrastructure data sources.**
|
|
4
7
|
|
|
5
8
|
GeoTap aggregates data from FEMA, USGS, EPA, NOAA, USDA, USFWS, DOT, Census, and more into a single REST API. This repository contains:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "geotap-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server for GeoTap — access 28+ US federal environmental and infrastructure data sources from Claude, Cursor, and other AI tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
},
|
|
50
50
|
"repository": {
|
|
51
51
|
"type": "git",
|
|
52
|
-
"url": "https://github.com/jcholly/geotap-
|
|
52
|
+
"url": "https://github.com/jcholly/geotap-developer"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/src/index.js
CHANGED
|
@@ -9,34 +9,39 @@ import { toolSources } from './sources.js';
|
|
|
9
9
|
|
|
10
10
|
const server = new McpServer({
|
|
11
11
|
name: 'geotap',
|
|
12
|
-
version: '1.
|
|
12
|
+
version: '1.2.0',
|
|
13
13
|
description: 'Access 28+ US federal environmental and infrastructure data sources. Query flood zones, wetlands, soils, rainfall, watersheds, water quality, endangered species, elevation, land use, and more for any location in the United States.',
|
|
14
14
|
instructions: `You have access to GeoTap, which provides real-time data from 28+ US federal agencies (FEMA, USGS, NOAA, EPA, NRCS, USFWS, USACE, and more).
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
START HERE — CORE TOOLS (use these for 90% of queries):
|
|
17
|
+
1. query_address — Geocode + environmental lookup in ONE call. Always start here when user gives an address.
|
|
18
|
+
2. identify_features_at_point — Same as above but when you already have lat/lng coordinates.
|
|
19
|
+
3. get_rainfall_data — NOAA Atlas 14 precipitation data for any US location.
|
|
20
|
+
4. get_environmental_summary — Quick feature counts for an area (no geometry, just numbers).
|
|
21
|
+
5. geocode_address — Convert address to coordinates (only needed if query_address doesn't cover your use case).
|
|
22
|
+
|
|
23
|
+
These 5 tools handle most questions. Use specialized tools only when these don't cover the request.
|
|
24
|
+
|
|
25
|
+
RESPONSE SIZE MANAGEMENT:
|
|
26
|
+
- query_address and identify_features_at_point always return <5KB (no geometry, just properties + interpretations).
|
|
27
|
+
- For all other spatial tools, ALWAYS set geometry="none" unless the user specifically needs coordinates.
|
|
28
|
+
- Always specify layers (e.g., layers="flood_zones,wetlands") instead of querying all 19 layers.
|
|
29
|
+
- In urban areas, full-geometry responses can exceed 1MB. Geometry="none" reduces this to <10KB.
|
|
27
30
|
|
|
28
31
|
COMMON WORKFLOWS:
|
|
29
|
-
- "
|
|
30
|
-
- "
|
|
31
|
-
- "Environmental due diligence" →
|
|
32
|
+
- "What flood zone is this address in?" → query_address (one call, done)
|
|
33
|
+
- "Is this a good place to build?" → query_address → get_rainfall_data → get_environmental_summary
|
|
34
|
+
- "Environmental due diligence" → query_address (covers flood, wetlands, soils, contamination, habitat)
|
|
35
|
+
- "What's the 100-year rainfall?" → get_rainfall_data
|
|
32
36
|
- "Hydrology analysis" → watershed delineate + curve numbers + rainfall + peak flow
|
|
33
|
-
- "Export data" → query
|
|
37
|
+
- "Export data" → query layers, then export tool for GeoJSON/Shapefile/CSV/KML
|
|
34
38
|
|
|
35
39
|
IMPORTANT NOTES:
|
|
36
|
-
- All data comes from authoritative federal sources. Always mention the source agency
|
|
37
|
-
-
|
|
40
|
+
- All data comes from authoritative federal sources. Always mention the source agency.
|
|
41
|
+
- Responses include _interpretation fields with plain-English summaries — use these in your answers.
|
|
42
|
+
- This data is for informational purposes. Remind users to verify critical data for engineering/regulatory decisions.
|
|
38
43
|
- Coordinates must be within the United States (including territories).
|
|
39
|
-
- Some tools (watershed delineation, hydrology) can take 10-60 seconds
|
|
44
|
+
- Some tools (watershed delineation, hydrology) can take 10-60 seconds.
|
|
40
45
|
- Layer names use underscores: flood_zones, wetlands, dem_elevation, building_footprints, etc.`
|
|
41
46
|
});
|
|
42
47
|
|
package/src/sources.js
CHANGED
|
@@ -63,6 +63,8 @@ const MULTI_SOURCE = [
|
|
|
63
63
|
*/
|
|
64
64
|
export const toolSources = {
|
|
65
65
|
// ── Spatial Queries ──
|
|
66
|
+
query_address: MULTI_SOURCE,
|
|
67
|
+
identify_features_at_point: MULTI_SOURCE,
|
|
66
68
|
get_environmental_data_for_area: MULTI_SOURCE,
|
|
67
69
|
get_environmental_data_near_point: MULTI_SOURCE,
|
|
68
70
|
get_environmental_summary: MULTI_SOURCE,
|
package/src/tools.js
CHANGED
|
@@ -17,27 +17,50 @@ export const tools = [
|
|
|
17
17
|
// ═══════════════════════════════════════════════════════════════════
|
|
18
18
|
// SPATIAL QUERIES — Query environmental data by geography
|
|
19
19
|
// ═══════════════════════════════════════════════════════════════════
|
|
20
|
+
{
|
|
21
|
+
name: 'query_address',
|
|
22
|
+
description: `The recommended starting tool for most queries. Geocodes a US address AND queries environmental data at that location in a single call. Returns flood zones, wetlands, soils, critical habitat, contamination sites, and more — with plain-English interpretations (e.g., "High-risk flood zone. Flood insurance required."). No geometry in response — just properties and interpretations. Response is always small (<5KB). Use this FIRST when the user provides an address. Only use geocode_address separately if you need coordinates for other tools.`,
|
|
23
|
+
parameters: {
|
|
24
|
+
address: z.string().describe('US street address (e.g., "123 Main St, Houston TX")'),
|
|
25
|
+
layers: z.string().optional().describe('Comma-separated layer names. Defaults to: flood_zones, wetlands, soil_map_units, critical_habitat, protected_lands, brownfields, superfund, npdes_outfalls, sole_source_aquifers')
|
|
26
|
+
},
|
|
27
|
+
endpoint: '/query-address',
|
|
28
|
+
method: 'GET'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'identify_features_at_point',
|
|
32
|
+
description: `Identify what environmental features exist at an exact lat/lng point. Returns ONLY properties (no geometry) with plain-English interpretations. Response is always small (<5KB). Use this when you already have coordinates. For addresses, use query_address instead (it geocodes + queries in one call). Returns flood zones, wetlands, soils, critical habitat, protected lands, brownfields, Superfund, NPDES outfalls, and sole source aquifers by default.`,
|
|
33
|
+
parameters: {
|
|
34
|
+
lat: z.number().describe('Latitude (WGS84)'),
|
|
35
|
+
lng: z.number().describe('Longitude (WGS84)'),
|
|
36
|
+
layers: z.string().optional().describe('Comma-separated layer names (e.g., "flood_zones,wetlands,soil_map_units"). Defaults to key regulatory layers.')
|
|
37
|
+
},
|
|
38
|
+
endpoint: '/spatial/point',
|
|
39
|
+
method: 'GET'
|
|
40
|
+
},
|
|
20
41
|
{
|
|
21
42
|
name: 'get_environmental_data_for_area',
|
|
22
|
-
description: `Query all available US federal environmental and infrastructure data within a geographic area (polygon). Returns features from 28+ data sources
|
|
43
|
+
description: `Query all available US federal environmental and infrastructure data within a geographic area (polygon). Returns features from 28+ data sources. WARNING: responses can be very large (100KB-2MB+) in urban areas with full geometry. ALWAYS set geometry="none" unless the user specifically needs coordinates. Specify layers to reduce response size. For simple "what's at this location?" questions, use query_address or identify_features_at_point instead — they're faster and return <5KB.`,
|
|
23
44
|
parameters: {
|
|
24
45
|
polygon: z.object({
|
|
25
46
|
type: z.literal('Polygon'),
|
|
26
47
|
coordinates: z.array(z.array(z.array(z.number())))
|
|
27
48
|
}).describe('GeoJSON Polygon geometry defining the area of interest'),
|
|
28
|
-
layers: z.array(z.string()).optional().describe('Optional array of specific layer names to query. If omitted, all layers are queried.')
|
|
49
|
+
layers: z.array(z.string()).optional().describe('Optional array of specific layer names to query. If omitted, all layers are queried.'),
|
|
50
|
+
geometry: z.enum(['none', 'simplified', 'full']).optional().describe('Geometry detail: "none" strips coordinates (smallest response), "simplified" reduces density, "full" returns complete geometry. Default: full. Use "none" when you only need properties.')
|
|
29
51
|
},
|
|
30
52
|
endpoint: '/spatial/in-polygon',
|
|
31
53
|
method: 'POST'
|
|
32
54
|
},
|
|
33
55
|
{
|
|
34
56
|
name: 'get_environmental_data_near_point',
|
|
35
|
-
description: `Query
|
|
57
|
+
description: `Query environmental data near a lat/lng point within a radius. WARNING: responses can be very large (50KB-1MB+) with default settings. ALWAYS set geometry="none" and specify layers to keep responses manageable. For "what's AT this exact location?" use identify_features_at_point or query_address instead — they return <5KB. Only use this tool when the user specifically needs data within a radius (e.g., "what EPA sites are within 2 miles?").`,
|
|
36
58
|
parameters: {
|
|
37
59
|
lat: z.number().describe('Latitude of the center point (WGS84)'),
|
|
38
60
|
lng: z.number().describe('Longitude of the center point (WGS84)'),
|
|
39
|
-
radius: z.number().optional().describe('Search radius in kilometers (default: 1)'),
|
|
40
|
-
layers: z.string().optional().describe('Comma-separated layer names to query. If omitted, all layers are queried.')
|
|
61
|
+
radius: z.number().optional().describe('Search radius in kilometers (min: 0.01, default: 1)'),
|
|
62
|
+
layers: z.string().optional().describe('Comma-separated layer names to query. If omitted, all layers are queried.'),
|
|
63
|
+
geometry: z.enum(['none', 'simplified', 'full']).optional().describe('Geometry detail: "none" strips coordinates (smallest response), "simplified" reduces density, "full" returns complete geometry. Default: full. Use "none" when you only need properties.')
|
|
41
64
|
},
|
|
42
65
|
endpoint: '/spatial/near',
|
|
43
66
|
method: 'GET'
|
|
@@ -57,10 +80,11 @@ export const tools = [
|
|
|
57
80
|
},
|
|
58
81
|
{
|
|
59
82
|
name: 'get_environmental_data_in_bbox',
|
|
60
|
-
description: `Query environmental data within a bounding box.
|
|
83
|
+
description: `Query environmental data within a bounding box. WARNING: responses can be very large with full geometry. Set geometry="none" and specify layers to keep responses small. For point lookups, use identify_features_at_point instead.`,
|
|
61
84
|
parameters: {
|
|
62
85
|
bbox: z.string().describe('Bounding box as "west,south,east,north" in WGS84 coordinates'),
|
|
63
|
-
layers: z.string().optional().describe('Comma-separated layer names to query')
|
|
86
|
+
layers: z.string().optional().describe('Comma-separated layer names to query'),
|
|
87
|
+
geometry: z.enum(['none', 'simplified', 'full']).optional().describe('Geometry detail: "none" strips coordinates (smallest response), "simplified" reduces density, "full" returns complete geometry. Default: full.')
|
|
64
88
|
},
|
|
65
89
|
endpoint: '/spatial/bbox',
|
|
66
90
|
method: 'GET'
|
|
@@ -90,7 +114,8 @@ export const tools = [
|
|
|
90
114
|
description: `Get features from a specific data layer within a bounding box. Use this tool when you need data from one specific source (e.g., just flood zones, or just wetlands) rather than all sources at once.`,
|
|
91
115
|
parameters: {
|
|
92
116
|
layerName: z.string().describe('The layer identifier (e.g., "flood_zones", "wetlands", "dem_elevation", "nlcd_land_cover", "contours", "building_footprints", "stream_gauges", "tide_stations", "weather_alerts", "air_quality")'),
|
|
93
|
-
bbox: z.string().describe('Bounding box as "west,south,east,north" in WGS84 coordinates')
|
|
117
|
+
bbox: z.string().describe('Bounding box as "west,south,east,north" in WGS84 coordinates'),
|
|
118
|
+
geometry: z.enum(['none', 'simplified', 'full']).optional().describe('Geometry detail: "none" strips coordinates (smallest response), "simplified" reduces density, "full" returns complete geometry. Default: full.')
|
|
94
119
|
},
|
|
95
120
|
endpoint: '/layers/{layerName}/features',
|
|
96
121
|
method: 'GET'
|