@cyanheads/epa-mcp-server 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CLAUDE.md +405 -0
  2. package/Dockerfile +98 -0
  3. package/README.md +322 -0
  4. package/changelog/0.1.x/0.1.0.md +22 -0
  5. package/changelog/0.1.x/0.1.1.md +18 -0
  6. package/changelog/template.md +119 -0
  7. package/dist/config/server-config.d.ts +15 -0
  8. package/dist/config/server-config.d.ts.map +1 -0
  9. package/dist/config/server-config.js +38 -0
  10. package/dist/config/server-config.js.map +1 -0
  11. package/dist/index.d.ts +7 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +28 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/mcp-server/resources/definitions/facility.resource.d.ts +9 -0
  16. package/dist/mcp-server/resources/definitions/facility.resource.d.ts.map +1 -0
  17. package/dist/mcp-server/resources/definitions/facility.resource.js +24 -0
  18. package/dist/mcp-server/resources/definitions/facility.resource.js.map +1 -0
  19. package/dist/mcp-server/resources/definitions/index.d.ts +12 -0
  20. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -0
  21. package/dist/mcp-server/resources/definitions/index.js +10 -0
  22. package/dist/mcp-server/resources/definitions/index.js.map +1 -0
  23. package/dist/mcp-server/resources/definitions/superfund-site.resource.d.ts +9 -0
  24. package/dist/mcp-server/resources/definitions/superfund-site.resource.d.ts.map +1 -0
  25. package/dist/mcp-server/resources/definitions/superfund-site.resource.js +26 -0
  26. package/dist/mcp-server/resources/definitions/superfund-site.resource.js.map +1 -0
  27. package/dist/mcp-server/tools/definitions/get-air-quality.tool.d.ts +46 -0
  28. package/dist/mcp-server/tools/definitions/get-air-quality.tool.d.ts.map +1 -0
  29. package/dist/mcp-server/tools/definitions/get-air-quality.tool.js +193 -0
  30. package/dist/mcp-server/tools/definitions/get-air-quality.tool.js.map +1 -0
  31. package/dist/mcp-server/tools/definitions/get-facility.tool.d.ts +61 -0
  32. package/dist/mcp-server/tools/definitions/get-facility.tool.d.ts.map +1 -0
  33. package/dist/mcp-server/tools/definitions/get-facility.tool.js +193 -0
  34. package/dist/mcp-server/tools/definitions/get-facility.tool.js.map +1 -0
  35. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.d.ts +26 -0
  36. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.d.ts.map +1 -0
  37. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.js +92 -0
  38. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.js.map +1 -0
  39. package/dist/mcp-server/tools/definitions/index.d.ts +305 -0
  40. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -0
  41. package/dist/mcp-server/tools/definitions/index.js +31 -0
  42. package/dist/mcp-server/tools/definitions/index.js.map +1 -0
  43. package/dist/mcp-server/tools/definitions/search-facilities.tool.d.ts +58 -0
  44. package/dist/mcp-server/tools/definitions/search-facilities.tool.d.ts.map +1 -0
  45. package/dist/mcp-server/tools/definitions/search-facilities.tool.js +182 -0
  46. package/dist/mcp-server/tools/definitions/search-facilities.tool.js.map +1 -0
  47. package/dist/mcp-server/tools/definitions/search-superfund.tool.d.ts +49 -0
  48. package/dist/mcp-server/tools/definitions/search-superfund.tool.d.ts.map +1 -0
  49. package/dist/mcp-server/tools/definitions/search-superfund.tool.js +155 -0
  50. package/dist/mcp-server/tools/definitions/search-superfund.tool.js.map +1 -0
  51. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.d.ts +29 -0
  52. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.d.ts.map +1 -0
  53. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.js +113 -0
  54. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.js.map +1 -0
  55. package/dist/mcp-server/tools/definitions/search-violations.tool.d.ts +48 -0
  56. package/dist/mcp-server/tools/definitions/search-violations.tool.d.ts.map +1 -0
  57. package/dist/mcp-server/tools/definitions/search-violations.tool.js +156 -0
  58. package/dist/mcp-server/tools/definitions/search-violations.tool.js.map +1 -0
  59. package/dist/mcp-server/tools/definitions/search-water-systems.tool.d.ts +38 -0
  60. package/dist/mcp-server/tools/definitions/search-water-systems.tool.d.ts.map +1 -0
  61. package/dist/mcp-server/tools/definitions/search-water-systems.tool.js +147 -0
  62. package/dist/mcp-server/tools/definitions/search-water-systems.tool.js.map +1 -0
  63. package/dist/services/airnow/airnow-service.d.ts +45 -0
  64. package/dist/services/airnow/airnow-service.d.ts.map +1 -0
  65. package/dist/services/airnow/airnow-service.js +160 -0
  66. package/dist/services/airnow/airnow-service.js.map +1 -0
  67. package/dist/services/airnow/types.d.ts +39 -0
  68. package/dist/services/airnow/types.d.ts.map +1 -0
  69. package/dist/services/airnow/types.js +6 -0
  70. package/dist/services/airnow/types.js.map +1 -0
  71. package/dist/services/dmap/dmap-service.d.ts +60 -0
  72. package/dist/services/dmap/dmap-service.d.ts.map +1 -0
  73. package/dist/services/dmap/dmap-service.js +320 -0
  74. package/dist/services/dmap/dmap-service.js.map +1 -0
  75. package/dist/services/dmap/types.d.ts +108 -0
  76. package/dist/services/dmap/types.d.ts.map +1 -0
  77. package/dist/services/dmap/types.js +6 -0
  78. package/dist/services/dmap/types.js.map +1 -0
  79. package/dist/services/echo/echo-service.d.ts +57 -0
  80. package/dist/services/echo/echo-service.d.ts.map +1 -0
  81. package/dist/services/echo/echo-service.js +295 -0
  82. package/dist/services/echo/echo-service.js.map +1 -0
  83. package/dist/services/echo/types.d.ts +198 -0
  84. package/dist/services/echo/types.d.ts.map +1 -0
  85. package/dist/services/echo/types.js +6 -0
  86. package/dist/services/echo/types.js.map +1 -0
  87. package/package.json +80 -0
  88. package/server.json +111 -0
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Barrel export for all EPA MCP server resource definitions.
3
+ * @module mcp-server/resources/definitions/index
4
+ */
5
+ export { facilityResource } from './facility.resource.js';
6
+ export { superfundSiteResource } from './superfund-site.resource.js';
7
+ import { facilityResource } from './facility.resource.js';
8
+ import { superfundSiteResource } from './superfund-site.resource.js';
9
+ export const allResourceDefinitions = [facilityResource, superfundSiteResource];
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AAErE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,gBAAgB,EAAE,qBAAqB,CAAU,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @fileoverview Resource for fetching a Superfund site record by SEMS site ID.
3
+ * @module mcp-server/resources/definitions/superfund-site.resource
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ export declare const superfundSiteResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{
7
+ site_id: z.ZodString;
8
+ }, z.core.$strip>, undefined, undefined>;
9
+ //# sourceMappingURL=superfund-site.resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"superfund-site.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/superfund-site.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAIrD,eAAO,MAAM,qBAAqB;;wCAyBhC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Resource for fetching a Superfund site record by SEMS site ID.
3
+ * @module mcp-server/resources/definitions/superfund-site.resource
4
+ */
5
+ import { resource, z } from '@cyanheads/mcp-ts-core';
6
+ import { notFound } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getDmapService } from '../../../services/dmap/dmap-service.js';
8
+ export const superfundSiteResource = resource('epa://superfund/{site_id}', {
9
+ name: 'epa-superfund-site',
10
+ description: 'Superfund site record from EPA SEMS by site ID. Returns NPL status, cleanup status, location, and coordinates.',
11
+ mimeType: 'application/json',
12
+ params: z.object({
13
+ site_id: z.string().describe('EPA SEMS Superfund site ID (obtained from epa_search_superfund)'),
14
+ }),
15
+ async handler(params, ctx) {
16
+ ctx.log.info('epa://superfund resource', { siteId: params.site_id });
17
+ // DMAP supports direct column equality filters — use site_id/equals/{id} directly
18
+ const sites = await getDmapService().searchSuperfundById(params.site_id, ctx);
19
+ const site = sites[0];
20
+ if (!site) {
21
+ throw notFound(`No Superfund site found with site ID "${params.site_id}". Use epa_search_superfund to discover valid site IDs.`, { siteId: params.site_id });
22
+ }
23
+ return site;
24
+ },
25
+ });
26
+ //# sourceMappingURL=superfund-site.resource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"superfund-site.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/superfund-site.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC,2BAA2B,EAAE;IACzE,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,gHAAgH;IAClH,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;KAChG,CAAC;IAEF,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG;QACvB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAErE,kFAAkF;QAClF,MAAM,KAAK,GAAG,MAAM,cAAc,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC9E,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,QAAQ,CACZ,yCAAyC,MAAM,CAAC,OAAO,yDAAyD,EAChH,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,CAC3B,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview Tool for getting AQI observations or forecasts for a location from AirNow.
3
+ * @module mcp-server/tools/definitions/get-air-quality.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const getAirQualityTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ zip_code: z.ZodOptional<z.ZodString>;
9
+ latitude: z.ZodOptional<z.ZodNumber>;
10
+ longitude: z.ZodOptional<z.ZodNumber>;
11
+ mode: z.ZodDefault<z.ZodEnum<{
12
+ current: "current";
13
+ forecast: "forecast";
14
+ }>>;
15
+ forecast_date: z.ZodOptional<z.ZodString>;
16
+ distance_miles: z.ZodDefault<z.ZodNumber>;
17
+ }, z.core.$strip>, z.ZodObject<{
18
+ observations: z.ZodArray<z.ZodObject<{
19
+ reportingArea: z.ZodOptional<z.ZodString>;
20
+ stateCode: z.ZodOptional<z.ZodString>;
21
+ latitude: z.ZodOptional<z.ZodNumber>;
22
+ longitude: z.ZodOptional<z.ZodNumber>;
23
+ dateObserved: z.ZodOptional<z.ZodString>;
24
+ hourObserved: z.ZodOptional<z.ZodNumber>;
25
+ localTimeZone: z.ZodOptional<z.ZodString>;
26
+ readings: z.ZodArray<z.ZodObject<{
27
+ parameterName: z.ZodString;
28
+ aqi: z.ZodNumber;
29
+ categoryNumber: z.ZodOptional<z.ZodNumber>;
30
+ categoryName: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strip>>;
32
+ }, z.core.$strip>>;
33
+ mode: z.ZodString;
34
+ message: z.ZodOptional<z.ZodString>;
35
+ }, z.core.$strip>, readonly [{
36
+ readonly reason: "no_location";
37
+ readonly code: JsonRpcErrorCode.InvalidParams;
38
+ readonly when: "Neither zip_code nor latitude+longitude was provided.";
39
+ readonly recovery: "Provide either zip_code or both latitude and longitude to identify the location.";
40
+ }, {
41
+ readonly reason: "forecast_date_required";
42
+ readonly code: JsonRpcErrorCode.InvalidParams;
43
+ readonly when: "Mode is \"forecast\" but forecast_date was not provided.";
44
+ readonly recovery: "Provide forecast_date as YYYY-MM-DD when using mode=\"forecast\".";
45
+ }]>;
46
+ //# sourceMappingURL=get-air-quality.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-air-quality.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-air-quality.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkO5B,CAAC"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * @fileoverview Tool for getting AQI observations or forecasts for a location from AirNow.
3
+ * @module mcp-server/tools/definitions/get-air-quality.tool
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getAirNowService } from '../../../services/airnow/airnow-service.js';
8
+ export const getAirQualityTool = tool('epa_get_air_quality', {
9
+ title: 'Get Air Quality Index',
10
+ description: 'Get current AQI observations or forecasts for a location from the AirNow API. Returns per-pollutant AQI values (PM2.5, ozone, CO, SO2, NO2), AQI category (Good through Hazardous), reporting area name, and observation timestamp. Provide either zip_code or both latitude and longitude. Set mode to "forecast" and provide forecast_date for next-day projections. Data is preliminary — suitable for awareness and informational use, not regulatory decisions. Responses are cached for ~1 hour.',
11
+ annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
12
+ input: z.object({
13
+ zip_code: z.string().optional().describe('5-digit ZIP code for the location'),
14
+ latitude: z
15
+ .number()
16
+ .optional()
17
+ .describe('Latitude in decimal degrees (use with longitude instead of zip_code)'),
18
+ longitude: z
19
+ .number()
20
+ .optional()
21
+ .describe('Longitude in decimal degrees (use with latitude instead of zip_code)'),
22
+ mode: z
23
+ .enum(['current', 'forecast'])
24
+ .default('current')
25
+ .describe('Data mode: "current" for latest AQI observations, "forecast" for next-day projections'),
26
+ forecast_date: z
27
+ .string()
28
+ .optional()
29
+ .describe('Date for forecast in ISO 8601 format (YYYY-MM-DD). Required when mode is "forecast".'),
30
+ distance_miles: z
31
+ .number()
32
+ .int()
33
+ .min(0)
34
+ .max(300)
35
+ .default(25)
36
+ .describe('Search radius in miles for finding reporting stations. Default 25 miles.'),
37
+ }),
38
+ output: z.object({
39
+ observations: z
40
+ .array(z
41
+ .object({
42
+ reportingArea: z
43
+ .string()
44
+ .optional()
45
+ .describe('Name of the AQI reporting area (e.g. "Seattle-Tacoma-Bellevue, WA")'),
46
+ stateCode: z.string().optional().describe('2-letter state code of the reporting area'),
47
+ latitude: z.number().optional().describe('Latitude of the reporting area centroid'),
48
+ longitude: z.number().optional().describe('Longitude of the reporting area centroid'),
49
+ dateObserved: z
50
+ .string()
51
+ .optional()
52
+ .describe('Observation or forecast date (YYYY-MM-DD)'),
53
+ hourObserved: z
54
+ .number()
55
+ .optional()
56
+ .describe('Hour of observation (0–23) in local time. Absent for daily forecasts.'),
57
+ localTimeZone: z
58
+ .string()
59
+ .optional()
60
+ .describe('Local time zone abbreviation (e.g. "PST")'),
61
+ readings: z
62
+ .array(z
63
+ .object({
64
+ parameterName: z
65
+ .string()
66
+ .describe('Pollutant name (e.g. "PM2.5", "Ozone", "CO")'),
67
+ aqi: z.number().describe('Air Quality Index value for this pollutant'),
68
+ categoryNumber: z
69
+ .number()
70
+ .optional()
71
+ .describe('AQI category number: 1=Good, 2=Moderate, 3=Unhealthy for Sensitive Groups, 4=Unhealthy, 5=Very Unhealthy, 6=Hazardous'),
72
+ categoryName: z
73
+ .string()
74
+ .optional()
75
+ .describe('AQI category name (e.g. "Good", "Moderate", "Unhealthy")'),
76
+ })
77
+ .describe('AQI reading for a single pollutant parameter'))
78
+ .describe('Per-pollutant AQI readings for this reporting area and time'),
79
+ })
80
+ .describe('AQI observation or forecast record for a single reporting area'))
81
+ .describe('AQI observation or forecast records grouped by reporting area'),
82
+ mode: z.string().describe('Data mode used: "current" or "forecast"'),
83
+ message: z
84
+ .string()
85
+ .optional()
86
+ .describe('Recovery hint when no observations are returned — suggests trying a different location or increasing distance_miles. Absent when data is returned.'),
87
+ }),
88
+ errors: [
89
+ {
90
+ reason: 'no_location',
91
+ code: JsonRpcErrorCode.InvalidParams,
92
+ when: 'Neither zip_code nor latitude+longitude was provided.',
93
+ recovery: 'Provide either zip_code or both latitude and longitude to identify the location.',
94
+ },
95
+ {
96
+ reason: 'forecast_date_required',
97
+ code: JsonRpcErrorCode.InvalidParams,
98
+ when: 'Mode is "forecast" but forecast_date was not provided.',
99
+ recovery: 'Provide forecast_date as YYYY-MM-DD when using mode="forecast".',
100
+ },
101
+ ],
102
+ async handler(input, ctx) {
103
+ // Validate location
104
+ const hasZip = !!input.zip_code?.trim();
105
+ const hasLatLng = input.latitude !== undefined && input.longitude !== undefined;
106
+ if (!hasZip && !hasLatLng) {
107
+ throw ctx.fail('no_location', 'Provide either zip_code or both latitude and longitude.', {
108
+ ...ctx.recoveryFor('no_location'),
109
+ });
110
+ }
111
+ // Validate forecast date
112
+ if (input.mode === 'forecast' && !input.forecast_date?.trim()) {
113
+ throw ctx.fail('forecast_date_required', 'forecast_date (YYYY-MM-DD) is required when mode is "forecast".', {
114
+ ...ctx.recoveryFor('forecast_date_required'),
115
+ });
116
+ }
117
+ ctx.log.info('epa_get_air_quality', {
118
+ mode: input.mode,
119
+ zip: input.zip_code,
120
+ lat: input.latitude,
121
+ });
122
+ const service = getAirNowService();
123
+ let observations;
124
+ if (input.mode === 'current') {
125
+ if (hasZip) {
126
+ observations = await service.getCurrentByZip({ zipCode: input.zip_code, distanceMiles: input.distance_miles }, ctx);
127
+ }
128
+ else {
129
+ observations = await service.getCurrentByLatLng({
130
+ latitude: input.latitude,
131
+ longitude: input.longitude,
132
+ distanceMiles: input.distance_miles,
133
+ }, ctx);
134
+ }
135
+ }
136
+ else {
137
+ if (hasZip) {
138
+ observations = await service.getForecastByZip({
139
+ zipCode: input.zip_code,
140
+ date: input.forecast_date,
141
+ distanceMiles: input.distance_miles,
142
+ }, ctx);
143
+ }
144
+ else {
145
+ observations = await service.getForecastByLatLng({
146
+ latitude: input.latitude,
147
+ longitude: input.longitude,
148
+ date: input.forecast_date,
149
+ distanceMiles: input.distance_miles,
150
+ }, ctx);
151
+ }
152
+ }
153
+ ctx.log.info('epa_get_air_quality completed', { areas: observations.length });
154
+ if (observations.length === 0) {
155
+ const location = hasZip
156
+ ? `zip_code="${input.zip_code}"`
157
+ : `lat=${input.latitude}, lng=${input.longitude}`;
158
+ return {
159
+ observations: [],
160
+ mode: input.mode,
161
+ message: `No AQI data found for ${location} within ${input.distance_miles} miles. Try increasing distance_miles or check that the location is within the US.`,
162
+ };
163
+ }
164
+ return { observations, mode: input.mode };
165
+ },
166
+ format: (result) => {
167
+ const lines = [];
168
+ lines.push(`## Air Quality Index — ${result.mode === 'forecast' ? 'Forecast' : 'Current Observations'} (mode: ${result.mode})`);
169
+ if (result.message)
170
+ lines.push(`\n> ${result.message}`);
171
+ for (const obs of result.observations) {
172
+ lines.push(`\n### ${obs.reportingArea ?? 'Unknown Area'}`);
173
+ if (obs.stateCode)
174
+ lines.push(`**State:** ${obs.stateCode}`);
175
+ if (obs.dateObserved) {
176
+ const timeStr = obs.hourObserved !== undefined
177
+ ? ` at ${obs.hourObserved}:00 ${obs.localTimeZone ?? ''}`
178
+ : '';
179
+ lines.push(`**Date:** ${obs.dateObserved}${timeStr}`);
180
+ }
181
+ if (obs.latitude !== undefined && obs.longitude !== undefined) {
182
+ lines.push(`**Coordinates:** ${obs.latitude}, ${obs.longitude}`);
183
+ }
184
+ for (const reading of obs.readings) {
185
+ const category = reading.categoryName ? ` (${reading.categoryName})` : '';
186
+ const catNum = reading.categoryNumber !== undefined ? ` [category ${reading.categoryNumber}]` : '';
187
+ lines.push(`**${reading.parameterName}:** AQI ${reading.aqi}${category}${catNum}`);
188
+ }
189
+ }
190
+ return [{ type: 'text', text: lines.join('\n') }];
191
+ },
192
+ });
193
+ //# sourceMappingURL=get-air-quality.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-air-quality.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-air-quality.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAGvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,EAAE;IAC3D,KAAK,EAAE,uBAAuB;IAC9B,WAAW,EACT,weAAwe;IAC1e,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE;IAE9E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC;QACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC7E,QAAQ,EAAE,CAAC;aACR,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sEAAsE,CAAC;QACnF,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sEAAsE,CAAC;QACnF,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;aAC7B,OAAO,CAAC,SAAS,CAAC;aAClB,QAAQ,CACP,uFAAuF,CACxF;QACH,aAAa,EAAE,CAAC;aACb,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,sFAAsF,CACvF;QACH,cAAc,EAAE,CAAC;aACd,MAAM,EAAE;aACR,GAAG,EAAE;aACL,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CAAC,0EAA0E,CAAC;KACxF,CAAC;IAEF,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC;aACZ,KAAK,CACJ,CAAC;aACE,MAAM,CAAC;YACN,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,qEAAqE,CAAC;YAClF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;YACtF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;YACnF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;YACrF,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2CAA2C,CAAC;YACxD,YAAY,EAAE,CAAC;iBACZ,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,uEAAuE,CAAC;YACpF,aAAa,EAAE,CAAC;iBACb,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CAAC,2CAA2C,CAAC;YACxD,QAAQ,EAAE,CAAC;iBACR,KAAK,CACJ,CAAC;iBACE,MAAM,CAAC;gBACN,aAAa,EAAE,CAAC;qBACb,MAAM,EAAE;qBACR,QAAQ,CAAC,8CAA8C,CAAC;gBAC3D,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;gBACtE,cAAc,EAAE,CAAC;qBACd,MAAM,EAAE;qBACR,QAAQ,EAAE;qBACV,QAAQ,CACP,uHAAuH,CACxH;gBACH,YAAY,EAAE,CAAC;qBACZ,MAAM,EAAE;qBACR,QAAQ,EAAE;qBACV,QAAQ,CAAC,0DAA0D,CAAC;aACxE,CAAC;iBACD,QAAQ,CAAC,8CAA8C,CAAC,CAC5D;iBACA,QAAQ,CAAC,6DAA6D,CAAC;SAC3E,CAAC;aACD,QAAQ,CAAC,gEAAgE,CAAC,CAC9E;aACA,QAAQ,CAAC,+DAA+D,CAAC;QAC5E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QACpE,OAAO,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,oJAAoJ,CACrJ;KACJ,CAAC;IAEF,MAAM,EAAE;QACN;YACE,MAAM,EAAE,aAAa;YACrB,IAAI,EAAE,gBAAgB,CAAC,aAAa;YACpC,IAAI,EAAE,uDAAuD;YAC7D,QAAQ,EAAE,kFAAkF;SAC7F;QACD;YACE,MAAM,EAAE,wBAAwB;YAChC,IAAI,EAAE,gBAAgB,CAAC,aAAa;YACpC,IAAI,EAAE,wDAAwD;YAC9D,QAAQ,EAAE,iEAAiE;SAC5E;KACF;IAED,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG;QACtB,oBAAoB;QACpB,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC;QAChF,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YAC1B,MAAM,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,yDAAyD,EAAE;gBACvF,GAAG,GAAG,CAAC,WAAW,CAAC,aAAa,CAAC;aAClC,CAAC,CAAC;QACL,CAAC;QAED,yBAAyB;QACzB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;YAC9D,MAAM,GAAG,CAAC,IAAI,CACZ,wBAAwB,EACxB,iEAAiE,EACjE;gBACE,GAAG,GAAG,CAAC,WAAW,CAAC,wBAAwB,CAAC;aAC7C,CACF,CAAC;QACJ,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAClC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,GAAG,EAAE,KAAK,CAAC,QAAQ;YACnB,GAAG,EAAE,KAAK,CAAC,QAAQ;SACpB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,IAAI,YAAgC,CAAC;QAErC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,GAAG,MAAM,OAAO,CAAC,eAAe,CAC1C,EAAE,OAAO,EAAE,KAAK,CAAC,QAAS,EAAE,aAAa,EAAE,KAAK,CAAC,cAAc,EAAE,EACjE,GAAG,CACJ,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,MAAM,OAAO,CAAC,kBAAkB,CAC7C;oBACE,QAAQ,EAAE,KAAK,CAAC,QAAS;oBACzB,SAAS,EAAE,KAAK,CAAC,SAAU;oBAC3B,aAAa,EAAE,KAAK,CAAC,cAAc;iBACpC,EACD,GAAG,CACJ,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,MAAM,EAAE,CAAC;gBACX,YAAY,GAAG,MAAM,OAAO,CAAC,gBAAgB,CAC3C;oBACE,OAAO,EAAE,KAAK,CAAC,QAAS;oBACxB,IAAI,EAAE,KAAK,CAAC,aAAc;oBAC1B,aAAa,EAAE,KAAK,CAAC,cAAc;iBACpC,EACD,GAAG,CACJ,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAG,MAAM,OAAO,CAAC,mBAAmB,CAC9C;oBACE,QAAQ,EAAE,KAAK,CAAC,QAAS;oBACzB,SAAS,EAAE,KAAK,CAAC,SAAU;oBAC3B,IAAI,EAAE,KAAK,CAAC,aAAc;oBAC1B,aAAa,EAAE,KAAK,CAAC,cAAc;iBACpC,EACD,GAAG,CACJ,CAAC;YACJ,CAAC;QACH,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;QAE9E,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM;gBACrB,CAAC,CAAC,aAAa,KAAK,CAAC,QAAQ,GAAG;gBAChC,CAAC,CAAC,OAAO,KAAK,CAAC,QAAQ,SAAS,KAAK,CAAC,SAAS,EAAE,CAAC;YACpD,OAAO;gBACL,YAAY,EAAE,EAAE;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,yBAAyB,QAAQ,WAAW,KAAK,CAAC,cAAc,oFAAoF;aAC9J,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACjB,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACR,0BAA0B,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,sBAAsB,WAAW,MAAM,CAAC,IAAI,GAAG,CACpH,CAAC;QACF,IAAI,MAAM,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAExD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,aAAa,IAAI,cAAc,EAAE,CAAC,CAAC;YAC3D,IAAI,GAAG,CAAC,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,cAAc,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YAC7D,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;gBACrB,MAAM,OAAO,GACX,GAAG,CAAC,YAAY,KAAK,SAAS;oBAC5B,CAAC,CAAC,OAAO,GAAG,CAAC,YAAY,OAAO,GAAG,CAAC,aAAa,IAAI,EAAE,EAAE;oBACzD,CAAC,CAAC,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,YAAY,GAAG,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,GAAG,CAAC,QAAQ,KAAK,SAAS,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC9D,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YACnE,CAAC;YACD,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;gBACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1E,MAAM,MAAM,GACV,OAAO,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,OAAO,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACtF,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,aAAa,WAAW,OAAO,CAAC,GAAG,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpD,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * @fileoverview Tool for retrieving a full compliance profile for a single EPA-regulated facility.
3
+ * @module mcp-server/tools/definitions/get-facility.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const getFacilityTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ registry_id: z.ZodString;
9
+ }, z.core.$strip>, z.ZodObject<{
10
+ registryId: z.ZodString;
11
+ name: z.ZodString;
12
+ street: z.ZodOptional<z.ZodString>;
13
+ city: z.ZodOptional<z.ZodString>;
14
+ state: z.ZodOptional<z.ZodString>;
15
+ zip: z.ZodOptional<z.ZodString>;
16
+ county: z.ZodOptional<z.ZodString>;
17
+ fipsCode: z.ZodOptional<z.ZodString>;
18
+ latitude: z.ZodOptional<z.ZodNumber>;
19
+ longitude: z.ZodOptional<z.ZodNumber>;
20
+ complianceStatus: z.ZodOptional<z.ZodString>;
21
+ programs: z.ZodObject<{
22
+ air: z.ZodBoolean;
23
+ water: z.ZodBoolean;
24
+ rcra: z.ZodBoolean;
25
+ tri: z.ZodBoolean;
26
+ sdwa: z.ZodBoolean;
27
+ }, z.core.$strip>;
28
+ triReleasesTransfersInLbs: z.ZodOptional<z.ZodNumber>;
29
+ compliance: z.ZodOptional<z.ZodObject<{
30
+ mediaStatusCode: z.ZodOptional<z.ZodString>;
31
+ mediaStatusDescription: z.ZodOptional<z.ZodString>;
32
+ quartersInViolation: z.ZodOptional<z.ZodNumber>;
33
+ }, z.core.$strip>>;
34
+ inspections: z.ZodArray<z.ZodObject<{
35
+ activityType: z.ZodOptional<z.ZodString>;
36
+ activityDate: z.ZodOptional<z.ZodString>;
37
+ description: z.ZodOptional<z.ZodString>;
38
+ }, z.core.$strip>>;
39
+ formalActions: z.ZodArray<z.ZodObject<{
40
+ caseId: z.ZodOptional<z.ZodString>;
41
+ settlementDate: z.ZodOptional<z.ZodString>;
42
+ penaltyAssessedInDollars: z.ZodOptional<z.ZodNumber>;
43
+ actionType: z.ZodOptional<z.ZodString>;
44
+ }, z.core.$strip>>;
45
+ airCompliance: z.ZodOptional<z.ZodObject<{
46
+ programId: z.ZodOptional<z.ZodString>;
47
+ status: z.ZodOptional<z.ZodString>;
48
+ statusDate: z.ZodOptional<z.ZodString>;
49
+ }, z.core.$strip>>;
50
+ waterCompliance: z.ZodOptional<z.ZodObject<{
51
+ programId: z.ZodOptional<z.ZodString>;
52
+ status: z.ZodOptional<z.ZodString>;
53
+ permitId: z.ZodOptional<z.ZodString>;
54
+ }, z.core.$strip>>;
55
+ }, z.core.$strip>, readonly [{
56
+ readonly reason: "facility_not_found";
57
+ readonly code: JsonRpcErrorCode.NotFound;
58
+ readonly when: "ECHO returned no facility record for the given Registry ID.";
59
+ readonly recovery: "Verify the Registry ID using epa_search_facilities and retry with a valid ID.";
60
+ }]>;
61
+ //# sourceMappingURL=get-facility.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-facility.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-facility.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2N1B,CAAC"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * @fileoverview Tool for retrieving a full compliance profile for a single EPA-regulated facility.
3
+ * @module mcp-server/tools/definitions/get-facility.tool
4
+ */
5
+ import { tool, z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ import { getEchoService } from '../../../services/echo/echo-service.js';
8
+ export const getFacilityTool = tool('epa_get_facility', {
9
+ title: 'Get EPA Facility Compliance Profile',
10
+ description: 'Retrieve a full compliance profile for a single EPA-regulated facility by EPA Registry ID. Returns facility metadata, per-program compliance status, inspection history, formal enforcement actions, penalty totals, and TRI release summary. Use epa_search_facilities to discover Registry IDs. For area-level enforcement discovery use epa_search_violations instead.',
11
+ annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
12
+ input: z.object({
13
+ registry_id: z
14
+ .string()
15
+ .min(1)
16
+ .describe('EPA FRS Registry ID for the facility (obtained from epa_search_facilities)'),
17
+ }),
18
+ output: z.object({
19
+ registryId: z.string().describe('EPA FRS Registry ID'),
20
+ name: z.string().describe('Facility name'),
21
+ street: z.string().optional().describe('Street address'),
22
+ city: z.string().optional().describe('City'),
23
+ state: z.string().optional().describe('2-letter state abbreviation'),
24
+ zip: z.string().optional().describe('ZIP code'),
25
+ county: z.string().optional().describe('County name'),
26
+ fipsCode: z.string().optional().describe('5-digit county FIPS code'),
27
+ latitude: z.number().optional().describe('Latitude in decimal degrees'),
28
+ longitude: z.number().optional().describe('Longitude in decimal degrees'),
29
+ complianceStatus: z.string().optional().describe('Overall compliance status text'),
30
+ programs: z
31
+ .object({
32
+ air: z.boolean().describe('Registered under Clean Air Act (CAA)'),
33
+ water: z.boolean().describe('Registered under Clean Water Act (CWA)'),
34
+ rcra: z.boolean().describe('Registered under RCRA (hazardous waste)'),
35
+ tri: z.boolean().describe('Participates in Toxic Release Inventory (TRI)'),
36
+ sdwa: z.boolean().describe('Regulated under Safe Drinking Water Act'),
37
+ })
38
+ .describe('Program registration flags'),
39
+ triReleasesTransfersInLbs: z
40
+ .number()
41
+ .optional()
42
+ .describe('Total TRI on/off-site releases and transfers in pounds'),
43
+ compliance: z
44
+ .object({
45
+ mediaStatusCode: z.string().optional().describe('Compliance media status code'),
46
+ mediaStatusDescription: z
47
+ .string()
48
+ .optional()
49
+ .describe('Human-readable compliance status description'),
50
+ quartersInViolation: z
51
+ .number()
52
+ .optional()
53
+ .describe('Number of quarters with compliance violations in the past 3 years'),
54
+ })
55
+ .optional()
56
+ .describe('Compliance summary from DFR. Absent when ECHO DFR compliance endpoint unavailable.'),
57
+ inspections: z
58
+ .array(z
59
+ .object({
60
+ activityType: z.string().optional().describe('Inspection activity type code'),
61
+ activityDate: z.string().optional().describe('Date of inspection'),
62
+ description: z.string().optional().describe('Activity type description'),
63
+ })
64
+ .describe('Single inspection record with activity type and date'))
65
+ .describe('Inspection history records'),
66
+ formalActions: z
67
+ .array(z
68
+ .object({
69
+ caseId: z.string().optional().describe('Enforcement case identifier'),
70
+ settlementDate: z.string().optional().describe('Settlement or resolution date'),
71
+ penaltyAssessedInDollars: z
72
+ .number()
73
+ .optional()
74
+ .describe('Penalty amount assessed in dollars'),
75
+ actionType: z.string().optional().describe('Type of formal enforcement action'),
76
+ })
77
+ .describe('Single formal enforcement action with case ID and penalty amount'))
78
+ .describe('Formal enforcement actions on record'),
79
+ airCompliance: z
80
+ .object({
81
+ programId: z.string().optional().describe('CAA program identifier'),
82
+ status: z.string().optional().describe('Air compliance status'),
83
+ statusDate: z.string().optional().describe('Date of status determination'),
84
+ })
85
+ .optional()
86
+ .describe('CAA-specific compliance details. Present only when facility is registered under CAA (programs.air=true).'),
87
+ waterCompliance: z
88
+ .object({
89
+ programId: z.string().optional().describe('CWA program identifier'),
90
+ status: z.string().optional().describe('Water compliance status'),
91
+ permitId: z.string().optional().describe('NPDES permit ID'),
92
+ })
93
+ .optional()
94
+ .describe('CWA/NPDES permit and compliance details. Present only when facility is registered under CWA (programs.water=true).'),
95
+ }),
96
+ errors: [
97
+ {
98
+ reason: 'facility_not_found',
99
+ code: JsonRpcErrorCode.NotFound,
100
+ when: 'ECHO returned no facility record for the given Registry ID.',
101
+ recovery: 'Verify the Registry ID using epa_search_facilities and retry with a valid ID.',
102
+ },
103
+ ],
104
+ async handler(input, ctx) {
105
+ ctx.log.info('epa_get_facility', { registryId: input.registry_id });
106
+ const profile = await getEchoService().getFacility(input.registry_id.trim(), ctx);
107
+ if (!profile.registryId) {
108
+ throw ctx.fail('facility_not_found', `No facility found for Registry ID "${input.registry_id}".`, {
109
+ ...ctx.recoveryFor('facility_not_found'),
110
+ });
111
+ }
112
+ ctx.log.info('epa_get_facility completed', {
113
+ registryId: profile.registryId,
114
+ inspections: profile.inspections.length,
115
+ formalActions: profile.formalActions.length,
116
+ });
117
+ return profile;
118
+ },
119
+ format: (result) => {
120
+ const lines = [];
121
+ lines.push(`## ${result.name}`);
122
+ lines.push(`**Registry ID:** ${result.registryId}`);
123
+ const location = [result.street, result.city, result.state, result.zip]
124
+ .filter(Boolean)
125
+ .join(', ');
126
+ if (location)
127
+ lines.push(`**Location:** ${location}`);
128
+ if (result.county)
129
+ lines.push(`**County:** ${result.county}${result.fipsCode ? ` (FIPS: ${result.fipsCode})` : ''}`);
130
+ if (result.latitude !== undefined && result.longitude !== undefined) {
131
+ lines.push(`**Coordinates:** ${result.latitude}, ${result.longitude}`);
132
+ }
133
+ if (result.complianceStatus)
134
+ lines.push(`**Compliance Status:** ${result.complianceStatus}`);
135
+ const activePrograms = Object.entries(result.programs)
136
+ .filter(([, v]) => v)
137
+ .map(([k]) => k.toUpperCase())
138
+ .join(', ');
139
+ if (activePrograms)
140
+ lines.push(`**Programs:** ${activePrograms}`);
141
+ if (result.triReleasesTransfersInLbs !== undefined) {
142
+ lines.push(`**TRI Releases+Transfers:** ${result.triReleasesTransfersInLbs.toLocaleString()} lbs`);
143
+ }
144
+ if (result.compliance) {
145
+ lines.push('\n### Compliance Summary');
146
+ if (result.compliance.mediaStatusCode)
147
+ lines.push(`**Status Code:** ${result.compliance.mediaStatusCode}`);
148
+ if (result.compliance.mediaStatusDescription)
149
+ lines.push(`**Description:** ${result.compliance.mediaStatusDescription}`);
150
+ if (result.compliance.quartersInViolation !== undefined) {
151
+ lines.push(`**Quarters in Violation (3yr):** ${result.compliance.quartersInViolation}`);
152
+ }
153
+ }
154
+ if (result.inspections.length > 0) {
155
+ lines.push('\n### Inspections');
156
+ for (const insp of result.inspections) {
157
+ const parts = [insp.activityDate, insp.activityType, insp.description]
158
+ .filter(Boolean)
159
+ .join(' — ');
160
+ lines.push(`- ${parts || 'Inspection record (no detail)'}`);
161
+ }
162
+ }
163
+ if (result.formalActions.length > 0) {
164
+ lines.push('\n### Formal Enforcement Actions');
165
+ for (const fa of result.formalActions) {
166
+ const penalty = fa.penaltyAssessedInDollars !== undefined
167
+ ? ` | Penalty: $${fa.penaltyAssessedInDollars.toLocaleString()}`
168
+ : '';
169
+ lines.push(`- ${fa.caseId ?? 'Case'}: ${fa.actionType ?? 'Action'}${penalty}${fa.settlementDate ? ` (${fa.settlementDate})` : ''}`);
170
+ }
171
+ }
172
+ if (result.airCompliance) {
173
+ lines.push('\n### Air (CAA) Compliance');
174
+ if (result.airCompliance.programId)
175
+ lines.push(`**Program ID:** ${result.airCompliance.programId}`);
176
+ if (result.airCompliance.status)
177
+ lines.push(`**Status:** ${result.airCompliance.status}`);
178
+ if (result.airCompliance.statusDate)
179
+ lines.push(`**Status Date:** ${result.airCompliance.statusDate}`);
180
+ }
181
+ if (result.waterCompliance) {
182
+ lines.push('\n### Water (CWA) Compliance');
183
+ if (result.waterCompliance.programId)
184
+ lines.push(`**Program ID:** ${result.waterCompliance.programId}`);
185
+ if (result.waterCompliance.status)
186
+ lines.push(`**Status:** ${result.waterCompliance.status}`);
187
+ if (result.waterCompliance.permitId)
188
+ lines.push(`**NPDES Permit:** ${result.waterCompliance.permitId}`);
189
+ }
190
+ return [{ type: 'text', text: lines.join('\n') }];
191
+ },
192
+ });
193
+ //# sourceMappingURL=get-facility.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-facility.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-facility.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @fileoverview Tool for querying TRI annual chemical release data for a specific facility.
3
+ * @module mcp-server/tools/definitions/get-tri-releases.tool
4
+ */
5
+ import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
+ export declare const getTriReleasesTool: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
8
+ facility_id: z.ZodString;
9
+ year: z.ZodOptional<z.ZodNumber>;
10
+ chemical_name: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>, z.ZodObject<{
12
+ releases: z.ZodArray<z.ZodObject<{
13
+ facilityId: z.ZodString;
14
+ chemicalName: z.ZodString;
15
+ reportingYear: z.ZodNumber;
16
+ totalReleasesInLbs: z.ZodOptional<z.ZodNumber>;
17
+ }, z.core.$strip>>;
18
+ facilityId: z.ZodString;
19
+ message: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>, readonly [{
21
+ readonly reason: "no_releases_found";
22
+ readonly code: JsonRpcErrorCode.NotFound;
23
+ readonly when: "No TRI records found for the given facility ID and filters.";
24
+ readonly recovery: "Verify the facility ID via epa_search_facilities. TRI data lags 18 months — try an earlier year.";
25
+ }]>;
26
+ //# sourceMappingURL=get-tri-releases.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-tri-releases.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-tri-releases.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;GA0G7B,CAAC"}