cyanheads avatar

Epa Mcp Server

cyanheads/epa-mcp-server

Wraps five EPA public data APIs into a single MCP interface: ECHO for facility compliance and enforcement actions, TRI for toxic chemical releases, AirNow for real-time air quality readings, CERCLA for Superfund site status, and SDWIS for drinking water violations. You get eight tools that let you search facilities by location or program, pull full compliance profiles with inspection history and penalties, query TRI releases by chemical and medium, check current AQI by ZIP or coordinates, and find Superfund sites or water systems with active violations. The facility search returns Registry IDs and county FIPS codes, which makes it easy to chain lookups or join with Census data. Useful for environmental compliance checks, public health analysis, or building location intelligence into regulatory workflows.

GitHub stars
2
tools
11
transport
STDIO, HTTP
env vars
8
last updated
Nov 1, 2026

Install

From registry metadata
$ npx add-mcp https://epa.caseyjhand.com/mcp --name epa

Run in your terminal. add-mcp asks which agents to add it to (Claude Code, Codex, Cursor and more). Add -g to install it for every project.

Review the command, arguments and environment values before installing. MCP servers run with your local permissions.

Other ways

Claude Code

$ claude mcp add --transport http epa https://epa.caseyjhand.com/mcp

Run in your terminal. Add --scope user to make it available in every project.

Tools

Verified live · 11 tools

Verified live against the running server on Nov 6, 2026.

epa_echo_search_facilitiesECHO: Search EPA-regulated facilities by location, county, facility name, NAICS industry code, environmental program, or compliance status across CAA, CWA, RCRA, TRI, and SDWA. Returns facility name, EPA Registry ID, coordinates, county FIPS code, per-program registration flag...15 params

ECHO: Search EPA-regulated facilities by location, county, facility name, NAICS industry code, environmental program, or compliance status across CAA, CWA, RCRA, TRI, and SDWA. Returns facility name, EPA Registry ID, coordinates, county FIPS code, per-program registration flag...

Parameters* required
active_onlyboolean
When true, return only facilities with an active permit
citystring
City name, case-insensitive; matches cities that begin with it ("TACOMA", or "SEAT" for SEATTLE and SEATAC). Pair with state.
countystring
County name, case-insensitive. A trailing County, Parish, Borough, City and Borough, Census Area, or Municipality is dropped ("King County" searches KING), then it matches recorded county names tha...
county_fipsstring
5-digit county FIPS code, state + county (e.g. "53033" for King County, WA); matches it exactly and scopes a search on its own. Leaves out registrations with no program record, which county includes.
facility_namestring
Facility name words, case-insensitive: every word must appear as a whole word, in any order, in a name ECHO records for the facility, so "BOEING" matches BOEING PLANT 2 and "OEING" matches nothing....
has_violationboolean
When true, return only facilities with at least one program in significant noncompliance (complianceStatus "Significant Violation")
latitudenumber
Latitude in decimal degrees. Pair with longitude and radius_miles for proximity search.
limitinteger
Maximum number of facilities to return in one call (1–100, default 50). A larger value, up to 5,000, returns 100 with a notice. Page past it with offset and nextOffset.default: 50
longitudenumber
Longitude in decimal degrees. Pair with latitude and radius_miles for proximity search.
naicsstring
NAICS industry code, 2–6 digits; fewer than six match every code that begins with them ("3364" for aerospace product and parts manufacturing). Pair with a geographic filter.
offsetinteger
Number of facilities to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
programsarray
Restrict results to facilities registered in one environmental program — ECHO filters on a single program per search, so pass one value. CAA=air, CWA=water, RCRA=hazardous waste, TRI=toxic releases...
radius_milesnumber
Search radius in miles around the given latitude/longitude (max 100). Requires latitude and longitude.
statestring
2-letter state or territory code (e.g. "WA", "PR"), case-insensitive. Required with county. ECHO also files facilities under codes outside the USPS set, such as DM for offshore Gulf of Mexico platf...
zip_codestring
5-digit ZIP code to search within; a ZIP+4 such as "98108-1234" searches its first five digits
epa_echo_get_facilityECHO: Retrieve a full compliance profile for a single EPA-regulated facility by EPA Registry ID or EPA program ID. Returns facility metadata, the NAICS industry codes its programs record, ECHO's facility-level compliance status, a per-statute (CAA, CWA, RCRA, SDWA, and others...5 params

