Skip to main content
Glama

get-observations-by-monitoring-site-by-geographic-bounding-box

Retrieve air quality observations from monitoring sites within a specific geographic area. Specify pollutants, data format, and time range to access detailed air quality data.

Instructions

Get observations by monitoring site within a geographic bounding box.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bboxYesGeographic bounding box of the area of interest in latitude and longitude. The format is a comma separated list minX,minY,maxX,maxY. Example: 122.715607,38.181254,-120.012970,39.022646
datatypeYesData type to return. Example: C
enddateNoThe end date and time of the data requested. Format: UTC Date or DateTime as end of measurement period. Examples: 2014-01-02T13:00, 2014-01-02T13, or 2014-01-02
formatYesMIME type of the file to be returned. Example: application/json
includerawconcentrationsNoWhen set to 1, an additional field that contains the raw concentration will be added to the output. Default is 0.
monitortypeNoThe type of monitor to be returned. Options include: Permanent Only (0), Mobile Only (1), Permanent and Mobile (2). Example: 0
parametersYesComma separated list of pollutant parameters short codes to return data for. Options include: ozone, pm25, pm10, co, no2, so2. Example: ozone,pm25
startdateNoThe start date and time of the data requested. Format: UTC Date or DateTime as beginning of measurement period. Examples: 2014-01-01T13:00, 2014-01-01T13, or 2014-01-01
verboseNoWhen set to 1, provides additional site information including Site Name, Agency Name, AQS ID, and Full AQS ID. Default is 0.

Implementation Reference

  • The handler function for the MCP tool that calls the AirNow API helper, handles errors, and returns the result as text content.
    async (params) => { const result = await airnowApi.fetchObservationsByMonitoringSiteByGeographicBoundingBox( params ); if (result === null) { return { content: [ { type: "text", text: "Failed to fetch observations data from AirNow API.", }, ], isError: true, }; } return { content: [ { type: "text", text: result, }, ], }; }
  • Zod schema for input parameters including bounding box, parameters, datatype, format, dates, monitor type, verbose, and raw concentrations.
    { bbox: z .string() .describe( "Geographic bounding box of the area of interest in latitude and longitude. The format is a comma separated list minX,minY,maxX,maxY. Example: 122.715607,38.181254,-120.012970,39.022646" ), parameters: z .string() .describe( "Comma separated list of pollutant parameters short codes to return data for. Options include: ozone, pm25, pm10, co, no2, so2. Example: ozone,pm25" ), datatype: z .enum(["A", "C", "B"]) .describe("Data type to return. Example: C"), format: z .enum([ "text/csv", "application/json", "application/xml", "application/vnd.google-earth.kml", ]) .describe( "MIME type of the file to be returned. Example: application/json" ), startdate: z .string() .optional() .describe( "The start date and time of the data requested. Format: UTC Date or DateTime as beginning of measurement period. Examples: 2014-01-01T13:00, 2014-01-01T13, or 2014-01-01" ), enddate: z .string() .optional() .describe( "The end date and time of the data requested. Format: UTC Date or DateTime as end of measurement period. Examples: 2014-01-02T13:00, 2014-01-02T13, or 2014-01-02" ), monitortype: z .enum(["0", "1", "2"]) .optional() .describe( "The type of monitor to be returned. Options include: Permanent Only (0), Mobile Only (1), Permanent and Mobile (2). Example: 0" ), verbose: z .enum(["0", "1"]) .optional() .describe( "When set to 1, provides additional site information including Site Name, Agency Name, AQS ID, and Full AQS ID. Default is 0." ), includerawconcentrations: z .enum(["0", "1"]) .optional() .describe( "When set to 1, an additional field that contains the raw concentration will be added to the output. Default is 0." ), },
  • The registration function exported from the tool file that registers the tool on the MCP server using server.tool(), including schema and handler.
    export const registerObservationsByBoundingBox = (server: McpServer): void => { server.tool( "get-observations-by-monitoring-site-by-geographic-bounding-box", "Get observations by monitoring site within a geographic bounding box.", { bbox: z .string() .describe( "Geographic bounding box of the area of interest in latitude and longitude. The format is a comma separated list minX,minY,maxX,maxY. Example: 122.715607,38.181254,-120.012970,39.022646" ), parameters: z .string() .describe( "Comma separated list of pollutant parameters short codes to return data for. Options include: ozone, pm25, pm10, co, no2, so2. Example: ozone,pm25" ), datatype: z .enum(["A", "C", "B"]) .describe("Data type to return. Example: C"), format: z .enum([ "text/csv", "application/json", "application/xml", "application/vnd.google-earth.kml", ]) .describe( "MIME type of the file to be returned. Example: application/json" ), startdate: z .string() .optional() .describe( "The start date and time of the data requested. Format: UTC Date or DateTime as beginning of measurement period. Examples: 2014-01-01T13:00, 2014-01-01T13, or 2014-01-01" ), enddate: z .string() .optional() .describe( "The end date and time of the data requested. Format: UTC Date or DateTime as end of measurement period. Examples: 2014-01-02T13:00, 2014-01-02T13, or 2014-01-02" ), monitortype: z .enum(["0", "1", "2"]) .optional() .describe( "The type of monitor to be returned. Options include: Permanent Only (0), Mobile Only (1), Permanent and Mobile (2). Example: 0" ), verbose: z .enum(["0", "1"]) .optional() .describe( "When set to 1, provides additional site information including Site Name, Agency Name, AQS ID, and Full AQS ID. Default is 0." ), includerawconcentrations: z .enum(["0", "1"]) .optional() .describe( "When set to 1, an additional field that contains the raw concentration will be added to the output. Default is 0." ), }, async (params) => { const result = await airnowApi.fetchObservationsByMonitoringSiteByGeographicBoundingBox( params ); if (result === null) { return { content: [ { type: "text", text: "Failed to fetch observations data from AirNow API.", }, ], isError: true, }; } return { content: [ { type: "text", text: result, }, ], }; } ); };
  • Core helper function that builds the query parameters for the AirNow API endpoint '/aq/data/' and fetches the observations data.
    export async function fetchObservationsByMonitoringSiteByGeographicBoundingBox(params: Record<string, string>): Promise<string | null> { const endpoint = 'aq/data/'; const queryParams = new URLSearchParams(); queryParams.append('bbox', params.bbox); queryParams.append('parameters', params.parameters); queryParams.append('datatype', params.datatype); queryParams.append('format', params.format); queryParams.append('verbose', params.verbose || '0'); queryParams.append('includerawconcentrations', params.includerawconcentrations || '0'); if (params.startdate && params.enddate) { queryParams.append('startdate', params.startdate); queryParams.append('enddate', params.enddate); } if (params.monitortype) queryParams.append('monitortype', params.monitortype); return airnowGet(endpoint, queryParams); }
  • Top-level registration call in the tools index that invokes the tool's registration function on the MCP server.
    registerObservationsByBoundingBox(server);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prsantos-com/airnow-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server