nfip-mcp-server
# nfip-mcp-server
[](https://github.com/YOUR-USERNAME/nfip-mcp-server/actions/workflows/ci.yml)
[](LICENSE)
[](pyproject.toml)
An MCP (Model Context Protocol) server exposing real US flood insurance
claims data — sourced live from FEMA's public OpenFEMA API — as tools an AI
agent can call: claim lookup, filtered search, aggregate stats, and flood
event summaries.
## Why this exists
Built as a hands-on project to learn MCP server design against a real,
non-trivial dataset rather than mock data — the same pattern used to expose
proprietary data (claims, policies, internal knowledge bases) to enterprise
AI agents.
- **Real data** — pulled directly from [FEMA's OpenFEMA API](https://www.fema.gov/about/openfema/api),
no key required, redacted for privacy, no PII.
- **Tested** — unit tests against the query layer, integration tests against
the real server subprocess, CI running both on every push.
- **Deployable** — pip-installable package, Dockerfile included.
## Available Tools
| Tool | Description |
|------|-------------|
| `get_claim` | Look up a single flood claim by its unique ID |
| `search_claims` | Filtered search by state, flood event, minimum building payment, and/or year |
| `claims_summary` | Aggregate stats (count, total/average payments, year range), optionally by state |
| `list_flood_events` | Distinct named flood events in the data with claim counts |
## Architecture
```
nfip-mcp-server/
├── src/nfip_mcp/
│ ├── db.py ← pure query functions (no MCP dependency, easy to unit test)
│ └── server.py ← FastMCP tool wrappers around db.py, entry point
├── data/
│ ├── nfip_raw.json ← real claims data pulled from the OpenFEMA API
│ └── claims.db ← SQLite database built from the raw data
├── scripts/
│ ├── build_db.py ← loads nfip_raw.json into claims.db
│ ├── fetch_more_data.py ← pulls a larger, filtered dataset from the live API
│ └── demo_client.py ← manual walkthrough of every tool
├── tests/
│ ├── test_db.py ← unit tests against the query layer
│ └── test_integration.py ← spins up the real server and calls it over stdio
└── .github/workflows/ci.yml
```
The query logic in `db.py` is deliberately free of any MCP-specific code —
it's plain functions taking a `sqlite3.Connection` and returning dicts, so
it's testable without spinning up a server or client. `server.py` just wires
thin `@mcp.tool()` wrappers around it.
## Setup
```bash
git clone https://github.com/YOUR-USERNAME/nfip-mcp-server
cd nfip-mcp-server
pip install -e ".[dev]"
python scripts/build_db.py
```
## Running the tests
```bash
pytest tests/ # everything
pytest tests/test_db.py # fast unit tests only
pytest -m integration # slower, spins up the real server subprocess
```
## Running the server
```bash
nfip-mcp-server # after pip install, runs over stdio
# or
python -m nfip_mcp.server
```
To see it working interactively without a full MCP host installed:
```bash
python scripts/demo_client.py
```
## Connecting to Claude Desktop (or another MCP host)
Add to your MCP host's config (e.g. `claude_desktop_config.json`):
```json
{
"mcpServers": {
"nfip-claims": {
"command": "nfip-mcp-server"
}
}
}
```
## Running with Docker
```bash
docker build -t nfip-mcp-server .
docker run -i nfip-mcp-server
```
Point your MCP host's `command` at `docker run -i nfip-mcp-server` to use
the containerized version instead.
## Scaling up the data
The bundled `data/claims.db` has a small (~24 record) real sample, enough
to prove the pipeline end to end. To pull a much larger, properly filtered
slice of the real data (this defaults to flood-prone Northeast states):
```bash
python scripts/fetch_more_data.py
python scripts/build_db.py
```
## License
MIT — see [LICENSE](LICENSE).
TDQS
Scored across 4 tools
Each tool has a clearly distinct purpose: listing flood events, retrieving a single claim, searching claims by filters, and producing aggregate statistics. There is minimal overlap in functionality, and descriptions make the boundaries obvious.
Three tools follow a consistent verb_noun pattern: list_flood_events, get_claim, and search_claims. claims_summary breaks the pattern by using a noun phrase, though it is still clear and readable.
Four tools is a well-scoped size for a read-only NFIP claims data server. Each tool covers a distinct query need without redundancy or bloat.
The surface covers the core read-only workflows: enumeration, single-record lookup, filtered search, and aggregate statistics. Minor gaps exist, such as summary filtering by flood event or year, but these do not create dead ends for common use cases.