@cyanheads/fema-mcp-server

v0.1.5 pre-1.0

Query FEMA disaster declarations, public assistance grants, housing aid, and NFIP flood insurance claims via MCP. STDIO or Streamable HTTP.

@cyanheads/fema-mcp-server
claude mcp add --transport http fema-mcp-server https://fema.caseyjhand.com/mcp
codex mcp add fema-mcp-server --url https://fema.caseyjhand.com/mcp
{
  "mcpServers": {
    "fema-mcp-server": {
      "url": "https://fema.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http fema-mcp-server https://fema.caseyjhand.com/mcp
{
  "mcpServers": {
    "fema-mcp-server": {
      "command": "bunx",
      "args": [
        "@cyanheads/fema-mcp-server@latest"
      ]
    }
  }
}
{
  "mcpServers": {
    "fema-mcp-server": {
      "type": "http",
      "url": "https://fema.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://fema.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

8

fema_search_disasters

open-world

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 designatedAreaCount 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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_search_disasters",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "state": {
      "description": "Two-letter US state/territory code (e.g., TX, CA, FL, PR). Filters by state.",
      "type": "string",
      "minLength": 2,
      "maxLength": 2
    },
    "incident_type": {
      "description": "Incident type filter (e.g., Flood, Hurricane, Tornado, Fire, Earthquake, Severe Storm). Case-insensitive substring match.",
      "type": "string"
    },
    "declaration_type": {
      "description": "Declaration type: DR (major disaster declaration), EM (emergency declaration), FM (fire management assistance declaration).",
      "type": "string",
      "enum": [
        "DR",
        "EM",
        "FM"
      ]
    },
    "date_from": {
      "description": "Start of declaration date range in ISO 8601 format (e.g., 2024-01-01). Inclusive.",
      "type": "string"
    },
    "date_to": {
      "description": "End of declaration date range in ISO 8601 format (e.g., 2024-12-31). Inclusive.",
      "type": "string"
    },
    "county": {
      "description": "Filter by designated area / county name substring (e.g., Harris, Los Angeles). Case-insensitive.",
      "type": "string"
    },
    "limit": {
      "default": 50,
      "description": "Maximum number of unique disaster declarations to return (1–1000, default 50).",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset in declarations (default 0). Use with limit to page through results.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

fema_get_disaster

Fetch all designated-area rows for a specific FEMA disaster by disaster number (e.g., 4781). Returns every county/municipality designated under the declaration along with programs activated, 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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_get_disaster",
    "arguments": {
      "disaster_number": "<disaster_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "disaster_number": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "FEMA disaster number (e.g., 4781). Obtain from fema_search_disasters."
    }
  },
  "required": [
    "disaster_number"
  ],
  "additionalProperties": false
}
view source ↗

fema_get_public_assistance

open-world

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).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_get_public_assistance",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "disaster_number": {
      "description": "FEMA disaster number to scope results to a single declaration.",
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991
    },
    "state": {
      "description": "Two-letter state code to browse all PA projects for a state.",
      "type": "string",
      "minLength": 2,
      "maxLength": 2
    },
    "county": {
      "description": "Filter by county name substring.",
      "type": "string"
    },
    "limit": {
      "default": 100,
      "description": "Maximum number of projects to return (1–1000, default 100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset (default 0).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

fema_get_housing_assistance

open-world

Retrieve Individual Assistance (IA) housing data for a disaster by disaster number. Returns owner and/or renter breakdowns by county and ZIP code — valid registrations, total approved IHP amounts, repair/rental amounts, and inspection data. Use type to select owners, renters, or both (default). Use disaster_number from fema_search_disasters.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_get_housing_assistance",
    "arguments": {
      "disaster_number": "<disaster_number>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "disaster_number": {
      "type": "integer",
      "exclusiveMinimum": 0,
      "maximum": 9007199254740991,
      "description": "FEMA disaster number. Obtain from fema_search_disasters."
    },
    "state": {
      "description": "Two-letter state code to narrow results when a disaster spans multiple states.",
      "type": "string",
      "minLength": 2,
      "maxLength": 2
    },
    "type": {
      "default": "both",
      "description": "Which housing assistance dataset to query: owners, renters, or both (default).",
      "type": "string",
      "enum": [
        "owners",
        "renters",
        "both"
      ]
    },
    "limit": {
      "default": 100,
      "description": "Maximum records per dataset to return (default 100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset (default 0).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "disaster_number",
    "type",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

fema_search_nfip

open-world

Search National Flood Insurance Program (NFIP) claims data by state, county, ZIP code, and year range. Returns claim counts, amounts paid on building and contents, flood zones, and loss years. state is required — the full NFIP dataset is 2.7 million rows; unfiltered access is prohibited. When DataCanvas is enabled (CANVAS_PROVIDER_TYPE=duckdb) and results exceed the inline preview, the full result set is staged on a canvas for SQL aggregation via fema_dataframe_query. Use fema_dataframe_describe to inspect the staged table schema before writing SQL. Without canvas, results are returned inline up to the limit.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_search_nfip",
    "arguments": {
      "state": "<state>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "state": {
      "type": "string",
      "minLength": 2,
      "maxLength": 2,
      "description": "Two-letter US state code (required). NFIP dataset is 2.7M rows — state filter is mandatory."
    },
    "county_code": {
      "description": "County code to narrow results within the state (e.g., 201 for Harris County TX). Use with state.",
      "type": "string"
    },
    "zip_code": {
      "description": "ZIP code to narrow results to a specific area.",
      "type": "string"
    },
    "year_from": {
      "description": "Start year of loss, inclusive (e.g., 2020).",
      "type": "integer",
      "minimum": 1970,
      "maximum": 2100
    },
    "year_to": {
      "description": "End year of loss, inclusive (e.g., 2023).",
      "type": "integer",
      "minimum": 1970,
      "maximum": 2100
    },
    "limit": {
      "default": 1000,
      "description": "Maximum rows to fetch (1–10000, default 1000).",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "canvas_id": {
      "description": "Optional canvas ID from a prior call. Omit to create a fresh canvas. The response returns the canvas_id to pass to fema_dataframe_query.",
      "type": "string"
    }
  },
  "required": [
    "state",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

fema_dataframe_query

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.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_dataframe_query",
    "arguments": {
      "canvas_id": "<canvas_id>",
      "query": "<query>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "canvas_id": {
      "type": "string",
      "description": "Canvas ID from the fema_search_nfip response (the canvas_id field)."
    },
    "query": {
      "type": "string",
      "description": "SQL SELECT statement to run against the staged table. Use the table name from fema_dataframe_describe. 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\""
    }
  },
  "required": [
    "canvas_id",
    "query"
  ],
  "additionalProperties": false
}
view source ↗

fema_dataframe_describe

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. The canvas holds the full NFIP claims result set — row count here is the total available for queries.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_dataframe_describe",
    "arguments": {
      "canvas_id": "<canvas_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "canvas_id": {
      "type": "string",
      "description": "Canvas ID from the fema_search_nfip response."
    }
  },
  "required": [
    "canvas_id"
  ],
  "additionalProperties": false
}
view source ↗

fema_query_dataset

open-world

Generic OData query against any OpenFEMA v2 dataset — the escape hatch for datasets the convenience tools do not cover (e.g., FimaNfipPolicies, IndividualAssistanceHousingRegistrantsLargeDisasters, FemaWebDeclarationAreas, PublicAssistanceApplicants). Accepts raw OData filter, select, orderby, and pagination parameters. For NFIP Policies, use propertyState (not state) as the state field — always include a county or ZIP filter to avoid timeout. The dataset name must match the exact OpenFEMA v2 entity name (case-sensitive, e.g., FimaNfipClaims). Unknown dataset names return an unknown_dataset error.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "fema_query_dataset",
    "arguments": {
      "dataset": "<dataset>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "dataset": {
      "type": "string",
      "minLength": 1,
      "description": "OpenFEMA v2 dataset entity name (case-sensitive, e.g., FimaNfipPolicies, FemaWebDeclarationAreas, PublicAssistanceApplicants)."
    },
    "filter": {
      "description": "OData $filter expression (e.g., \"state eq 'TX' and declarationDate ge '2024-01-01T00:00:00.000Z'\"). String values in single quotes.",
      "type": "string"
    },
    "select": {
      "description": "Comma-separated field names to return (e.g., \"disasterNumber,state,declarationDate\").",
      "type": "string"
    },
    "orderby": {
      "description": "OData $orderby expression (e.g., \"declarationDate desc\").",
      "type": "string"
    },
    "limit": {
      "default": 100,
      "description": "Maximum records to return (1–10000, default 100).",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    },
    "offset": {
      "default": 0,
      "description": "Pagination offset (default 0).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "dataset",
    "limit",
    "offset"
  ],
  "additionalProperties": false
}
view source ↗

Resources

1

Summary for a specific FEMA disaster declaration — title, state, incident type, programs declared (IA/PA/HM), incident period, and designated area count. Read-once context injection for agents already holding a disaster number.

uri fema://disaster/{disasterNumber}