ECHO: Retrieve a full compliance profile for a single EPA-regulated facility by EPA Registry ID or EPA program ID. Returns facility metadata, the NAICS industry codes its programs record, ECHO's facility-level compliance status, a per-statute (CAA, CWA, RCRA, SDWA, and others...

Parameters* required
drinking_water_violations_limitinteger
Maximum number of drinking-water violations to return in one call (1–200, default 50). A larger value, up to 5,000, returns 200 with a notice. Page past it with drinking_water_violations_offset and...default: 50
drinking_water_violations_offsetinteger
Number of drinking-water violations to skip before this page (default 0). Pass the previous call's drinkingWaterViolationsNextOffset to continue; a value past the end returns an empty page.default: 0
inspections_limitinteger
Maximum number of inspections to return in one call (1–100, default 100). A larger value, up to 5,000, returns 100 with a notice. Page past it with inspections_offset and inspectionsNextOffset.default: 100
inspections_offsetinteger
Number of inspections to skip before this page (default 0). Pass the previous call's inspectionsNextOffset to continue; a value past the end returns an empty page.default: 0
registry_id*string
EPA FRS Registry ID for the facility (from epa_echo_search_facilities), or an EPA program ID ECHO resolves to one: a public water system PWSID (from epa_water_search_systems, e.g. WA5300484), a TRI...
epa_echo_search_violationsECHO: Search EPA civil and criminal enforcement cases by state, ZIP code, regulatory program, case type, or filing-date range. Returns case identifier, case type and status, lead agency (EPA or state), primary law and section, enforcement outcome, federal and state penalties,...8 params

ECHO: Search EPA civil and criminal enforcement cases by state, ZIP code, regulatory program, case type, or filing-date range. Returns case identifier, case type and status, lead agency (EPA or state), primary law and section, enforcement outcome, federal and state penalties,...

