mcp-server-usgs-nationalmap
Provides tools for querying USGS NHDPlus HR hydrography data via ArcGIS REST MapServer, including streams, rivers, lakes, gages, water features, and watershed boundaries.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-server-usgs-nationalmapFind the watershed for lat 40.7128, lon -74.0060"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-server-usgs-nationalmap
An MCP (Model Context Protocol) server that wraps the USGS NHDPlus High Resolution (NHDPlus HR) ArcGIS REST MapServer, letting an LLM query official U.S. hydrography — streams, rivers, lakes, stream gages, water features, and watershed boundaries — for a point or arbitrary GeoJSON geometry.
Service:
https://hydro.nationalmap.gov/arcgis/rest/services/NHDPlus_HR/MapServerSource: USGS — National Hydrography Dataset Plus High Resolution
Auth: none (public service)
Package:
hydro_mcp
What the dataset is
NHDPlus HR is a nationally seamless, routed hydrography network built from the high-resolution NHD, the Watershed Boundary Dataset (WBD), and 3DEP elevation. The MapServer exposes 13 layers; this server wraps the ones most useful for site/hydrology analysis.
Related MCP server: geocontext
Tools
All geometry tools accept either a lat + lon pair (convenience) or a
GeoJSON geometry string. Supported GeoJSON types: Point, MultiPoint,
LineString, MultiLineString, Polygon, MultiPolygon, plus a BoundingBox
shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}.
All coordinates are WGS84 decimal degrees. Feature geometry is not returned
(payloads stay small); results include provenance.
Tool | Layers | Purpose |
| NetworkNHDFlowline (3), optional NonNetworkNHDFlowline (4) | Streams/rivers/canals with stream order, drainage area, slope, elevation, and EROM modeled flow ( |
| NHDWaterbody (9), NHDArea (8) | Lakes, ponds, reservoirs, swamps, and areal water features (wide rivers, bays, rapids, dams). |
| NHDPlusGage (0) | Stream gages with NWIS linkage ( |
| NHDPoint (2), NHDLine (7) | Springs, waterfalls, dams/weirs, gates, levees, wells, etc. |
| WBDHU12 (12) | HUC12 watershed name, 12-digit code, downstream HUC ( |
| any of the above | Count-only guardrail; check result size before a |
| service root | Discover all 13 layers (id, name, geometry type). |
Conventions & gotchas
Coordinates: WGS84 lat/lon. Convert addresses/place names to coordinates first.
Point/line layers (gages, water features): pass a
PolygonorBoundingBoxto capture nearby features — a bare point rarely coincides exactly with a point/line feature.Feature codes:
ftype/fcodeare integers; results addftype_label/fcode_label(e.g.46006 → "Stream/River: Perennial").hutypeandpurpcodeare similarly labeled.Drainage-area units differ: gages report
dasqmiin square miles; flowlines/watersheds useAreaSqKm/TotalDrainageAreaSqKm.Pagination: each layer caps at 2000 records/request; results paginate automatically and set
truncated: trueif a cap is hit.Field names on the service are lowercase; the CamelCase forms are aliases.
Setup
uv syncRun
# stdio (Claude Desktop, Claude Code, local MCP clients)
uv run python -m hydro_mcp.app
# HTTP (set PORT or DATABRICKS_APP_PORT); served at /mcp, health at /health
PORT=8000 uv run python -m hydro_mcp.appProject structure
src/hydro_mcp/
├── app.py # FastMCP init, instructions, transport wiring
├── routes.py # /health endpoint
├── models.py # constants, layer IDs, curated field lists, code label maps, dataclasses
├── utils.py # ArcGIS HTTP client (stdlib urllib), GeoJSON->Esri, code translation
└── tools/ # one file per tool
├── __init__.py # register_tools(mcp)
├── find_waterways.py
├── find_waterbodies.py
├── find_gages.py
├── find_water_features.py
├── identify_watershed.py
├── count_features.py
└── list_layers.pyPossible future add-ons
The current tools are geometry-intersection queries. NHDPlus HR is a fully routed network, which opens up several higher-value tools not yet implemented:
Upstream/downstream network tracing (
hydro_trace_upstream/hydro_trace_downstream): walk the flowline network from a starting reach usinghydroseq,levelpathi,uphydroseq/dnhydroseq, andfromnode/tonode. Enables "what's upstream of this point?" and pollutant/ flow-path questions.Watershed routing traversal: follow
tohucfrom a starting HUC12 down the drainage chain (or accumulate the upstream set) to build drainage lineages.Catchment lookup (NHDPlusCatchment, layer 10): return the elevation-based incremental catchment polygon(s) for a location, and join to flowline VAAs via
nhdplusid.Reach-code / NHDPlusID lookup tools: fetch a specific reach or feature by
reachcode/permanent_identifier/nhdplusidrather than by geometry.Gage cross-walk to NWIS: resolve
sourceid/gageidmato live USGS NWIS streamflow observations.Attribute filtering: expose a
wherefilter (e.g. minimum stream order, perennial-only) on thefind_*tools for large-area queries.
Data source & attribution
USGS The National Map — National Hydrography Dataset Plus High Resolution (NHDPlus HR). Public domain. See https://www.usgs.gov/national-hydrography/national-hydrography-dataset.
Available Tools
7 toolshydro_count_featuresCount NHDPlus HR Features at GeometryARead-onlyIdempotent
Return ONLY how many features of a layer intersect a point or geometry (size check).
Use before the find_* tools to gauge result size without fetching full attributes -- useful for large polygons or densely mapped areas. A count of 0 means the geometry is outside coverage or has no features of that type.
Returns: { "count": int, "layer": str, "query_geometry": {"type": str, "crs_epsg": int}, "provenance": {...} }
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon'. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat'. Omit when supplying 'geometry'. | |
| layer | Yes | Which feature layer to count. One of: 'waterways' (flowlines), 'waterbodies', 'areas', 'gages', 'points', 'lines', 'watershed'. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or BoundingBox shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already declaring readOnlyHint and idempotentHint, the description adds substantial behavioral context: the tool returns ONLY a count (no full attributes), interprets a count of 0, provides exact return JSON structure, and lists specific error messages. This goes beyond what annotations alone convey, covering edge cases and response semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized and every sentence earns its place: a clear purpose, a usage guideline, an interpretation of results, and a concise return/error format. The inclusion of JSON and error examples is justified for agent clarity, and the structure is easily scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a relatively simple tool with 4 params and an output schema, the description fully covers the tool's role, output structure, and error conditions. It also addresses the only non-obvious outcome (zero count) and provides enough context for an agent to decide when to invoke it without needing to see the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the input schema already fully documents all parameters (lat, lon, layer, geometry) with their constraints and inter-dependencies. The tool description adds no extra parameter semantics beyond what is already in the schema, meeting the baseline for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool counts features intersecting a point or geometry, using a specific verb ('Return ONLY how many') and resource ('features of a layer'). It differentiates from sibling find_* tools by framing it as a size check, making its purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent exactly when to use this tool: 'Use before the find_* tools to gauge result size without fetching full attributes', and for what scenarios (large polygons, densely mapped areas). It also clarifies the meaning of a zero count, effectively guiding when not to proceed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_find_gagesFind NHDPlus Stream GagesARead-onlyIdempotent
Find NHDPlus stream gages intersecting a geometry (NHDPlusGage, layer 0).
Each gage links to NWIS via sourceid + sourceagency and reports the monitored drainage area (dasqmi, in SQUARE MILES) and reach location.
Use when: "What stream gages are in this watershed / bounding box?", "Which gage monitors this river reach?"
Because gages are point features, supply a Polygon or BoundingBox to find gages within an area (a bare point rarely coincides exactly with a gage).
Returns: { "finding": str, "count": int, "truncated": bool, "features": [...], # station_nm, sourceid, sourceagency, dasqmi (SQ MILES), ... "provenance": {...}, "query_geometry": {"type": str, "crs_epsg": int} }
NOTE: dasqmi is drainage area in SQUARE MILES (not sq km).
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon'. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat'. Omit when supplying 'geometry'. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or BoundingBox shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. Gages are points, so use a Polygon or BoundingBox to capture nearby gages. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent hints, the description extensively discloses behavior: the return payload structure, the unit clarification for dasqmi, explicit error messages, and the guidance about gage point sparsity affecting geometry choice. This is far richer than minimal annotation coverage requires.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections for purpose, usage, return values, units, and errors. While longer than the minimal example, each section provides necessary contract-level detail. Minor redundancy exists between the return structure and the unit note, but overall the information is dense and justified.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the full lifecycle of using this tool: what it does, when to use it, how to supply geometry, the exact return format, unit conventions, and error scenarios. With an output schema already present, the description adds no unnecessary return-value explanation and leaves no significant gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for all three parameters, including the mutual-exclusion rule and the recommendation to use Polygon/BoundingBox. The description only reiterates this guidance without adding new parameter-specific meaning, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Find NHDPlus stream gages intersecting a geometry' and identifies the specific layer (NHDPlusGage, layer 0). It also explains the gage attributes (NWIS linkage, drainage area) and distinguishes this from sibling tools by focusing on gages rather than waterways or waterbodies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes an explicit 'Use when:' section with example queries and provides practical advice on using Polygon/BoundingBox because gages are point features. It does not explicitly name alternative tools or when-not-to-use cases, but the context is clear enough for an agent to choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_find_waterbodiesFind NHD Waterbodies & Areal Water FeaturesARead-onlyIdempotent
Find NHD waterbodies (lakes, ponds, reservoirs, swamps) and areal water features.
Queries NHDWaterbody (layer 9) and/or NHDArea (layer 8) polygons intersecting the geometry. Both carry gnis_name, ftype/fcode, areasqkm, and elevation.
Use when: "Is there a lake within this parcel?", "What reservoirs intersect this bounding box?", "Name the waterbody at this point."
Returns: { "finding": str, "waterbody": {count, truncated, features, provenance}, # if requested "area": {count, truncated, features, provenance}, # if requested "query_geometry": {"type": str, "crs_epsg": int} }
ftype/fcode are integer codes; ftype_label/fcode_label give readable names.
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon'. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat'. Omit when supplying 'geometry'. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or BoundingBox shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. | |
| feature_class | No | Which polygon layer(s) to query: 'waterbody' (lakes/ponds/reservoirs/swamps), 'area' (wide rivers/bays/rapids/dams), or 'both'. Default 'both'. | both |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description adds substantial behavior not in annotations: queries layers 8/9, intersects geometry, returns structured result, and lists exact error messages. Annotations already declare readOnly/idempotent, but this details the operational contract.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose, use-case list, compact return snippet, and error examples. Every section earns its place; no filler despite being longer than average.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only query tool with output schema and 4 optional params, the description is remarkably complete: target layers, coordinate alternatives, return shape, and failure modes. No critical gap for an agent to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters, so baseline is 3. Description adds layer mapping (NHDWaterbody layer 9, NHDArea layer 8) and clarifies the feature_class options, plus shared attributes returned. This is extra semantic value, though most parameter syntax remains in schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opening line names exact targets ('NHD waterbodies ... and areal water features') with examples (lakes, ponds, reservoirs, swamps). This distinguishes from sibling hydro_find_waterways, which implies linear features, and the rest are distinct tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'Use when' examples (e.g., 'Is there a lake within this parcel?'). It gives clear contexts but doesn't state when NOT to use or name alternatives, so not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_find_water_featuresFind NHD Point & Line Water FeaturesARead-onlyIdempotent
Find NHD point & line water features (springs, waterfalls, dams, gates, levees, ...).
Queries NHDPoint (layer 2) and/or NHDLine (layer 7) intersecting the geometry. Both carry gnis_name and ftype/fcode; point features also carry reachcode.
Use when: "Are there any waterfalls or springs near this point?", "What dams/weirs cross this river within the bounding box?"
Because these are point/line features, supply a Polygon or BoundingBox to find features within an area.
Returns: { "finding": str, "point": {count, truncated, features, provenance}, # if requested "line": {count, truncated, features, provenance}, # if requested "query_geometry": {"type": str, "crs_epsg": int} }
ftype/fcode are integer codes; ftype_label/fcode_label give readable names.
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon'. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat'. Omit when supplying 'geometry'. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or BoundingBox shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. Use a Polygon or BoundingBox to capture nearby point/line features. | |
| feature_class | No | Which layer(s) to query: 'point' (springs/waterfalls/dams/gates/wells), 'line' (dams/gates/walls/levees/bridges), or 'both'. Default 'both'. | both |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint, idempotent, etc.), the description adds valuable context: it names the specific NHD layers (NHDPoint layer 2, NHDLine layer 7), explains return fields (gnis_name, ftype/fcode, reachcode), describes the JSON return structure with counts and truncation, and enumerates error responses. This is rich behavioral disclosure, though it could mention data freshness or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured and front-loaded, starting with a clear purpose, then usage guidance, then output format, and finally errors. It is moderately sized and each sentence adds value. Slight verbosity in the return section could be trimmed, but it is not gratuitous.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only query tool with no required parameters and a detailed output schema in the description, the tool description is nearly complete. It covers use cases, output format, and error handling. It could be improved by referencing sibling tools for alternatives, but overall it fully equips an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides descriptions for all four parameters (100% coverage). The description adds meaningful guidance beyond the schema: it stresses using Polygon/BoundingBox for area searches, clarifies that point features include reachcode, and explains the ftype/fcode vs ftype_label/fcode_label distinction, helping the agent interpret results correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool finds NHD point & line water features, listing specific examples (springs, waterfalls, dams, gates, levees). It uses a specific verb 'Find' and the resource is well-defined, distinguishing it from sibling tools that focus on waterways/waterbodies/gages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit 'Use when' examples with concrete queries ('Are there any waterfalls or springs near this point?') and notes the geometric requirement (Polygon or BoundingBox) for point/line features. However, it does not explicitly mention alternative sibling tools when those are more appropriate, so it lacks direct exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_find_waterwaysFind NHD Waterways (Flowlines)ARead-onlyIdempotent
Find NHD flowlines (streams, rivers, canals, artificial paths) intersecting a geometry.
Uses NHDPlus HR NetworkNHDFlowline (layer 3), which carries stream order, total drainage area (totdasqkm), slope, smoothed elevation, and EROM mean-annual flow (qama, cfs) / velocity (vama, fps) estimates.
Use lat+lon when: "What river runs through 45.5, -122.6?" Use geometry when: "What streams cross this project polygon / pipeline corridor?" Set include_non_network=True to also capture isolated (non-routed) flowlines. Set verbose=True for the full attribute set (network IDs + full EROM suite).
Returns: { "finding": str, # plain-language summary "count": int, "truncated": bool, # true if capped at max_records "features": [...], # flowline attributes (+ ftype_label / fcode_label) "non_network": {...}, # present only when include_non_network=True "provenance": {...}, "query_geometry": {"type": str, "crs_epsg": int} }
ftype/fcode are integer codes; ftype_label/fcode_label give readable names.
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon' for a quick point query. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat' for a quick point query. Omit when supplying 'geometry'. | |
| verbose | No | Return ALL flowline attributes (~80 fields incl. full EROM modeled-flow suite and network-navigation IDs) instead of the curated core set. Only applies to the network flowline layer. Default False. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon. Also accepts a BoundingBox shorthand: {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. | |
| include_non_network | No | Also query the NonNetworkNHDFlowline layer (isolated flowlines with identity attributes only, no stream order / drainage area / flow). Default False. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, idempotent), the description discloses truncation via 'truncated' field, conditional fields like 'non_network' only present when include_non_network=True, and lists exact error response strings. It also details the data source and attribute set, providing rich behavioral context without contradicting annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections: purpose, data source, usage examples, return format, and error messages. Every sentence contributes useful information, and the formatting improves readability. It is thorough yet not verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity, the description covers input methods, optional flags, return structure, error handling, and provenance information. The presence of an output schema does not make this redundant; the description adds practical examples and clarifies expected outputs. It is fully adequate for an agent to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with detailed descriptions for each parameter. The description reinforces and adds usage context (e.g., lat/lon for point queries, geometry for polygons/corridors), and explains the meaning of verbose and include_non_network in practical terms. This adds value over the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool finds NHD flowlines (streams, rivers, canals, artificial paths) intersecting a geometry. It uses specific verbs and resources and distinguishes itself from sibling tools like hydro_find_waterbodies and hydro_find_gages by focusing on flowlines/waterways.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage scenarios: 'Use lat+lon when...' and 'Use geometry when...', with concrete example queries. It also explains when to set include_non_network and verbose, giving actionable guidance. However, it does not explicitly name alternative tools for when-not-to-use, though the sibling list and purpose make this mostly clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_identify_watershedIdentify HUC12 WatershedARead-onlyIdempotent
Identify the HUC12 watershed(s) containing/intersecting a geometry (WBDHU12, layer 12).
Returns the watershed name, 12-digit HUC code, downstream HUC (tohuc, for routing), hydrologic-unit type (hutype + label), area, and states.
Use when: "What watershed is this point in?", "Which HUC12 does this river reach drain to?", "List the sub-watersheds this project boundary spans."
A point returns the single containing HUC12; a polygon/bbox may intersect several.
Returns: { "finding": str, "count": int, "truncated": bool, "features": [...], # huc12, name, tohuc, hutype (+ hutype_label), areasqkm, states, ... "provenance": {...}, "query_geometry": {"type": str, "crs_epsg": int} }
Error responses:
"Error: supply either lat+lon or geometry, not both (or neither)"
"Error: unsupported geometry type ..."
"Error: NHDPlus HR request failed: ..."
| Name | Required | Description | Default |
|---|---|---|---|
| lat | No | Latitude in decimal degrees (WGS84). Use with 'lon'. Omit when supplying 'geometry'. | |
| lon | No | Longitude in decimal degrees (WGS84). Use with 'lat'. Omit when supplying 'geometry'. | |
| geometry | No | GeoJSON geometry object as a JSON string. Supported types: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon, or BoundingBox shorthand {"type": "BoundingBox", "bbox": [minLon, minLat, maxLon, maxLat]}. All coordinates must be WGS84 decimal degrees. Supply either this OR lat+lon, not both. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, and non-destructive hints, but the description adds substantial behavioral context: the full return JSON structure (finding, count, truncated, features, provenance, query_geometry), error message formats, and the point-vs-polygon intersection behavior. This goes far beyond the annotations and fully discloses side effects (none) and edge cases.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, then efficiently organized into return schema, use cases, and error responses. Every section earns its place; the JSON return block is compact and informative, and there is no redundant filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an existing output schema, the description includes a clear return structure and error handling, making it self-contained. It covers usage scenarios, input constraints, output fields, and possible failure modes, leaving no significant ambiguity for an agent selecting or invoking the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%—all three parameters (lat, lon, geometry) are described in the schema. The description adds value by explicitly stating the mutual exclusivity of lat/lon vs. geometry, listing supported geometry types including BoundingBox, and noting that coordinates must be WGS84. This supplements, rather than repeats, the schema info.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Identify the HUC12 watershed(s) containing/intersecting a geometry' and adds context 'WBDHU12, layer 12'. It clearly distinguishes from sibling tools (waterways, waterbodies, gages) by focusing on watershed identification, reinforced by concrete use-case questions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a 'Use when:' section with three example queries, providing clear context for when to invoke the tool. It also explains the differing behavior for point vs. polygon inputs. However, it does not explicitly mention when not to use it or direct users to an alternative sibling tool, so it lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
hydro_list_layersList NHDPlus HR Service LayersARead-onlyIdempotent
List the layers available in the NHDPlus HR service (id, name, geometry type).
Use when: You need to discover available layers beyond those wrapped by the find_* tools (e.g. NHDPlusCatchment, NHDPlusSink, FlowDirection, NHDPlusBoundaryUnit) or to confirm current layer IDs.
Returns: { "layers": [{"id": int, "name": str, "geometry_type": str}, ...], "provenance": {...} }
Error responses:
"Error: NHDPlus HR request failed: ..." -- network or service error
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds useful behavioral context by specifying the return structure (layers array with id/name/geometry_type and provenance) and error response format, which goes beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-organized: it opens with a one-line purpose, then provides a 'Use when' section, a Returns JSON example, and an error response format. Every sentence serves a clear function with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter listing tool with an output schema and strong annotations, the description fully covers the tool's behavior, output shape, and error handling. It also contextualizes its role among the find_* siblings, leaving no relevant gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema coverage is 100% and the description carries no parameter burden. Per the rubric, a 0-param tool receives a baseline of 4, and no additional parameter explanation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'List the layers available in the NHDPlus HR service (id, name, geometry type)' which clearly identifies the verb (list), the resource (NHDPlus HR service layers), and the specific output fields. It also differentiates from the find_* sibling tools by noting it covers layers 'beyond those wrapped by the find_* tools.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'Use when' section explicitly states two scenarios: discovering available layers beyond the wrapped find_* tools, and confirming current layer IDs. It also names the find_* tools as alternatives for feature-specific queries, providing clear context for when to prefer this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct NHD feature type or utility: flowlines, waterbodies/areas, gages, point/line features, watersheds, counting, and layer listing. Descriptions clearly separate geometry types and layer IDs, so no two tools overlap in purpose.
All tools follow a consistent hydro_<verb>_<noun> pattern in snake_case. The verbs (find, identify, count, list) appropriately reflect each action, and the noun components are unique and descriptive.
Seven tools is well-scoped for a hydrography-focused server, covering query, discovery, and utility operations without redundancy. Each tool earns its place.
The core NHD feature layers are covered (flowlines, waterbodies, gages, point/line features, HUC12), and count/list tools aid discovery. However, hydro_list_layers exposes additional layers like catchments and sinks that cannot be queried directly, leaving a minor gap.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Mireye Earth — federal-source-cited geospatial data for any MCP-aware agent.
Geospatial AI MCP server — satellite imagery, embeddings, weather, GNS governance
Hosted MCP server for live public-data APIs and Skills for AI agents.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn MCP server that gives LLMs access to geographic data conversion tools, enabling transformations between different formats like WKT, GeoJSON, CSV, TopoJSON, and KML, as well as performing reverse geocoding.92616MIT
- AlicenseNot gradedqualityFmaintenanceAn experimental MCP server providing spatial context for LLMs by interfacing with French Geoplateforme services. It enables tasks such as geocoding, altitude lookups, and querying administrative, cadastral, or urban planning data.124MIT
- AlicenseAqualityBmaintenanceAn MCP server that gives AI agents clean, token-efficient access to US civic & property data — geocoding, census tracts, Opportunity Zones, ACS demographics, and FEMA flood zones — sourced entirely from free federal open data.5521MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that gives AI assistants direct access to the FEMA National Flood Hazard Layer (NFHL) for flood zone lookups, FIRM panel information, and flood map data in the United States.15MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/GSA-TTS/mcp-server-usgs-nationalmap'
If you have feedback or need assistance with the MCP directory API, please join our Discord server