.codex-plugin — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited .codex-plugin (MCP Server) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
<div align="center"> <h1>@cyanheads/usgs-water-mcp-server</h1> <p><b>Query real-time and historical water data from ~8,000 USGS stream gages and groundwater wells via MCP. STDIO or Streamable HTTP.</b> <div>7 Tools • 2 Resources</div> </p> </div>
<div align="center">
</div>
<div align="center">
</div>
<div align="center">
Public Hosted Server: https://usgs-water.caseyjhand.com/mcp
</div>
Five tools for querying USGS water data, plus two for SQL analytics over the DuckDB-backed canvas dataframes that water_get_series materializes:
| Tool | Description |
|---|---|
water_list_parameters | Static lookup of well-known USGS parameter codes with names, units, and domain. No network call. |
water_find_sites | Find USGS monitoring sites by bounding box, state, county, or HUC watershed. Filter by site type and parameter availability. |
water_get_readings | Get the latest instantaneous values (~15 min real-time) for up to 100 USGS sites. |
water_get_series | Get a time series of daily or instantaneous values for a site over a date range. Large ranges spill to DataCanvas. |
water_get_conditions | Get current hydrologic conditions ranked against the full period-of-record percentile statistics. |
water_dataframe_describe | List tables and columns staged on a DataCanvas by water_get_series. |
water_dataframe_query | Run a read-only SQL SELECT against time-series tables staged by water_get_series. |
water_list_parametersStatic lookup of well-known USGS parameter codes — no network call, instant response.
00060 = Discharge (ft³/s), 00065 = Gage height (ft), 00010 = Temperature (°C), 72019 = Depth to water level (ft), and morestreamflow, groundwater, temperature, meteorological, water-quality, or allwater_find_sitesDiscover USGS monitoring sites before calling data tools — all other tools require a site number.
"west,south,east,north" decimal degrees), state code, FIPS county code, or HUC watershed codeST (stream), GW (groundwater well), LK (lake/reservoir), SP (spring), and moreiv), daily (dv), or groundwater (gw) datawater_get_readingsGet the latest instantaneous (~15 min) values for one or more USGS monitoring sites.
water_list_parametersPT2H = last 2 hours, P7D = last 7 days)parameterCd=72019 (the legacy gwlevels endpoint was decommissioned November 2025 — use the IV service instead)water_get_seriesGet a historical time series for a site and parameter over a date range.
CANVAS_PROVIDER_TYPE=duckdb is set — response includes canvas_id and table_name for follow-up SQL via water_dataframe_querytruncated flag and totalRecords countcanvas_id to append data to an existing canvaswater_get_conditionsGet current hydrologic conditions placed in full historical context.
record-high (≥ p95), above-normal (p75–p95), normal (p25–p75), below-normal (p10–p25), low (p05–p10), record-low (< p05)historicalContext: null and an explanatory notewater_dataframe_describe / water_dataframe_queryIn-conversation SQL analytics over the time-series dataframes that water_get_series materializes on a DuckDB-backed canvas.
Workflow:
water_get_series with a large date range — when DataCanvas is enabled, the response includes canvas_id and table_namewater_dataframe_describe with the canvas_id to confirm the table schema (columns: date_time, value, qualifiers, site_number, parameter_cd, unit_code)water_dataframe_query with the canvas_id and a SELECT statement to run aggregates, filter by qualifier, or join multiple seriesRead-only by default — only SELECT statements are permitted. Results are capped at 10,000 rows. Requires CANVAS_PROVIDER_TYPE=duckdb in the server environment.
| Type | Name | Description |
|---|---|---|
| Resource | usgs-water://site/{siteId} | Site metadata: name, coordinates, type, HUC, state, county, and available data types |
| Resource | usgs-water://parameters | Full parameter code catalog (same data as water_list_parameters) |
All resource data is also reachable via tools. Use water_find_sites for geographic site discovery.
Built on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1USGS NWIS–specific:
water_get_readings accepts up to 100 site numbers in one callwater_get_series materializes large date-range responses as DuckDB-backed df_<id> tables queryable via water_dataframe_query72019 — the legacy gwlevels endpoint was decommissioned November 2025Agent-friendly output:
percentileClass string (record-high, normal, record-low, etc.) they can act on directly without parsing numeric thresholdshistoricalContext: null with an explanatory note rather than an error, so the current reading is always available when the site is validwater_get_series always reports totalRecords and truncated so callers know when a preview is incomplete, and canvas_id / table_name tell them exactly how to retrieve the restA public instance is available at https://usgs-water.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:
{
"mcpServers": {
"usgs-water-mcp-server": {
"type": "streamable-http",
"url": "https://usgs-water.caseyjhand.com/mcp"
}
}
}Add the following to your MCP client configuration file.
{
"mcpServers": {
"usgs-water-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/usgs-water-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"usgs-water-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/usgs-water-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}Or with Docker:
{
"mcpServers": {
"usgs-water-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/usgs-water-mcp-server:latest"
]
}
}
}To enable DataCanvas for SQL analytics over large time-series results, add CANVAS_PROVIDER_TYPE=duckdb to the env block in any of the configs above.
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcpgit clone https://github.com/cyanheads/usgs-water-mcp-server.gitcd usgs-water-mcp-serverbun installcp .env.example .env
# Edit .env to set any optional overrides| Variable | Description | Default |
|---|---|---|
CANVAS_PROVIDER_TYPE | Set to duckdb to enable DataCanvas spillover for large time-series results from water_get_series. | — |
USGS_USER_AGENT | Custom User-Agent string sent to USGS NWIS. USGS requests a descriptive User-Agent per their terms. | usgs-water-mcp-server/0.1.7 (contact: https://github.com/cyanheads/usgs-water-mcp-server) |
USGS_REQUEST_TIMEOUT_MS | HTTP request timeout in milliseconds for NWIS calls. | 30000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
LOGS_DIR | Directory for log files (Node.js only). | <project-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry instrumentation (spans, metrics, completion logs). | false |
See .env.example for the full list of optional overrides.
# One-time build
bun run rebuild
# Run the built server
bun run start:stdio
# or
bun run start:http bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against specdocker build -t usgs-water-mcp-server .
docker run --rm -p 3010:3010 usgs-water-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/usgs-water-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools/resources and inits services. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts). |
src/mcp-server/resources | Resource definitions (*.resource.ts). |
src/services/nwis | NWIS HTTP client — IV, DV, site, and stat endpoints with HTML error detection. |
src/services/canvas | DataCanvas accessor for DuckDB-backed spillover. |
tests/ | Unit and integration tests mirroring src/. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagesrc/mcp-server/*/definitions/index.tsIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testApache-2.0 — see LICENSE for details.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.