Skip to main content
Glama

usgs-water-mcp-server

Water Get Series

water_get_series
Read-onlyIdempotent

Get a daily or instantaneous time series for one USGS site and parameter over a date range, as time-ordered value records. NWIS can hold several series for one query — one per daily statistic (mean, maximum, minimum) and one per sensor (method); this returns one, reporting its statCd and methodId, and lists the rest in otherSeries so any can be re-requested with the statCd and methodId inputs. By default it returns the daily mean when NWIS returns one with values, and the method with the most records. Large sets (>500 records) return the most recent records inline with truncated=true — the last 500 without DataCanvas, and with DataCanvas enabled the complete series also spills to a canvas (canvas_id/table_name): inspect the staged table with water_dataframe_describe, then read the full series with water_dataframe_query. Use water_find_sites and water_list_parameters to resolve inputs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
siteYesUSGS site number (8–15 digits, e.g. "01646500" for Potomac River at Little Falls). Use water_find_sites to discover valid site numbers.
statCdNoDaily statistic to return, as a 5-digit NWIS code: "00003" mean, "00001" maximum, "00002" minimum. Omit for the mean when NWIS returns one with values, otherwise the first statistic that has values; the response names the one returned and lists the others in otherSeries. Daily series only — instantaneous values carry just "00000".
endDateYesEnd date in YYYY-MM-DD format (e.g. "2024-12-31").
methodIdNoNWIS method ID of the sensor series to return — the methodId or an otherSeries[].methodId from a prior response for the same site, parameter, and seriesType. Omit for the method with the most records. IDs differ between daily and instantaneous series and between daily statistics.
canvas_idNoCanvas ID from a prior call to add this series as a table on an existing canvas rather than creating a new one. Each distinct site, parameter code, series type, date range, and selected statistic and method gets its own table name, so re-running the identical query replaces its own table while a different query adds another alongside it. Applies only when the series spills to a canvas. Omit to start a fresh canvas.
startDateYesStart date in YYYY-MM-DD format (e.g. "2024-01-01").
seriesTypeNo"daily" returns one value per day (DV service, typically mean/max/min). "instantaneous" returns ~15-minute readings (IV service). Default: "daily". Use "instantaneous" for high-resolution analysis.daily
parameterCdYesA single 5-digit USGS parameter code (e.g. "00060" for discharge, "00065" for gage height). One code per call — this tool returns one series. Use water_list_parameters to discover available codes.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
errorNoPresent when the call failed. Absent on success.
queryNoQuery parameters used for this request.
noticeNoAdvisory about this result: the staged canvas table and how to read it, the advice to narrow the date range when the series was truncated with no canvas available, or the fact that a supplied canvas_id went unused because nothing was staged.
statCdNoNWIS statistic code of the returned series: "00003" daily mean, "00001" daily maximum, "00002" daily minimum, "00000" for instantaneous values.
valuesNoTime-ordered value records, oldest first within the slice. Holds every record when truncated is false; when truncated, the most recent records only — the last 500 without DataCanvas, or the last N that fit the inline preview budget when the full series is staged on a canvas.
methodIdNoNWIS method ID of the sensor series returned. Pass it back as the methodId input to request this series again. Null only when NWIS returned the series with no method block.
siteNameNoHuman-readable USGS site name.
statNameNoStatistic name NWIS attaches to statCd (e.g. "Mean", "Maximum"). Null when NWIS gives none, as for instantaneous values.
unitCodeNoUnit of measure for all values in this series (e.g. "ft3/s", "ft").
canvas_idNoCanvas ID for the DataCanvas holding the full time series. Present only when truncated=true and DataCanvas is enabled. Pass to water_dataframe_describe then water_dataframe_query.
truncatedNoTrue when the result exceeds 500 records and only the most recent were returned inline. When canvas_id is present, inspect the staged table with water_dataframe_describe then read the full series with water_dataframe_query; otherwise narrow the date range.
seriesTypeNo"daily" = one value per day (DV service); "instantaneous" = ~15-minute readings (IV service).
siteNumberNoUSGS site number (8–15 digits, e.g. "01646500").
table_nameNoDuckDB table name in the canvas holding all records. Present when canvas_id is present. Use as the FROM target in water_dataframe_query SQL.
otherSeriesNoEvery other statistic × method series NWIS returned for this query — re-request one with its statCd and methodId. Empty when the query produced a single series. A method block with no values over the range is omitted when another method of the same statistic has values.
parameterCdNo5-digit USGS parameter code (e.g. "00060" for discharge).
totalRecordsNoTotal number of records in the upstream result set (before any truncation).
parameterNameNoHuman-readable parameter name with units (e.g. "Streamflow, ft³/s").
methodDescriptionNoNWIS description of that method (e.g. "From multiparameter sonde", "7.1 ft from riverbed (top), [Discontinued]"). Null when NWIS leaves it blank, as it does for the default series at most single-sensor sites.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed14 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Canvas ID from a prior call to add this series as a table on an existing canvas rather than creating a new one. Each distinct site, parameter code, series type, and date range gets its own table name, so re-running the identical query replaces its own table while a different query adds another alongside it. Applies only when the series spills to a canvas. Omit to start a fresh canvas."New value: +"Canvas ID from a prior call to add this series as a table on an existing canvas rather than creating a new one. Each distinct site, parameter code, series type, date range, and selected statistic and method gets its own table name, so re-running the identical query replaces its own table while a different query adds another alongside it. Applies only when the series spills to a canvas. Omit to start a fresh canvas."
    • addedInput schema / properties / methodId
      Added value: +{
      +  "description": "NWIS method ID of the sensor series to return — the methodId or an otherSeries[].methodId from a prior response for the same site, parameter, and seriesType. Omit for the method with the most records. IDs differ between daily and instantaneous series and between daily statistics.",
      +  "type": "string"
      +}
    • addedInput schema / properties / statCd
      Added value: +{
      +  "description": "Daily statistic to return, as a 5-digit NWIS code: \"00003\" mean, \"00001\" maximum, \"00002\" minimum. Omit for the mean when NWIS returns one with values, otherwise the first statistic that has values; the response names the one returned and lists the others in otherSeries. Daily series only — instantaneous values carry just \"00000\".",
      +  "type": "string"
      +}
    • changedOutput schema / anyOf
      Previous value: -[
      -  {
      -    "not": {
      -      "required": [
      -        "error"
      -      ]
      -    },
      -    "required": [
      -      "siteNumber",
      -      "siteName",
      -      "parameterCd",
      -      "parameterName",
      -      "unitCode",
      -      "seriesType",
      -      "values",
      -      "totalRecords",
      -      "truncated",
      -      "query"
      -    ]
      -  },
      -  {
      -    "required": [
      -      "error"
      -    ]
      -  }
      -]New value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "siteNumber",
      +      "siteName",
      +      "parameterCd",
      +      "parameterName",
      +      "unitCode",
      +      "seriesType",
      +      "statCd",
      +      "statName",
      +      "methodId",
      +      "methodDescription",
      +      "values",
      +      "totalRecords",
      +      "truncated",
      +      "otherSeries",
      +      "query"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `no_data_for_range`: The site and parameter combination has no data in the requested date range. `invalid_date_range`: endDate is before startDate, or a date passes the YYYY-MM-DD shape check but is not a real calendar date. `invalid_request`: NWIS rejected the request. Input formats are validated against NWIS-accepted patterns before the call, so this surfaces a value that is well-formed but unacceptable upstream. `upstream_error`: NWIS returned a 5xx error or the request timed out. `canvas_not_found`: The supplied canvas_id names a canvas that never existed or has expired. Raised before the NWIS request, so no upstream call is spent on it. `canvas_capacity_exhausted`: canvas_id was omitted and a fresh canvas was needed to stage the series, but this tenant already holds the maximum number of active canvases. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_data_for_range`: The site and parameter combination has no data in the requested date range. `invalid_date_range`: endDate is before startDate, or a date passes the YYYY-MM-DD shape check but is not a real calendar date. `invalid_stat_cd`: statCd is not a 5-digit NWIS statistic code. Raised before the NWIS request. `stat_cd_for_instantaneous`: statCd names a daily statistic but seriesType is \"instantaneous\", whose values carry only statistic \"00000\". Raised before the NWIS request. `method_not_found`: No series NWIS returned for this query carries the requested methodId (within the requested statCd, when one is given), or that method returned no values over the range. `invalid_request`: NWIS rejected the request. Input formats are validated against NWIS-accepted patterns before the call, so this surfaces a value that is well-formed but unacceptable upstream. `upstream_error`: NWIS returned a 5xx error, timed out, or sent a response body that is not valid WaterML-JSON (cut off mid-document), and retrying did not clear it. `canvas_not_found`: The supplied canvas_id names a canvas that never existed or has expired. Raised before the NWIS request, so no upstream call is spent on it. `canvas_capacity_exhausted`: canvas_id was omitted and a fresh canvas was needed to stage the series, but this tenant already holds the maximum number of active canvases. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "no_data_for_range",
      -  "invalid_date_range",
      -  "invalid_request",
      -  "upstream_error",
      -  "canvas_not_found",
      -  "canvas_capacity_exhausted"
      -]New value: +[
      +  "no_data_for_range",
      +  "invalid_date_range",
      +  "invalid_stat_cd",
      +  "stat_cd_for_instantaneous",
      +  "method_not_found",
      +  "invalid_request",
      +  "upstream_error",
      +  "canvas_not_found",
      +  "canvas_capacity_exhausted"
      +]
    • addedOutput schema / properties / methodDescription
      Added value: +{
      +  "description": "NWIS description of that method (e.g. \"From multiparameter sonde\", \"7.1 ft from riverbed (top), [Discontinued]\"). Null when NWIS leaves it blank, as it does for the default series at most single-sensor sites.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / methodId
      Added value: +{
      +  "description": "NWIS method ID of the sensor series returned. Pass it back as the methodId input to request this series again. Null only when NWIS returned the series with no method block.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / otherSeries
      Added value: +{
      +  "description": "Every other statistic × method series NWIS returned for this query — re-request one with its statCd and methodId. Empty when the query produced a single series. A method block with no values over the range is omitted when another method of the same statistic has values.",
      +  "items": {
      +    "additionalProperties": false,
      +    "description": "One series NWIS returned for this query that was not selected.",
      +    "properties": {
      +      "methodDescription": {
      +        "description": "NWIS description of the method; null when blank.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "methodId": {
      +        "description": "NWIS method ID of this series — pass as the methodId input.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "recordCount": {
      +        "description": "Number of value records this series holds over the requested range.",
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "statCd": {
      +        "description": "NWIS statistic code of this series (e.g. \"00001\").",
      +        "type": "string"
      +      },
      +      "statName": {
      +        "description": "Statistic name for statCd (e.g. \"Maximum\"); null when NWIS gives none.",
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "required": [
      +      "statCd",
      +      "statName",
      +      "methodId",
      +      "methodDescription",
      +      "recordCount"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / query / properties / methodId
      Added value: +{
      +  "description": "Method ID requested, if any.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / query / properties / statCd
      Added value: +{
      +  "description": "Statistic code requested, if any.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / statCd
      Added value: +{
      +  "description": "NWIS statistic code of the returned series: \"00003\" daily mean, \"00001\" daily maximum, \"00002\" daily minimum, \"00000\" for instantaneous values.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / statName
      Added value: +{
      +  "description": "Statistic name NWIS attaches to statCd (e.g. \"Mean\", \"Maximum\"). Null when NWIS gives none, as for instantaneous values.",
      +  "type": [
      +    "string",
      +    "null"
      +  ]
      +}
    • changedOutput schema / properties / values / items / properties / value / description
      Previous value: -"Measured value as a string (empty string means no data for that interval)."New value: +"Measured value as a string. Empty string when NWIS reported no value for that interval — qualifiers then give the reason (e.g. \"Ssn\" seasonal, \"Dis\" discontinued, \"Dry\", \"Eqp\" equipment malfunction). A staged canvas table holds NULL for these."
  2. Changed6 schema fields changed
    • changedInput schema / properties / canvas_id / description
      Previous value: -"Canvas ID from a prior water_get_series call to append data to an existing canvas rather than creating a new one. Omit to start a fresh canvas."New value: +"Canvas ID from a prior call to add this series as a table on an existing canvas rather than creating a new one. Each distinct site, parameter code, series type, and date range gets its own table name, so re-running the identical query replaces its own table while a different query adds another alongside it. Applies only when the series spills to a canvas. Omit to start a fresh canvas."
    • changedOutput schema / properties / error / properties / data / properties / reason / description
      Previous value: -"Machine-readable failure mode. Declared by this tool: `no_data_for_range`: The site and parameter combination has no data in the requested date range. `invalid_date_range`: endDate is before startDate, or a date passes the YYYY-MM-DD shape check but is not a real calendar date. `invalid_request`: NWIS rejected the request. Input formats are validated against NWIS-accepted patterns before the call, so this surfaces a value that is well-formed but unacceptable upstream. `upstream_error`: NWIS returned a 5xx error or the request timed out. Other values are possible when a failure originates below the handler."New value: +"Machine-readable failure mode. Declared by this tool: `no_data_for_range`: The site and parameter combination has no data in the requested date range. `invalid_date_range`: endDate is before startDate, or a date passes the YYYY-MM-DD shape check but is not a real calendar date. `invalid_request`: NWIS rejected the request. Input formats are validated against NWIS-accepted patterns before the call, so this surfaces a value that is well-formed but unacceptable upstream. `upstream_error`: NWIS returned a 5xx error or the request timed out. `canvas_not_found`: The supplied canvas_id names a canvas that never existed or has expired. Raised before the NWIS request, so no upstream call is spent on it. `canvas_capacity_exhausted`: canvas_id was omitted and a fresh canvas was needed to stage the series, but this tenant already holds the maximum number of active canvases. Other values are possible when a failure originates below the handler."
    • changedOutput schema / properties / error / properties / data / properties / reason / examples
      Previous value: -[
      -  "no_data_for_range",
      -  "invalid_date_range",
      -  "invalid_request",
      -  "upstream_error"
      -]New value: +[
      +  "no_data_for_range",
      +  "invalid_date_range",
      +  "invalid_request",
      +  "upstream_error",
      +  "canvas_not_found",
      +  "canvas_capacity_exhausted"
      +]
    • changedOutput schema / properties / notice / description
      Previous value: -"Advisory when the result was truncated — narrow the date range or enable DataCanvas for full access."New value: +"Advisory about this result: the staged canvas table and how to read it, the advice to narrow the date range when the series was truncated with no canvas available, or the fact that a supplied canvas_id went unused because nothing was staged."
    • changedOutput schema / properties / truncated / description
      Previous value: -"True when the result exceeds 500 records and was trimmed. Query the full series via water_dataframe_query when canvas_id is present, or narrow the date range."New value: +"True when the result exceeds 500 records and only the most recent were returned inline. When canvas_id is present, inspect the staged table with water_dataframe_describe then read the full series with water_dataframe_query; otherwise narrow the date range."
    • changedOutput schema / properties / values / description
      Previous value: -"Time-ordered value records. Contains all records when not truncated, or the most recent 500 when truncated (no canvas) or a preview slice (with canvas)."New value: +"Time-ordered value records, oldest first within the slice. Holds every record when truncated is false; when truncated, the most recent records only — the last 500 without DataCanvas, or the last N that fit the inline preview budget when the full series is staged on a canvas."
  3. Changed1 schema field changed
    • addedInput schema / properties / canvas_id / pattern
      Added value: +"^[A-Za-z0-9_-]{10}$"
  4. Changed6 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedInput schema / additionalProperties
      Added value: +false
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • addedOutput schema / anyOf
      Added value: +[
      +  {
      +    "not": {
      +      "required": [
      +        "error"
      +      ]
      +    },
      +    "required": [
      +      "siteNumber",
      +      "siteName",
      +      "parameterCd",
      +      "parameterName",
      +      "unitCode",
      +      "seriesType",
      +      "values",
      +      "totalRecords",
      +      "truncated",
      +      "query"
      +    ]
      +  },
      +  {
      +    "required": [
      +      "error"
      +    ]
      +  }
      +]
    • addedOutput schema / properties / error
      Added value: +{
      +  "additionalProperties": {},
      +  "description": "Present when the call failed. Absent on success.",
      +  "properties": {
      +    "code": {
      +      "description": "JSON-RPC error code for this failure.",
      +      "maximum": 9007199254740991,
      +      "minimum": -9007199254740991,
      +      "type": "integer"
      +    },
      +    "data": {
      +      "additionalProperties": {},
      +      "properties": {
      +        "reason": {
      +          "description": "Machine-readable failure mode. Declared by this tool: `no_data_for_range`: The site and parameter combination has no data in the requested date range. `invalid_date_range`: endDate is before startDate, or a date passes the YYYY-MM-DD shape check but is not a real calendar date. `invalid_request`: NWIS rejected the request. Input formats are validated against NWIS-accepted patterns before the call, so this surfaces a value that is well-formed but unacceptable upstream. `upstream_error`: NWIS returned a 5xx error or the request timed out. Other values are possible when a failure originates below the handler.",
      +          "examples": [
      +            "no_data_for_range",
      +            "invalid_date_range",
      +            "invalid_request",
      +            "upstream_error"
      +          ],
      +          "type": "string"
      +        },
      +        "recovery": {
      +          "additionalProperties": {},
      +          "description": "Actionable next step for the caller.",
      +          "properties": {
      +            "hint": {
      +              "type": "string"
      +            }
      +          },
      +          "required": [
      +            "hint"
      +          ],
      +          "type": "object"
      +        },
      +        "retryable": {
      +          "description": "Whether retrying may succeed.",
      +          "type": "boolean"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "message": {
      +      "description": "Human-readable description of what went wrong.",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "code",
      +    "message"
      +  ],
      +  "type": "object"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "siteNumber",
      -  "siteName",
      -  "parameterCd",
      -  "parameterName",
      -  "unitCode",
      -  "seriesType",
      -  "values",
      -  "totalRecords",
      -  "truncated",
      -  "query"
      -]
  5. Changed3 schema fields changed
    • changedInput schema / properties / parameterCd / description
      Previous value: -"5-digit USGS parameter code (e.g. \"00060\" for discharge, \"00065\" for gage height). Use water_list_parameters to discover available codes."New value: +"A single 5-digit USGS parameter code (e.g. \"00060\" for discharge, \"00065\" for gage height). One code per call — this tool returns one series. Use water_list_parameters to discover available codes."
    • addedInput schema / properties / parameterCd / pattern
      Added value: +"^\\d{5}$"
    • addedInput schema / properties / site / pattern
      Added value: +"^\\d{8,15}$"
  6. Changed2 schema fields changed
    • addedInput schema / properties / endDate / pattern
      Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
    • addedInput schema / properties / startDate / pattern
      Added value: +"^\\d{4}-\\d{2}-\\d{2}$"
  7. First observed

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/openWorld/idempotent annotations, the description discloses rich behavior: NWIS can hold multiple series, only one is returned while others are listed, default selection is based on daily mean and most-record method, and large sets are truncated to the last 500 records with a truncated=true flag. It also explains the DataCanvas spill workflow, giving the agent a clear model of what happens during execution.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but appropriately sized for a tool with 8 parameters and non-trivial selection/truncation behavior. The core purpose is front-loaded, and every subsequent sentence adds necessary operational detail (defaults, truncation, canvas spill, and helper tools). There is no filler or repetition of annotation values.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the rich input schema, output schema, and annotations, the description covers the remaining operational context: how to resolve inputs, what happens when multiple series exist, how large sets are handled, and how to retrieve the full staged series. An agent has enough guidance to invoke the tool correctly and interpret its follow-up actions.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds meaningful cross-parameter context beyond the schema by explaining how statCd and methodId interact with otherSeries, how defaults are chosen, and how large-result truncation changes the output. It does not deeply redefine individual parameters because the schema already does that, but it supplies selection logic that is not fully obvious from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource: 'Get a daily or instantaneous time series for one USGS site and parameter over a date range, as time-ordered value records.' This clearly differentiates the tool from sibling tools like water_get_conditions and water_get_readings by emphasizing time-series retrieval for one site/parameter. It also explains the one-series-per-query behavior with otherSeries, adding further distinctiveness.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear workflow guidance: use water_find_sites and water_list_parameters to resolve inputs, and use water_dataframe_describe and water_dataframe_query for spilled large datasets. It does not explicitly state when NOT to use this tool versus water_get_readings or water_get_conditions, so it falls just short of fully explicit alternative selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.