mcp-usgs-water-data
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-usgs-water-dataWhat's the flow of the Chattahoochee in Atlanta?"
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-usgs-water-data
An MCP server that exposes the USGS Instantaneous Values (IV) web service as tools — real-time and historical streamflow, gage height, water temperature, and related measurements from USGS gauges across the United States.
It is built for a language model to use safely. The USGS API is designed for browsers and bulk downloads; feeding its responses straight to a model goes wrong in ways that are easy to miss and hard to notice — a state-wide query returns megabytes of JSON, a "latest value" can be seven years old, and a river with no gauge returns an empty result the model will invent a reason for. This server exists to turn those traps into structured, self-describing answers.
What it does
Three tools:
Tool | Purpose |
| Resolve a place or river name to USGS station numbers. Start here when you know the river but not its 8- or 15-digit site number. |
| Fetch readings for one or more sites. The main tool. |
| Look up the 5-digit USGS code for a measurement (e.g. streamflow = |
The usual flow is find_sites → get_instantaneous_values. A model asking "what's the flow
of the Chattahoochee in Atlanta?" resolves the name to site 02336000, then reads it.
Related MCP server: SNOTEL MCP Server
Requirements
Node.js 22+ (uses native
fetchwith transparent gzip; no HTTP dependencies).
Install
npm install
npm run build # compiles TypeScript to dist/
npm test # 189 tests, no network access requiredConfigure your MCP client
The server speaks MCP over stdio. Point your client at the built entry file.
Claude Code (project-scoped, committable):
claude mcp add usgs-water --scope project -- node /absolute/path/to/dist/src/index.jsThis writes .mcp.json. Project-scoped servers are never auto-trusted — restart claude
in the project directory and approve the server once when prompted.
Any MCP client, directly:
{
"mcpServers": {
"usgs-water": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/dist/src/index.js"]
}
}
}The config runs
dist/, not the TypeScript source. Runnpm run buildafter any code change, or the server will keep running the old build.
Tools
get_instantaneous_values
Exactly one major filter is required to scope the query — providing zero or more than one is rejected before any network call:
Filter | Type | Notes |
|
| Station numbers, e.g. |
|
| Two-letter state code, e.g. |
|
| 5-digit FIPS codes, e.g. |
|
| Hydrologic Unit Codes: one 2-digit region, or up to ten 8-digit sub-basins. |
|
|
|
Optional narrowing: parameterCd (which measurements), siteType, siteStatus,
modifiedSince, agencyCd.
Time window — pick one, they are mutually exclusive:
(none) — the single latest value per sensor.
period— an ISO-8601 duration ending now, e.g."P7D"(last 7 days),"PT6H"(last 6 hours).startDT/endDT— an absolute range, e.g."2024-01-01"or"2024-01-01T12:00".endDTrequiresstartDT. Data begins 2007-10-01.
Output:
mode—"values"(default; individual readings) or"summary"(count, min, max, mean, first, last). Use"summary"for any window longer than a day — a single site over one year is ~35,000 readings.maxValues— cap on readings per series in"values"mode (default 200, max 1000).
find_sites
Same one-major-filter rule (sites / stateCd / countyCd / huc / bBox), plus:
nameContains— case-insensitive substring match on the station name. Applied client-side after fetching by the major filter, so it narrows the results, not the request. AstateCdquery can return hundreds of sites before filtering.siteType,siteStatus(default"active"),hasDataTypeCd(default"iv"— only sites that report instantaneous values),maxSites(default 50, max 500).
list_common_parameter_codes
No input. Returns the table below.
Code | Measurement | Unit |
| Discharge (streamflow) | ft³/s |
| Gage height | ft |
| Water temperature | °C |
| Specific conductance | µS/cm @25°C |
| Dissolved oxygen | mg/L |
| pH | std units |
| Turbidity | FNU |
| Precipitation | in |
| Depth to water level | ft |
| Lake/reservoir elevation (NGVD 1929) | ft |
| Lake/reservoir elevation (NAVD 1988) | ft |
| Air temperature | °C |
| Barometric pressure | mm Hg |
| Wind speed | mph |
| Wind direction | degrees |
| Relative humidity | % |
| Stream velocity (point) | ft/s |
Reading the output
The response has a top-level series array. Each series carries the site, the variable, the
sensor method, qualifier codes, and either readings or a summary. A few fields exist
specifically to prevent a confidently wrong answer, and a consumer should check them.
On each series:
stale(true/false/null) —truemeans the latest reading is more than 48 hours behind the query's reference time. USGS returns decommissioned sensors in a latest-value query, frozen at their final reading — a temperature sensor switched off in 2019 will otherwise look current.nullmeans staleness could not be evaluated. Check this before reporting any value as current.discontinued— the sensor is marked decommissioned in its metadata. A hint that explains why a series is stale; not itself a freshness signal.truncated/totalValues— set whenmaxValuescapped a series. You are seeing the most recent N, not the whole record.qualifiers — most recent USGS data is provisional (code
P) and subject to revision. These are never stripped.
On the response (not the series):
missingParameterCodes— present when you requested aparameterCda site does not measure. Series are not positionally aligned with the codes you asked for; match on each series'variable.code.note— a plain-language explanation attached to empty results, stale series, or dropped parameters, so an empty or partial answer is never silently ambiguous.
When a response would exceed 256 KB even after shaping, the server returns an error naming
summary mode rather than truncating silently.
Rate limiting
USGS publishes no numeric rate limit but blocks IP addresses it judges to be "seriously impacting others." A single client session can fan out — subagents issuing many concurrent tool calls all route through this one server process on one IP — so the server gates its own outbound traffic: a shared limiter with a concurrency cap, minimum spacing between requests, and a load-shedding valve that returns a "retry shortly" error rather than hanging when a burst overwhelms it. There is deliberately no retry-on-failure loop — retrying into a throttling server is how you earn the block.
Three environment variables, read once at startup:
Variable | Default | Meaning |
|
| Requests in flight at once. |
|
| Minimum gap between request starts (~13/s ceiling). |
|
| Shed a request that would wait longer than this. |
Tune concurrency and spacing up for a purely interactive deployment, down for a
scheduled batch collector. Negative and non-numeric values fall back to the default. Zero
falls back for concurrency and queue-wait (both are degenerate at 0 — a zero concurrency
cap deadlocks, a zero queue-wait sheds every request), but 0 is a valid "no added spacing"
setting for the interval.
The upstream base URLs are not currently configurable; they are constants in src/usgs.ts
and src/sites.ts.
Scope and limits
No site lookup by coordinates-you-assert.
find_sitesresolves names and geographic filters; a bounding box you get wrong will still return an honest (possibly empty) result.Groundwater-only filters (aquifer codes, well/hole depth) are not exposed. Additive if needed.
503is not retried. The gate prevents the burst that causes throttling; it does not retry after one occurs.One documented staleness corner: a future
endDTcombined with a payload missing its request timestamp marks live data as stale. Unobserved in practice, errs toward caution.
Design rationale for every one of these decisions — and the live-service behavior that drove
them — is in DESIGN.md.
Development
npm run build # tsc -> dist/
npm test # build, then node --test (no network)Tests are deterministic and hermetic: no live network calls, no wall-clock or timezone
dependence (the suite passes identically under any TZ). Fixtures under test/fixtures/ are
real captured USGS responses, not synthesized.
License
MIT. USGS water data is in the public domain; this license covers the server code only.
Available Tools
3 toolsfind_sitesA
Look up USGS station numbers (siteNumber) to pass to
get_instantaneous_values - use this whenever you have a place or river name
("what's the flow of the Chattahoochee in Atlanta") rather than a station
number. Returned siteNumber values vary in length - typically 8 digits,
but 15 for many groundwater/well sites - pass them through to
get_instantaneous_values exactly as returned; do not truncate or pad.
Exactly one major filter is required: sites, stateCd, huc, bBox, or countyCd
same rule and the same named {west, south, east, north} bBox object as get_instantaneous_values.
nameContains filters results CLIENT-SIDE after fetching, not on the
request - the /site/ service silently ignores name-search parameters, so
this NARROWS a major filter's results rather than replacing it, and cannot
be used alone. Matching is case-insensitive (most USGS station names are
uppercase, e.g. "CHATTAHOOCHEE RIVER AT ATLANTA, GA", but not all are), so
match casually.
A broad major filter with no nameContains can return hundreds of sites -
Georgia alone has 544 IV-reporting sites - so pair a broad filter (stateCd,
a wide bBox) with nameContains when looking for a specific place, and
prefer a narrower filter (countyCd, huc) otherwise.
Defaults to hasDataTypeCd:"iv" (only sites that report instantaneous
values), since a site without IV data cannot be used with
get_instantaneous_values. Also defaults to siteStatus:"active", unlike
get_instantaneous_values (which sends no siteStatus default and so returns
readings from ALL sites) - the same major filter can therefore list fewer
sites here than get_instantaneous_values will actually return readings for.
Pass siteStatus:"all" to see inactive/discontinued sites too. Results are
capped at maxSites (default 50, maximum 500); when more match,
truncated:true and totalMatched: show how many were found in total. The
cap keeps the FIRST maxSites in USGS site-number order, which runs roughly
by drainage basin - raising maxSites therefore returns a geographic slice,
not a broader or more relevant sample. Narrow with nameContains or a
tighter major filter instead of raising maxSites.
| Name | Required | Description | Default |
|---|---|---|---|
| huc | No | Hydrologic Unit Codes: either one 2-digit major HUC, or one or more 8-digit HUCs (up to 10 total). At most one 2-digit HUC per request; 8-digit HUCs can be combined freely. | |
| bBox | No | Bounding box in decimal degrees, as named fields (not a positional array) so west/south/east/north cannot be silently transposed. Area (east-west)*(north-south) must be <= 25 square degrees. | |
| sites | No | USGS site numbers, typically 8 digits (e.g. "01646500"), but 15 digits for many groundwater/well sites (e.g. "334207084254801"). Pass them exactly as find_sites returns them; do not truncate or pad. Site-name lookup (e.g. "Potomac River") is not supported directly - use find_sites to resolve a name to a site number first. | |
| stateCd | No | ||
| countyCd | No | 5-digit FIPS county codes (state FIPS + county FIPS), e.g. "24031" for Montgomery County, MD. | |
| maxSites | No | ||
| siteType | No | ||
| siteStatus | No | active | |
| nameContains | No | Case-insensitive substring match against station names, applied CLIENT-SIDE after fetching - the /site/ service silently ignores name-search parameters, so this NARROWS the results of the major filter rather than the request itself. Cannot be used without a major filter. | |
| hasDataTypeCd | No | Only return sites that report this data type. Defaults to "iv" (instantaneous values), since a site with no IV data cannot be used with get_instantaneous_values. | iv |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and delivers richly: discloses that nameContains is applied client-side after fetching and that the /site/ service silently ignores name-search params; explains result ordering (first maxSites in USGS site-number order by drainage basin); exposes the siteStatus default divergence from get_instantaneous_values; documents the capped results and truncated/totalMatched behavior.
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 long but every paragraph earns its place—each covers a distinct, non-obvious behavioral or usage topic. Front-loaded with the purpose and primary use case, then progressively deeper caveats. Slightly verbose in places but justifiably so for the complexity of the behavior being disclosed.
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 10-parameter tool with no annotations and no output schema, the description is remarkably complete. It covers filters, defaults, side effects (truncation, client-side filtering), return quirks (siteNumber length variance, truncating/totalMatched), and ordering semantics. No meaningful gap remains for the agent to make bad decisions.
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 60%, so the description adds moderate value. It clearly explains the crucial nameContains client-side behavior (which the schema already touches on, but the description expands with the 'cannot be used alone' and 'narrows rather than replaces' semantics) and the major-filter-required rule. It doesn't re-explain already-covered params like huc/bBox, appropriately relying on the schema for those.
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+resource ('Look up USGS station numbers') and immediately ties it to a downstream consumer (get_instantaneous_values), distinguishing it from sibling tools. It gives concrete use cases (place/river name queries) that differentiate it from get_instantaneous_values and list_common_parameter_codes.
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 exhaustive when-to-use guidance: use when you have a place/river name rather than a station number; names get_instantaneous_values as the intended downstream consumer; explicitly contrasts siteStatus/default behavior with get_instantaneous_values; gives concrete strategy advice (pair broad filters with nameContains, prefer narrow filters otherwise) and tells when NOT to raise maxSites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_instantaneous_valuesA
Query the USGS Instantaneous Values (IV) service for real-time and recent surface-water and groundwater readings (streamflow, gage height, water temperature, etc). Data is available from 2007-10-01 onward.
Exactly one major filter is required to scope the query: sites, stateCd, huc,
bBox, or countyCd. Providing zero, or more than one, is rejected. sites
are USGS station numbers, typically 8 digits but 15 digits for many
groundwater/well sites - pass them exactly as find_sites returns them, do
not truncate or pad. Looking up a site by name (e.g. "Potomac River") is
not supported by this tool; call find_sites first to resolve a name to a
station number. bBox is an object
{west, south, east, north} in decimal degrees - west/east are longitude
(negative in the continental US), south/north are latitude (positive in the
continental US) - with area (east-west)*(north-south) capped at 25 square
degrees.
Date range: use either period (an ISO-8601 duration, e.g. P7D for the last
7 days) OR startDT/endDT for an absolute range - never both. endDT
requires startDT. A query - dated or not - can return readings that are
years old: a latest-value query returns the latest reading PER SENSOR,
including sensors quietly gone dormant or decommissioned years ago, and a
dated range can end early for one sensor while its siblings keep reporting
through the end of the window. Every series carries stale, which is
TRI-STATE, not a plain boolean: true (latest reading is more than 48 hours
behind the query's reference time), false (it is not), or null (staleness
could not be evaluated - no resolvable reference time, or no readings at
all). Treat null as "not verified", never as current - check stale before
reporting ANY value as current. discontinued explains WHY when USGS says
so in the sensor's method description, but is not itself the signal to
check - a sensor can go stale with no marker at all. When any returned
series is stale or unevaluable, the response includes a note naming which
ones, their reading dates, and how far behind they are.
This tool sends no siteStatus default, so USGS returns readings from ALL
sites regardless of status - unlike find_sites, which defaults to
siteStatus:"active". The same major filter can therefore return readings
from sites find_sites didn't list. This is unrelated to stale/discontinued:
a stale or decommissioned sensor sits at an otherwise-active site, so no
siteStatus value filters it out.
Use mode:"summary" (not the default "values") for any window longer than a
day. It returns {count, nonNullCount, min, max, mean, first, last} per series
instead of every reading, avoiding truncation. mode:"values" returns up to
maxValues (default 200, maximum 1000) of the MOST RECENT readings PER
SERIES and sets truncated:true when more exist - a site with two sensors
for the same parameter returns two series, each capped independently, so a
2-sensor site can still ship up to 2x maxValues readings total.
checkResponseSize backstops the overall payload regardless. A single site
over a single year already returns roughly 35,000 readings per series -
windows beyond about a year should always use mode:"summary".
Returned values may be provisional (qualifier code "P") and subject to revision - present them as such, not as final measurements.
A series is omitted entirely, with no placeholder, when a site does not
measure a requested parameter - a query for 3 parameterCd values can return
fewer than 3 series. Match results on each series' variable.code; do not
assume series[i] corresponds to parameterCd[i]. When this happens the
result includes missingParameterCodes.
Don't know the 5-digit parameter code for what you want? Call list_common_parameter_codes first.
| Name | Required | Description | Default |
|---|---|---|---|
| huc | No | Hydrologic Unit Codes: either one 2-digit major HUC, or one or more 8-digit HUCs (up to 10 total). At most one 2-digit HUC per request; 8-digit HUCs can be combined freely. | |
| bBox | No | Bounding box in decimal degrees, as named fields (not a positional array) so west/south/east/north cannot be silently transposed. Area (east-west)*(north-south) must be <= 25 square degrees. | |
| mode | No | values | |
| endDT | No | ||
| sites | No | USGS site numbers, typically 8 digits (e.g. "01646500"), but 15 digits for many groundwater/well sites (e.g. "334207084254801"). Pass them exactly as find_sites returns them; do not truncate or pad. Site-name lookup (e.g. "Potomac River") is not supported directly - use find_sites to resolve a name to a site number first. | |
| period | No | ISO-8601 duration for a relative window ending now, e.g. "P7D" for the last 7 days or "PT6H" for the last 6 hours. Cannot be combined with startDT/endDT. | |
| startDT | No | ||
| stateCd | No | ||
| agencyCd | No | ||
| countyCd | No | 5-digit FIPS county codes (state FIPS + county FIPS), e.g. "24031" for Montgomery County, MD. | |
| siteType | No | ||
| maxValues | No | ||
| siteStatus | No | ||
| parameterCd | No | ||
| modifiedSince | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden and delivers richly. It discloses tri-state `stale` semantics, how `discontinued` works, siteStatus default behavior differing from siblings, per-sensor capping of maxValues, truncation behavior, omission of series without placeholders and the missingParameterCodes signal, provisional ('P') qualifier handling, and that dated queries return readings as old as the window regardless.
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?
Long but every sentence earns its place, covering genuinely non-obvious behavior (stale being tri-state, per-sensor capping, no placeholder for missing series, years-old dormant readings). Well organized with thematic paragraphs and a closing pointer to list_common_parameter_codes. None of the length is filler or tautology.
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 15-parameter tool with no output schema and no annotations, this is remarkably complete. It covers the cardinality constraint, date-range exclusivity, the two modes' payload implications, staleness semantics, series-to-parameter matching, and sibling-tool handoffs. The only mild gap is no mention of `modifiedSince` or `agencyCd`, but the schema covers those adequately.
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 only 33%, so the description must compensate, and it does extensively for the critical params: sites (exact digits, from find_sites, no truncation), bBox (named fields, decimal degree signs, area cap), period (ISO-8601 examples), mode (summary vs values tradeoffs). It adds meaning beyond schema for these. Some params like modifiedSince, agencyCd, siteType get no prose, but those have self-evident schema descriptions.
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 begins with a specific verb-resource statement ('Query the USGS Instantaneous Values (IV) service for real-time and recent surface-water and groundwater readings') naming exact data types. It clearly differentiates from siblings: find_sites resolves names to station numbers (this tool does not), list_common_parameter_codes provides parameter codes. The scope is unambiguous.
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?
Exceptionally explicit: states the exactly-one-filter requirement (sites/stateCd/huc/bBox/countyCd) and that zero or more than one is rejected. Names alternatives explicitly ('call find_sites first', 'use list_common_parameter_codes first'). Distinguishes from find_sites' default siteStatus behavior and explains when summary mode should be used.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_common_parameter_codesA
Look up the 5-digit USGS parameter code for a common measurement (e.g. streamflow, gage height, water temperature, dissolved oxygen) before calling get_instantaneous_values. Returns a static table of {code, name, unit, description}. No network call.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses a key behavioral trait: 'No network call' and 'Returns a static table of {code, name, unit, description}' — describing the returned structure. This is good transparency for a zero-annotation tool, though it could mention whether the table is exhaustive or limited to common codes only.
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, two sentences, and front-loaded with the primary purpose. Every sentence earns its place — purpose, examples, return structure, and the non-network caveat. Slightly redundant phrasing could be trimmed, but it is appropriately concise.
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 static lookup tool with 0 params and no output schema, the description is quite complete: it covers what it returns, that it makes no network call, and the example use cases. It could list the full set of supported measurements or any limitations, but for its simplicity it is well-rounded.
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 0 parameters and 100% schema coverage (empty schema completes the picture). Baseline for 0-param tools is 4. The description adds useful context about what the returned record fields are ({code, name, unit, description}), which is additional value beyond the empty 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?
The description clearly states a specific verb+resource: 'Look up the 5-digit USGS parameter code for a common measurement.' It explicitly distinguishes from siblings by naming the purpose (getting codes before calling get_instantaneous_values) and noting this is a lookup/reference tool vs. the data-fetching siblings.
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?
It explicitly states when to use it: 'before calling get_instantaneous_values.' It gives the context (for common measurements like streamflow, gage height, water temperature, dissolved oxygen) and lists examples of what kind of lookup it serves, which orients the agent toward the correct choice among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
The three tools have clearly distinct purposes: get_instantaneous_values fetches readings, find_sites resolves place names to station numbers, and list_common_parameter_codes maps common measurements to parameter codes. There is minor potential confusion between find_sites and get_instantaneous_values since both share the same filter options (sites/stateCd/huc/bBox/countyCd), but their distinct roles (lookup vs. data retrieval) are well documented.
The names mix conventions: get_instantaneous_values and list_common_parameter_codes use verb_object patterns but get_instantaneous_values is awkwardly verbose while find_sites and the others are not consistently phrased. There's no consistent verb (get, list, find) and no consistent noun form, though all are readable snake_case verbs followed by a noun.
Three tools form a tight, well-scoped workflow: resolve sites, look up parameter codes, then fetch values. Each tool is essential and earns its place with no obvious redundancy. The tight coupling (find_sites feeds get_instantaneous_values, list_common_parameter_codes feeds parameterCd) justifies exactly these three.
The core workflow of finding sites, mapping parameters, and retrieving instantaneous values is fully covered. Minor gaps exist such as no support for daily values or other USGS services (which are out of scope given the server name), and the user must manually chain the three tools, but within the stated 'instantaneous values' domain the surface is complete.
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
Query real-time and historical USGS water data from ~8,000 stream gages and groundwater wells.
Real-time water levels and flow rates from USGS stream gauges
USGS Water MCP — wraps USGS National Water Information System (NWIS) REST services (free, no auth)
USGS Water Services (NWIS) MCP.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceProvides access to real-time water data from the USGS Water Services API, allowing users to fetch instantaneous measurements like stream flow, gage height, temperature, and water quality parameters from thousands of monitoring stations across the US.3
- AlicenseNot gradedqualityDmaintenanceProvides access to real-time and historical snow conditions, weather data, and snowpack analysis from over 800 SNOTEL stations across the western United States through the USDA Air and Water Database API.2MIT
- AlicenseNot gradedqualityFmaintenanceWraps USGS NWIS REST services to query water data such as streamflow, groundwater levels, and water quality.6MIT
- AlicenseNot gradedqualityAmaintenanceQuery real-time and historical water data from ~8,000 USGS stream gages and groundwater wells via MCP, with 7 tools and 2 resources.1461Apache 2.0
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/higherpass/mcp-usgs-water-data'
If you have feedback or need assistance with the MCP directory API, please join our Discord server