io. github. cyanheads/ fema-mcp-server
by cyanheads · remote · local (npm) · no sign-in to list tools · v0.4.1 · published by GitHub user cyanheads
Query FEMA disaster declarations, public assistance grants, housing aid, and NFIP claims.
8 tools: 1 change things and 7 only read.
Scanned Oct 21, 2026
- Deletes or cancels0Claude Code: deny
- Can't be undone0Claude Code: ask
- Changes things1Claude Code: ask: see these tools
- Only reads7Claude Code: allow: see these tools
1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http fema https://fema.caseyjhand.com/mcpFindings
Matches of fixed checks, with the text they matched.
The server marks "fema_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "fema_dataframe_query" says "query": a word for reading.
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
8 tools
Changes things 1Claude Code: ask
fema_dataframe_queryRun a read-only SQL SELECT against a DataCanvas table staged by fema_search_nfip.1 finding
Why it is in this group
- The name "fema_dataframe_query" says "query": a word for reading.
- The description's first verb is "run": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Warn
The server marks "fema_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "fema_dataframe_query" says "query": a word for reading.
Description, as the server wrote it Run a read-only SQL SELECT against a DataCanvas table staged by fema_search_nfip. Enables aggregation, GROUP BY, SUM/COUNT, time-series, and filtered analysis over the full NFIP claims result without re-fetching from the API. Call fema_dataframe_describe first to get the exact table name and column names needed for valid SQL. Only SELECT statements are allowed — DDL, DML, COPY, and file-reading functions are blocked. A response holds at most 100,000 characters of rows; when it holds fewer rows than the query returned, truncated and shown are set and the notice says how to page with OFFSET.
Annotations the server declares
- readOnlyHint: true
- idempotentHint: true
- openWorldHint: false
Only reads 7Claude Code: allow
fema_dataframe_describeList tables and column schemas on a DataCanvas staged by fema_search_nfip.No findings
Why it is in this group
- The name "fema_dataframe_describe" says "describe": a word for reading.
Description, as the server wrote it List tables and column schemas on a DataCanvas staged by fema_search_nfip. Call this before fema_dataframe_query to discover the exact table name, column names, and DuckDB data types needed to write valid SQL. Row count reflects what was actually staged — check truncated in the fema_search_nfip response to know whether the canvas holds the full matching set.
Annotations the server declares
- readOnlyHint: true
- idempotentHint: true
- openWorldHint: false
fema_get_disasterFetch up to 1,000 designated-area rows for a specific FEMA disaster by disaster number (e.g., 4781).No findings
Why it is in this group
- The name "fema_get_disaster" says "get": a word for reading.
Description, as the server wrote it Fetch up to 1,000 designated-area rows for a specific FEMA disaster by disaster number (e.g., 4781). Discloses partial area and program coverage when more rows exist. Returns counties/municipalities along with programs observed, incident period, and state info. Use fema_search_disasters to find disaster numbers. The returned disaster_number chains to fema_get_public_assistance and fema_get_housing_assistance.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: false
fema_get_housing_assistanceRetrieve Individual Assistance (IA) housing data for a disaster by disaster number.No findings
Why it is in this group
- The name "fema_get_housing_assistance" says "get": a word for reading.
Description, as the server wrote it Retrieve Individual Assistance (IA) housing data for a disaster by disaster number. Returns owner and/or renter records aggregated by county, city, and ZIP code — valid registrations, total approved IHP amounts, repair/rental/other-needs amounts, and inspection counts (owners also carry inspected damage in USD). Narrow with state, county, or zip_code; owners_count, renters_count, and offset then count the filtered records. Use type to select owners, renters, or both (default). A page holds at most 100,000 characters of records, owners and renters cut at the same row count so one offset continues both; when records remain past it, next_offset is the offset to continue from. Use disaster_number from fema_search_disasters.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: true
fema_get_public_assistanceRetrieve Public Assistance (PA) funded project records for a disaster or state — shows where federal recovery money was obligated.No findings
Why it is in this group
- The name "fema_get_public_assistance" says "get": a word for reading.
Description, as the server wrote it Retrieve Public Assistance (PA) funded project records for a disaster or state — shows where federal recovery money was obligated. Returns applicant, damage category, project size and status, federal share obligated, and total obligated amounts. Either disaster_number or state must be provided. Use disaster_number (from fema_search_disasters) to scope to a single declaration, or state to browse all PA projects for a state. PA projects are created only when the PA program is declared (pa_declared: true on the disaster). A page holds at most 100,000 characters of projects; when projects remain past it, next_offset is the offset to continue from.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: true
fema_query_datasetGeneric OData query against any dataset in the OpenFEMA dataset catalog — the escape hatch for datasets the convenience tools do not cover (e.g., NfipPolicies, IndividualAssistance…No findings
Why it is in this group
- The name "fema_query_dataset" says "query": a word for reading.
Description, as the server wrote it Generic OData query against any dataset in the OpenFEMA dataset catalog — the escape hatch for datasets the convenience tools do not cover (e.g., NfipPolicies, IndividualAssistanceHousingRegistrantsLargeDisasters, FemaWebDeclarationAreas, PublicAssistanceApplicants). Accepts raw OData filter, select, orderby, and pagination parameters. For NfipPolicies, use propertyState (not state) for the state and reportedZipCode for the ZIP code — it has no countyCode; always include a ZIP filter to avoid timeout. The dataset name must match the exact OpenFEMA entity name (case-sensitive, e.g., NfipClaims). Names missing from the catalog return an unknown_dataset error; a listed dataset OpenFEMA does not serve through the API, or a retired version, returns dataset_not_served. A page holds at most 100,000 characters of records; when records remain past it, next_offset is the offset to continue from.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: true
fema_search_disastersSearch federal disaster declarations by state, incident type, declaration type, date range, and county.No findings
Why it is in this group
- The name "fema_search_disasters" says "search": a word for reading.
Description, as the server wrote it Search federal disaster declarations by state, incident type, declaration type, date range, and county. Returns deduplicated declaration-level summaries — each disaster number appears once with a designated_area_count showing how many counties/municipalities were designated. The disaster number is the chain key for fema_get_disaster, fema_get_public_assistance, and fema_get_housing_assistance. Use declaration_type to filter: DR (major disaster, most common), EM (emergency), FM (fire management). Date filters apply to the declaration date. Use fema_get_disaster to retrieve all designated-area rows for a specific declaration. county selects the declarations that designated a matching area; their area counts and program flags still describe the whole declaration, and matched_areas lists the matching areas with their own program flags. A search reads the most recent 10,000 designated-area rows; when more match, it returns the declarations dated after the day that window ends, sets truncated, and its notice names the date_to that continues with older declarations. A page holds at most 100,000 characters of declarations; when declarations remain past it, next_offset is the offset to continue from.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: true
fema_search_nfipSearch National Flood Insurance Program (NFIP) claims data by state, county, ZIP code, and year range.No findings
Why it is in this group
- The name "fema_search_nfip" says "search": a word for reading.
Description, as the server wrote it Search National Flood Insurance Program (NFIP) claims data by state, county, ZIP code, and year range. Returns the matching claim count and claim records — amounts paid on building and contents, damage estimates, flood zones, cause and occupancy codes, and loss dates — newest loss first. state is required — the full NFIP dataset is 2.7 million rows; unfiltered access is prohibited. Page the inline claims with limit and offset; a page holds at most 100,000 characters of claims, and while claims remain past it, next_offset is the offset to continue from. When DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) and the match exceeds that inline budget, a call at offset 0 stages the match (up to 50,000 claims) on a canvas: inspect the staged table with fema_dataframe_describe, then aggregate it with SQL via fema_dataframe_query.
Annotations the server declares
- readOnlyHint: true
- openWorldHint: true
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Install
Pinned to version 0.4.1. Values in angle brackets are yours to fill in.
claude mcp add --transport http fema https://fema.caseyjhand.com/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__fema__fema_search_disasters",
"mcp__fema__fema_get_disaster",
"mcp__fema__fema_get_public_assistance",
"mcp__fema__fema_get_housing_assistance",
"mcp__fema__fema_search_nfip",
"mcp__fema__fema_dataframe_describe",
"mcp__fema__fema_query_dataset"
],
"ask": [
"mcp__fema__fema_dataframe_query"
],
"deny": []
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as fema. Review it before you use it.
