mcp-usgs-water-data

mcp-usgs-water-data

Enables querying USGS water data including real-time and historical streamflow, gage height, and water temperature from USGS gauges across the United States.

Category
访问服务器

README

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
find_sites 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.
get_instantaneous_values Fetch readings for one or more sites. The main tool.
list_common_parameter_codes Look up the 5-digit USGS code for a measurement (e.g. streamflow = 00060). No network call.

The usual flow is find_sitesget_instantaneous_values. A model asking "what's the flow of the Chattahoochee in Atlanta?" resolves the name to site 02336000, then reads it.

Requirements

  • Node.js 22+ (uses native fetch with transparent gzip; no HTTP dependencies).

Install

npm install
npm run build   # compiles TypeScript to dist/
npm test        # 189 tests, no network access required

Configure 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.js

This 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. Run npm run build after 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
sites string[] Station numbers, e.g. ["01646500"]. Up to 100. Not river names — use find_sites.
stateCd string Two-letter state code, e.g. "NY".
countyCd string[] 5-digit FIPS codes, e.g. ["24031"]. Up to 20.
huc string[] Hydrologic Unit Codes: one 2-digit region, or up to ten 8-digit sub-basins.
bBox object { west, south, east, north } in decimal degrees. Longitudes are negative in the US. Area capped at 25 square degrees.

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". endDT requires startDT. 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. A stateCd query 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
00060 Discharge (streamflow) ft³/s
00065 Gage height ft
00010 Water temperature °C
00095 Specific conductance µS/cm @25°C
00300 Dissolved oxygen mg/L
00400 pH std units
63680 Turbidity FNU
00045 Precipitation in
72019 Depth to water level ft
62614 Lake/reservoir elevation (NGVD 1929) ft
62615 Lake/reservoir elevation (NAVD 1988) ft
00020 Air temperature °C
00025 Barometric pressure mm Hg
00035 Wind speed mph
00036 Wind direction degrees
00052 Relative humidity %
00055 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) — true means 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. null means 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 when maxValues capped 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 a parameterCd a 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
USGS_MAX_CONCURRENCY 4 Requests in flight at once.
USGS_MIN_INTERVAL_MS 75 Minimum gap between request starts (~13/s ceiling).
USGS_MAX_QUEUE_WAIT_MS 45000 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_sites resolves 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.
  • 503 is not retried. The gate prevents the burst that causes throttling; it does not retry after one occurs.
  • One documented staleness corner: a future endDT combined 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.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选