@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,295 @@
1
+ /**
2
+ * @fileoverview ECHO API service for EPA facility compliance and enforcement data.
3
+ * Wraps echodata.epa.gov/echo REST endpoints for facility search, facility detail,
4
+ * and enforcement case search.
5
+ * @module services/echo/echo-service
6
+ */
7
+ import { serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
8
+ import { httpErrorFromResponse, withRetry } from '@cyanheads/mcp-ts-core/utils';
9
+ import { getServerConfig } from '../../config/server-config.js';
10
+ /** Normalizes a raw ECHO facility to the domain type. */
11
+ function normalizeFacility(raw) {
12
+ const penaltyAir = parseFloat(raw.AIRPenalties ?? '0') || 0;
13
+ const penaltyCwa = parseFloat(raw.CWAPenalties ?? '0') || 0;
14
+ const penaltyRcr = parseFloat(raw.RCRPenalties ?? '0') || 0;
15
+ const totalPenalties = penaltyAir + penaltyCwa + penaltyRcr;
16
+ return {
17
+ registryId: raw.RegistryID ?? '',
18
+ name: raw.FacName ?? '',
19
+ ...(raw.FacStreet && { street: raw.FacStreet }),
20
+ ...(raw.FacCity && { city: raw.FacCity }),
21
+ ...(raw.FacState && { state: raw.FacState }),
22
+ ...(raw.FacZip && { zip: raw.FacZip }),
23
+ ...(raw.FacCounty && { county: raw.FacCounty }),
24
+ ...(raw.FacFIPSCode && { fipsCode: raw.FacFIPSCode }),
25
+ ...(raw.FacLat &&
26
+ !Number.isNaN(parseFloat(raw.FacLat)) && { latitude: parseFloat(raw.FacLat) }),
27
+ ...(raw.FacLon &&
28
+ !Number.isNaN(parseFloat(raw.FacLon)) && { longitude: parseFloat(raw.FacLon) }),
29
+ ...(raw.FacComplianceStatus && { complianceStatus: raw.FacComplianceStatus }),
30
+ programs: {
31
+ air: raw.AIRFlag === 'Y',
32
+ water: raw.CWAFlag === 'Y',
33
+ rcra: raw.RCRFlag === 'Y',
34
+ tri: raw.TRIFlag === 'Y',
35
+ sdwa: raw.SDWAFlag === 'Y',
36
+ },
37
+ ...(raw.TRIReleasesTransfers &&
38
+ !Number.isNaN(parseFloat(raw.TRIReleasesTransfers)) && {
39
+ triReleasesTransfersInLbs: parseFloat(raw.TRIReleasesTransfers),
40
+ }),
41
+ ...(raw.InspectionCount &&
42
+ !Number.isNaN(parseInt(raw.InspectionCount, 10)) && {
43
+ inspectionCount: parseInt(raw.InspectionCount, 10),
44
+ }),
45
+ ...(totalPenalties > 0 && { totalPenaltiesInDollars: totalPenalties }),
46
+ };
47
+ }
48
+ export class EchoService {
49
+ baseUrl;
50
+ // config and storage retained for future caching/state use
51
+ constructor(_config, _storage) {
52
+ this.baseUrl = getServerConfig().echoBaseUrl;
53
+ }
54
+ /** Build URL with query params. */
55
+ buildUrl(path, params) {
56
+ const url = new URL(`${this.baseUrl}/${path}`);
57
+ for (const [key, val] of Object.entries(params)) {
58
+ if (val !== undefined && val !== '') {
59
+ url.searchParams.set(key, String(val));
60
+ }
61
+ }
62
+ return url.toString();
63
+ }
64
+ /** Fetch JSON from ECHO with retry. */
65
+ // biome-ignore lint/suspicious/useAwait: delegates to withRetry() which returns a Promise — async typing is correct
66
+ async fetchJson(url, ctx) {
67
+ return withRetry(async () => {
68
+ const response = await fetch(url, {
69
+ signal: ctx.signal,
70
+ headers: { 'User-Agent': '@cyanheads/epa-mcp-server/0.1.1' },
71
+ });
72
+ if (!response.ok) {
73
+ throw await httpErrorFromResponse(response, { service: 'ECHO', data: { url } });
74
+ }
75
+ const text = await response.text();
76
+ if (/^\s*<(!DOCTYPE\s+html|html[\s>])/i.test(text)) {
77
+ throw serviceUnavailable('ECHO API returned HTML instead of JSON — likely rate-limited or unavailable.', { url });
78
+ }
79
+ const parsed = JSON.parse(text);
80
+ // ECHO returns bot-blocking errors in Results.Error.ErrorMessage rather than HTTP error codes
81
+ const errorMsg = parsed.Results
82
+ ?.Error?.ErrorMessage;
83
+ if (errorMsg) {
84
+ throw serviceUnavailable(`ECHO API error: ${errorMsg}`, { url });
85
+ }
86
+ return parsed;
87
+ }, {
88
+ operation: 'EchoService.fetchJson',
89
+ baseDelayMs: 1000,
90
+ signal: ctx.signal,
91
+ });
92
+ }
93
+ /**
94
+ * Search EPA-regulated facilities using ECHO get_facility_info.
95
+ * At least one geographic parameter must be supplied.
96
+ */
97
+ async searchFacilities(params, ctx) {
98
+ const qparams = {
99
+ output: 'JSON',
100
+ p_limit: params.limit ?? 50,
101
+ };
102
+ if (params.zipCode)
103
+ qparams.p_zip = params.zipCode;
104
+ if (params.state)
105
+ qparams.p_state = params.state;
106
+ if (params.city)
107
+ qparams.p_city = params.city;
108
+ if (params.activeOnly)
109
+ qparams.p_act = 'Y';
110
+ if (params.hasViolation)
111
+ qparams.p_sv_flag = 'Y';
112
+ // Program filters — comma-separated list restricts to facilities in those programs
113
+ if (params.programs?.length) {
114
+ const programMap = {
115
+ CAA: 'AIR',
116
+ CWA: 'CWA',
117
+ RCRA: 'RCRA',
118
+ TRI: 'TRI',
119
+ SDWA: 'SDWA',
120
+ };
121
+ const mapped = params.programs.map((p) => programMap[p]).filter(Boolean);
122
+ if (mapped.length)
123
+ qparams.p_naa = mapped.join(',');
124
+ }
125
+ const url = this.buildUrl('echo_rest_services.get_facility_info', qparams);
126
+ ctx.log.debug('ECHO facility search', { url });
127
+ const data = await this.fetchJson(url, ctx);
128
+ const raw = data.Results?.Facilities ?? [];
129
+ const totalCount = parseInt(data.Results?.TotalCount ?? '0', 10) || raw.length;
130
+ return {
131
+ facilities: raw.map((f) => normalizeFacility(f)),
132
+ totalCount,
133
+ };
134
+ }
135
+ /**
136
+ * Retrieve a full compliance profile for a single facility, aggregating multiple DFR endpoints.
137
+ * Steps 2-5 run in parallel after the initial facility info fetch.
138
+ */
139
+ async getFacility(registryId, ctx) {
140
+ // Step 1: Get base facility info + program flags
141
+ const facilityUrl = this.buildUrl('echo_rest_services.get_facility_info', {
142
+ output: 'JSON',
143
+ p_id: registryId,
144
+ p_limit: 1,
145
+ });
146
+ ctx.log.debug('ECHO get_facility_info', { registryId });
147
+ const facilityData = await this.fetchJson(facilityUrl, ctx);
148
+ const rawFacilities = facilityData.Results?.Facilities ?? [];
149
+ const raw = rawFacilities[0];
150
+ if (!raw?.RegistryID) {
151
+ throw serviceUnavailable(`ECHO returned no facility for Registry ID "${registryId}". Check the ID and try again.`, { registryId });
152
+ }
153
+ const base = normalizeFacility(raw);
154
+ // Steps 2-5: Parallel DFR calls
155
+ const [complianceResult, inspEnfResult, airResult, waterResult] = await Promise.allSettled([
156
+ this.fetchJson(this.buildUrl('dfr_rest_services.get_compliance_summary', {
157
+ output: 'JSON',
158
+ p_id: registryId,
159
+ }), ctx),
160
+ this.fetchJson(this.buildUrl('dfr_rest_services.get_inspection_enforcement', {
161
+ output: 'JSON',
162
+ p_id: registryId,
163
+ }), ctx),
164
+ base.programs.air
165
+ ? this.fetchJson(this.buildUrl('dfr_rest_services.get_air', { output: 'JSON', p_id: registryId }), ctx)
166
+ : Promise.resolve(null),
167
+ base.programs.water
168
+ ? this.fetchJson(this.buildUrl('dfr_rest_services.get_water', { output: 'JSON', p_id: registryId }), ctx)
169
+ : Promise.resolve(null),
170
+ ]);
171
+ // Extract compliance summary
172
+ let compliance;
173
+ if (complianceResult.status === 'fulfilled') {
174
+ const cs = complianceResult.value?.Results?.ComplianceSummary;
175
+ if (cs) {
176
+ compliance = {
177
+ ...(cs.MediaStatusCode && { mediaStatusCode: cs.MediaStatusCode }),
178
+ ...(cs.MediaStatusDesc && { mediaStatusDescription: cs.MediaStatusDesc }),
179
+ ...(cs.QtrsInViol !== undefined && { quartersInViolation: Number(cs.QtrsInViol) }),
180
+ };
181
+ }
182
+ }
183
+ // Extract inspections and formal actions
184
+ const inspections = [];
185
+ const formalActions = [];
186
+ if (inspEnfResult.status === 'fulfilled') {
187
+ const ie = inspEnfResult.value?.Results;
188
+ for (const insp of ie?.Inspections ?? []) {
189
+ inspections.push({
190
+ ...(insp.ActivityType && { activityType: insp.ActivityType }),
191
+ ...(insp.ActivityDate && { activityDate: insp.ActivityDate }),
192
+ ...(insp.ActivityTypeDescription && { description: insp.ActivityTypeDescription }),
193
+ });
194
+ }
195
+ for (const fa of ie?.FormalActions ?? []) {
196
+ formalActions.push({
197
+ ...(fa.CaseID && { caseId: fa.CaseID }),
198
+ ...(fa.SettlementDate && { settlementDate: fa.SettlementDate }),
199
+ ...(fa.PenaltyAssessed !== undefined && {
200
+ penaltyAssessedInDollars: Number(fa.PenaltyAssessed),
201
+ }),
202
+ ...(fa.FormalActionType && { actionType: fa.FormalActionType }),
203
+ });
204
+ }
205
+ }
206
+ // Extract air compliance
207
+ let airCompliance;
208
+ if (airResult.status === 'fulfilled' && airResult.value) {
209
+ const ac = airResult.value?.Results?.AirComplianceSummary;
210
+ if (ac) {
211
+ airCompliance = {
212
+ ...(ac.ProgramID && { programId: ac.ProgramID }),
213
+ ...(ac.Status && { status: ac.Status }),
214
+ ...(ac.StatusDate && { statusDate: ac.StatusDate }),
215
+ };
216
+ }
217
+ }
218
+ // Extract water compliance
219
+ let waterCompliance;
220
+ if (waterResult.status === 'fulfilled' && waterResult.value) {
221
+ const wc = waterResult.value?.Results?.WaterCompliance;
222
+ if (wc) {
223
+ waterCompliance = {
224
+ ...(wc.ProgramID && { programId: wc.ProgramID }),
225
+ ...(wc.Status && { status: wc.Status }),
226
+ ...(wc.PermitID && { permitId: wc.PermitID }),
227
+ };
228
+ }
229
+ }
230
+ return {
231
+ ...base,
232
+ ...(compliance && { compliance }),
233
+ inspections,
234
+ formalActions,
235
+ ...(airCompliance && { airCompliance }),
236
+ ...(waterCompliance && { waterCompliance }),
237
+ };
238
+ }
239
+ /**
240
+ * Search EPA enforcement cases using ECHO case_rest_services.
241
+ */
242
+ async searchViolations(params, ctx) {
243
+ const qparams = {
244
+ output: 'JSON',
245
+ p_limit: params.limit ?? 50,
246
+ };
247
+ if (params.state)
248
+ qparams.p_state = params.state;
249
+ if (params.zipCode)
250
+ qparams.p_zip = params.zipCode;
251
+ if (params.program)
252
+ qparams.p_act = params.program;
253
+ if (params.dateFiledStart)
254
+ qparams.p_date_filed_from = params.dateFiledStart;
255
+ if (params.dateFiledEnd)
256
+ qparams.p_date_filed_to = params.dateFiledEnd;
257
+ // Case type filter
258
+ if (params.caseType && params.caseType !== 'all') {
259
+ qparams.p_case_category = params.caseType === 'criminal' ? 'C' : 'V';
260
+ }
261
+ const url = this.buildUrl('case_rest_services.get_case_info', qparams);
262
+ ctx.log.debug('ECHO case search', { url });
263
+ const data = await this.fetchJson(url, ctx);
264
+ const raw = data.Results?.Cases ?? [];
265
+ const totalCount = parseInt(data.Results?.TotalCount ?? '0', 10) || raw.length;
266
+ const cases = raw.map((c) => ({
267
+ ...(c.CaseID && { caseId: c.CaseID }),
268
+ ...(c.CaseName && { caseName: c.CaseName }),
269
+ ...(c.FacName && { facilityName: c.FacName }),
270
+ ...(c.RegistryID && { registryId: c.RegistryID }),
271
+ ...(c.ProgramsViolated && { programsViolated: String(c.ProgramsViolated) }),
272
+ ...(c.CaseType && { caseType: String(c.CaseType) }),
273
+ ...(c.PenaltyAssessed !== undefined &&
274
+ !Number.isNaN(Number(c.PenaltyAssessed)) && {
275
+ penaltyAssessedInDollars: Number(c.PenaltyAssessed),
276
+ }),
277
+ ...(c.SettlementDate && { settlementDate: String(c.SettlementDate) }),
278
+ ...(c.FiledDate && { filedDate: String(c.FiledDate) }),
279
+ ...(c.State && { state: String(c.State) }),
280
+ }));
281
+ return { cases, totalCount };
282
+ }
283
+ }
284
+ // --- Init/accessor pattern ---
285
+ let _service;
286
+ export function initEchoService(config, storage) {
287
+ _service = new EchoService(config, storage);
288
+ }
289
+ export function getEchoService() {
290
+ if (!_service) {
291
+ throw new Error('EchoService not initialized — call initEchoService() in setup()');
292
+ }
293
+ return _service;
294
+ }
295
+ //# sourceMappingURL=echo-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echo-service.js","sourceRoot":"","sources":["../../../src/services/echo/echo-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAa5D,yDAAyD;AACzD,SAAS,iBAAiB,CAAC,GAAuC;IAChE,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;IAE5D,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,EAAE;QAChC,IAAI,EAAE,GAAG,CAAC,OAAO,IAAI,EAAE;QACvB,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;QAC/C,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;QACzC,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC5C,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;QACtC,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC;QAC/C,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QAChF,GAAG,CAAC,GAAG,CAAC,MAAM;YACZ,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACjF,GAAG,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,gBAAgB,EAAE,GAAG,CAAC,mBAAmB,EAAE,CAAC;QAC7E,QAAQ,EAAE;YACR,GAAG,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG;YACxB,KAAK,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG;YAC1B,IAAI,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG;YACzB,GAAG,EAAE,GAAG,CAAC,OAAO,KAAK,GAAG;YACxB,IAAI,EAAE,GAAG,CAAC,QAAQ,KAAK,GAAG;SAC3B;QACD,GAAG,CAAC,GAAG,CAAC,oBAAoB;YAC1B,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI;YACrD,yBAAyB,EAAE,UAAU,CAAC,GAAG,CAAC,oBAAoB,CAAC;SAChE,CAAC;QACJ,GAAG,CAAC,GAAG,CAAC,eAAe;YACrB,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,IAAI;YAClD,eAAe,EAAE,QAAQ,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC;SACnD,CAAC;QACJ,GAAG,CAAC,cAAc,GAAG,CAAC,IAAI,EAAE,uBAAuB,EAAE,cAAc,EAAE,CAAC;KACvE,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,WAAW;IACL,OAAO,CAAS;IAEjC,2DAA2D;IAC3D,YAAY,OAAkB,EAAE,QAAwB;QACtD,IAAI,CAAC,OAAO,GAAG,eAAe,EAAE,CAAC,WAAW,CAAC;IAC/C,CAAC;IAED,mCAAmC;IAC3B,QAAQ,CACd,IAAY,EACZ,MAA6D;QAE7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;QAC/C,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;gBACpC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED,uCAAuC;IACvC,oHAAoH;IAC5G,KAAK,CAAC,SAAS,CAAI,GAAW,EAAE,GAAY;QAClD,OAAO,SAAS,CACd,KAAK,IAAI,EAAE;YACT,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,OAAO,EAAE,EAAE,YAAY,EAAE,iCAAiC,EAAE;aAC7D,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,MAAM,qBAAqB,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YAClF,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,MAAM,kBAAkB,CACtB,8EAA8E,EAC9E,EAAE,GAAG,EAAE,CACR,CAAC;YACJ,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;YAC3D,8FAA8F;YAC9F,MAAM,QAAQ,GAAI,MAA8D,CAAC,OAAO;gBACtF,EAAE,KAAK,EAAE,YAAY,CAAC;YACxB,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,kBAAkB,CAAC,mBAAmB,QAAQ,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,MAAW,CAAC;QACrB,CAAC,EACD;YACE,SAAS,EAAE,uBAAuB;YAClC,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CACF,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB,CACpB,MAQC,EACD,GAAY;QAEZ,MAAM,OAAO,GAA0D;YACrE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;SAC5B,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;QACnD,IAAI,MAAM,CAAC,KAAK;YAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;QACjD,IAAI,MAAM,CAAC,IAAI;YAAE,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC;QAC9C,IAAI,MAAM,CAAC,UAAU;YAAE,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC;QAC3C,IAAI,MAAM,CAAC,YAAY;YAAE,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC;QAEjD,mFAAmF;QACnF,IAAI,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;YAC5B,MAAM,UAAU,GAA2B;gBACzC,GAAG,EAAE,KAAK;gBACV,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,MAAM;gBACZ,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,MAAM;aACb,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACzE,IAAI,MAAM,CAAC,MAAM;gBAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,sCAAsC,EAAE,OAAO,CAAC,CAAC;QAC3E,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,sBAAsB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAE/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAA0B,GAAG,EAAE,GAAG,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC;QAC3C,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC;QAE/E,OAAO;YACL,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAuC,CAAC,CAAC;YACtF,UAAU;SACX,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,GAAY;QAChD,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,sCAAsC,EAAE;YACxE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,CAAC;SACX,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;QACxD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,SAAS,CAA0B,WAAW,EAAE,GAAG,CAAC,CAAC;QACrF,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,IAAI,EAAE,CAAC;QAC7D,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAmD,CAAC;QAE/E,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,CAAC;YACrB,MAAM,kBAAkB,CACtB,8CAA8C,UAAU,gCAAgC,EACxF,EAAE,UAAU,EAAE,CACf,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAEpC,gCAAgC;QAChC,MAAM,CAAC,gBAAgB,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC;YACzF,IAAI,CAAC,SAAS,CACZ,IAAI,CAAC,QAAQ,CAAC,0CAA0C,EAAE;gBACxD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,UAAU;aACjB,CAAC,EACF,GAAG,CACJ;YACD,IAAI,CAAC,SAAS,CACZ,IAAI,CAAC,QAAQ,CAAC,8CAA8C,EAAE;gBAC5D,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,UAAU;aACjB,CAAC,EACF,GAAG,CACJ;YACD,IAAI,CAAC,QAAQ,CAAC,GAAG;gBACf,CAAC,CAAC,IAAI,CAAC,SAAS,CACZ,IAAI,CAAC,QAAQ,CAAC,2BAA2B,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAChF,GAAG,CACJ;gBACH,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,KAAK;gBACjB,CAAC,CAAC,IAAI,CAAC,SAAS,CACZ,IAAI,CAAC,QAAQ,CAAC,6BAA6B,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,EAClF,GAAG,CACJ;gBACH,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;SAC1B,CAAC,CAAC;QAEH,6BAA6B;QAC7B,IAAI,UAA4C,CAAC;QACjD,IAAI,gBAAgB,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAC5C,MAAM,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC;YAC9D,IAAI,EAAE,EAAE,CAAC;gBACP,UAAU,GAAG;oBACX,GAAG,CAAC,EAAE,CAAC,eAAe,IAAI,EAAE,eAAe,EAAE,EAAE,CAAC,eAAe,EAAE,CAAC;oBAClE,GAAG,CAAC,EAAE,CAAC,eAAe,IAAI,EAAE,sBAAsB,EAAE,EAAE,CAAC,eAAe,EAAE,CAAC;oBACzE,GAAG,CAAC,EAAE,CAAC,UAAU,KAAK,SAAS,IAAI,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;iBACnF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,yCAAyC;QACzC,MAAM,WAAW,GAAsC,EAAE,CAAC;QAC1D,MAAM,aAAa,GAAwC,EAAE,CAAC;QAC9D,IAAI,aAAa,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACzC,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC;YACxC,KAAK,MAAM,IAAI,IAAI,EAAE,EAAE,WAAW,IAAI,EAAE,EAAE,CAAC;gBACzC,WAAW,CAAC,IAAI,CAAC;oBACf,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC7D,GAAG,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC7D,GAAG,CAAC,IAAI,CAAC,uBAAuB,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,uBAAuB,EAAE,CAAC;iBACnF,CAAC,CAAC;YACL,CAAC;YACD,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,aAAa,IAAI,EAAE,EAAE,CAAC;gBACzC,aAAa,CAAC,IAAI,CAAC;oBACjB,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;oBACvC,GAAG,CAAC,EAAE,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC,cAAc,EAAE,CAAC;oBAC/D,GAAG,CAAC,EAAE,CAAC,eAAe,KAAK,SAAS,IAAI;wBACtC,wBAAwB,EAAE,MAAM,CAAC,EAAE,CAAC,eAAe,CAAC;qBACrD,CAAC;oBACF,GAAG,CAAC,EAAE,CAAC,gBAAgB,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,gBAAgB,EAAE,CAAC;iBAChE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,IAAI,aAAkD,CAAC;QACvD,IAAI,SAAS,CAAC,MAAM,KAAK,WAAW,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACxD,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,oBAAoB,CAAC;YAC1D,IAAI,EAAE,EAAE,CAAC;gBACP,aAAa,GAAG;oBACd,GAAG,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC;oBAChD,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;oBACvC,GAAG,CAAC,EAAE,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,EAAE,CAAC;iBACpD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,2BAA2B;QAC3B,IAAI,eAAsD,CAAC;QAC3D,IAAI,WAAW,CAAC,MAAM,KAAK,WAAW,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;YAC5D,MAAM,EAAE,GAAG,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,eAAe,CAAC;YACvD,IAAI,EAAE,EAAE,CAAC;gBACP,eAAe,GAAG;oBAChB,GAAG,CAAC,EAAE,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC;oBAChD,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;oBACvC,GAAG,CAAC,EAAE,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,CAAC;iBAC9C,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO;YACL,GAAG,IAAI;YACP,GAAG,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,CAAC;YACjC,WAAW;YACX,aAAa;YACb,GAAG,CAAC,aAAa,IAAI,EAAE,aAAa,EAAE,CAAC;YACvC,GAAG,CAAC,eAAe,IAAI,EAAE,eAAe,EAAE,CAAC;SAC5C,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,MAQC,EACD,GAAY;QAEZ,MAAM,OAAO,GAAgD;YAC3D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE;SAC5B,CAAC;QAEF,IAAI,MAAM,CAAC,KAAK;YAAE,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;QACjD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;QACnD,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;QACnD,IAAI,MAAM,CAAC,cAAc;YAAE,OAAO,CAAC,iBAAiB,GAAG,MAAM,CAAC,cAAc,CAAC;QAC7E,IAAI,MAAM,CAAC,YAAY;YAAE,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,YAAY,CAAC;QAEvE,mBAAmB;QACnB,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YACjD,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACvE,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAC;QACvE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAE3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAsB,GAAG,EAAE,GAAG,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,IAAI,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC;QAE/E,MAAM,KAAK,GAAc,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACvC,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YACrC,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC3C,GAAG,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;YAC7C,GAAG,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC;YACjD,GAAG,CAAC,CAAC,CAAC,gBAAgB,IAAI,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,CAAC,CAAC,eAAe,KAAK,SAAS;gBACjC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,IAAI;gBAC1C,wBAAwB,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC;aACpD,CAAC;YACJ,GAAG,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC;YACrE,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;YACtD,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;SAC3C,CAAC,CAAC,CAAC;QAEJ,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAC/B,CAAC;CACF;AAED,gCAAgC;AAEhC,IAAI,QAAiC,CAAC;AAEtC,MAAM,UAAU,eAAe,CAAC,MAAiB,EAAE,OAAuB;IACxE,QAAQ,GAAG,IAAI,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,198 @@
1
+ /**
2
+ * @fileoverview ECHO API response types and normalized domain types for facility compliance data.
3
+ * @module services/echo/types
4
+ */
5
+ /** Raw ECHO get_facility_info response facility record. Fields may be absent or empty string. */
6
+ export interface RawEchoFacility {
7
+ AIRFlag?: string;
8
+ AIRPenalties?: string;
9
+ CWAFlag?: string;
10
+ CWAPenalties?: string;
11
+ FacCity?: string;
12
+ FacComplianceStatus?: string;
13
+ FacCounty?: string;
14
+ FacFIPSCode?: string;
15
+ FacLat?: string;
16
+ FacLon?: string;
17
+ FacName?: string;
18
+ FacState?: string;
19
+ FacStreet?: string;
20
+ FacZip?: string;
21
+ InspectionCount?: string;
22
+ RCRFlag?: string;
23
+ RCRPenalties?: string;
24
+ RegistryID?: string;
25
+ SDWAFlag?: string;
26
+ TRIFlag?: string;
27
+ TRIReleasesTransfers?: string;
28
+ [key: string]: string | undefined;
29
+ }
30
+ /** Raw ECHO get_facility_info top-level response envelope. */
31
+ export interface RawEchoFacilityResponse {
32
+ Results?: {
33
+ Facilities?: RawEchoFacility[];
34
+ QueryID?: string;
35
+ PageNo?: string;
36
+ TotalPagesAvailable?: string;
37
+ TotalCount?: string;
38
+ };
39
+ }
40
+ /** Raw ECHO DFR compliance summary response envelope. */
41
+ export interface RawEchoDfrComplianceSummary {
42
+ Results?: {
43
+ ComplianceSummary?: {
44
+ MediaStatusCode?: string;
45
+ MediaStatusDesc?: string;
46
+ QtrsInViol?: string | number;
47
+ QtrsInNC?: string | number;
48
+ };
49
+ };
50
+ }
51
+ /** Raw inspection/enforcement record from ECHO DFR. */
52
+ export interface RawEchoInspection {
53
+ ActivityDate?: string;
54
+ ActivityType?: string;
55
+ ActivityTypeDescription?: string;
56
+ }
57
+ /** Raw formal action/penalty record from ECHO DFR. */
58
+ export interface RawEchoFormalAction {
59
+ CaseID?: string;
60
+ FormalActionType?: string;
61
+ PenaltyAssessed?: string | number;
62
+ SettlementDate?: string;
63
+ }
64
+ /** Raw ECHO DFR inspection and enforcement response. */
65
+ export interface RawEchoDfrInspectionEnforcement {
66
+ Results?: {
67
+ Inspections?: RawEchoInspection[];
68
+ FormalActions?: RawEchoFormalAction[];
69
+ };
70
+ }
71
+ /** Raw ECHO DFR air compliance record. */
72
+ export interface RawEchoDfrAir {
73
+ Results?: {
74
+ AirComplianceSummary?: {
75
+ ProgramID?: string;
76
+ Status?: string;
77
+ StatusDate?: string;
78
+ };
79
+ };
80
+ }
81
+ /** Raw ECHO DFR water compliance record. */
82
+ export interface RawEchoDfrWater {
83
+ Results?: {
84
+ WaterCompliance?: {
85
+ ProgramID?: string;
86
+ Status?: string;
87
+ PermitID?: string;
88
+ };
89
+ };
90
+ }
91
+ /** Raw ECHO enforcement case from case_rest_services. */
92
+ export interface RawEchoCase {
93
+ CaseID?: string;
94
+ CaseName?: string;
95
+ CaseType?: string;
96
+ FacName?: string;
97
+ FiledDate?: string;
98
+ PenaltyAssessed?: string | number;
99
+ ProgramsViolated?: string;
100
+ RegistryID?: string;
101
+ SettlementDate?: string;
102
+ State?: string;
103
+ [key: string]: string | number | undefined;
104
+ }
105
+ /** Raw ECHO case search response envelope. */
106
+ export interface RawEchoCaseResponse {
107
+ Results?: {
108
+ Cases?: RawEchoCase[];
109
+ QueryID?: string;
110
+ TotalCount?: string;
111
+ };
112
+ }
113
+ /** Normalized EPA facility record for tool responses. */
114
+ export interface EpaFacility {
115
+ city?: string;
116
+ complianceStatus?: string;
117
+ county?: string;
118
+ fipsCode?: string;
119
+ inspectionCount?: number;
120
+ latitude?: number;
121
+ longitude?: number;
122
+ name: string;
123
+ programs: {
124
+ air: boolean;
125
+ water: boolean;
126
+ rcra: boolean;
127
+ tri: boolean;
128
+ sdwa: boolean;
129
+ };
130
+ registryId: string;
131
+ state?: string;
132
+ street?: string;
133
+ totalPenaltiesInDollars?: number;
134
+ triReleasesTransfersInLbs?: number;
135
+ zip?: string;
136
+ }
137
+ /** Normalized enforcement case. */
138
+ export interface EpaCase {
139
+ caseId?: string;
140
+ caseName?: string;
141
+ caseType?: string;
142
+ facilityName?: string;
143
+ filedDate?: string;
144
+ penaltyAssessedInDollars?: number;
145
+ programsViolated?: string;
146
+ registryId?: string;
147
+ settlementDate?: string;
148
+ state?: string;
149
+ }
150
+ /** Full facility compliance profile aggregated from multiple DFR endpoints. */
151
+ export interface EpaFacilityProfile {
152
+ airCompliance?: {
153
+ programId?: string;
154
+ status?: string;
155
+ statusDate?: string;
156
+ };
157
+ city?: string;
158
+ compliance?: {
159
+ mediaStatusCode?: string;
160
+ mediaStatusDescription?: string;
161
+ quartersInViolation?: number;
162
+ };
163
+ complianceStatus?: string;
164
+ county?: string;
165
+ fipsCode?: string;
166
+ formalActions: Array<{
167
+ caseId?: string;
168
+ settlementDate?: string;
169
+ penaltyAssessedInDollars?: number;
170
+ actionType?: string;
171
+ }>;
172
+ inspections: Array<{
173
+ activityType?: string;
174
+ activityDate?: string;
175
+ description?: string;
176
+ }>;
177
+ latitude?: number;
178
+ longitude?: number;
179
+ name: string;
180
+ programs: {
181
+ air: boolean;
182
+ water: boolean;
183
+ rcra: boolean;
184
+ tri: boolean;
185
+ sdwa: boolean;
186
+ };
187
+ registryId: string;
188
+ state?: string;
189
+ street?: string;
190
+ triReleasesTransfersInLbs?: number;
191
+ waterCompliance?: {
192
+ programId?: string;
193
+ status?: string;
194
+ permitId?: string;
195
+ };
196
+ zip?: string;
197
+ }
198
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/echo/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @fileoverview ECHO API response types and normalized domain types for facility compliance data.
3
+ * @module services/echo/types
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/services/echo/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@cyanheads/epa-mcp-server",
3
+ "version": "0.1.1",
4
+ "description": "Access EPA environmental data — facility compliance (ECHO), toxic releases (TRI), Superfund sites, drinking water systems, and real-time air quality (AirNow) via MCP. STDIO or Streamable HTTP.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "epa-mcp-server": "dist/index.js"
10
+ },
11
+ "files": [
12
+ "changelog/",
13
+ "dist/",
14
+ "README.md",
15
+ "LICENSE",
16
+ "CLAUDE.md",
17
+ "Dockerfile",
18
+ "server.json"
19
+ ],
20
+ "scripts": {
21
+ "build": "tsx scripts/build.ts",
22
+ "rebuild": "tsx scripts/clean.ts && tsx scripts/build.ts",
23
+ "clean": "tsx scripts/clean.ts",
24
+ "devcheck": "tsx scripts/devcheck.ts",
25
+ "audit:refresh": "rm -f bun.lock && bun install && bun audit",
26
+ "tree": "tsx scripts/tree.ts",
27
+ "list-skills": "tsx scripts/list-skills.ts",
28
+ "format": "biome check --write --unsafe .",
29
+ "lint:mcp": "tsx scripts/lint-mcp.ts",
30
+ "lint:packaging": "tsx scripts/lint-packaging.ts",
31
+ "bundle": "npm run build && npx -y @anthropic-ai/mcpb pack . dist/epa-mcp-server.mcpb",
32
+ "changelog:build": "tsx scripts/build-changelog.ts",
33
+ "changelog:check": "tsx scripts/build-changelog.ts --check",
34
+ "test": "vitest run",
35
+ "start": "node dist/index.js",
36
+ "start:stdio": "MCP_TRANSPORT_TYPE=stdio node dist/index.js",
37
+ "start:http": "MCP_TRANSPORT_TYPE=http node dist/index.js"
38
+ },
39
+ "keywords": [
40
+ "mcp",
41
+ "mcp-server",
42
+ "model-context-protocol",
43
+ "epa",
44
+ "environmental",
45
+ "air-quality",
46
+ "toxic-release-inventory",
47
+ "superfund",
48
+ "drinking-water",
49
+ "compliance",
50
+ "echo-epa",
51
+ "airnow"
52
+ ],
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/cyanheads/epa-mcp-server.git"
56
+ },
57
+ "license": "Apache-2.0",
58
+ "engines": {
59
+ "bun": ">=1.3.0",
60
+ "node": ">=24.0.0"
61
+ },
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "dependencies": {
66
+ "@cyanheads/mcp-ts-core": "^0.9.9",
67
+ "pino-pretty": "^13.1.3",
68
+ "zod": "^4.4.3"
69
+ },
70
+ "devDependencies": {
71
+ "@biomejs/biome": "^2.4.15",
72
+ "@types/node": "^25.9.1",
73
+ "depcheck": "^1.4.7",
74
+ "ignore": "^7.0.5",
75
+ "tsc-alias": "^1.8.17",
76
+ "tsx": "^4.22.3",
77
+ "typescript": "^6.0.3",
78
+ "vitest": "^4.1.7"
79
+ }
80
+ }