Skip to main content
Glama
pgang002

nfip-mcp-server

by pgang002
README.md
# nfip-mcp-server

[![CI](https://github.com/YOUR-USERNAME/nfip-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/YOUR-USERNAME/nfip-mcp-server/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](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

A4.3/5.0

Scored across 4 tools

Disambiguation5/5

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.

Naming Consistency4/5

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.

Tool Count5/5

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.

Completeness4/5

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.

Maintenance

ActivitySlowing
ResponsivenessNo issues