关于 fema-mcp-server
fema-mcp-server 面向灾害研究者和公共部门分析人员,提供 FEMA 灾害声明、公共援助、住房援助和 NFIP 理赔数据查询。它还支持 OpenFEMA 数据集查询,并可对暂存的理赔结果运行 SQL。
主要功能
- 01按州、类型和日期搜索灾害声明
- 02查看灾害指定区域与项目标记
- 03查询公共援助项目及拨款
- 04查询住房援助与 NFIP 理赔
- 05对暂存理赔数据运行只读 SQL
适用场景
- 01查找某州或某类灾害声明
- 02梳理灾害的公共援助资金去向
- 03查看县或邮编层级的住房援助
- 04分析指定地区的洪水保险理赔
MCP 相关
作为 MCP 服务,它通过 STDIO 或 Streamable HTTP 提供灾害、援助和理赔查询工具,以及灾害摘要资源;大型 NFIP 结果可暂存并用 SQL 查询。OpenFEMA API 无需密钥。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://fema.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-fema https://fema.caseyjhand.com/mcp{"mcpServers":{"cyanheads-fema":{"type":"http","url":"https://fema.caseyjhand.com/mcp"}}}在 Cursor 中打开{"servers":{"cyanheads-fema":{"type":"http","url":"https://fema.caseyjhand.com/mcp"}}}在 VS Code 中打开{"mcpServers":{"cyanheads-fema":{"type":"http","url":"https://fema.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-fema":{"serverUrl":"https://fema.caseyjhand.com/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
8| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | integer | 否 | 要返回的唯一灾害声明的最大数量(1–1000,默认值为 50)。每页还受 100,000 个声明字符的限制(约 290 条声明;包含县时约 190 条);任一上限导致仍有匹配声明未返回时,next_offset 会提供继续查询的偏移量。 |
| state | string | 否 | 美国州/领地的两字母代码(例如 TX、CA、FL、PR)。按州筛选。 |
| county | string | 否 | 按指定区域/县名称筛选(例如 Harris、Los Angeles、dekalb)。不区分大小写的子字符串匹配:harris 也会匹配 Harrison。选择指定区域匹配的声明;designated_area_count 和程序标志仍描述整个声明,matched_areas 列出匹配的区域。 |
| offset | integer | 否 | 声明中的分页偏移量(默认值为 0)。传入上一页的 next_offset 以继续。 |
| date_to | any | 否 | 声明日期范围的结束日期,格式为 YYYY-MM-DD 的日历日期(例如 2024-12-31)。包含该日期;查询单日时,将其设为与 date_from 相同。 |
| date_from | any | 否 | 声明日期范围的开始日期,格式为 YYYY-MM-DD 的日历日期(例如 2024-01-01)。包含该日期;不得晚于 date_to。 |
| incident_type | string | 否 | 事件类型筛选条件(例如 Flood、Hurricane、Tornado、Fire、Earthquake、Severe Storm)。不区分大小写的子字符串匹配:storm 也会匹配 Snowstorm 和 Winter Storm。 |
| declaration_type | enum | 否 | 声明类型:DR(重大灾害声明)、EM(紧急情况声明)、FM(火灾管理援助声明)。DR | EM | FM |
详细介绍
@cyanheads/fema-mcp-server
通过 MCP 查询 FEMA 灾害声明、公共援助拨款、住房援助和 NFIP 洪水保险理赔。支持 STDIO 或 Streamable HTTP。
公共托管服务: https://fema.caseyjhand.com/mcp
概述
来自 FEMA 的联邦灾害恢复数据:灾害声明、公共援助拨款、个人住房援助和 NFIP 洪水保险理赔。按州或事件搜索声明,查看任何灾害对应的公共援助和住房援助,并对大量洪水理赔结果集运行 SQL。
工具
| 工具 | 描述 |
|---|---|
fema_search_disasters | 按州、事件类型、声明类型、日期范围和县搜索联邦灾害声明 |
fema_get_disaster | 获取特定灾害最多 1,000 条指定区域记录,并说明覆盖不完整的情况 |
fema_get_public_assistance | 获取某场灾害或某个州的公共援助资助项目——了解联邦救灾资金的去向 |
fema_get_housing_assistance | 获取某场灾害的个人住房援助数据——按县或 ZIP 查看房主和租户细分情况及检查数量,并可按县或 ZIP 筛选 |
fema_search_nfip | 按州、县或 ZIP 搜索 NFIP 洪水保险理赔数据,可选启用 DataCanvas 溢出,以进行 SQL 分析 |
fema_dataframe_describe | 列出由 fema_search_nfip 暂存的 DataCanvas 表的列和行数 |
fema_dataframe_query | 对由 fema_search_nfip 暂存的 DataCanvas 表运行 SELECT 查询 |
fema_dataframe_drop | 移除暂存的 DataCanvas 表或视图——需主动启用,默认不显示在 tools/list 中 |
fema_query_dataset | 对 OpenFEMA 目录中的任意数据集运行通用 OData 查询——用于查询便捷工具未涵盖的数据集 |
fema_dataframe_drop 需主动启用:只有在 FEMA_ENABLE_CANVAS_DROP=true 时才会显示在 tools/list 中。其他八种工具始终会列出。
资源
| 资源 | 描述 |
|---|---|
fema://disaster/{disasterNumber} | 特定 FEMA 灾害声明的摘要——标题、州、事件类型、计划和事件期间 |
所有资源数据也可通过工具获取。若要查看指定区域详情(最多 1,000 行),请使用 fema_get_disaster。
功能参考
fema_search_disasters 工具
- 筛选条件:
state、incident_type、declaration_type(DR/EM/FM)、包含首尾日期的date_from/date_to(YYYY-MM-DD)和county。incident_type和county使用不区分大小写的子字符串匹配。使用limit(1–1000,默认值为 50)和offset分页;单页达到 100,000 个字符时会停止,next_offset会指出续查位置。 - 每个灾害编号返回一条摘要,包含
designated_area_count、计划标记和声明总额。指定county时,total_area_rows和matched_areas(FIPS 代码及各区域标记)会显示匹配的区域。错误:invalid_state、invalid_range(date_from晚于date_to)、request_too_long。 - 搜索最近的 10,000 条指定区域记录。达到上限时,结果会标记为
truncated,总数为下限,notice会指出下一个date_to。
fema_get_disaster 工具
- 需要提供来自
fema_search_disasters的disaster_number。 - 返回最多 1,000 条指定区域记录、FIPS 代码、事件期间,以及根据已获取区域汇总的计划标记;若找不到灾害,则返回
not_found。存在更多记录时,areas_truncated、total_designated_area_count和notice会说明覆盖不完整。未获取行中的计划不会因标记为 false 而被排除;如需查询完整声明,请使用fema_query_dataset。
fema_get_public_assistance 工具
- 需要提供
disaster_number或state;可选参数包括county(不区分大小写的子字符串)、limit(1–10000,默认值为 100)和offset。单页达到 100,000 个字符时会停止;next_offset会指出续查位置。 - 返回申请人、损害类别、项目规模/状态,以及联邦和总承诺金额。错误:
invalid_state、missing_filter、not_found、request_too_long。
fema_get_housing_assistance 工具
- 必需参数:
disaster_number;可选参数:state、county(不区分大小写的子字符串)、zip_code(5 位数字)、type(owners/renters/both,默认为both)、limit(1–10000,默认为 100)和offset。单页内容达到 100,000 个字符时会停止;一个next_offset可同时继续获取业主和租户数据。 - 返回分别包含业主和租户数据的
owners和renters数组,其中包含按县/邮政编码统计的登记数、批准金额和检查次数,以及owners_count/renters_count。业主数据还包含以美元计的已检查损失;租户数据仅包含损失程度计数。错误:invalid_state、not_found、request_too_long。
fema_search_nfip 工具
- 必需参数:
state;可选参数:county_code(5 位 FIPS 代码,如48201;或会自动添加州前缀的 3 位代码,如201)、zip_code、year_from/year_to、limit(1–10000,默认为 1000)和offset。结果按损失时间从新到旧排列。 - 内联理赔数据达到 100,000 个字符时会停止;
next_offset和notice会说明如何继续。错误:invalid_state、invalid_county_code(非 1–5 位数字,或用于 FM、MH、PW 的短代码)、invalid_range(year_from晚于year_to)。 - 按县搜索时,会在同一州和年份范围内检查没有县代码的理赔数据,使用一次仅计数的请求,不重试,截止时间为两秒。只有当主页面的数据已就绪时,响应才会使用该计数;否则会说明未检查覆盖情况。这些理赔数据无法分配到所选县或邮政编码。移除
county_code并视情况搜索已知邮政编码可能会有所帮助;邮政编码搜索结果不保证完整,也不一定等同于县级结果。 - 当
CANVAS_PROVIDER_TYPE=duckdb时,如果第一页的匹配结果超过内联限制,系统会暂存最多 50,000 行。canvas_id、canvas_table和staged_count用于标识暂存数据,truncated: true表示已达到上限,total_count是完整匹配数。使用fema_dataframe_describe查看数据,然后使用fema_dataframe_query查询。
fema_dataframe_describe 工具
- 需要来自
fema_search_nfip的canvas_id。 - 列出表/视图名称、列类型、是否可为空以及暂存行数。类型化错误:
canvas_not_found、canvas_unavailable。
fema_dataframe_query 工具
- 需要
canvas_id和单条 SQLquery;仅允许 SELECT。 - 行数受画布行数上限限制,内容上限为 100,000 个字符;结果被截断时会显示
truncated/shown和 OFFSET 使用说明。错误:canvas_unavailable、canvas_not_found、missing_table、invalid_sql、non_select_statement、multi_statement、denied_function、plan_operator_not_allowed、sql_read_only、sql_execution_error(使用TRY_CAST或筛选不兼容的值)。
fema_dataframe_drop 工具
- 需要
canvas_id和来自fema_dataframe_describe的准确table_name。 - 移除一个暂存表或视图;
dropped: false表示该名称不存在。错误:canvas_not_found、canvas_unavailable。 - 通过
FEMA_ENABLE_CANVAS_DROP=true启用。
fema_query_dataset 工具
- 需要区分大小写的 OpenFEMA
dataset;可选参数:ODatafilter/select/orderby、limit(1–10000,默认为 100)和offset。单页内容达到 100,000 个字符时会停止;next_offset会说明从何处继续。 - 返回记录和
total_count。错误:unknown_dataset、dataset_not_served、catalog_unavailable(可重试)、invalid_filter、invalid_select、invalid_orderby、invalid_odata_syntax、request_too_long(URL 超过约 8,900 个字符)、filter_too_complex(嵌套超过 100 层)。 - 对于值列表,使用
field in ('a','b'),而不是链式or比较(约允许 90 个值)。对于NfipPolicies,使用propertyState和reportedZipCode,并始终包含邮政编码筛选条件,以避免超时。
fema://disaster/{disasterNumber} 资源
disasterNumber必须是由数字组成的字符串。- 返回标题、州、事件类型、声明类型/日期、事件期间、
programs_declared和获取到的designated_area_count(最多 500)。如果还有更多行,摘要会包含areas_truncated、total_designated_area_count和notice:计划仅描述已获取的行,空列表并不能证明相关内容不存在。使用fema_query_dataset获取完整行。not_found会指向fema_search_disasters。
功能
基于 @cyanheads/mcp-ts-core 构建:支持 stdio 和 Streamable HTTP 传输、可插拔身份验证(none / jwt / oauth)、可切换存储(in-memory、filesystem、Supabase、Cloudflare KV/R2/D1),以及支持可选 OpenTelemetry 跟踪的结构化日志记录。
OpenFEMA 专属功能:
- 县和事件类型筛选器不区分大小写,使用随附的声明名称以及 PA 县的精确拼写。使用
bun run vocabulary:build刷新:顺序完整导出会按 ID 顺序读取声明,并在不排序的情况下读取非空 PA 县数据,同时进行有界的瞬时错误重试。每次导出都必须与其报告的数量一致;刷新失败或不完整时,快照保持不变。 DisasterDeclarationsSummaries行会合并为每项声明一条摘要,并包含designated_area_countfema_search_nfip要求提供state,以避免获取无界的 270 万行数据- 大型 NFIP 结果集会溢出到 DuckDB 表中,你可以通过 DataCanvas 使用 SQL 查询这些表
- 无需 API 密钥 — OpenFEMA 是免费的公共 API
便于 Agent 使用的输出:
- 灾害编号是各工具之间的关联键,因此调用可以串联进行,无需重复搜索
- 空搜索会在两个响应界面中返回空数组、零总数和包含筛选条件提示的
notice;援助调用可以使用fema_get_disaster检查已声明的计划。总数非零时,翻页超出范围会提供单独的偏移量提示。 - 每个工具都会返回类型化错误(
invalid_state、invalid_county_code、invalid_range、not_found、missing_filter、unknown_dataset、dataset_not_served、invalid_filter、invalid_select、invalid_orderby、invalid_odata_syntax、request_too_long、filter_too_complex、canvas_unavailable),且每种错误都附带恢复提示 - 搜索结果中的
designated_area_count会显示是否值得继续调用fema_get_disaster
开始使用
公共托管实例
可使用公共实例:https://fema.caseyjhand.com/mcp — 无需安装。通过 Streamable HTTP 将任意 MCP 客户端指向该实例:
{
"mcpServers": {
"fema-mcp-server": {
"type": "streamable-http",
"url": "https://fema.caseyjhand.com/mcp"
}
}
}
自托管 / 本地运行
将以下内容添加到 MCP 客户端配置文件中。
{
"mcpServers": {
"fema-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/fema-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
或者使用 npx(无需 Bun):
{
"mcpServers": {
"fema-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/fema-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
或者使用 Docker:
{
"mcpServers": {
"fema-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/fema-mcp-server:latest"
]
}
}
}
对于 Streamable HTTP,设置传输方式并启动服务:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
如需为 NFIP Claims 启用由 DuckDB 驱动的 SQL 分析:
{
"mcpServers": {
"fema-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/fema-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"CANVAS_PROVIDER_TYPE": "duckdb"
}
}
}
}
先决条件
- Bun v1.4.0 或更高版本(或 Node.js v24+)。
- 无需 API 密钥 — OpenFEMA 是免费的公共 API。
- 可选:设置
CANVAS_PROVIDER_TYPE=duckdb,以便对大型 NFIP Claims 结果集启用 SQL 分析。
安装
- 克隆仓库:
git clone https://github.com/cyanheads/fema-mcp-server.git
- 进入目录:
cd fema-mcp-server
- 安装依赖项:
bun install
- 配置环境:
cp .env.example .env
# edit .env — no required vars, but CANVAS_PROVIDER_TYPE=duckdb enables SQL analytics
配置
所有配置都会在启动时通过 src/config/server-config.ts 中的 Zod 模式进行验证。主要环境变量:
| 变量 | 描述 | 默认值 |
|---|---|---|
FEMA_BASE_URL | OpenFEMA API 根地址。 | https://www.fema.gov/api/open |
FEMA_REQUEST_TIMEOUT_MS | 单次上游请求(包括重试)的总时间预算,单位为毫秒。 | 30000 |
CANVAS_PROVIDER_TYPE | 设置为 duckdb 以启用针对 NFIP 理赔的 DataCanvas SQL 分析。 | — |
FEMA_ENABLE_CANVAS_DROP | 启用 fema_dataframe_drop 工具。 | false |
MCP_TRANSPORT_TYPE | 传输方式:stdio 或 http。 | stdio |
MCP_SESSION_MODE | 会话模式:auto、stateful 或 stateless。 | stateless |
MCP_HTTP_PORT | HTTP 服务端口。 | 3010 |
MCP_AUTH_MODE | 身份验证模式:none、jwt 或 oauth。 | none |
MCP_LOG_LEVEL | 日志级别(debug、info、warning、error 等)。 | info |
LOG_TOOL_FAILURE_PAYLOADS | 记录失败调用的参数和结果,并按键名进行脱敏。自由格式值中的机密信息会保留。 | false |
LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES | 每条日志载荷的字节上限。 | 16384 |
OTEL_EXPORTER_OTLP_ENDPOINT | 用于跟踪和指标的 OTLP 基础 URL。 | — |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT | 跟踪端点,按原样使用。 | — |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT | 指标端点,按原样使用。 | — |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | 日志导出端点;仅在设置此项时才会导出日志。 | — |
LOGS_DIR | 日志文件目录(仅限 Node.js)。 | <project-root>/logs |
OTEL_ENABLED | 启用 OpenTelemetry 检测。 | false |
完整的可选覆盖项列表请参见 .env.example。
运行服务
本地开发
-
构建并运行:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
运行检查和测试:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t fema-mcp-server .
docker run --rm -e MCP_TRANSPORT_TYPE=stdio fema-mcp-server
Dockerfile 默认使用 HTTP 传输、无状态会话模式,并将日志写入 /var/log/fema-mcp-server。默认会安装 OpenTelemetry 对等依赖;构建时使用 --build-arg OTEL_ENABLED=false 可省略这些依赖。
项目结构
| 目录 | 用途 |
|---|---|
src/index.ts | createApp() 入口点——注册工具和资源,并初始化服务。 |
src/config | 解析并验证服务专用环境变量,使用 Zod 进行验证。 |
src/mcp-server/tools | 工具定义(*.tool.ts)——每个工具对应一个文件。 |
src/mcp-server/resources | 资源定义(*.resource.ts)。 |
src/services/openfema | OpenFEMA REST API 客户端,以及不区分大小写的名称匹配器及其内置名称词汇表。 |
src/services/canvas | DataCanvas 集成——使用 DuckDB 处理较大的 NFIP 结果集。 |
tests/ | 与 src/ 结构对应的单元测试和集成测试。 |
开发指南
开发指南和架构规则请参见 CLAUDE.md。简要说明:
- 处理器抛出异常,框架负责捕获——工具逻辑中不要使用
try/catch - 使用
ctx.log记录请求级日志,使用ctx.state存储租户级数据 - 在
src/index.ts中注册新工具和资源 - 封装外部 API 调用:验证原始数据 → 规范化为领域类型 → 返回输出模式;绝不伪造缺失字段
贡献
欢迎提交问题。提交前请运行检查和测试:
bun run devcheck
bun run test
数据源
数据由 OpenFEMA API 提供。这是由联邦紧急事务管理局维护的免费公共 API。使用须遵守 OpenFEMA 条款和条件。
本产品使用联邦紧急事务管理局的 OpenFEMA API,但并未获得 FEMA 背书。数据从该机构的网站检索后,联邦政府或 FEMA 无法保证这些数据或基于这些数据得出的分析的可靠性。
在研究或出版物中引用 OpenFEMA 数据集时,请使用 FEMA 指定的格式:
Federal Emergency Management Agency (FEMA), OpenFEMA Dataset: <name>. Retrieved from <URL> on <date>.
许可证
Apache-2.0 — 详情请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。