Skip to main content
Glama
higherpass

mcp-epa-echo

by higherpass

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
find_facility

Look up NPDES-permitted water dischargers by name, city+state, or NPDES permit number - use this before any other ECHO tool that takes a facility, since they all need an npdesId (or a name they resolve internally).

ID SOUP: ECHO exposes at least two IDs per facility - npdesId (the NPDES permit number, e.g. "GA0038202") and registryId (EPA's cross-program facility ID). Pass npdesId to the other ECHO tools, never registryId.

Provide at least one of: name, city+state together, or npdesId. name and city are matched SERVER-SIDE as a substring by ECHO itself (city requires state alongside it - city alone is rejected as too broad). nameContains is a SEPARATE, CLIENT-SIDE substring filter applied AFTER the server-side search returns, narrowing further - it does not go to ECHO and cannot be used to broaden a search that came back empty.

When npdesId is given, that value IS the identifier and is always returned - ECHO is only asked to CONFIRM and enrich it (name, registryId, lat/lon, permit status). If that confirm lookup finds nothing (typo, unindexed permit, or a transient ECHO error), the response still contains the npdesId you passed, with every other field null and confirmed:false - this is not a failure, and the note explains why. Never treat confirmed:false as proof the permit is invalid.

A name/city+state search can match more than one facility - the response is never guessed down to one. Multiple matches produce a note saying so; narrow with nameContains, add state, or switch to npdesId once you have it.

permitStatus can be "Effective", "Terminated", "Expired", "Admin Continued", and others - a facility appearing in results does NOT mean it is currently permitted to discharge; check permitStatus before assuming so.

Results are capped at maxResults (default 50, max 500); when more match, truncated:true and totalMatched show how many were found in total.

facilities_near

Find NPDES-permitted water dischargers (majors AND minors) in a geographic area - answers "what's permitted to discharge near/on this reach," not "what IS being discharged" (pair with get_dmr_values per facility for that).

Exactly one spatial filter is required: bBox {west, south, east, north} in decimal degrees, OR lat+lon+radiusMiles together (radiusMiles capped at 25). Providing zero, both, or a partial lat/lon/radiusMiles set is rejected with a clear error naming what's missing.

Results are FACILITY PERMIT LOCATIONS (the address/coordinates on file for the permit), not the physical location of a discharge pipe or outfall - a facility's outfall can be meaningfully upstream/downstream/offset from the permit address. Do not treat a facility appearing in radius/bbox results as proof it discharges exactly at that point.

Each result includes permitStatus and majorMinor - a "Terminated" or "Expired" facility can still appear (it was permitted here at some point); check permitStatus before assuming it currently discharges. majorMinor is "M" (major) or "N" (minor) per ECHO's convention.

Results are capped at maxResults (default 50, max 500); when more match, truncated:true and totalMatched show how many were found in total. A dense urban area within even a 2-mile radius can return hundreds of stormwater/general-permit facilities alongside majors - narrow the radius or bbox rather than raising maxResults if you want a smaller, more relevant set.

get_permit_limits

Get the effluent limits ECHO has on file for a facility's outfall(s) - one row per (outfall x parameter x statistical basis x limit type). "DAILY AV" vs "DAILY MX" for the same parameter are DISTINCT limits, not duplicates - and a parameter routinely carries BOTH a mass limit (limitType "Q1"/"Q2", e.g. lb/d) AND a concentration limit ("C1"/"C2", e.g. mg/L) at the SAME statistical basis, which are also distinct limits, not duplicates.

Identify the facility with npdesId (preferred) or name (resolved internally - ambiguous names return a note asking you to call find_facility first). Omit startDate/endDate for the CURRENT permit's limits (the common case). A permit reissuance changes limits: pass a historical startDate/endDate (YYYY-MM-DD) to see a PRIOR permit's limits instead - verified live against real historical ECHO data (see get_dmr_values for the same date-range mechanism). The response's note always states which permit window (permitStart-permitEnd) the returned limits belong to.

limitValue:null for a parameter means monitoring is required but no numeric limit is assigned (a real, meaningful distinction from "no limit information exists") - do not treat it as missing data.

Optionally filter to one outfall with outfall (e.g. "001"); omit to see limits for all outfalls.

get_dmr_valuesA

Get measured Discharge Monitoring Report (DMR) values for a facility - the actual reported effluent values, not just limits (use get_permit_limits for that).

Identify the facility with npdesId (preferred) or name (resolved internally - ambiguous names return a note asking you to call find_facility first).

THE WINDOWING TRAP, SOLVED: omitting startDate/endDate returns ONLY the facility's CURRENT permit window - which can be as narrow as the last few years, hiding older discharges entirely. The response ALWAYS notes this when no date range is given, even if current-window rows come back. To reach historical discharges (e.g. a pre-2023 permit), pass startDate/endDate (YYYY-MM-DD) - ECHO honors these and returns REAL DATA from the facility's OLDER permit(s), verified live (a 2011-2012 query against a real facility returned 360 real historical report rows). There is no separate historical endpoint to call - passing the date range through to this same tool IS the fix.

If a date range IS given but zero rows come back, the response explains the returned permit window rather than implying "no discharge occurred" - a range outside any permit ECHO has data for looks identical to a genuinely clean period unless you check the window ECHO actually returned.

dmrValue:null with a populated nodiFlag means ECHO recorded a specific reason no value was reported (e.g. monitoring not required that period) - this is NOT the same as a missing/unreported value; nodiFlag:null with dmrValue:null on an overdue report means the value is simply missing. Values may be provisional and subject to revision.

Optionally filter with parameter - matches EITHER an exact parameter code (e.g. "00530") OR a case-insensitive substring of the parameter name (e.g. "suspended"). Results are capped at maxResults (default 50, max 500); when more match, truncated:true and totalMatched show how many were found in total.

get_violations

Get DMR-derived violations for a facility - effluent/compliance flags ECHO computed from Discharge Monitoring Reports. This is DIFFERENT from get_enforcement_actions: a facility can have violations here with no formal case ever filed, and a single enforcement case can resolve violations from several different reporting periods - the two tools do not correspond 1:1.

Identify the facility with npdesId (preferred) or name (resolved internally - ambiguous names return a note asking you to call find_facility first).

SAME WINDOWING TRAP AS get_dmr_values, same fix: omitting startDate/ endDate returns only the CURRENT permit window, and the response ALWAYS notes this, even when current-window violations come back. Pass startDate/endDate (YYYY-MM-DD) to reach historical violations - verified live: a 2011-2012 query surfaced real "DMR, Limited - Numeric Violation" flags for a BOD exceedance that the current-permit view alone would never show.

A row is included here ONLY when ECHO itself recorded a violation (NPDESViolations) - a NODI ("no data") code alone, even one that looks violation-adjacent, is NOT treated as a violation on its own; verified live that real NODI codes (e.g. "Conditional Monitoring Not Required") never co-occur with an actual violation flag in practice. Two distinct kinds of violation appear, both carrying violationCode/violationDescription/ severity, and neither is "more real" than the other:

  • Reporting/monitoring violations (e.g. code D80, "DMR, Monitor Only - Overdue") - a required report wasn't submitted on time, independent of whether effluent was ever out of spec.

  • Effluent/numeric violations (e.g. code E90, "DMR, Limited - Numeric Violation") - a reported value exceeded its limit; exceedancePct is populated when ECHO computed by how much.

If a date range returns zero rows, the response distinguishes "no monitoring reports at all in this window" from "reports came back, none were flagged as violations" - the second is a genuinely clean compliance result, not missing data, and is reported as such rather than implied to be an error.

Results are capped at maxResults (default 50, max 500); when more match, truncated:true and totalMatched show how many were found in total.

get_enforcement_actions

Get FORMAL ICIS-NPDES enforcement cases for a facility - consent orders, administrative orders, and their penalties. DIFFERENT from get_violations: a facility can accumulate DMR violations with no case ever filed, and one case can resolve violations spanning multiple years - do not assume a 1:1 relationship between the two tools, and do not assume "no cases here" means "no violations" (check get_violations separately).

Identify the facility with npdesId (preferred) or name (resolved internally - ambiguous names return a note asking you to call find_facility first). Enforcement cases are looked up by the facility's ECHO Registry ID, NOT the NPDES permit number - verified live: case_rest_services.get_cases links via p_facility_id=<RegistryID>; p_id, p_pid, p_reg, and several other plausible-looking param names all silently no-op on this service (they fall through to a whole-database row-limit error instead of filtering). If this facility's Registry ID could not be confirmed (see find_facility's confirmed:false), this tool cannot look up cases and says so rather than guessing at a param that won't work.

Penalties are frequently penalty:0 (the FEDERAL penalty field) even for cases with real financial consequences - many enforcement actions are STATE-level consent orders, and their penalty shows up in stateLocalPenalty instead. Verified live against an 11-case real enforcement history where EVERY federal penalty was $0.00 but state penalties ranged from $2,900 to $150,000 - checking penalty alone would have reported that facility's entire enforcement history as penalty-free, which was false. Check both fields; a $0 in one is not evidence of "no penalty at all."

Optional startDate/endDate (YYYY-MM-DD) filter to cases with a filed OR settlement date in range, applied CLIENT-SIDE (ECHO's case search does not support server-side date filtering - p_daterange and similar guesses were tried and silently ignored). A case with no date on file at all is excluded when a range is given, since it can't be confirmed to fall inside it.

Results are capped at maxResults (default 50, max 500); when more match, truncated:true and totalMatched show how many were found in total.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

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-epa-echo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server