{"_id":"@cyanheads/openaq-mcp-server","_rev":"15-33b5d8ceedd479d80da927523253fe7f","name":"@cyanheads/openaq-mcp-server","dist-tags":{"latest":"0.4.1"},"versions":{"0.1.0":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.0","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":{"name":"cyanheads","email":"casey@caseyjhand.com"},"license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.0","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"c8f1fe7abb8f85b5456a94080743311e90eaf3b8","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.0.tgz","fileCount":73,"integrity":"sha512-9vTGswPdSn9gBUsgXNPm5sM+xXt62w/psBVvLtGOUxPLqjK5m4cuwwW15zPzmz4MUKOa8zeDSj+iZAmNPSRxAw==","signatures":[{"sig":"MEYCIQCmGnEmb+tOIuTA6YWAogZRzPsMn+qTFacgPvEM/dqZvQIhAOvuqJm2xBMPQSfpFMlBoPYFr0BGBZcnbrOOGPcmsMJO","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":265803},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"bun":">=1.3.0","node":">=24.0.0"},"gitHead":"81b341415e9edaa7b79cda91530bd1e1e422a1bc","mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"11.12.1","description":"Find air-quality monitoring stations and read measured pollutant observations (PM2.5, PM10, O3, NO2, SO2, CO, and more) from government monitors worldwide via the OpenAQ v3 API, with DataCanvas SQL over historical series.","directories":{},"_nodeVersion":"26.0.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.3-r.3","@cyanheads/mcp-ts-core":"^0.10.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ignore":"^7.0.5","vitest":"^4.1.8","depcheck":"^1.4.7","tsc-alias":"^1.8.17","typescript":"^6.0.3","@types/node":"25.9.3","@biomejs/biome":"2.5.0"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.0_1781432173609_0.6989429208161462","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.1","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"cyanheads <casey@caseyjhand.com>","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.1","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"73f892ecb52184a737abcb9a3622c08cfdf31433","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.1.tgz","fileCount":74,"integrity":"sha512-at3RftqP/PqEt5ghc7gp7yuk9bIy9GcwKmZdBJrevcvCQ2Oel3cY/yhmWGvJWh79U7hls8kWR9cPcEnGMICfJQ==","signatures":[{"sig":"MEQCIFEo41MyJhObLrQiStcAx48WLvx/774y1i9cRz8jFfwNAiA3sYzkkHSIaAjvvlaqi8BcSmNAUSJ+pa0frTL2NObyZw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":267490},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"73f892ecb52184a737abcb9a3622c08cfdf31433","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-at3RftqP/PqEt5ghc7gp7yuk9bIy9GcwKmZdBJrevcvCQ2Oel3cY/yhmWGvJWh79U7hls8kWR9cPcEnGMICfJQ==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations and read measured pollutant observations (PM2.5, PM10, O3, NO2, SO2, CO, and more) from government monitors worldwide via the OpenAQ v3 API, with DataCanvas SQL over historical series.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.3-r.3","@cyanheads/mcp-ts-core":"^0.10.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ignore":"^7.0.5","vitest":"^4.1.9","depcheck":"^1.4.7","tsc-alias":"^1.8.17","typescript":"^6.0.3","@types/node":"25.9.3","@biomejs/biome":"2.5.0"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.1_1781545703364_0.4413644957413285","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.2","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"cyanheads <casey@caseyjhand.com>","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.2","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"9d15d5daabd875aeeb4510b98c364eda7fc06574","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.2.tgz","fileCount":75,"integrity":"sha512-LtAPmRYDlXkDyL1lItiXtaDRHjJziZoJTOaw8LHJLznFp+QUfCc3jHEkVGQq9KR13lkDvyKUbMY69ykBHSZzBQ==","signatures":[{"sig":"MEUCIGT0sgj3lkGYWnMqU8kXNRr8izRtQo2NK6Vq8ZB2mMDaAiEAhBWBVAQ9TbkpHs7ByoAPLuw2zBORcBX+7qh7jCUOf2Y=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":269308},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"9d15d5daabd875aeeb4510b98c364eda7fc06574","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-LtAPmRYDlXkDyL1lItiXtaDRHjJziZoJTOaw8LHJLznFp+QUfCc3jHEkVGQq9KR13lkDvyKUbMY69ykBHSZzBQ==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations and read measured pollutant observations (PM2.5, PM10, O3, NO2, SO2, CO, and more) from government monitors worldwide via the OpenAQ v3 API, with DataCanvas SQL over historical series.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.4-r.1","@cyanheads/mcp-ts-core":"^0.10.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ignore":"^7.0.5","vitest":"^4.1.9","depcheck":"^1.4.7","tsc-alias":"^1.8.17","typescript":"^6.0.3","@types/node":"26.0.0","@biomejs/biome":"2.5.0"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.2_1781976629139_0.19432381324704906","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.3","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"cyanheads <casey@caseyjhand.com>","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.3","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"aea0ef4dc1bdd77ad337cdc01eb1ed98938ca8e9","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.3.tgz","fileCount":76,"integrity":"sha512-MYMKU/HLz67Myjw6EQouByMHpXPW6aCG+SVQCJHfq8UnV8zmCbRxyJUm542HPe8lZAqNqoNoOwOdvofS5omC/A==","signatures":[{"sig":"MEYCIQCqTNUk5pcUcvIWttbV4VXWR8qyqBQ/ISMmQsEWraGMQwIhAL7mvAh0bPOIwNlzf9bl9ek4C1LqoCIg93SUxxlAqG3g","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":277603},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"aea0ef4dc1bdd77ad337cdc01eb1ed98938ca8e9","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-MYMKU/HLz67Myjw6EQouByMHpXPW6aCG+SVQCJHfq8UnV8zmCbRxyJUm542HPe8lZAqNqoNoOwOdvofS5omC/A==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations and read measured pollutant observations (PM2.5, PM10, O3, NO2, SO2, CO, and more) from government monitors worldwide via the OpenAQ v3 API, with DataCanvas SQL over historical series.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.4-r.1","@cyanheads/mcp-ts-core":"^0.10.10"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ignore":"^7.0.5","vitest":"^4.1.9","depcheck":"^1.4.7","tsc-alias":"^1.8.17","typescript":"^6.0.3","@types/node":"26.0.1","@biomejs/biome":"2.5.1"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.3_1782868913177_0.062200467794272685","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.4","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.4","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"f368f5c1c41c06eeae3b72a19e2e74fdd463eddb","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.4.tgz","fileCount":77,"integrity":"sha512-UUkHpT7HmXCIkyHo7xDmOlgNmlSsZXCFXMMKP/V/L0dCi5uGVbXUSUMKD/tCosvoH7x6R+CbTEobDK9t5La1yA==","signatures":[{"sig":"MEUCIQCDSNQyOtAW4h86Xjhzy+6/7kB0Zkb3Zrbhjo3PmpclvwIgBgitZoAlhm+0RnsKd92ilw+Qy/nEAxpL191w+6JZZDw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":291929},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"f368f5c1c41c06eeae3b72a19e2e74fdd463eddb","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-UUkHpT7HmXCIkyHo7xDmOlgNmlSsZXCFXMMKP/V/L0dCi5uGVbXUSUMKD/tCosvoH7x6R+CbTEobDK9t5La1yA==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.1","@cyanheads/mcp-ts-core":"^0.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ignore":"^7.0.6","vitest":"^4.1.10","depcheck":"^1.4.7","tsc-alias":"^1.9.1","typescript":"^7.0.2","@types/node":"26.1.1","@biomejs/biome":"2.5.5","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.4_1785103768653_0.6790889440293129","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.5","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.5","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"2c3b9adab0044111a3a126a4686ddb2bfce137a2","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.5.tgz","fileCount":82,"integrity":"sha512-nxRJY5dR1J5VBw1iLTXUD9KawTFl8Gi7FMCuC+PlELomEI7QOJVjx6EoBvKBZyItuTWKOKEgtlwdaEHyoa+MhQ==","signatures":[{"sig":"MEUCIQClVaKQuyBo1O0PXrycLfysOMCZpgecc/cAW8+87MkmLwIgIqMVFZDlNhcga4o07ZpfSuwYb5SzQdnYfkbhImUrBo8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":325300},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"2c3b9adab0044111a3a126a4686ddb2bfce137a2","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-nxRJY5dR1J5VBw1iLTXUD9KawTFl8Gi7FMCuC+PlELomEI7QOJVjx6EoBvKBZyItuTWKOKEgtlwdaEHyoa+MhQ==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.1","@cyanheads/mcp-ts-core":"^0.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ignore":"^7.0.6","vitest":"^4.1.10","depcheck":"^1.4.7","tsc-alias":"^1.9.1","typescript":"^7.0.2","@types/node":"26.1.1","@biomejs/biome":"2.5.5","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.5_1785107105809_0.29372663538992905","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.6","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.6","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"4b7b20036c09c96d7e6f46a469bd355f88dfde1d","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.6.tgz","fileCount":87,"integrity":"sha512-OiJiTE7I+fglOwN+r9sVoVYeOL2pqZY6D6PWaq5Br10tHueKBmjmjrPHaWb+je7KMCv2ObO4zAKDTijfI0v5gA==","signatures":[{"sig":"MEQCIH77dkJilTkBJw6yPBRK5U5Wt9umQ9LHNL7InVSy5uwcAiBYsY1N2tG6hEVJ2JSyFY11SjEvao2miB8hHnawVrcQFg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":344800},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"4b7b20036c09c96d7e6f46a469bd355f88dfde1d","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-OiJiTE7I+fglOwN+r9sVoVYeOL2pqZY6D6PWaq5Br10tHueKBmjmjrPHaWb+je7KMCv2ObO4zAKDTijfI0v5gA==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.1","@cyanheads/mcp-ts-core":"^0.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ignore":"^7.0.6","vitest":"^4.1.10","depcheck":"^1.4.7","tsc-alias":"^1.9.1","typescript":"^7.0.2","@types/node":"26.1.1","@biomejs/biome":"2.5.5","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.6_1785110307572_0.12161767144166435","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.7","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.7","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"3da8794d329027c725a27ade60b58a00500efa28","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.7.tgz","fileCount":88,"integrity":"sha512-9R0cbV3U8xAwQXPKgvZuUJBDO2LbeahYRjEhxwkWb454SnesyfMTVg3DEeAn4hj9Hpwn21oGd2+B9Gg4n+rybw==","signatures":[{"sig":"MEUCIQDCerZU2OlOBwsF/Y+R44jySzDrGpEF/TrPkG3+RypApwIgFIa2F8AWMWsJ+4yxFnjDVle1QVS9eebFa5AZgru01fY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":361035},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"3da8794d329027c725a27ade60b58a00500efa28","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-9R0cbV3U8xAwQXPKgvZuUJBDO2LbeahYRjEhxwkWb454SnesyfMTVg3DEeAn4hj9Hpwn21oGd2+B9Gg4n+rybw==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"24.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.1","@cyanheads/mcp-ts-core":"^0.11.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.3.14","devDependencies":{"ignore":"^7.0.6","vitest":"^4.1.10","depcheck":"^1.4.7","tsc-alias":"^1.9.1","typescript":"^7.0.2","@types/node":"26.1.1","@biomejs/biome":"2.5.5","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.7_1785112552287_0.7030295845544507","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.8","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.8","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"a245152b1acebc0b711deb068aa3837f16c8197f","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.8.tgz","fileCount":89,"integrity":"sha512-ncVV1g3NzEb3cDCvEnAVqezu3bROufPtq0kXWsCkcYtiPYQsKToVvjNAAXLqwCT91g+Oa67zrhqJqAjJHpj6uA==","signatures":[{"sig":"MEUCIHBLLBbIkL0Av6TGwy8ZPCgDRFFRKhekVwkiIGTUELitAiEArmPORTeDZcMd0aVl/PIhYemFpEUpSZX6VfuAHbgexww=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":369715},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"a245152b1acebc0b711deb068aa3837f16c8197f","engines":{"bun":">=1.3.0","node":">=24.0.0"},"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-ncVV1g3NzEb3cDCvEnAVqezu3bROufPtq0kXWsCkcYtiPYQsKToVvjNAAXLqwCT91g+Oa67zrhqJqAjJHpj6uA==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.4.3","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.4","@cyanheads/mcp-ts-core":"^0.12.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.0","devDependencies":{"ignore":"^7.0.6","vitest":"^4.1.11","depcheck":"^1.4.7","tsc-alias":"^1.9.2","typescript":"^7.0.2","@types/node":"26.2.0","@biomejs/biome":"2.5.10","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.8_1787637496937_0.29605053989460006","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.9","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.9","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"0497602fe8752814e3b1873ef46dd3abb4f1adcb","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.9.tgz","fileCount":90,"integrity":"sha512-JpFuCvQRj8jZ+pM/rOH5QIAC+61Sl180B6WzZmTTveh6VFTdOXa1XW7XPl/uT8Zaugj0kXoBxsODGaOibKU23A==","signatures":[{"sig":"MEUCICKd9QxsyfiS1d/olzyJIj5Z2Ikax9I+GeAua5QMprgoAiEA+eyoEBWJoQ++FVecN4rzG9fErSYqeY+Mr5qkw4HlpS0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIFP9M0aqQejqXdhcrMtwml8/MJ02My5p7z0YiO7S4aArAiEAsTHOYLUbD7abM0+2TZUNE9KyOvRxpECg6cWDQs6GZHw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":385684},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"0497602fe8752814e3b1873ef46dd3abb4f1adcb","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-JpFuCvQRj8jZ+pM/rOH5QIAC+61Sl180B6WzZmTTveh6VFTdOXa1XW7XPl/uT8Zaugj0kXoBxsODGaOibKU23A==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.0","devDependencies":{"ignore":"^7.0.9","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.1","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.9_1789914592400_0.31527093743463275","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"@cyanheads/openaq-mcp-server","version":"0.1.10","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.1.10","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"32c5ea8c041ee1ef2331c3047300e329bf7c5fce","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.1.10.tgz","fileCount":91,"integrity":"sha512-21cvqZgOVr0UAhBFskO55XLPLihy12ZK1l3hhRHZjocqZMWE9/2UI9BatM5dGYKCzUQ/q0LxpvGrJt11+XbFdw==","signatures":[{"sig":"MEUCIFsxfwdq0Yp9uhJ9EuHWlotu5iuorAf/UydCv1cKFFnCAiEAv/OJ1vXKPSwn8JhFr9ZuLLHSeHMvT9VZsPCantGA2DQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDuYomNJ6NPrvUU/GJALjJtp5Tpy+TMWuc3PdCUMRK5QAIgYIgatnTOUnpFxzz8+yxziQ2EVJdcd9Emv8ngdKxut/E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":398093},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"32c5ea8c041ee1ef2331c3047300e329bf7c5fce","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-21cvqZgOVr0UAhBFskO55XLPLihy12ZK1l3hhRHZjocqZMWE9/2UI9BatM5dGYKCzUQ/q0LxpvGrJt11+XbFdw==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.0","devDependencies":{"ignore":"^7.0.9","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.1","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.1.10_1790097614312_0.23948334470851118","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@cyanheads/openaq-mcp-server","version":"0.2.0","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.2.0","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"97d2c76a01cbee3c16ffafeadfc09057b65d863b","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.2.0.tgz","fileCount":92,"integrity":"sha512-wWgxujYcBXvbaFVDCjE4ijo73lfj4v/m9RWZ9zcJter65S23/oX40Ub/OkT/w11kh+BrdLEi/88DcwlLnIXFZA==","signatures":[{"sig":"MEUCIQC9NMm3U65KrIT7PTfQHXdJr+Vrvrf8BlUjqmstV1lVqAIgEG6ZtEGRkLUZ70YR7XKWSQD1A/QIn0xZ/W2hHZmPYV0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDH0R5vlkiqdFvRUyTwSIOPs4EJSThAhhPp5MXjR1VOxgIgCwYPsFL8X/RD4Bg2aTHbn2h5RkjTK/c5kR3wvX2Mf70=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":420595},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"97d2c76a01cbee3c16ffafeadfc09057b65d863b","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-wWgxujYcBXvbaFVDCjE4ijo73lfj4v/m9RWZ9zcJter65S23/oX40Ub/OkT/w11kh+BrdLEi/88DcwlLnIXFZA==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.0","devDependencies":{"ignore":"^7.0.9","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.1","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.2.0_1790228993253_0.34600750027604454","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@cyanheads/openaq-mcp-server","version":"0.3.0","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.3.0","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"a1810b322889fae846fdfc4ca50e031ddeb06c5d","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.3.0.tgz","fileCount":93,"integrity":"sha512-Mb17TS78tfE2J2Y4NFri/crfDO0QRTNk0mzQjy7ERS7YKw3Hfz/QCXfwngmyPd8SiKq0i1phf/MoWaWx4Pqhjw==","signatures":[{"sig":"MEYCIQCqxc2fw176ydJDAzrmSqTrTPSJke6vaSowHYmKAKM55gIhAJq/d2HlBCn7VSDsJ7XVMVnEhW4buIBme1TjCD8GnYAd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIEC5x99lwbyIhcCjSXeLECs+smZY911dtF8zTK9RK0zSAiBAIrHpSeItK2U8p9PO2ZIimp5sVxZCSXYThGieatav5Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":450263},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"a1810b322889fae846fdfc4ca50e031ddeb06c5d","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-Mb17TS78tfE2J2Y4NFri/crfDO0QRTNk0mzQjy7ERS7YKw3Hfz/QCXfwngmyPd8SiKq0i1phf/MoWaWx4Pqhjw==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.6"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.0","devDependencies":{"ignore":"^7.0.9","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.1","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.3.0_1790234899829_0.3697590402823647","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@cyanheads/openaq-mcp-server","version":"0.4.0","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","_id":"@cyanheads/openaq-mcp-server@0.4.0","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"bin":{"openaq-mcp-server":"dist/index.js"},"dist":{"shasum":"7472ea04b5798000e3bd7bd60a19bee78d702414","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.4.0.tgz","fileCount":98,"integrity":"sha512-YaAbTOzGzedMoQ4/2Evv1einyRuj/dyogc4awpdg69fZLqk14N9Lh3NUE14lBq6MPtP+gA6QtOCuyuySJ2hdCg==","signatures":[{"sig":"MEUCIF4A42dIuoy1kMjiA0FP3N/EfHqfkJjB+SQyNxe7qM05AiEAvfbuTHu2gkIQH/MOQoeH3BCwdy9FezbJYqGLfVoD+a0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIA629zy/qtS9n2BfroEVlhjv5dCdLUr8DhBtLGZ9P0kgAiEAvW63O+yL/KVEzyt7JEIyVObMlcF+kOwiNW6DnAJMqvQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":465279},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","shasum":"7472ea04b5798000e3bd7bd60a19bee78d702414","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"_integrity":"sha512-YaAbTOzGzedMoQ4/2Evv1einyRuj/dyogc4awpdg69fZLqk14N9Lh3NUE14lBq6MPtP+gA6QtOCuyuySJ2hdCg==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.2","devDependencies":{"ignore":"^7.0.10","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.2","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.3"},"_npmOperationalInternal":{"tmp":"tmp/openaq-mcp-server_0.4.0_1790459684237_0.3167981210682018","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"_id":"@cyanheads/openaq-mcp-server@0.4.1","bin":{"openaq-mcp-server":"dist/index.js"},"bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"dist":{"shasum":"1129d776e9fc6c661bcfffbae84b476e0255edc3","tarball":"https://registry.npmjs.org/@cyanheads/openaq-mcp-server/-/openaq-mcp-server-0.4.1.tgz","fileCount":99,"integrity":"sha512-3riUYXK8jRnNI1Jjd+w/W94I/xXnhNSTYZsa8LRiZlCdbiJjrqtLcYXaRbzQP8/QltMPsJzBbyAJKZq9GgyEug==","signatures":[{"sig":"MEUCIQDIFFLLhBGXqUChA6sLl6m2AJsE9Qj5Ku39vq2YNT2nhwIgYULp/Olz1zrVtoYVT+FMFj/tHU4bmNtrnaqqQ/CNm/4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDd0a/KV/1hcq2qQXPiDcjSGF6IWlpJpTOGuErXa7ElIgIgJa6LYid6CumjQqx2frQEVpAGmjSEYiB2BunbTObkto8="}],"unpackedSize":466244},"main":"dist/index.js","name":"@cyanheads/openaq-mcp-server","type":"module","types":"dist/index.d.ts","author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","shasum":"1129d776e9fc6c661bcfffbae84b476e0255edc3","engines":{"bun":">=1.4.0","node":">=24.0.0"},"funding":[{"url":"https://github.com/sponsors/cyanheads","type":"github"},{"url":"https://www.buymeacoffee.com/cyanheads","type":"buy_me_a_coffee"}],"license":"Apache-2.0","mcpName":"io.github.cyanheads/openaq-mcp-server","scripts":{"test":"vitest run","tree":"bun run scripts/tree.ts","build":"bun run scripts/build.ts","clean":"bun run scripts/clean.ts","start":"node dist/index.js","bundle":"bun run build && npx -y @anthropic-ai/mcpb pack . dist/openaq-mcp-server.mcpb && bun run scripts/clean-mcpb.ts dist/openaq-mcp-server.mcpb","format":"biome check --write .","rebuild":"bun run scripts/clean.ts && bun run scripts/build.ts","devcheck":"bun run scripts/devcheck.ts","lint:mcp":"bun run scripts/lint-mcp.ts","audit:fix":"bun audit fix","start:http":"MCP_TRANSPORT_TYPE=http node dist/index.js","list-skills":"bun run scripts/list-skills.ts","publish-mcp":"mcp-publisher login github -token \"$(security find-generic-password -a \"$USER\" -s mcp-publisher-github-pat -w)\" && mcp-publisher publish","start:stdio":"MCP_TRANSPORT_TYPE=stdio node dist/index.js","audit:refresh":"rm -f bun.lock && bun install && bun audit","format:unsafe":"biome check --write --unsafe .","lint:packaging":"bun run scripts/lint-packaging.ts","release:github":"bun run scripts/release-github.ts","changelog:build":"bun run scripts/build-changelog.ts","changelog:check":"bun run scripts/build-changelog.ts --check"},"version":"0.4.1","_npmUser":{"name":"cyanheads","email":"casey@caseyjhand.com"},"homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"_integrity":"sha512-3riUYXK8jRnNI1Jjd+w/W94I/xXnhNSTYZsa8LRiZlCdbiJjrqtLcYXaRbzQP8/QltMPsJzBbyAJKZq9GgyEug==","repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"_npmVersion":"10.8.3","description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","directories":{},"maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"_nodeVersion":"26.3.0","dependencies":{"zod":"^4.6.5","pino-pretty":"^13.1.3","@duckdb/node-api":"^1.5.5-r.5","@cyanheads/mcp-ts-core":"^0.13.9"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"bun@1.4.2","devDependencies":{"ignore":"^7.0.10","vitest":"^5.0.1","depcheck":"^1.4.7","tsc-alias":"^1.9.5","typescript":"^7.0.2","@types/node":"26.6.2","@biomejs/biome":"2.5.14","@socketsecurity/bun-security-scanner":"^1.1.3"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/openaq-mcp-server_0.4.1_1790460980254_0.9231735386939124"}}},"time":{"created":"2026-06-14T10:16:13.402Z","modified":"2026-09-26T22:16:20.517Z","0.1.0":"2026-06-14T10:16:13.804Z","0.1.1":"2026-06-15T17:48:23.516Z","0.1.2":"2026-06-20T17:30:29.305Z","0.1.3":"2026-07-01T01:21:53.340Z","0.1.4":"2026-07-26T22:09:28.817Z","0.1.5":"2026-07-26T23:05:05.949Z","0.1.6":"2026-07-26T23:58:27.750Z","0.1.7":"2026-07-27T00:35:52.469Z","0.1.8":"2026-08-25T05:58:17.114Z","0.1.9":"2026-09-20T14:29:52.495Z","0.1.10":"2026-09-22T17:20:14.402Z","0.2.0":"2026-09-24T05:49:53.366Z","0.3.0":"2026-09-24T07:28:20.019Z","0.4.0":"2026-09-26T21:54:44.327Z","0.4.1":"2026-09-26T22:16:20.350Z"},"bugs":{"url":"https://github.com/cyanheads/openaq-mcp-server/issues"},"author":"Casey Hand <casey@caseyjhand.com> (https://caseyjhand.com)","license":"Apache-2.0","homepage":"https://github.com/cyanheads/openaq-mcp-server#readme","keywords":["mcp","mcp-server","model-context-protocol","typescript","bun","stdio","streamable-http","openaq","air-quality","pm25","pollution","environment"],"repository":{"url":"git+https://github.com/cyanheads/openaq-mcp-server.git","type":"git"},"description":"Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.","maintainers":[{"name":"cyanheads","email":"casey@caseyjhand.com"}],"readme":"<div align=\"center\">\n  <h1>@cyanheads/openaq-mcp-server</h1>\n  <p><b>Find air-quality monitoring stations, read latest sensor values, and pull historical pollutant series via MCP. STDIO or Streamable HTTP.</b>\n  <div>8 Tools (7 enabled by default) • 2 Resources</div>\n  </p>\n</div>\n\n<div align=\"center\">\n\n[![npm](https://img.shields.io/npm/v/@cyanheads/openaq-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/openaq-mcp-server) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/openaq-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.1.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.2-blueviolet.svg?style=flat-square)](https://bun.sh/)\n\n</div>\n\n<div align=\"center\">\n\n[![Install in Claude Desktop](https://img.shields.io/badge/Install_in-Claude_Desktop-D97757?style=for-the-badge&logo=anthropic&logoColor=white)](https://github.com/cyanheads/openaq-mcp-server/releases/latest/download/openaq-mcp-server.mcpb) [![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=openaq-mcp-server&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBjeWFuaGVhZHMvb3BlbmFxLW1jcC1zZXJ2ZXIiXSwiZW52Ijp7Ik9QRU5BUV9BUElfS0VZIjoieW91ci1hcGkta2V5In19) [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=for-the-badge&logo=visualstudiocode&logoColor=white)](https://vscode.dev/redirect?url=vscode:mcp/install?%7B%22name%22%3A%22openaq-mcp-server%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40cyanheads%2Fopenaq-mcp-server%22%5D%2C%22env%22%3A%7B%22OPENAQ_API_KEY%22%3A%22your-api-key%22%7D%7D)\n\n[![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-67E8F9?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)\n\n</div>\n\n<div align=\"center\">\n\n**Public Hosted Server:** [https://openaq.caseyjhand.com/mcp](https://openaq.caseyjhand.com/mcp)\n\n</div>\n\n---\n\n## Overview\n\nMeasured air quality from the OpenAQ v3 API: physical-sensor observations from government reference monitors and research-grade sensors worldwide. Find monitoring stations, read current values, and pull historical pollutant series from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.\n\n### Tools\n\n| Tool | Description |\n|:---|:---|\n| `openaq_find_locations` | Find monitoring stations near a point, in a bounding box, or by country; the location ids the other tools take |\n| `openaq_get_readings` | Latest value for every sensor at a station, labeled with its pollutant and unit |\n| `openaq_get_measurements` | Historical series for one pollutant at one station, raw or rolled up hourly/daily |\n| `openaq_list_parameters` | Pollutant catalog with canonical units; maps a pollutant and unit to its parameter id |\n| `openaq_list_countries` | Country coverage: data span and the parameters measured in each |\n| `openaq_dataframe_describe` | List the tables and columns staged on a DataCanvas |\n| `openaq_dataframe_query` | Run a read-only SQL `SELECT` over staged measurement series |\n| `openaq_dataframe_drop` | Delete a complete staged canvas; opt-in with `OPENAQ_ENABLE_CANVAS_DROP=true` |\n\n### Resources\n\n| Resource | Description |\n|:---|:---|\n| `openaq://location/{locationId}` | Metadata for one station: coordinates, provider, sensors with units, data span |\n| `openaq://parameters` | Full pollutant and unit catalog |\n\nBoth resources mirror tool output, so tool-only clients lose nothing.\n\n## Capability reference\n\n### `openaq_find_locations` <sub>tool</sub>\n\n- Scope by `coordinates` with `radius` (metres, 1–25000, default 12000), `bbox`, and/or `iso` (a code from `openaq_list_countries`); at least one is required, and `coordinates` and `bbox` exclude each other. `parametersId`, `monitor`, `mobile`, and `providersId` narrow further; up to 100 stations per page (`limit`, default 20), 1-based `page`\n- Each station carries `id`, `distanceMeters` (coordinate search only), `provider`/`providerId`, `isMonitor`/`isMobile`, its `parameters` with units, and the `datetimeFirst`/`datetimeLast` span; `coordinates`, `country`, and `provider` are null when OpenAQ lists none\n- `totalCount` counts stations through the current page and is a floor when `totalCountIsLowerBound` is set; no match fails as `no_locations_found`, a page past the end as `page_exhausted`\n\n---\n\n### `openaq_get_readings` <sub>tool</sub>\n\n- A `locationId`, or `coordinates` plus `parametersId` to resolve the nearest station within 25 km that measures it (compared across up to 1,000 matching stations; a full 1,000 adds a `notice`); with `locationId`, `parametersId` optionally filters to one parameter\n- One reading per sensor with `value`, `unit`, `sensorId`, and `datetimeUtc`/`datetimeLocal`, plus the station's `provider`, `providerId`, `timezone`, and `datetimeLast`\n- Misses are typed: `location_not_found`, `parameter_not_at_location` (with the station's `available` ids), `no_station_near_coordinates`, `no_recent_values`\n\n---\n\n### `openaq_get_measurements` <sub>tool</sub>\n\n- Requires `locationId` and `parametersId`; `datetimeFrom`/`datetimeTo` accept UTC timestamps or station-local `YYYY-MM-DD` dates (UTC days when the station has no timezone). `aggregation` is `raw` (default), `hourly`, or `daily`; up to 5,000 rows per call\n- Returns `series`, `sensorId`, `pulledCount`, `pullComplete`, `effectiveRange`, and station `provider`, `providerId`, and `timezone`. `totalCount` is a floor when `totalCountIsLowerBound` is set; rollups add summary statistics, `gapCount`, the first 20 missing intervals as `gaps`, and a notice when edge buckets are clipped\n- Past 100 rows, `series` is a preview (`truncated`) and the pulled rows stage on a DataCanvas as `measurements_<sensorId>` (`canvasId`, `tableName`) when `CANVAS_PROVIDER_TYPE=duckdb`; a supplied `canvas_id` stages onto that canvas at any size. One table per sensor: a second sensor adds a table to join against, and re-staging the same sensor overwrites its earlier series\n\n---\n\n### `openaq_list_parameters` <sub>tool</sub>\n\n- Optional case-insensitive `query` over code, display name, and description; `pollutantsOnly` drops meteorological and particle-count channels\n- Rows carry `id`, `name`, `displayName`, `unit`, and `description`; one pollutant can appear under several ids by unit (CO is 4 in µg/m³, 8 in ppm, 102 in ppb)\n\n---\n\n### `openaq_list_countries` <sub>tool</sub>\n\n- Optional `query` (a two-letter value matches an ISO 3166-1 alpha-2 code first; otherwise code or name substrings match) and `parametersId`; up to 100 per page (`limit`, default 20), 1-based `page`\n- Rows carry `code` (the `iso` value for `openaq_find_locations`), `name`, the `datetimeFirst`/`datetimeLast` span, and the `parameters` measured anywhere in the country; `totalCount` is the full filtered count\n\n---\n\n### `openaq_dataframe_describe` <sub>tool</sub>\n\n- Takes a `canvas_id` from `openaq_get_measurements` and returns each staged table's `name`, `rowCount`, and `columns`. Call it before `openaq_dataframe_query`: the staged table is flat (`min`, `sd`) while the inline `series` nests those under `summary`\n- Fails as `canvas_unavailable` unless `CANVAS_PROVIDER_TYPE=duckdb`, or `canvas_not_found` for an unknown or expired id\n\n---\n\n### `openaq_dataframe_query` <sub>tool</sub>\n\n- A `canvas_id` and one read-only `SELECT`; writes, DDL, and file/network table functions are rejected\n- At most 200 rows per response, with `truncated` set when the cap cut the result; page with `ORDER BY` plus `LIMIT`/`OFFSET`\n- Fails as `canvas_unavailable`, `canvas_not_found`, or `missing_table`\n\n---\n\n### `openaq_dataframe_drop` <sub>tool</sub>\n\n- Registered only with `OPENAQ_ENABLE_CANVAS_DROP=true`; calls fail as `canvas_unavailable` unless `CANVAS_PROVIDER_TYPE=duckdb`. When disabled, the HTTP landing page shows the enable hint and `tools/list` omits the tool\n- Takes a `canvas_id` and deletes that whole canvas, including all staged tables. Other agents sharing the id lose access; OpenAQ's source data is unaffected\n- Returns the requested `canvasId` and `dropped`: true when deleted, false when no reachable canvas exists. With authentication off, callers share a tenant: anyone holding an id can delete its canvas when enabled\n\n---\n\n### `openaq://location/{locationId}` <sub>resource</sub>\n\n- `application/json`: name, locality, timezone, country, provider, `isMonitor`/`isMobile`, coordinates, `sensors` (each with `parameterId` and `unit`), and the `datetimeFirst`/`datetimeLast` span\n- `locationId` comes from `openaq_find_locations`; cached 5 minutes\n\n---\n\n### `openaq://parameters` <sub>resource</sub>\n\n- `application/json` catalog, the same rows as an unfiltered `openaq_list_parameters`\n- Cached 1 hour\n\n## Features\n\nBuilt on [`@cyanheads/mcp-ts-core`](https://github.com/cyanheads/mcp-ts-core): stdio and Streamable HTTP transports, pluggable auth (`none` / `jwt` / `oauth`), swappable storage (`in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`), structured logging with optional OpenTelemetry tracing.\n\nOpenAQ-specific:\n\n- One typed client over the OpenAQ v3 REST API: `X-API-Key` auth, retry with backoff, and typed upstream failures (`invalid_api_key`, `rate_limited`, `upstream_timeout`, `upstream_error`) on every OpenAQ call\n- Hides the v3 location → sensor → measurement hierarchy: readings join the latest feed to the station's sensor map, and measurements resolve a station plus parameter to its sensor\n- Coordinates and bbox corners are range-checked and contradictory search scopes rejected before any request reaches OpenAQ\n- Large measurement series stage on a DataCanvas for read-only DuckDB SQL, one table per sensor, so two series on one `canvas_id` can be joined\n\nAgent-friendly output:\n\n- Measured, not modeled: a search with no station fails as `no_locations_found` or `no_station_near_coordinates`, stated as no coverage rather than clean air\n- Units travel with every value and are never converted; `parametersId` selects pollutant and unit together\n- Freshness and truncation are explicit: per-value timestamps and `datetimeLast`, and `totalCount` / `truncated` / `notice` on capped results\n\n## Getting started\n\n### Public Hosted Instance\n\nA public instance is available at `https://openaq.caseyjhand.com/mcp` — no installation required. Point any MCP client at it via Streamable HTTP:\n\n```json\n{\n  \"mcpServers\": {\n    \"openaq-mcp-server\": {\n      \"type\": \"streamable-http\",\n      \"url\": \"https://openaq.caseyjhand.com/mcp\"\n    }\n  }\n}\n```\n\n### Self-Hosted / Local\n\nAdd the following to your MCP client configuration file.\n\n```json\n{\n  \"mcpServers\": {\n    \"openaq-mcp-server\": {\n      \"type\": \"stdio\",\n      \"command\": \"bunx\",\n      \"args\": [\"@cyanheads/openaq-mcp-server@latest\"],\n      \"env\": {\n        \"MCP_TRANSPORT_TYPE\": \"stdio\",\n        \"OPENAQ_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\nOr with npx (no Bun required):\n\n```json\n{\n  \"mcpServers\": {\n    \"openaq-mcp-server\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@cyanheads/openaq-mcp-server@latest\"],\n      \"env\": {\n        \"MCP_TRANSPORT_TYPE\": \"stdio\",\n        \"OPENAQ_API_KEY\": \"your-api-key\"\n      }\n    }\n  }\n}\n```\n\nOr with Docker:\n\n```json\n{\n  \"mcpServers\": {\n    \"openaq-mcp-server\": {\n      \"type\": \"stdio\",\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-e\", \"MCP_TRANSPORT_TYPE=stdio\",\n        \"-e\", \"OPENAQ_API_KEY=your-api-key\",\n        \"ghcr.io/cyanheads/openaq-mcp-server:latest\"\n      ]\n    }\n  }\n}\n```\n\nAdd `\"CANVAS_PROVIDER_TYPE\": \"duckdb\"` to `env` to enable DataCanvas SQL over large measurement series.\n\nFor Streamable HTTP, set the transport and start the server:\n\n```sh\nMCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 OPENAQ_API_KEY=your-api-key bun run start:http\n# Server listens at http://localhost:3010/mcp\n```\n\n### Prerequisites\n\n- [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).\n- A free OpenAQ v3 API key from an [OpenAQ Explorer](https://explore.openaq.org/) account.\n\n### Installation\n\n1. **Clone the repository:**\n\n```sh\ngit clone https://github.com/cyanheads/openaq-mcp-server.git\n```\n\n2. **Navigate into the directory:**\n\n```sh\ncd openaq-mcp-server\n```\n\n3. **Install dependencies:**\n\n```sh\nbun install\n```\n\n4. **Configure environment:**\n\n```sh\ncp .env.example .env\n# edit .env and set OPENAQ_API_KEY\n```\n\n## Configuration\n\n| Variable | Description | Default |\n|:---|:---|:---|\n| `OPENAQ_API_KEY` | **Required.** OpenAQ v3 API key, sent as the `X-API-Key` header. | — |\n| `OPENAQ_API_BASE_URL` | OpenAQ v3 API base URL, for a proxy or test mirror. | `https://api.openaq.org/v3` |\n| `CANVAS_PROVIDER_TYPE` | `duckdb` stages large measurement series for SQL via the dataframe tools; without it, large series return a preview plus a notice. The `.mcpb` bundle ships without DuckDB, so use npm, npx, or Docker for canvas work. | `none` |\n| `OPENAQ_ENABLE_CANVAS_DROP` | Enable `openaq_dataframe_drop` to delete entire canvases and release their resources. Requires DuckDB; an id shared with another agent grants deletion access within the same tenant. | `false` |\n| `MCP_TRANSPORT_TYPE` | Transport: `stdio` or `http`. | `stdio` |\n| `MCP_HTTP_PORT` | HTTP server port. | `3010` |\n| `MCP_SESSION_MODE` | HTTP session mode: `stateless`, `stateful`, or `auto`. Overrides the server's explicit stateless posture; `auto` resolves to stateful. | `stateless` |\n| `MCP_AUTH_MODE` | Authentication: `none`, `jwt`, or `oauth`. | `none` |\n| `MCP_LOG_LEVEL` | Log level (`debug`, `info`, `warning`, `error`, etc.). | `info` |\n| `OTEL_ENABLED` | Enable [OpenTelemetry](https://github.com/cyanheads/mcp-ts-core/tree/main/docs/telemetry). | `false` |\n| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP base URL; traces use `/v1/traces` and metrics use `/v1/metrics`. Signal-specific endpoints override it. | — |\n| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Opt into OTLP log export with a full endpoint URL. The base endpoint never enables logs. | — |\n| `LOG_TOOL_FAILURE_PAYLOADS` | Log failed calls' arguments and results. Redacts by key name only; secrets in free-form values remain. | `false` |\n| `LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES` | UTF-8 byte cap per logged failure payload. | `16384` |\n\nSee [`.env.example`](./.env.example) for the full list of optional overrides.\n\n## Running the server\n\n### Local development\n\n- **Build and run:**\n\n  ```sh\n  bun run rebuild\n  bun run start:http   # or start:stdio\n  ```\n\n- **Run checks and tests:**\n\n  ```sh\n  bun run devcheck   # Lint, format, typecheck, security, changelog sync\n  bun run test       # Vitest test suite\n  bun run lint:mcp   # Validate MCP definitions against spec\n  ```\n\n### Docker\n\n```sh\ndocker build -t openaq-mcp-server .\ndocker run --rm -e OPENAQ_API_KEY=your-api-key -p 3010:3010 openaq-mcp-server\n```\n\nThe image defaults to HTTP transport, stateless session mode, and logs to `/var/log/openaq-mcp-server`. DuckDB ships in the image, so DataCanvas works once `CANVAS_PROVIDER_TYPE=duckdb` is set. OpenTelemetry peer dependencies are installed by default; build with `--build-arg OTEL_ENABLED=false` to omit them.\n\n## Project structure\n\n| Directory | Purpose |\n|:---|:---|\n| `src/index.ts` | `createApp()` entry point: registers tools and resources, wires the service and canvas. |\n| `src/config` | Server-specific environment variable parsing and validation with Zod. |\n| `src/mcp-server/tools` | Tool definitions (`definitions/*.tool.ts`) and shared input, error, and format helpers (`shared/`). |\n| `src/mcp-server/resources` | Resource definitions (`definitions/*.resource.ts`). |\n| `src/services` | OpenAQ v3 client and domain types (`openaq/`), plus the DataCanvas accessor. |\n| `tests/` | Unit and integration tests mirroring `src/`. |\n\n## Development guide\n\nSee [`CLAUDE.md`](./CLAUDE.md) / [`AGENTS.md`](./AGENTS.md) for development guidelines and architectural rules. The short version:\n\n- Handlers throw, framework catches — catch only to map a failure to a declared error reason or to keep a partial result\n- Use `ctx.log` for request-scoped logging, `ctx.state` for tenant-scoped storage\n- Register new tools and resources in the `createApp()` arrays\n- Wrap the OpenAQ API: validate raw → normalize to the domain type → return the output schema; surface units verbatim and never fabricate missing fields\n\n## Contributing\n\nIssues are welcome. Run checks and tests before submitting:\n\n```sh\nbun run devcheck\nbun run test\n```\n\n## License\n\nApache-2.0 — see [LICENSE](./LICENSE) for details.\n\nData comes from the [OpenAQ](https://openaq.org) platform, and attribution to OpenAQ is required when using this server's output ([Terms of Use](https://docs.openaq.org/about/terms)). OpenAQ aggregates measurements from government agencies, research institutions, and other networks, each of which may set its own attribution or licensing terms. The `provider` field on `openaq_find_locations`, `openaq_get_readings`, and `openaq_get_measurements` results and the `openaq://location/{locationId}` resource names the originating network; review and follow the terms of any provider whose data you use.\n","readmeFilename":"README.md"}