@cyanheads/epa-mcp-server 0.3.3 → 0.4.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/AGENTS.md +5 -5
  2. package/CLAUDE.md +5 -5
  3. package/Dockerfile +3 -3
  4. package/README.md +58 -23
  5. package/changelog/0.4.x/0.4.0.md +35 -0
  6. package/changelog/0.4.x/0.4.1.md +34 -0
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp-server/resources/definitions/facility.resource.d.ts +8 -1
  10. package/dist/mcp-server/resources/definitions/facility.resource.d.ts.map +1 -1
  11. package/dist/mcp-server/resources/definitions/facility.resource.js +13 -7
  12. package/dist/mcp-server/resources/definitions/facility.resource.js.map +1 -1
  13. package/dist/mcp-server/resources/definitions/index.d.ts +7 -1
  14. package/dist/mcp-server/resources/definitions/index.d.ts.map +1 -1
  15. package/dist/mcp-server/tools/definitions/get-air-quality.tool.d.ts +23 -9
  16. package/dist/mcp-server/tools/definitions/get-air-quality.tool.d.ts.map +1 -1
  17. package/dist/mcp-server/tools/definitions/get-air-quality.tool.js +165 -93
  18. package/dist/mcp-server/tools/definitions/get-air-quality.tool.js.map +1 -1
  19. package/dist/mcp-server/tools/definitions/get-facility.tool.d.ts +30 -2
  20. package/dist/mcp-server/tools/definitions/get-facility.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/get-facility.tool.js +211 -53
  22. package/dist/mcp-server/tools/definitions/get-facility.tool.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.d.ts +5 -2
  24. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.js +18 -15
  26. package/dist/mcp-server/tools/definitions/get-tri-releases.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/definitions/index.d.ts +165 -32
  28. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/definitions/search-facilities.tool.d.ts.map +1 -1
  30. package/dist/mcp-server/tools/definitions/search-facilities.tool.js +39 -26
  31. package/dist/mcp-server/tools/definitions/search-facilities.tool.js.map +1 -1
  32. package/dist/mcp-server/tools/definitions/search-superfund.tool.d.ts +3 -1
  33. package/dist/mcp-server/tools/definitions/search-superfund.tool.d.ts.map +1 -1
  34. package/dist/mcp-server/tools/definitions/search-superfund.tool.js +13 -9
  35. package/dist/mcp-server/tools/definitions/search-superfund.tool.js.map +1 -1
  36. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.d.ts +17 -3
  37. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.d.ts.map +1 -1
  38. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.js +64 -12
  39. package/dist/mcp-server/tools/definitions/search-tri-releases.tool.js.map +1 -1
  40. package/dist/mcp-server/tools/definitions/search-violations.tool.d.ts +20 -3
  41. package/dist/mcp-server/tools/definitions/search-violations.tool.d.ts.map +1 -1
  42. package/dist/mcp-server/tools/definitions/search-violations.tool.js +84 -15
  43. package/dist/mcp-server/tools/definitions/search-violations.tool.js.map +1 -1
  44. package/dist/mcp-server/tools/definitions/search-water-systems.tool.d.ts +3 -1
  45. package/dist/mcp-server/tools/definitions/search-water-systems.tool.d.ts.map +1 -1
  46. package/dist/mcp-server/tools/definitions/search-water-systems.tool.js +22 -7
  47. package/dist/mcp-server/tools/definitions/search-water-systems.tool.js.map +1 -1
  48. package/dist/mcp-server/tools/format-lbs.d.ts +14 -0
  49. package/dist/mcp-server/tools/format-lbs.d.ts.map +1 -0
  50. package/dist/mcp-server/tools/format-lbs.js +16 -0
  51. package/dist/mcp-server/tools/format-lbs.js.map +1 -0
  52. package/dist/mcp-server/tools/format-location.d.ts +18 -0
  53. package/dist/mcp-server/tools/format-location.d.ts.map +1 -0
  54. package/dist/mcp-server/tools/format-location.js +26 -0
  55. package/dist/mcp-server/tools/format-location.js.map +1 -0
  56. package/dist/mcp-server/tools/format-tri-release.d.ts +16 -0
  57. package/dist/mcp-server/tools/format-tri-release.d.ts.map +1 -0
  58. package/dist/mcp-server/tools/format-tri-release.js +23 -0
  59. package/dist/mcp-server/tools/format-tri-release.js.map +1 -0
  60. package/dist/services/airnow/airnow-service.d.ts +10 -29
  61. package/dist/services/airnow/airnow-service.d.ts.map +1 -1
  62. package/dist/services/airnow/airnow-service.js +156 -97
  63. package/dist/services/airnow/airnow-service.js.map +1 -1
  64. package/dist/services/airnow/types.d.ts +62 -23
  65. package/dist/services/airnow/types.d.ts.map +1 -1
  66. package/dist/services/airnow/types.js +2 -1
  67. package/dist/services/airnow/types.js.map +1 -1
  68. package/dist/services/call-budget.d.ts +22 -0
  69. package/dist/services/call-budget.d.ts.map +1 -0
  70. package/dist/services/call-budget.js +28 -0
  71. package/dist/services/call-budget.js.map +1 -0
  72. package/dist/services/dmap/dmap-service.d.ts +76 -7
  73. package/dist/services/dmap/dmap-service.d.ts.map +1 -1
  74. package/dist/services/dmap/dmap-service.js +461 -144
  75. package/dist/services/dmap/dmap-service.js.map +1 -1
  76. package/dist/services/dmap/types.d.ts +17 -4
  77. package/dist/services/dmap/types.d.ts.map +1 -1
  78. package/dist/services/echo/echo-service.d.ts +38 -11
  79. package/dist/services/echo/echo-service.d.ts.map +1 -1
  80. package/dist/services/echo/echo-service.js +417 -223
  81. package/dist/services/echo/echo-service.js.map +1 -1
  82. package/dist/services/echo/types.d.ts +167 -80
  83. package/dist/services/echo/types.d.ts.map +1 -1
  84. package/dist/services/ejscreen/ejscreen-service.d.ts.map +1 -1
  85. package/dist/services/ejscreen/ejscreen-service.js +9 -3
  86. package/dist/services/ejscreen/ejscreen-service.js.map +1 -1
  87. package/package.json +7 -7
  88. package/server.json +9 -3
