Query FEMA disaster declarations, public assistance grants, housing aid, and NFIP claims.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh 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.
Canvas ID from the fema_search_nfip response.
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.
| Argument | Type | Description |
|---|---|---|
| canvas_id* | string | Canvas ID from the fema_search_nfip response. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"canvas_id"
],
"properties": {
"canvas_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{10}$",
"description": "Canvas ID from the fema_search_nfip response."
}
},
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| query* | string | SQL SELECT statement to run against the staged table. Use the table name from fema_dataframe_describe. Results are capped at the canvas row limit and at 100,000 characters of rows; append LIMIT/OFFSET, under an ORDER BY, to page through additional rows, or aggregate (GROUP BY, COUNT, SUM) to summarize the full set in one query. Example: "SELECT year_of_loss, COUNT(*) AS claims, SUM(amount_paid_building) AS total_building_paid FROM df_nfip_abc123 GROUP BY year_of_loss ORDER BY year_of_loss" |
| canvas_id* | string | Canvas ID from the fema_search_nfip response (the canvas_id field). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"canvas_id",
"query"
],
"properties": {
"query": {
"type": "string",
"description": "SQL SELECT statement to run against the staged table. Use the table name from fema_dataframe_describe. Results are capped at the canvas row limit and at 100,000 characters of rows; append LIMIT/OFFSET, under an ORDER BY, to page through additional rows, or aggregate (GROUP BY, COUNT, SUM) to summarize the full set in one query. Example: \"SELECT year_of_loss, COUNT(*) AS claims, SUM(amount_paid_building) AS total_building_paid FROM df_nfip_abc123 GROUP BY year_of_loss ORDER BY year_of_loss\""
},
"canvas_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{10}$",
"description": "Canvas ID from the fema_search_nfip response (the canvas_id field)."
}
},
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| disaster_number* | integer | FEMA disaster number (e.g., 4781). Obtain from fema_search_disasters. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"disaster_number"
],
"properties": {
"disaster_number": {
"type": "integer",
"maximum": 9007199254740991,
"description": "FEMA disaster number (e.g., 4781). Obtain from fema_search_disasters.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}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.
| Argument | Type | Description |
|---|---|---|
| type | string | Which housing assistance dataset to query: owners, renters, or both (default). |
| limit | integer | Maximum records per dataset to return (1–10000, default 100). A page also stops at 100,000 characters of owner and renter records together, cutting both datasets at the same row count; when either bound leaves matching records out, next_offset names the offset to continue from. |
| state | string | Two-letter state code to narrow results when a disaster spans multiple states. |
| county | string | Filter by county name (e.g., Harris, dekalb). Case-insensitive substring match: harris also matches Harrison. OpenFEMA stores the county with its type, such as Harris (County) or Evangeline (Parish), and as the applicant reported it. |
| offset |
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.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Maximum number of projects to return (1–10000, default 100). A page also stops at 100,000 characters of projects (roughly 220 projects); when either bound leaves matching projects out, next_offset names the offset to continue from. |
| state | string | Two-letter state code to browse all PA projects for a state. |
| county | string | Filter by county name (e.g., Harris, dekalb). Case-insensitive substring match: harris also matches Harrison. |
| offset | integer | Pagination offset (default 0). Pass the previous page’s next_offset to continue. |
| disaster_number | integer | FEMA disaster number to scope results to a single declaration. Numbers above 32767 match no declaration. |
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.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Maximum records to return (1–10000, default 100). A page also stops at 100,000 characters of records; when either bound leaves matching records out, next_offset names the offset to continue from. |
| filter | string | OData $filter expression (e.g., "state eq 'TX' and declarationDate ge '2024-01-01T00:00:00.000Z'"). String values in single quotes. For a list of values use field in ('a','b'): OpenFEMA rejects filters nested more than 100 levels deep (about 90 chained and/or comparisons) and request URLs past about 8,900 characters. |
| offset | integer | Pagination offset (default 0). Pass the previous page’s next_offset to continue. |
| select | string | Comma-separated field names to return (e.g., "disasterNumber,state,declarationDate"). |
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.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Maximum number of unique disaster declarations to return (1–1000, default 50). A page also stops at 100,000 characters of declarations (roughly 290 declarations, about 190 with county); when either bound leaves matching declarations out, next_offset names the offset to continue from. |
| state | string | Two-letter US state/territory code (e.g., TX, CA, FL, PR). Filters by state. |
| county | string | Filter by designated area / county name (e.g., Harris, Los Angeles, dekalb). Case-insensitive substring match: harris also matches Harrison. Selects the declarations that designated a matching area; designated_area_count and the program flags still describe the whole declaration, and matched_areas lists the matching areas. |
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.
| Argument | Type | Description |
|---|---|---|
| limit | integer | Maximum claims to return inline (1–10000, default 1000). A page also stops at 100,000 characters of claims (roughly 330 claims); when either bound leaves matching claims out, next_offset names the offset to continue from. When DataCanvas is enabled and the match exceeds that character budget, a call at offset 0 stages the match on a canvas regardless of this value. |
| state* | string | Two-letter US state code (required). NFIP dataset is 2.7M rows — state filter is mandatory. |
| offset | integer | Pagination offset into the matching claims, ordered newest date of loss first (default 0). Pass the previous page’s next_offset to continue. Only a call at offset 0 stages a match on a canvas; a later offset returns just its inline page. After a spill (spilled=true), read rows past the inline claims from the canvas table with fema_dataframe_query. |
| integer |
| Pagination offset into each queried dataset (default 0). Pass the previous page’s next_offset to continue both. |
| zip_code | any | Filter by 5-digit ZIP code, as a string with leading zeros kept (e.g., 77084, 00609). ZIP+4 is not accepted. One ZIP can return several records, one per county and city spelling. |
| disaster_number* | integer | FEMA disaster number. Obtain from fema_search_disasters. Numbers above 32767 match no declaration. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"disaster_number"
],
"properties": {
"type": {
"enum": [
"owners",
"renters",
"both"
],
"type": "string",
"default": "both",
"description": "Which housing assistance dataset to query: owners, renters, or both (default)."
},
"limit": {
"type": "integer",
"default": 100,
"maximum": 10000,
"minimum": 1,
"description": "Maximum records per dataset to return (1–10000, default 100). A page also stops at 100,000 characters of owner and renter records together, cutting both datasets at the same row count; when either bound leaves matching records out, next_offset names the offset to continue from."
},
"state": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Two-letter state code to narrow results when a disaster spans multiple states."
},
"county": {
"type": "string",
"description": "Filter by county name (e.g., Harris, dekalb). Case-insensitive substring match: harris also matches Harrison. OpenFEMA stores the county with its type, such as Harris (County) or Evangeline (Parish), and as the applicant reported it."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset into each queried dataset (default 0). Pass the previous page’s next_offset to continue both."
},
"zip_code": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"pattern": "^\\d{5}$",
"description": "5-digit ZIP code."
}
],
"description": "Filter by 5-digit ZIP code, as a string with leading zeros kept (e.g., 77084, 00609). ZIP+4 is not accepted. One ZIP can return several records, one per county and city spelling."
},
"disaster_number": {
"type": "integer",
"maximum": 9007199254740991,
"description": "FEMA disaster number. Obtain from fema_search_disasters. Numbers above 32767 match no declaration.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"default": 100,
"maximum": 10000,
"minimum": 1,
"description": "Maximum number of projects to return (1–10000, default 100). A page also stops at 100,000 characters of projects (roughly 220 projects); when either bound leaves matching projects out, next_offset names the offset to continue from."
},
"state": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Two-letter state code to browse all PA projects for a state."
},
"county": {
"type": "string",
"description": "Filter by county name (e.g., Harris, dekalb). Case-insensitive substring match: harris also matches Harrison."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset (default 0). Pass the previous page’s next_offset to continue."
},
"disaster_number": {
"type": "integer",
"maximum": 9007199254740991,
"description": "FEMA disaster number to scope results to a single declaration. Numbers above 32767 match no declaration.",
"exclusiveMinimum": 0
}
},
"additionalProperties": false
}| dataset* | string | OpenFEMA dataset entity name (case-sensitive, e.g., NfipPolicies, FemaWebDeclarationAreas, PublicAssistanceApplicants). |
| orderby | string | OData $orderby expression (e.g., "declarationDate desc"). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"dataset"
],
"properties": {
"limit": {
"type": "integer",
"default": 100,
"maximum": 10000,
"minimum": 1,
"description": "Maximum records to return (1–10000, default 100). A page also stops at 100,000 characters of records; when either bound leaves matching records out, next_offset names the offset to continue from."
},
"filter": {
"type": "string",
"description": "OData $filter expression (e.g., \"state eq 'TX' and declarationDate ge '2024-01-01T00:00:00.000Z'\"). String values in single quotes. For a list of values use field in ('a','b'): OpenFEMA rejects filters nested more than 100 levels deep (about 90 chained and/or comparisons) and request URLs past about 8,900 characters."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset (default 0). Pass the previous page’s next_offset to continue."
},
"select": {
"type": "string",
"description": "Comma-separated field names to return (e.g., \"disasterNumber,state,declarationDate\")."
},
"dataset": {
"type": "string",
"minLength": 1,
"description": "OpenFEMA dataset entity name (case-sensitive, e.g., NfipPolicies, FemaWebDeclarationAreas, PublicAssistanceApplicants)."
},
"orderby": {
"type": "string",
"description": "OData $orderby expression (e.g., \"declarationDate desc\")."
}
},
"additionalProperties": false
}| offset | integer | Pagination offset in declarations (default 0). Pass the previous page’s next_offset to continue. |
| date_to | any | End of the declaration date range as a calendar date in YYYY-MM-DD format (e.g., 2024-12-31). Inclusive; equal to date_from for a single day. |
| date_from | any | Start of the declaration date range as a calendar date in YYYY-MM-DD format (e.g., 2024-01-01). Inclusive; not after date_to. |
| incident_type | string | Incident type filter (e.g., Flood, Hurricane, Tornado, Fire, Earthquake, Severe Storm). Case-insensitive substring match: storm also matches Snowstorm and Winter Storm. |
| declaration_type | string | Declaration type: DR (major disaster declaration), EM (emergency declaration), FM (fire management assistance declaration). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 1000,
"minimum": 1,
"description": "Maximum number of unique disaster declarations to return (1–1000, default 50). A page also stops at 100,000 characters of declarations (roughly 290 declarations, about 190 with county); when either bound leaves matching declarations out, next_offset names the offset to continue from."
},
"state": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Two-letter US state/territory code (e.g., TX, CA, FL, PR). Filters by state."
},
"county": {
"type": "string",
"description": "Filter by designated area / county name (e.g., Harris, Los Angeles, dekalb). Case-insensitive substring match: harris also matches Harrison. Selects the declarations that designated a matching area; designated_area_count and the program flags still describe the whole declaration, and matched_areas lists the matching areas."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset in declarations (default 0). Pass the previous page’s next_offset to continue."
},
"date_to": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
"description": "Calendar date, YYYY-MM-DD."
}
],
"description": "End of the declaration date range as a calendar date in YYYY-MM-DD format (e.g., 2024-12-31). Inclusive; equal to date_from for a single day."
},
"date_from": {
"anyOf": [
{
"type": "string",
"const": ""
},
{
"type": "string",
"format": "date",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$",
"description": "Calendar date, YYYY-MM-DD."
}
],
"description": "Start of the declaration date range as a calendar date in YYYY-MM-DD format (e.g., 2024-01-01). Inclusive; not after date_to."
},
"incident_type": {
"type": "string",
"description": "Incident type filter (e.g., Flood, Hurricane, Tornado, Fire, Earthquake, Severe Storm). Case-insensitive substring match: storm also matches Snowstorm and Winter Storm."
},
"declaration_type": {
"enum": [
"DR",
"EM",
"FM"
],
"type": "string",
"description": "Declaration type: DR (major disaster declaration), EM (emergency declaration), FM (fire management assistance declaration)."
}
},
"additionalProperties": false
}| year_to | integer | End year of loss, inclusive (e.g., 2023). Equal to year_from for a single year. |
| zip_code | string | ZIP code to narrow results to a specific area (5-digit, e.g., 77002). |
| canvas_id | string | Optional canvas ID from a prior call, to stage this match as another table on that canvas. Used only when the match is staged; omit it to stage on a fresh canvas. Pass the returned canvas_id to fema_dataframe_describe for the table columns, then to fema_dataframe_query for SQL. |
| year_from | integer | Start year of loss, inclusive (e.g., 2020). Not after year_to. |
| county_code | string | County FIPS code to narrow results within the state: the full 5-digit state+county code (e.g., 48201 for Harris County TX), or the 3-digit county part (e.g., 201), to which the server prepends the state FIPS. A shorter county part is zero-padded to 3 digits (1 → 001), and a 4-digit code is zero-padded to 5 (1001 → 01001), the form a numeric 01001 arrives in. Any other value is rejected before the search runs. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"state"
],
"properties": {
"limit": {
"type": "integer",
"default": 1000,
"maximum": 10000,
"minimum": 1,
"description": "Maximum claims to return inline (1–10000, default 1000). A page also stops at 100,000 characters of claims (roughly 330 claims); when either bound leaves matching claims out, next_offset names the offset to continue from. When DataCanvas is enabled and the match exceeds that character budget, a call at offset 0 stages the match on a canvas regardless of this value."
},
"state": {
"type": "string",
"maxLength": 2,
"minLength": 2,
"description": "Two-letter US state code (required). NFIP dataset is 2.7M rows — state filter is mandatory."
},
"offset": {
"type": "integer",
"default": 0,
"maximum": 9007199254740991,
"minimum": 0,
"description": "Pagination offset into the matching claims, ordered newest date of loss first (default 0). Pass the previous page’s next_offset to continue. Only a call at offset 0 stages a match on a canvas; a later offset returns just its inline page. After a spill (spilled=true), read rows past the inline claims from the canvas table with fema_dataframe_query."
},
"year_to": {
"type": "integer",
"maximum": 2100,
"minimum": 1970,
"description": "End year of loss, inclusive (e.g., 2023). Equal to year_from for a single year."
},
"zip_code": {
"type": "string",
"pattern": "^\\d{5}$",
"description": "ZIP code to narrow results to a specific area (5-digit, e.g., 77002)."
},
"canvas_id": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{10}$",
"description": "Optional canvas ID from a prior call, to stage this match as another table on that canvas. Used only when the match is staged; omit it to stage on a fresh canvas. Pass the returned canvas_id to fema_dataframe_describe for the table columns, then to fema_dataframe_query for SQL."
},
"year_from": {
"type": "integer",
"maximum": 2100,
"minimum": 1970,
"description": "Start year of loss, inclusive (e.g., 2020). Not after year_to."
},
"county_code": {
"type": "string",
"description": "County FIPS code to narrow results within the state: the full 5-digit state+county code (e.g., 48201 for Harris County TX), or the 3-digit county part (e.g., 201), to which the server prepends the state FIPS. A shorter county part is zero-padded to 3 digits (1 → 001), and a 4-digit code is zero-padded to 5 (1001 → 01001), the form a numeric 01001 arrives in. Any other value is rejected before the search runs."
}
},
"additionalProperties": false
}