Parameters* required
case_typestring
Filter by case type: civil (regulatory violations), criminal (willful violations), or all. A filing-date range covers civil cases only: with a date, all returns civil cases and criminal is rejected.one of civil · criminal · alldefault: all
date_filed_endvalue
Latest filing date, inclusive (YYYY-MM-DD). Civil cases only. Omit, or pass "", for no upper bound.
date_filed_startvalue
Earliest filing date, inclusive (YYYY-MM-DD). Civil cases only. Omit, or pass "", for no lower bound.
limitinteger
Maximum number of cases to return in one call (1–100, default 50). A larger value, up to 5,000, returns 100 with a notice. Page past it with offset and nextOffset.default: 50
offsetinteger
Number of cases to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
programstring
Filter by regulatory program: CAA=Clean Air Act, CWA=Clean Water Act, RCRA=hazardous waste, SDWA=drinking water, CERCLA=Superfund, EPCRA=emergency planning and community right-to-know (the statute...one of CAA · CWA · RCRA · SDWA · CERCLA · EPCRA
statestring
2-letter state or territory code where the case is located (e.g. "TX", "PR"), case-insensitive. A case spanning several states matches each of them. ECHO also files some cases under codes outside t...
zip_codestring
5-digit ZIP code of the case's facility location; a ZIP+4 such as "98108-1234" searches its first five digits
epa_echo_get_caseECHO: Retrieve one civil enforcement case by case number, with the facilities, defendants, and settlements behind it. Returns the case's category, enforcement type, status, lead agency, relief sought, outcome, court and DOJ docket numbers, summary, and penalty, cost-recovery,...1 params

ECHO: Retrieve one civil enforcement case by case number, with the facilities, defendants, and settlements behind it. Returns the case's category, enforcement type, status, lead agency, relief sought, outcome, court and DOJ docket numbers, summary, and penalty, cost-recovery,...

Parameters* required
case_id*string
Civil enforcement case number: a caseId from epa_echo_search_violations (e.g. "03-2014-7010", "WA-100446") or a formal action's caseId from epa_echo_get_facility (e.g. "WAPSCAF000000000000000416")....
epa_tri_get_facility_releasesTRI: Query Toxic Release Inventory annual chemical release data for a specific facility. Returns per-chemical release records with chemical name, reporting year, on-site releases by medium (air, water, land, underground injection) and their total, and the Form R one-time relea...5 params

TRI: Query Toxic Release Inventory annual chemical release data for a specific facility. Returns per-chemical release records with chemical name, reporting year, on-site releases by medium (air, water, land, underground injection) and their total, and the Form R one-time relea...

Parameters* required
chemical_namestring
Optional filter to restrict results to a specific chemical (partial match, case-insensitive). Commas, apostrophes, brackets, and Greek letters are matched as written, e.g. "4,4'-Methylenedianiline".
facility_id*string
15-character TRI facility ID (e.g. "9867WSNRWD1981S") — the facilityId field returned by epa_tri_search_releases, or an entry of epa_echo_get_facility triFacilityIds. A 12-digit EPA Registry ID mat...
limitinteger
Maximum number of filings to return in one call (1–500, default 500). A larger value, up to 5,000, returns 500 with a notice. Page past it with offset and nextOffset.default: 500
offsetinteger
Number of filings to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
yearinteger
Reporting year to retrieve. Omit for all available years, newest first. TRI data is typically available through ~2 years prior to the current year.
epa_tri_search_releasesTRI: Search Toxic Release Inventory data across facilities in a state or county, for one reporting year or, without year, every available year newest first. Returns facility name and county, TRI facility ID, EPA Registry ID (the registry_id epa_echo_get_facility takes), parent...7 params

TRI: Search Toxic Release Inventory data across facilities in a state or county, for one reporting year or, without year, every available year newest first. Returns facility name and county, TRI facility ID, EPA Registry ID (the registry_id epa_echo_get_facility takes), parent...

Parameters* required
chemical_namestring
Optional filter to restrict results to a specific chemical (partial match, case-insensitive). Commas, apostrophes, brackets, and Greek letters are matched as written, e.g. "4,4'-Methylenedianiline".
countystring
County name to narrow results within the state, e.g. "King". Case-insensitive partial match on the bare name, so a short name can also match a longer one (LAKE matches LAKE OF THE WOODS; check coun...
include_release_breakdownboolean
Add on-site releases by medium (air, water, land, underground injection) and their total to each record. Costs one extra upstream request, which can add about 20 seconds when EPA has not cached it.default: false
limitinteger
Maximum number of release records to return in one call (1–200, default 50). A larger value, up to 5,000, returns 200 with a notice. Page past it with offset and nextOffset.default: 50
offsetinteger
Number of release records to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
state*string
2-letter US state or territory code (required, e.g. "WA", "TX", "PR")
yearinteger
Reporting year. Omit to search every available year in the state, newest reporting year first, so the first page holds the most recent filings. TRI data lags ~18 months.
epa_superfund_search_sitesSuperfund: Search Superfund (CERCLA/SEMS) sites by location or NPL listing status. Returns site identifiers, source NPL status labels, non-NPL assessment and archive metadata when available, coordinates, and county FIPS code. Accepts either state/city/ZIP, returned in SEMS sit...10 params

Superfund: Search Superfund (CERCLA/SEMS) sites by location or NPL listing status. Returns site identifiers, source NPL status labels, non-NPL assessment and archive metadata when available, coordinates, and county FIPS code. Accepts either state/city/ZIP, returned in SEMS sit...

Parameters* required
citystring
City name (partial match within state, case-insensitive). Punctuation is matched as written ("St. Louis", "Coeur d'Alene").
exclude_archivedboolean
Exclude archived sites by requiring SEMS archived_ind=N; false retains all archive statusesdefault: false
latitudenumber
Latitude for proximity search (use with longitude and radius_miles)
limitinteger
Maximum number of sites to return in one call (1–200, default 50). A larger value, up to 5,000, returns 200 with a notice. Page past it with offset and nextOffset.default: 50
longitudenumber
Longitude for proximity search (use with latitude and radius_miles)
npl_statusstring
Filter by NPL status: listed=final or part of an NPL site (F,A), not-listed=N, proposed=P, deleted=D, removed=R, withdrawn=W, all=include allone of listed · not-listed · proposed · deleted · removed · withdrawndefault: all
offsetinteger
Number of sites to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
radius_milesnumber
Search radius in miles from the given coordinates. Required when using latitude+longitude.
statestring
2-letter US state or territory code to filter sites, e.g. "WA"
zip_codestring
5-digit ZIP code to filter sites; a ZIP+4 searches its 5-digit ZIP. Matches sites recorded under the ZIP or any ZIP+4 within it.
epa_superfund_get_siteSuperfund: Retrieve a site by exact SEMS site ID from epa_superfund_search_sites, with all recorded contaminant associations and their media, operable units, and EPA actions. Repeated chemicals in different contexts and duplicate source rows are retained. An existing site with...1 params

Superfund: Retrieve a site by exact SEMS site ID from epa_superfund_search_sites, with all recorded contaminant associations and their media, operable units, and EPA actions. Repeated chemicals in different contexts and duplicate source rows are retained. An existing site with...

Parameters* required
site_id*string
SEMS siteId from epa_superfund_search_sites; preserve leading zeros
epa_water_search_systemsDrinking water (SDWIS): Search public water systems by state, ZIP code, or county served. Returns system name, PWSID, population served, primary water source, and activity status, in PWSID order; page through a large match with offset and nextOffset. zip_code matches a system'...8 params

Drinking water (SDWIS): Search public water systems by state, ZIP code, or county served. Returns system name, PWSID, population served, primary water source, and activity status, in PWSID order; page through a large match with offset and nextOffset. zip_code matches a system'...

Parameters* required
active_onlyboolean
When true, return only systems SDWIS lists as active (activity code A). The default false also returns inactive systems and ones changed to non-public.default: false
countystring
County the system serves, e.g. "King"; requires state. Case-insensitive, and a trailing "County", "Parish", "Borough", "City and Borough", "Census Area", or "Municipality" is dropped, so "Anchorage...
has_violationboolean
When true, return only systems with a current SDWA violation in EPA's ECHO, its compliance status for the system, which clears violations SDWIS still lists as unresolved. Works with state, zip_code...
limitinteger
Maximum number of systems to return in one call (1–200, default 50). A larger value, up to 5,000, returns 200 with a notice. Page past it with offset and nextOffset.default: 50
offsetinteger
Number of systems to skip before this page (default 0). Pass the previous call's nextOffset to continue; a value past the end returns an empty page.default: 0
pws_typestring
Filter by public water system type: community=permanent residences, non-transient=regular non-residents (schools, businesses), transient=occasional users (campgrounds)one of community · non-transient · transient
statestring
2-letter US state or territory code (e.g. "WA", "CA"), or an EPA region code 01–10 for tribal systems, whose primacy agency is the EPA region
zip_codestring
5-digit ZIP code of the water system's address of record — often its owner's or operator's office, which can be far from the area the system serves. Matches stored ZIP+4s within it; a ZIP+4 searche...
epa_ejscreen_get_scoresEJScreen: Get EJScreen environmental-justice indicators for a point and surrounding buffer. Returns the 13 EJScreen environmental indicators (PM2.5, ozone, diesel particulate, NO2, lead paint, traffic proximity, Superfund/RMP/hazardous-waste/wastewater proximity, underground s...4 params

EJScreen: Get EJScreen environmental-justice indicators for a point and surrounding buffer. Returns the 13 EJScreen environmental indicators (PM2.5, ozone, diesel particulate, NO2, lead paint, traffic proximity, Superfund/RMP/hazardous-waste/wastewater proximity, underground s...

Parameters* required
distancenumber
Buffer radius around the point, in the given unit (default 1). The miles-equivalent must be 15 or less.default: 1
latitude*number
Latitude in decimal degrees.
longitude*number
Longitude in decimal degrees.
unitstring
Unit for distance. Kilometers are converted to miles (× 0.621371) before the request.one of miles · kilometersdefault: miles
epa_airnow_get_conditionsAirNow: Get current AQI observations or the issued AQI forecast for a US location from the AirNow API. Provide either zip_code or both latitude and longitude. Current mode returns the latest hourly NowCast AQI for each pollutant (PM2.5, ozone, PM10) from the closest monitor wi...5 params

AirNow: Get current AQI observations or the issued AQI forecast for a US location from the AirNow API. Provide either zip_code or both latitude and longitude. Current mode returns the latest hourly NowCast AQI for each pollutant (PM2.5, ozone, PM10) from the closest monitor wi...

Parameters* required
forecast_datestring
Forecast mode only (rejected in current mode): keep just the forecast valid on this date (YYYY-MM-DD). Omit to get every issued forecast day. When no issued day matches, the result is empty and its...
latitudenumber
Latitude in decimal degrees (use with longitude instead of zip_code)
longitudenumber
Longitude in decimal degrees (use with latitude instead of zip_code)
modestring
Data mode: "current" for the latest hourly observations, "forecast" for every forecast day the reporting area has issuedone of current · forecastdefault: current
zip_codestring
US ZIP code for the location: 5 digits, or a ZIP+4 such as 98108-1234, which searches its first five digits

Sponsors

Configuration

AIRNOW_API_KEY

Optional AirNow API key for real-time and forecast air quality data. When unset, the epa_airnow_get_conditions tool is not registered and the other tools run without it. Free registration at docs.airnowapi.org.

EJSCREEN_API_BASE_URLdefault: https://api.ejanalysis.com

Optional override for the EJScreen (EJAM) API base URL used by epa_ejscreen_get_scores. Defaults to https://api.ejanalysis.com — the community-maintained EJScreen rehost by Public Environmental Data Partners.

MCP_LOG_LEVELdefault: info

Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').

MCP_TRANSPORT_TYPEdefault: http

Selects the HTTP transport.

MCP_HTTP_HOSTdefault: 127.0.0.1

The hostname for the HTTP server.

MCP_HTTP_PORTdefault: 3010

The port to run the HTTP server on.

MCP_HTTP_ENDPOINT_PATHdefault: /mcp

The endpoint path for the MCP server.

MCP_AUTH_MODEdefault: none

Authentication mode to use: 'none', 'jwt', or 'oauth'.

Readme

@cyanheads/epa-mcp-server

Search and retrieve EPA environmental data: facility compliance (ECHO), toxic releases (TRI), Superfund sites, drinking water systems, environmental-justice screening (EJScreen), and real-time air quality (AirNow). STDIO or Streamable HTTP.

11 Tools • 2 Resources

Details

Repository
github.com/cyanheads/epa-mcp-server
Categories
Search & Web Crawling, Data & Analytics
Package
@cyanheads/epa-mcp-server
Transport
STDIO, HTTP
Registry
MCP registry, active
Resources
1
Tools verified
Nov 6, 2026

More from cyanheads

Related Search & Web Crawling MCP servers

View all
1cyanheads avatarFbi Crime Mcp Servercyanheads/fbi-crime-mcp-serverFBI Crime Data Explorer — offense rates, hate crime, arrests, NIBRS, LEOKA stats, agency search.2stars
2cyanheads avatarFederal Regulations Mcp Servercyanheads/federal-regulations-mcp-serverSearch and trace US federal rules across the Federal Register, eCFR, and Regulations.gov.2stars
3cyanheads avatarOpenfoodfacts Mcp Servercyanheads/openfoodfacts-mcp-serverBarcode lookup, nutrition search, and product comparison for 3M+ crowd-sourced food products.2stars
4cyanheads avatarReliefweb Mcp Servercyanheads/reliefweb-mcp-serverSearch ReliefWeb humanitarian reports, disasters, jobs, training, and country profiles via MCP.2stars
5cyanheads avatarSmithsonian Mcp Servercyanheads/smithsonian-mcp-serverSearch 14.5M Smithsonian Open Access objects, get CC0 images, find cross-collection connections.2stars
6cyberpapiii avatarImessage Maxcyberpapiii/imessage-maxAI-optimized MCP server for iMessage on macOS. Read, search, and send messages.2stars