EPA MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@EPA MCP ServerFind facilities in Houston, TX"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Overview
EPA environmental data across five federal programs — facility compliance (ECHO), toxic chemical releases (TRI), Superfund cleanup sites, drinking water systems (SDWIS), and environmental-justice screening (EJScreen) — plus real-time air quality via AirNow. Search facilities by location or compliance status, pull inspection and enforcement history, track toxic releases across a region, and screen a point for environmental-justice risk from any MCP client. Runs as a stdio process or a local Streamable HTTP server.
Tools
Tool | Description |
| Search EPA-regulated facilities by location, industry program, or compliance status across CAA, CWA, RCRA, TRI, and SDWA |
| Full compliance profile for one facility by EPA Registry ID — inspections, enforcement actions, and penalties |
| Search EPA civil and criminal enforcement cases by state, program, or date range |
| Current AQI observations or next-day forecasts from AirNow |
| Per-chemical Toxic Release Inventory data for a single facility |
| Toxic Release Inventory records across facilities in a state or county |
| Search Superfund (CERCLA/SEMS) sites by location or NPL listing status |
| Search drinking water systems (SDWIS) by state or ZIP code |
| EJScreen environmental-justice indicators for a point and buffer |
Resources
Resource | Description |
| Full compliance profile for a facility by EPA Registry ID (same data as |
| Superfund site record by SEMS site ID |
All resource data is also reachable via tools — use epa_get_facility and epa_search_superfund for programmatic access in tool-only MCP clients.
Related MCP server: mcp-epa-envirofacts
Capability reference
epa_search_facilities tool
Geographic filters: ZIP code, state, city (pair with state), or latitude + longitude + radius_miles (max 100 miles) for proximity search — at least one is required
Optional
programsfilter narrows to CAA, CWA, RCRA, TRI, or SDWA registrants;has_violationsurfaces only non-compliant facilitiesReturns
registryIdforepa_get_facility, plusfipsCodewhen available for Census chainingUp to 100 results per call (default 50)
epa_get_facility tool
Input:
registry_id, obtained fromepa_search_facilitiesAggregates 3–5 ECHO DFR endpoints in parallel — program flags and TRI totals, compliance summary, inspection/enforcement history, CAA details, CWA/NPDES permit details
Uses
Promise.allSettled— partial data is returned even when one upstream endpoint failsairCompliance/waterComplianceare present only when the facility is registered under that programfacility_not_foundwhen ECHO has no record for the Registry ID
epa_search_violations tool
At least one of
stateorzip_codeis requiredprogramfilter covers CAA, CWA, RCRA, SDWA, CERCLA, FIFRA, or TSCA;case_typeis civil, criminal, or all (default all)Date range filter by filing date (ISO 8601
date_filed_start/date_filed_end)facilityNameandregistryIdare not populated by ECHO's enforcement-case endpoint — chain intoepa_get_facilityfor facility detailUp to 100 cases per call (default 50)
epa_get_air_quality tool
Provide
zip_codeor bothlatitudeandlongitudemode:current(default) orforecast(requiresforecast_date, ISO 8601)Per-pollutant AQI (PM2.5, ozone, CO, SO2, NO2) with numeric
categoryNumber(1 Good – 6 Hazardous) andcategoryNamedistance_milessets the reporting-station search radius (default 25, max 300)Data is preliminary — informational use only, not for regulatory decisions; responses are cached ~1 hour
Only registered when
AIRNOW_API_KEYis set
epa_get_tri_releases tool
facility_idis the TRIfacilityIdfromepa_search_tri_releases; optionalyear(1987–2030, defaults to all available years) andchemical_name(partial match)Per-chemical breakdown by medium — air, water, land, underground injection — plus a separate one-time/non-routine release total
TRI data lags ~18 months; the most recent available year is typically 2 years prior to the current year
epa_search_tri_releases tool
stateis required (2-letter); optionalcounty(partial match),year, andchemical_nameUp to 200 records per call (default 50); an enrichment flag marks the result truncated when it hits the limit
Complement to
epa_get_tri_releases— use this for area discovery, then drill into a specific facility
epa_search_superfund tool
Two input shapes:
state/city/zip_code, orlatitude+longitude+radius_miles(0.1–500 miles) — one is requirednpl_statusfilter:listed,not-listed,proposed, orall(defaultall)Up to 200 sites per call (default 50)
epa_search_water_systems tool
At least one of
stateorzip_codeis requiredhas_violationsurfaces only systems with active violations;pws_typefilters tocommunity,non-transient, ortransient(outputtypereports the SDWIS codes CWS / NTNCWS / TNCWS)Up to 200 systems per call (default 50)
epa_get_ejscreen tool
Input:
latitude,longitude,distance(default 1), andunit(milesorkilometers, defaultmiles); kilometers are converted to miles before the request, and the buffer is capped at 15 milesReturns 13 environmental and 6 demographic indicators, each with national/state percentiles, plus the Demographic Index and Supplemental Demographic Index
Points outside US coverage return
coverage.valid: falsewith a note instead of fabricated indicatorsData source: EJScreen v2.2 (2022) via the community-maintained EJAM API (Public Environmental Data Partners) — not a live EPA endpoint
epa://facility/{registry_id} resource
Same data as
epa_get_facility;registry_idcomes fromepa_search_facilitiesErrors when the Registry ID has no ECHO record
epa://superfund/{site_id} resource
Same data as
epa_search_superfundrecords;site_idcomes fromepa_search_superfundErrors when the site ID has no SEMS record
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.
EPA-specific:
Multiple environmental data sources unified behind a single
epa_tool surface: ECHO (facility compliance), Envirofacts DMAP (TRI, Superfund, SDWIS), AirNow (real-time air quality), and the community-maintained EJAM API rehosting EJScreen data (v2.2, 2022)Parallel ECHO DFR aggregation in
epa_get_facility— 3–5 upstream calls resolved concurrently withPromise.allSettledAirNow response caching (~1 hour TTL) to stay within per-key rate limits
Agent-friendly output:
Facility search supplies
registryIdfor compliance lookups andfipsCodewhen available for Census queries; TRI search suppliesfacilityIdfor release detailsStructured partial failure —
epa_get_facilityreturns available program data even when one DFR endpoint is unavailable, withairCompliance/waterCompliancepresent only when that program appliesRecovery-hint messages on empty results — every search tool returns a
messagefield that echoes the applied filters and suggests how to broaden the search
Getting started
Add the following to your MCP client configuration file. An AirNow API key is optional — set AIRNOW_API_KEY to enable epa_get_air_quality (register free at docs.airnowapi.org); without it the server starts with the other 8 tools. ECHO, DMAP, and EJScreen tools work without authentication.
{
"mcpServers": {
"epa-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/epa-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"AIRNOW_API_KEY": "your-airnow-key"
}
}
}
}Or with npx (no Bun required):
{
"mcpServers": {
"epa-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/epa-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info",
"AIRNOW_API_KEY": "your-airnow-key"
}
}
}
}Or with Docker:
{
"mcpServers": {
"epa-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"-e", "AIRNOW_API_KEY=your-airnow-key",
"ghcr.io/cyanheads/epa-mcp-server:latest"
]
}
}
}For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 AIRNOW_API_KEY=... bun run start:http
# Server listens at http://localhost:3010/mcpPrerequisites
Bun v1.4.0 or higher (or Node.js v24+).
(Optional) An AirNow API key to enable
epa_get_air_quality— register free at docs.airnowapi.org/account/request. Without it the server runs the other 8 tools. ECHO, DMAP, and EJScreen tools require no API key.
Installation
Clone the repository:
git clone https://github.com/cyanheads/epa-mcp-server.gitNavigate into the directory:
cd epa-mcp-serverInstall dependencies:
bun installConfigure environment:
cp .env.example .env
# optionally set AIRNOW_API_KEY to enable the air quality toolConfiguration
All configuration is validated at startup via Zod schemas in src/config/. Key environment variables:
Variable | Description | Default |
| Optional. Enables | — |
| ECHO API base URL |
|
| Envirofacts DMAP API base URL |
|
| AirNow API base URL |
|
| Optional. EJScreen (EJAM) API base URL used by |
|
| Transport: |
|
| HTTP server port |
|
| HTTP endpoint path |
|
| HTTP sessions: |
|
| Auth mode: |
|
| Log level (RFC 5424) |
|
| Directory for log files (Node.js only) |
|
| Storage backend: |
|
| Enable OpenTelemetry tracing and metrics |
|
See .env.example for the full list of optional overrides.
Running the server
Local development
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:httpRun checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t epa-mcp-server .
docker run --rm -e AIRNOW_API_KEY=your-key -p 3010:3010 epa-mcp-serverThe Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/epa-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Directory | Purpose |
|
|
| Server-specific environment variable parsing and validation with Zod. |
| Tool definitions ( |
| Resource definitions ( |
| ECHO REST API service layer — facility search, facility detail, enforcement cases. |
| Envirofacts DMAP service layer — TRI releases, Superfund sites, drinking water systems. |
| AirNow service layer — current and forecast AQI observations. |
| EJScreen (EJAM) service layer — environmental-justice indicators for a point + buffer. |
| Unit and integration tests mirroring |
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
Handlers throw, framework catches — no
try/catchin tool logicUse
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storageRegister new tools and resources via the barrels in
src/mcp-server/*/definitions/index.tsWrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
ECHO searches must enforce at least one geographic parameter — unscoped queries time out against the live API
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run testLicense
Apache-2.0 — see LICENSE for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
EPA ECHO MCP — wraps EPA ECHO Web Services (free, no auth)
EPA Emissions MCP — wraps EPA Envirofacts REST API (free, no auth)
EPA AirNow MCP — official US real-time AQI + forecast (free key)
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceExposes EPA Computational Toxicology (CompTox) evidence federation through MCP, enabling chemical identity, hazard, exposure, and bioactivity data retrieval for AI agents.6Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables querying US EPA Envirofacts data using natural language, providing access to environmental information through the Pipeworx MCP gateway.300 npmMIT
- AlicenseAqualityBmaintenanceAn MCP server that exposes EPA ECHO water quality data as tools, enabling facility search, permit limits, discharge measurements, violations, and enforcement actions.6MIT
- AlicenseNot gradedqualityBmaintenanceWraps EPA ECHO Web Services (free, no auth) to enable querying environmental data via natural language.287 npmMIT