@@ -1,16 +1,35 @@
1
1
  /**
2
- * @fileoverview Tool for getting AQI observations or forecasts for a location from AirNow.
2
+ * @fileoverview Tool for getting current AQI observations or the issued AQI forecast for a
3
+ * location from AirNow.
3
4
  * @module mcp-server/tools/definitions/get-air-quality.tool
4
5
  */
5
6
  import { tool, z } from '@cyanheads/mcp-ts-core';
6
7
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
8
  import { getAirNowService } from '../../../services/airnow/airnow-service.js';
9
+ const AIRNOW_PROGRAM = 'the U.S. EPA AirNow program (www.airnow.gov)';
10
+ const PRELIMINARY_NOTICE = 'AirNow data are preliminary and unverified; do not use them for regulatory, trend, or enforcement decisions.';
11
+ /** Credit line naming the agencies behind the returned readings and the AirNow program. */
12
+ function attributionFor(mode, areas) {
13
+ const agencies = [
14
+ ...new Set(areas.flatMap((area) => area.readings.flatMap((r) => {
15
+ const agency = r.reportingAgency ?? r.forecastAgency;
16
+ return agency ? [agency] : [];
17
+ }))),
18
+ ];
19
+ const list = (items) => new Intl.ListFormat('en', { type: 'conjunction' }).format(items);
20
+ const credit = mode === 'current'
21
+ ? `Data courtesy of ${list([...agencies, AIRNOW_PROGRAM])}.`
22
+ : agencies.length > 0
23
+ ? `Forecasts issued by ${list(agencies)} and distributed by ${AIRNOW_PROGRAM}.`
24
+ : `Forecasts distributed by ${AIRNOW_PROGRAM}.`;
25
+ return `${credit} ${PRELIMINARY_NOTICE}`;
26
+ }
8
27
  export const getAirQualityTool = tool('epa_get_air_quality', {
9
28
  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.',
29
+ description: "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 within 50 miles, with the monitor site name, site ID, and reporting agency; pollutants in one reporting area can come from different monitors. Forecast mode returns every day the reporting area's agency has issued (typically one to five), each with the AQI category, an action-day flag, and the issue date, plus the agency's forecast discussion when one exists; some agencies forecast a category without an AQI number. In forecast mode, set forecast_date to keep only the forecast valid on that date; current mode rejects it. Data are preliminary — suitable for awareness, not regulatory, trend, or enforcement decisions. Responses are cached for ~1 hour.",
11
30
  annotations: { readOnlyHint: true, openWorldHint: true, idempotentHint: true },
12
31
  input: z.object({
13
- zip_code: z.string().optional().describe('5-digit ZIP code for the location'),
32
+ zip_code: z.string().optional().describe('5-digit US ZIP code for the location'),
14
33
  latitude: z
15
34
  .number()
16
35
  .optional()
@@ -22,18 +41,11 @@ export const getAirQualityTool = tool('epa_get_air_quality', {
22
41
  mode: z
23
42
  .enum(['current', 'forecast'])
24
43
  .default('current')
25
- .describe('Data mode: "current" for latest AQI observations, "forecast" for next-day projections'),
44
+ .describe('Data mode: "current" for the latest hourly observations, "forecast" for every forecast day the reporting area has issued'),
26
45
  forecast_date: z
27
46
  .string()
28
47
  .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.'),
48
+ .describe('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 message lists the issued dates.'),
37
49
  }),
38
50
  output: z.object({
39
51
  observations: z
@@ -42,48 +54,91 @@ export const getAirQualityTool = tool('epa_get_air_quality', {
42
54
  reportingArea: z
43
55
  .string()
44
56
  .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'),
57
+ .describe('Name of the AQI reporting area (e.g. "Seattle-Bellevue-Kent Valley")'),
58
+ reportingAreaCode: z
59
+ .string()
60
+ .optional()
61
+ .describe('AirNow reporting area code (e.g. "wa004"). Forecast mode only.'),
62
+ stateCode: z
63
+ .string()
64
+ .optional()
65
+ .describe('2-letter state code of the reporting area. Forecast mode only.'),
49
66
  dateObserved: z
50
67
  .string()
51
68
  .optional()
52
- .describe('Observation or forecast date (YYYY-MM-DD)'),
69
+ .describe('Observation date (YYYY-MM-DD). Current mode only.'),
53
70
  hourObserved: z
54
- .number()
71
+ .string()
55
72
  .optional()
56
- .describe('Hour of observation (0–23) in local time. Absent for daily forecasts.'),
73
+ .describe('Local hour of the observation as "HH:00". Current mode only.'),
57
74
  localTimeZone: z
58
75
  .string()
59
76
  .optional()
60
- .describe('Local time zone abbreviation (e.g. "PST")'),
77
+ .describe('Local time zone abbreviation for hourObserved (e.g. "PDT"). Current mode only.'),
78
+ discussion: z
79
+ .string()
80
+ .optional()
81
+ .describe("The forecasting agency's discussion for this area, verbatim (may contain HTML). Forecast mode only; omitted when the agency issued none."),
61
82
  readings: z
62
83
  .array(z
63
84
  .object({
64
85
  parameterName: z
65
86
  .string()
66
- .describe('Pollutant name (e.g. "PM2.5", "Ozone", "CO")'),
67
- aqi: z.number().describe('Air Quality Index value for this pollutant'),
87
+ .describe('Pollutant name as AirNow reports it (e.g. "PM2.5", "OZONE", "PM10")'),
88
+ aqi: z
89
+ .number()
90
+ .optional()
91
+ .describe('Air Quality Index value. Omitted when the agency issued only a category (category-only forecast).'),
68
92
  categoryNumber: z
69
93
  .number()
70
94
  .optional()
71
- .describe('AQI category number: 1=Good, 2=Moderate, 3=Unhealthy for Sensitive Groups, 4=Unhealthy, 5=Very Unhealthy, 6=Hazardous'),
95
+ .describe('AQI category number: 1=Good, 2=Moderate, 3=Unhealthy for Sensitive Groups, 4=Unhealthy, 5=Very Unhealthy, 6=Hazardous. Omitted when AirNow reports an unrecognized category.'),
72
96
  categoryName: z
73
97
  .string()
74
98
  .optional()
75
99
  .describe('AQI category name (e.g. "Good", "Moderate", "Unhealthy")'),
100
+ siteName: z
101
+ .string()
102
+ .optional()
103
+ .describe('Monitor site that produced this observation. Current mode only.'),
104
+ siteID: z
105
+ .string()
106
+ .optional()
107
+ .describe('AirNow ID of the monitor site. Current mode only.'),
108
+ reportingAgency: z
109
+ .string()
110
+ .optional()
111
+ .describe('Agency that reported this observation. Current mode only.'),
112
+ dateIssue: z
113
+ .string()
114
+ .optional()
115
+ .describe('Date the forecast was issued (YYYY-MM-DD). Forecast mode only.'),
116
+ dateValid: z
117
+ .string()
118
+ .optional()
119
+ .describe('Date the forecast applies to (YYYY-MM-DD). Forecast mode only.'),
120
+ forecastAgency: z
121
+ .string()
122
+ .optional()
123
+ .describe('Agency that issued the forecast. Forecast mode only.'),
124
+ actionDay: z
125
+ .boolean()
126
+ .optional()
127
+ .describe('True when the agency declared an air quality action day for this date. Forecast mode only.'),
76
128
  })
77
- .describe('AQI reading for a single pollutant parameter'))
78
- .describe('Per-pollutant AQI readings for this reporting area and time'),
129
+ .describe('AQI reading for one pollutant (and, in forecast mode, one valid date)'))
130
+ .describe('Per-pollutant AQI readings for this reporting area'),
79
131
  })
80
- .describe('AQI observation or forecast record for a single reporting area'))
132
+ .describe('AQI readings for one reporting area — per observed hour in current mode, per area across all forecast days in forecast mode'))
81
133
  .describe('AQI observation or forecast records grouped by reporting area'),
82
134
  mode: z.string().describe('Data mode used: "current" or "forecast"'),
83
135
  message: z
84
136
  .string()
85
137
  .optional()
86
- .describe('Recovery hint when no observations are returned — suggests trying a different location or increasing distance_miles. Absent when data is returned.'),
138
+ .describe("Why the result is empty: AirNow's own explanation, the issued forecast dates when forecast_date matched none, or a coverage hint. Absent when data is returned."),
139
+ attribution: z
140
+ .string()
141
+ .describe('Credit to the reporting or forecasting agencies and the U.S. EPA AirNow program, with the preliminary-data notice. Reproduce it when passing this data on.'),
87
142
  }),
88
143
  errors: [
89
144
  {
@@ -93,98 +148,115 @@ export const getAirQualityTool = tool('epa_get_air_quality', {
93
148
  recovery: 'Provide either zip_code or both latitude and longitude to identify the location.',
94
149
  },
95
150
  {
96
- reason: 'forecast_date_required',
151
+ reason: 'forecast_date_needs_forecast_mode',
152
+ code: JsonRpcErrorCode.ValidationError,
153
+ when: 'forecast_date was set while mode is "current", where it has no effect.',
154
+ recovery: 'Set mode to "forecast" to filter by forecast_date, or omit forecast_date.',
155
+ },
156
+ {
157
+ reason: 'invalid_zip_code',
97
158
  code: JsonRpcErrorCode.ValidationError,
98
- when: 'Mode is "forecast" but forecast_date was not provided.',
99
- recovery: 'Provide forecast_date as YYYY-MM-DD when using mode="forecast".',
159
+ when: 'AirNow rejected zip_code as invalid (HTTP 400).',
160
+ recovery: 'Check that zip_code is a valid 5-digit US ZIP code, or pass latitude and longitude instead.',
161
+ thrownBy: 'service',
100
162
  },
101
163
  ],
102
164
  async handler(input, ctx) {
103
- // Resolve the location once into a discriminated shape so the service branches below
104
- // narrow without non-null assertions. Zip takes precedence over lat/lng, and the raw
105
- // (untrimmed) zip_code is forwarded to match prior behavior.
106
- const zip = input.zip_code;
107
- const loc = zip !== undefined && zip.trim() !== ''
165
+ // Zip takes precedence over lat/lng; a blank zip (form clients) falls through to lat/lng.
166
+ const zip = input.zip_code?.trim();
167
+ const location = zip
108
168
  ? { kind: 'zip', zipCode: zip }
109
169
  : input.latitude !== undefined && input.longitude !== undefined
110
170
  ? { kind: 'latlng', latitude: input.latitude, longitude: input.longitude }
111
171
  : undefined;
112
- if (!loc) {
172
+ if (!location) {
113
173
  throw ctx.fail('no_location', 'Provide either zip_code or both latitude and longitude.');
114
174
  }
115
- // forecast mode requires a date — validate up front so the error path is unchanged.
116
- let forecastDate = '';
117
- if (input.mode === 'forecast') {
118
- if (input.forecast_date === undefined || input.forecast_date.trim() === '') {
119
- throw ctx.fail('forecast_date_required', 'forecast_date (YYYY-MM-DD) is required when mode is "forecast".');
120
- }
121
- forecastDate = input.forecast_date;
175
+ const forecastDate = input.forecast_date?.trim() || undefined;
176
+ if (forecastDate && input.mode === 'current') {
177
+ throw ctx.fail('forecast_date_needs_forecast_mode', `forecast_date "${forecastDate}" only filters forecasts; current mode returns the latest observations.`);
122
178
  }
123
179
  ctx.log.info('epa_get_air_quality', {
124
180
  mode: input.mode,
125
- zip: input.zip_code,
126
- lat: input.latitude,
181
+ location: location.kind,
182
+ forecastDate,
127
183
  });
128
184
  const service = getAirNowService();
129
- let observations;
130
- if (input.mode === 'current') {
131
- observations =
132
- loc.kind === 'zip'
133
- ? await service.getCurrentByZip({ zipCode: loc.zipCode, distanceMiles: input.distance_miles }, ctx)
134
- : await service.getCurrentByLatLng({
135
- latitude: loc.latitude,
136
- longitude: loc.longitude,
137
- distanceMiles: input.distance_miles,
138
- }, ctx);
185
+ const lookup = input.mode === 'forecast'
186
+ ? await service.getForecast(location, ctx)
187
+ : await service.getCurrent(location, ctx);
188
+ const observations = input.mode === 'forecast' && forecastDate
189
+ ? lookup.areas.flatMap((area) => {
190
+ const readings = area.readings.filter((r) => r.dateValid === forecastDate);
191
+ return readings.length > 0 ? [{ ...area, readings }] : [];
192
+ })
193
+ : lookup.areas;
194
+ ctx.log.info('epa_get_air_quality completed', { areas: observations.length });
195
+ const attribution = attributionFor(input.mode, observations);
196
+ if (observations.length > 0)
197
+ return { observations, mode: input.mode, attribution };
198
+ const where = location.kind === 'zip'
199
+ ? `zip_code="${location.zipCode}"`
200
+ : `latitude=${location.latitude}, longitude=${location.longitude}`;
201
+ let message;
202
+ if (lookup.noDataMessage !== undefined) {
203
+ message = `AirNow returned no data for ${where}: "${lookup.noDataMessage}"`;
139
204
  }
140
- else {
141
- observations =
142
- loc.kind === 'zip'
143
- ? await service.getForecastByZip({ zipCode: loc.zipCode, date: forecastDate, distanceMiles: input.distance_miles }, ctx)
144
- : await service.getForecastByLatLng({
145
- latitude: loc.latitude,
146
- longitude: loc.longitude,
147
- date: forecastDate,
148
- distanceMiles: input.distance_miles,
149
- }, ctx);
205
+ else if (lookup.areas.length > 0) {
206
+ const issued = [
207
+ ...new Set(lookup.areas.flatMap((a) => a.readings.flatMap((r) => r.dateValid ?? []))),
208
+ ].sort();
209
+ message = `No forecast valid on ${forecastDate} for ${where}. ${issued.length > 0 ? `Issued forecast dates: ${issued.join(', ')}.` : 'AirNow listed no valid dates.'} Omit forecast_date to get every issued day.`;
150
210
  }
151
- ctx.log.info('epa_get_air_quality completed', { areas: observations.length });
152
- if (observations.length === 0) {
153
- const location = loc.kind === 'zip'
154
- ? `zip_code="${input.zip_code}"`
155
- : `lat=${input.latitude}, lng=${input.longitude}`;
156
- return {
157
- observations: [],
158
- mode: input.mode,
159
- 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.`,
160
- };
211
+ else {
212
+ message = `No AQI data found for ${where}. AirNow observations come from monitors within 50 miles and forecasts from the location's reporting area; check that the location is in the US, or try a nearby ZIP code.`;
161
213
  }
162
- return { observations, mode: input.mode };
214
+ return { observations: [], mode: input.mode, message, attribution };
163
215
  },
164
216
  format: (result) => {
165
- const lines = [];
166
- lines.push(`## Air Quality Index — ${result.mode === 'forecast' ? 'Forecast' : 'Current Observations'} (mode: ${result.mode})`);
217
+ const lines = [
218
+ `## Air Quality Index — ${result.mode === 'forecast' ? 'Forecast' : 'Current Observations'} (mode: ${result.mode})`,
219
+ ];
167
220
  if (result.message)
168
221
  lines.push(`\n> ${result.message}`);
169
- for (const obs of result.observations) {
170
- lines.push(`\n### ${obs.reportingArea ?? 'Unknown Area'}`);
171
- if (obs.stateCode)
172
- lines.push(`**State:** ${obs.stateCode}`);
173
- if (obs.dateObserved) {
174
- const timeStr = obs.hourObserved !== undefined
175
- ? ` at ${obs.hourObserved}:00 ${obs.localTimeZone ?? ''}`
222
+ for (const area of result.observations) {
223
+ lines.push(`\n### ${area.reportingArea ?? 'Unknown Area'}`);
224
+ const meta = [
225
+ area.stateCode && `**State:** ${area.stateCode}`,
226
+ area.reportingAreaCode && `**Reporting area code:** ${area.reportingAreaCode}`,
227
+ ].filter(Boolean);
228
+ if (meta.length > 0)
229
+ lines.push(meta.join(' | '));
230
+ if (area.dateObserved || area.hourObserved) {
231
+ const time = area.hourObserved
232
+ ? ` at ${area.hourObserved}${area.localTimeZone ? ` ${area.localTimeZone}` : ''}`
176
233
  : '';
177
- lines.push(`**Date:** ${obs.dateObserved}${timeStr}`);
234
+ lines.push(`**Observed:** ${area.dateObserved ?? 'date not reported'}${time}`);
178
235
  }
179
- if (obs.latitude !== undefined && obs.longitude !== undefined) {
180
- lines.push(`**Coordinates:** ${obs.latitude}, ${obs.longitude}`);
181
- }
182
- for (const reading of obs.readings) {
183
- const category = reading.categoryName ? ` (${reading.categoryName})` : '';
184
- const catNum = reading.categoryNumber !== undefined ? ` [category ${reading.categoryNumber}]` : '';
185
- lines.push(`**${reading.parameterName}:** AQI ${reading.aqi}${category}${catNum}`);
236
+ for (const r of area.readings) {
237
+ const label = r.dateValid ? `${r.dateValid} ${r.parameterName}` : r.parameterName;
238
+ const value = r.aqi !== undefined
239
+ ? `AQI ${r.aqi}${r.categoryName ? ` (${r.categoryName})` : ''}`
240
+ : (r.categoryName ?? 'Category not reported');
241
+ const category = r.categoryNumber !== undefined ? ` [category ${r.categoryNumber}]` : '';
242
+ const categoryOnly = r.aqi === undefined ? ' (category only, no AQI number)' : '';
243
+ const site = r.siteName || r.siteID
244
+ ? ` — ${[r.siteName, r.siteID && `site ${r.siteID}`].filter(Boolean).join(', ')}`
245
+ : '';
246
+ const details = [
247
+ r.reportingAgency,
248
+ (r.dateIssue || r.forecastAgency) &&
249
+ ['issued', r.dateIssue, r.forecastAgency && `by ${r.forecastAgency}`]
250
+ .filter(Boolean)
251
+ .join(' '),
252
+ r.actionDay !== undefined && `action day: ${r.actionDay ? 'yes' : 'no'}`,
253
+ ].filter(Boolean);
254
+ lines.push(`- **${label}:** ${value}${category}${categoryOnly}${site}${details.length > 0 ? ` · ${details.join(' · ')}` : ''}`);
186
255
  }
256
+ if (area.discussion)
257
+ lines.push(`\n**Discussion:**\n${area.discussion}`);
187
258
  }
259
+ lines.push(`\n**Source:** ${result.attribution}`);
188
260
  return [{ type: 'text', text: lines.join('\n') }];
189
261
  },
190
262
  });
@@ -1 +1 @@
1
- {"version":3,"file":"get-air-quality.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-air-quality.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-air-quality.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-air-quality.tool.ts"],"names":[],"mappings":"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"}
@@ -25,22 +25,47 @@ export declare const getFacilityTool: import("@cyanheads/mcp-ts-core").ToolDefin
25
25
  tri: z.ZodBoolean;
26
26
  sdwa: z.ZodBoolean;
27
27
  }, z.core.$strip>;
28
+ triFacilityIds: z.ZodArray<z.ZodString>;
28
29
  triReleasesTransfersInLbs: z.ZodOptional<z.ZodNumber>;
30
+ triReleasesTransfersYear: z.ZodOptional<z.ZodNumber>;
29
31
  compliance: z.ZodOptional<z.ZodObject<{
30
32
  mediaStatusCode: z.ZodOptional<z.ZodString>;
31
33
  mediaStatusDescription: z.ZodOptional<z.ZodString>;
32
34
  quartersInViolation: z.ZodOptional<z.ZodNumber>;
33
35
  }, z.core.$strip>>;
36
+ programCompliance: z.ZodArray<z.ZodObject<{
37
+ statute: z.ZodString;
38
+ currentStatus: z.ZodOptional<z.ZodString>;
39
+ quartersInNoncompliance: z.ZodOptional<z.ZodNumber>;
40
+ quartersInSignificantNoncompliance: z.ZodOptional<z.ZodNumber>;
41
+ inspections: z.ZodOptional<z.ZodNumber>;
42
+ lastInspectionDate: z.ZodOptional<z.ZodString>;
43
+ informalActions: z.ZodOptional<z.ZodNumber>;
44
+ formalActions: z.ZodOptional<z.ZodNumber>;
45
+ totalPenaltiesInDollars: z.ZodOptional<z.ZodNumber>;
46
+ threeYearPeriodStart: z.ZodOptional<z.ZodString>;
47
+ fiveYearPeriodStart: z.ZodOptional<z.ZodString>;
48
+ periodEnd: z.ZodOptional<z.ZodString>;
49
+ }, z.core.$strip>>;
34
50
  inspections: z.ZodArray<z.ZodObject<{
51
+ category: z.ZodOptional<z.ZodString>;
35
52
  activityType: z.ZodOptional<z.ZodString>;
36
53
  activityDate: z.ZodOptional<z.ZodString>;
37
54
  description: z.ZodOptional<z.ZodString>;
55
+ statute: z.ZodOptional<z.ZodString>;
56
+ sourceId: z.ZodOptional<z.ZodString>;
57
+ leadAgency: z.ZodOptional<z.ZodString>;
38
58
  }, z.core.$strip>>;
59
+ inspectionsTotal: z.ZodNumber;
39
60
  formalActions: z.ZodArray<z.ZodObject<{
40
61
  caseId: z.ZodOptional<z.ZodString>;
41
62
  settlementDate: z.ZodOptional<z.ZodString>;
42
63
  penaltyAssessedInDollars: z.ZodOptional<z.ZodNumber>;
43
64
  actionType: z.ZodOptional<z.ZodString>;
65
+ actionDate: z.ZodOptional<z.ZodString>;
66
+ statute: z.ZodOptional<z.ZodString>;
67
+ sourceId: z.ZodOptional<z.ZodString>;
68
+ leadAgency: z.ZodOptional<z.ZodString>;
44
69
  }, z.core.$strip>>;
45
70
  airCompliance: z.ZodOptional<z.ZodObject<{
46
71
  programId: z.ZodOptional<z.ZodString>;
@@ -55,7 +80,10 @@ export declare const getFacilityTool: import("@cyanheads/mcp-ts-core").ToolDefin
55
80
  }, z.core.$strip>, readonly [{
56
81
  readonly reason: "facility_not_found";
57
82
  readonly code: JsonRpcErrorCode.NotFound;
58
- readonly when: "ECHO returned no facility record for the given Registry ID.";
83
+ readonly when: "ECHO has no facility for the given Registry ID.";
59
84
  readonly recovery: "Verify the Registry ID using epa_search_facilities and retry with a valid ID.";
60
- }], undefined>;
85
+ readonly thrownBy: "service";
86
+ }], {
87
+ readonly notice: z.ZodOptional<z.ZodString>;
88
+ }>;
61
89
  //# sourceMappingURL=get-facility.tool.d.ts.map
@@ -1 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAwN1B,CAAC"}
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;AAKjE,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4Z1B,CAAC"}