us-drought-monitor-mcp-server
RemoteAbout us-drought-monitor-mcp-server
An MCP server for weekly U.S. Drought Monitor data across national, state, county, watershed, and other geographies. It supports severity snapshots, time series, area rankings, drought-duration counts, and staged SQL analysis of large results.
Key features
- 01Query current or dated drought severity
- 02Retrieve weekly metrics and time series
- 03Rank states or counties by drought measures
- 04Count county weeks in drought
- 05Stage large results for read-only SQL
- 06Browse geography and category references
Use cases
- 01Compare drought severity across states
- 02Track drought metrics for an area over time
- 03Find counties meeting a drought-duration threshold
- 04Analyze large result tables with SQL
MCP support
Exposes eight tools to MCP clients through stdio or Streamable HTTP, with a public hosted endpoint. The tools query U.S. Drought Monitor data, and large outputs can be staged for read-only SQL.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://us-drought-monitor.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-us-drought-monitor https://us-drought-monitor.caseyjhand.com/mcp{"mcpServers":{"cyanheads-us-drought-monitor":{"type":"http","url":"https://us-drought-monitor.caseyjhand.com/mcp"}}}Open in Cursor{"servers":{"cyanheads-us-drought-monitor":{"type":"http","url":"https://us-drought-monitor.caseyjhand.com/mcp"}}}Open in VS Code{"mcpServers":{"cyanheads-us-drought-monitor":{"type":"http","url":"https://us-drought-monitor.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-us-drought-monitor":{"serverUrl":"https://us-drought-monitor.caseyjhand.com/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
7| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Maximum records on this page. |
| state | string | No | County-only filter: exact state postal code, two-digit FIPS or full name. |
| topic | enum | Yes | Reference family to browse.categories | dsci | area_types | coverage | states | counties | tribal | climate_divisions | huc |
| cursor | string | No | Continuation cursor from the previous page with the same filters. |
| hucLevel | any | No | Required for huc; exact identifier width. |
| nameContains | string | No | All normalized tokens must appear in the reference name. |
Details
From the project README@cyanheads/us-drought-monitor-mcp-server
Query U.S. Drought Monitor severity, DSCI, population, and drought duration via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://us-drought-monitor.caseyjhand.com/mcp
Overview
Weekly drought statistics from the U.S. Drought Monitor (USDM) data services. Snapshot an area's current or dated severity, follow weekly history, rank states and counties, and count county weeks in drought across national, state, county, HUC watershed, tribal, climate-division and River Forecast Center geographies. Large results stage as tables for read-only SQL. No API key is required.
The caller guide covers interpretation and complete analytical retrieval; the server also serves it as a skill resource.
Tools
| Tool | Description |
|---|---|
drought_list_reference | Browse drought categories, DSCI formulas, coverage and exact geography identifiers |
drought_get_current_severity | Current or dated snapshot with area, square miles, population, DSCI and 4/52-week DSCI change |
drought_get_timeseries | Weekly metrics and DSCI for explicit areas, with missing-data runs and peak summaries |
drought_compare_areas | Rank states or counties by DSCI or D2+/D3+ coverage, or by change from a baseline week |
drought_get_weeks_in_drought | County consecutive streaks or non-consecutive week counts at a drought category or worse |
drought_dataframe_describe | Inspect a staged canvas: tables, columns, expiry and full producer metadata |
drought_dataframe_query | Page read-only SQL over staged drought tables |
drought_dataframe_drop | Remove one disposable staged table; opt-in via DROUGHT_DATAFRAME_DROP_ENABLED=true |
Capability reference
drought_list_reference tool
topic:categories,dsci,area_types,coverage,states,counties,tribal,climate_divisions,river_forecast_centersorhuc;nameContainstoken filter,statefor counties or climate divisions,hucLevel(2, 4, 6 or 8) required forhuc. OptionalparentHucselects descendants of an existing shorter HUC at level 2, 4 or 6- Default 25 records per page, clamped to 200; continued via
nextCursorwith unchanged filters. Explicit pages return the effective count, fewer only at exhaustion;totalCountcounts every match - Records keep leading-zero identifiers, climate-state postal codes and source vintages;
bundleVersionand topic-dependentsourceMetadata(source URLs and SHA-256 hashes) date the offline bundle.provenance.sourceUrlsuses the same source selection
drought_get_current_severity tool
- One
area(areaType+aoi, plushucLevelfor HUC;aoitakes an exact identifier or exact state or"County Name, ST"name); unique suffix-free county names such as"King, WA"are accepted after exact-name matching. Optionaldatedefaults to the latest published map;usselects both CONUS and Total - Each snapshot carries cumulative and categorical area percent, cumulative square miles, cumulative population (
populationStatusunsupportedoutside US/state/county),dsci, anddsciChange4Weeks/dsciChange52Weeksagainst exactly 28 and 364 days earlier, each with anavailable/missing/before_coveragestatus - A date outside published coverage returns
found: falsewithguidance - River Forecast Centers use
areaType: "river_forecast_center"with an official code (for exampleCBRFC) or exact name (Colorado Basin); area percentages, square miles and DSCI are supported. Unknown RFCs fail local reference resolution
drought_get_timeseries tool
- 1–100
areassharing oneareaTypeand HUC level; inclusivestartDate/endDate;metricarea_percent(default),area_sq_miles,population_percentorpopulation_count(US/state/county only);statisticsTypecumulative(default) orcategorical - Rows carry the metric buckets plus
dsci;missingAreas,missingObservations(date runs per metric and DSCI component) and per-areasummary(every tied peak) cover the complete series - Rows past the inline budget stage behind a preview, with the table in
staging; optionalcanvas_idstages into an existing canvas. Metadata remains complete inline whenever it fits. Overflow automatically retains complete rows and metadata, including zero-observation results;metadata_pagesgives each array's total, returned count and next offset
drought_compare_areas tool
scopestatesorcounties(optionalstate, else nationwide);metricdsci(default),d2_d4ord3_d4; optionaldate(default latest) andbaselineDateto rank the change;directiondesc(default) orasc- Competition ranks share ties;
excludedAreasnames each area missing its target or baseline value;changeUnitisindexorpercentage_points limit(default 20, clamped to 200) sizes the inline preview; the complete ranking stages, with optionalcanvas_idreuse
drought_get_weeks_in_drought tool
startDate,endDate,minCategory(D0–D4) andminWeeksrequired;modeconsecutive(default) ornon_consecutive;statesor onecounty, never both, or neither for nationwide counties- Rows give
fips,county,state, and eitherstartDate/endDate/consecutiveWeeksornonConsecutiveWeeks; a county qualifies when any part of it reaches the category or worse, and streaks are bounded by the requested window - Consecutive
startMayExtendEarlierandendMayContinueflag boundaries touching the effective window; they express uncertainty about continuation. The Monday end is compared with the final map Tuesday plus six days. Non-consecutive rows omit these flags - Default 25 rows per page, clamped to 200;
nextCursorstays valid five minutes with unchanged filters. Explicit pages return the effective count, fewer only at exhaustion. Counts are duration statistics, not program eligibility
drought_dataframe_describe tool
canvas_idfrom a staging response; tables with SQL column types, row counts and expiry- With
table_name, that table's full producer metadata: requested and effective ranges, units, bucket-column mapping, missing data, summaries and provenance - Oversized metadata returns first-page prefixes with
metadata_pages. To read a complete retained collection, supplytable_name,metadata_field(areas,summary,missingAreas,missingObservations),metadata_offsetandmetadata_limit(default 20, clamped to 100); followmetadata_page.next_offsetuntil null. Explicit pages return the effective count, fewer only at exhaustion, from the same snapshot without fetching upstream again
drought_dataframe_query tool
canvas_idplus one DuckDB read expression with an optional terminal semicolon; writes, multiple statements, external reads and system catalogs are refused- A column named
current_schemamust be table-qualified (t.current_schema); unqualified references are refused because DuckDB can bind them as an engine-settings function limit(default 25, clamped to 500) andoffsetup to 250,000; continuenext_offsetwith identical SQL until null. Explicit pages return the effective count, fewer only at exhaustion, regardless of cell width.SELECT * FROM <table_name> ORDER BY row_idreturns the original rows in ordercountIsExactis true only when one page from offset 0 holds every row; useSELECT COUNT(*)for totals
drought_dataframe_drop tool
canvas_idandtable_name; removes the analytical copy only, returningdropped: falsewhen the table is already gone; an expired canvas fails ascanvas_not_found- Opt-in: absent from
tools/listunlessDROUGHT_DATAFRAME_DROP_ENABLED=true
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
USDM-specific:
- Fixed-origin client for the USDM data services (
usdmdataservices.unl.edu): no key, at most 64 upstream requests and 64 MiB per call, three concurrent upstream requests, one retry that honorsRetry-After - Dates snap to the containing Tuesday–Monday map week; coverage starts 2000-01-04, and the latest map (usually published Thursday) is discovered from upstream
- Cumulative buckets (
d1_d4= D1 or worse) overlap; categorical buckets (d1_only) are exclusive. DSCI is upstream's experimental 0–500 index, never recomputed - Offline geography bundle: 52 states and jurisdictions, 3,230 counties (Connecticut planning regions included), 323 tribal areas, 357 climate divisions, 13 River Forecast Centers and 2,916 HUCs, refreshed by
scripts/update-reference-data.ts - Staged tables live in DuckDB with a 30-minute sliding lifetime renewed by queries; canvas tokens are tenant-scoped, shareable capabilities, so treat them as credentials
- At the four-canvas process cap, omitted-token staging reuses the tenant's most recently used service-owned canvas with a free slot (eight tables per canvas). Explicitly supplied canvases remain caller-owned; live tables are never evicted.
staging_capacity_exhaustedadvises token reuse or expiry, whilestaging_busyadvises waiting for active work. The two-workflow admission bound applies before fetching, including inline reads - Connecticut's eight legacy county FIPS remain discoverable but are omitted from comparison populations. Their empty observation lookups explain that USDM serves Connecticut by planning region; call
drought_list_referencewithtopic: counties,state: CT. Counties are never mapped onto different planning-region boundaries;currentUsdm: falsealone is not a historical-coverage rule - Node acquisition uses a private reusable Undici HTTP/1.1 dispatcher, released during server teardown; Bun retains native fetch
Agent-friendly output:
- Reference records, query rows and describe columns use compact tables with JSON cells; empty cells distinguish absent optional fields from null values. Metadata, nested values and clickable URLs remain complete on both response surfaces
- Positive integer page/preview limits above 200 (references, comparisons, duration), 500 (SQL), or 100 (metadata) are clamped;
effectiveLimitandlimitNoticedisclose the result. SetDROUGHT_CLAMP_LIMITS=falseto advertise and enforce these maxima instead. Clamps emit a request log and thedrought.limit_clampscounter. Continuation retains every record. Nonpositive and fractional limits are rejected; count ceilings do not bound response bytes - Date inputs advertise
YYYY-MM-DDand validate real calendar dates; blank optional snapshot and comparison dates retain their defaults. A duration threshold beyond its window advises loweringminWeeksor widening the dates - Provenance on every response:
sourceUrls,retrievedAt, the USDMcreditline and the experimental-DSCI citation - Supported population snapshots and population series add
provenance.populationInterpretation, retained through dataframe describe/query: USDM population figures are rough census-based estimates assuming uniform population within counties, with artificial precision rather than exact contemporary headcounts. Source values remain unchanged; no census vintage is inferred - Missing data stays explicit: nulls with
dsciStatus/populationStatus,missingAreas,missingObservationsdate runs andexcludedAreas, never zero-filled - Range and identity echo:
requestedRange/effectiveRange,latestMapDate,resolvedAreas, and staging handles that namedrought_dataframe_describeanddrought_dataframe_query
Getting started
Connect to the hosted instance:
claude mcp add --transport http us-drought-monitor-mcp-server https://us-drought-monitor.caseyjhand.com/mcp
Or run it locally:
claude mcp add us-drought-monitor-mcp-server -- npx -y @cyanheads/us-drought-monitor-mcp-server
For other clients, add this to the MCP configuration file:
{
"mcpServers": {
"us-drought-monitor-mcp-server": {
"command": "npx",
"args": ["-y", "@cyanheads/us-drought-monitor-mcp-server"]
}
}
}
No API key or account is required. Set DROUGHT_DATAFRAME_DROP_ENABLED=true to expose table removal. For Docker or a source build, see Running the server.
Configuration
| Variable | Description | Default |
|---|---|---|
DROUGHT_DATAFRAME_DROP_ENABLED | Expose drought_dataframe_drop for disposable staged tables. | false |
DROUGHT_CLAMP_LIMITS | Clamp oversized positive limits; false advertises and enforces maxima. | true |
CANVAS_PROVIDER_TYPE | Analytical engine: duckdb, or none to disable staging and SQL. | duckdb |
CANVAS_DEFAULT_MEMORY_LIMIT_MB | Memory limit per canvas engine. | 128 |
CANVAS_MAX_CANVASES_PER_TENANT | Provider canvas cap; the server separately admits four live canvases per process. | 4 |
CANVAS_DEFAULT_ROW_LIMIT | Provider query row cap; at least 501 when the canvas is enabled. | 10000 |
CANVAS_TTL_MS | Sliding canvas lifetime, in ms; staged tables expire after 30 minutes without use. | 86400000 |
CANVAS_ABSOLUTE_CAP_MS | Absolute canvas lifetime, in ms. | 604800000 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_HOST | HTTP bind address. | 127.0.0.1 |
MCP_HTTP_PORT | HTTP server port. | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path. | /mcp |
MCP_SESSION_MODE | HTTP session mode: stateless, stateful, or auto. | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.). | info |
LOGS_DIR | Directory for log files (Node.js only). | <app-root>/logs |
OTEL_ENABLED | Enable OpenTelemetry. | false |
See .env.example for every server setting and the common framework overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
git clone https://github.com/cyanheads/us-drought-monitor-mcp-server.git
cd us-drought-monitor-mcp-server
bun install
cp .env.example .env
# optional: set DROUGHT_DATAFRAME_DROP_ENABLED or canvas limits
Staging and SQL need native DuckDB, included in npm and Docker installs. The portable Claude Desktop .mcpb bundle fixes CANVAS_PROVIDER_TYPE=none: producers return complete inline results within acquisition limits. Explicit canvas tokens and dataframe operations still require an analytical provider; invalid, expired or foreign tokens never fall back to inline success.
-
Build and run the production version:
# One-time build bun run rebuild # Run the built server bun run start:http # or bun run start:stdio -
Run checks and tests:
bun run devcheck # Lints, formats, type-checks, and more bun run test # Runs the test suite
Docker
docker run --rm -p 127.0.0.1:3010:3010 ghcr.io/cyanheads/us-drought-monitor-mcp-server:latest
The image runs on Bun with native DuckDB, defaults to HTTP on port 3010 in stateless session mode, and logs to /var/log/us-drought-monitor-mcp-server. OpenTelemetry peer dependencies are installed by default; build with --build-arg OTEL_ENABLED=false to omit them.
To build locally, run docker build -t us-drought-monitor-mcp-server .. For stdio clients, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/us-drought-monitor-mcp-server:latest"].
Project structure
| Directory | Purpose |
|---|---|
src/mcp-server/tools | Tool definitions (*.tool.ts). Eight drought and dataframe tools. |
src/services/drought | USDM client, geography resolution, map-week dates, workflows, staging and rendering. |
src/services/canvas-accessor.ts | Access to the framework DataCanvas configured at startup. |
src/config | Environment loading, canvas defaults, count schemas and clamp telemetry. |
src/data | Generated geography reference bundle (reference.json). |
scripts/update-reference-data.ts | Maintainer refresh of the reference bundle from official sources. |
tests/ | Unit, contract and integration tests, mirroring the src/ structure. |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Service errors carry the
reasondeclared in each tool's inlineerrors[]contract - Register new tools in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
The U.S. Drought Monitor is jointly produced by the National Drought Mitigation Center at the University of Nebraska-Lincoln, the United States Department of Agriculture, the National Oceanic and Atmospheric Administration and the National Aeronautics and Space Administration. Map courtesy of NDMC.
DSCI: Akyuz, F. A. 2017. Drought Severity and Coverage Index. United States Drought Monitor.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.