Skip to main content
Glama
zapperedge-prabhu

NPI MCP Server

README.md
# NPI MCP Server

An **offline-capable** MCP (Model Context Protocol) server for the CMS NPPES NPI Registry, written in Python, deployable on Azure App Service as a Docker container.

## Features

- βœ… **Works offline** β€” uses a local SQLite database
- πŸ”„ **Auto-updates every 7 days** from CMS NPPES (background scheduler)
- 🐳 **Docker-ready** with multi-stage build
- ☁️ **Azure App Service** deployment with persistent storage
- πŸ” **Full-text search** with wildcard support
- βœ”οΈ **Luhn validation** for NPI check digits
- πŸ“Š **~8M+ provider records** from the full NPPES dataset

---

## MCP Tools

| Tool | Description |
|------|-------------|
| `npi_search` | Search by name, specialty, city, state, ZIP |
| `npi_lookup` | Look up a specific NPI number |
| `npi_validate` | Validate NPI format + Luhn check digit (offline) |
| `db_status` | Check DB record count, last/next update time |
| `db_update` | Manually trigger a data refresh |

---

## Quick Start (Local)

### 1. Build and run with Docker Compose

```bash
git clone <this-repo>
cd npi-mcp-server

# Build and start
docker compose up -d

# Trigger initial data load (one-time, ~30-60 min)
curl -X POST "http://localhost:8000/update?force=true"

# Monitor progress
docker compose logs -f
```

### 2. Check health
```bash
curl http://localhost:8000/health
```

### 3. Connect MCP client
Point your MCP client to: `http://localhost:8000/sse`

---

## Azure Deployment

### Prerequisites
- Azure CLI installed: `brew install azure-cli` or see [docs](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
- Docker installed
- Azure subscription

### Deploy

```bash
# Log in to Azure
az login

# Edit variables at top of script
nano deploy-azure.sh

# Run deployment (takes ~5 minutes)
chmod +x deploy-azure.sh
./deploy-azure.sh
```

### After deployment

Trigger the initial NPI data load (one-time, requires internet):
```bash
curl -X POST "https://your-app.azurewebsites.net/update?force=true"
```

The full NPPES file is ~900MB compressed / ~8GB uncompressed. Loading takes 30-60 minutes. After that, weekly incremental updates run automatically.

---

## Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Azure App Service                   β”‚
β”‚                                                      β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  FastAPI/SSE │───▢│  MCP Server (mcp SDK)    β”‚   β”‚
β”‚  β”‚  HTTP layer  β”‚    β”‚  - npi_search            β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚  - npi_lookup            β”‚   β”‚
β”‚                      β”‚  - npi_validate          β”‚   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚  - db_status/update      β”‚   β”‚
β”‚  β”‚  Background  β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β”‚  Scheduler   β”‚              β”‚                    β”‚
β”‚  β”‚  (every 7d)  β”‚              β–Ό                    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚                      β”‚  SQLite Database          β”‚   β”‚
β”‚                      β”‚  /data/npi.db             β”‚   β”‚
β”‚                      β”‚  (~5-10 GB)               β”‚   β”‚
β”‚                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚                                  β”‚                   β”‚
β”‚                      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚                      β”‚  Azure File Share         β”‚   β”‚
β”‚                      β”‚  (persistent volume)      β”‚   β”‚
β”‚                      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β”‚ (weekly, when internet available)
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  CMS NPPES          β”‚
β”‚  download.cms.gov   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

---

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `NPI_DB_PATH` | `/data/npi.db` | SQLite database path |
| `NPI_UPDATE_DAYS` | `7` | Days between auto-updates |
| `DOWNLOAD_TIMEOUT` | `3600` | Download timeout in seconds |
| `PORT` | `8000` | HTTP server port |

---

## API Endpoints

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/` | GET | Server info |
| `/health` | GET | Health check (used by Azure) |
| `/status` | GET | DB status (record count, last update) |
| `/update` | POST | Trigger manual update (`?force=true`) |
| `/sse` | GET | MCP SSE connection endpoint |
| `/messages` | POST | MCP messages endpoint |

---

## Storage Requirements

| Component | Size |
|-----------|------|
| NPPES ZIP download | ~900 MB |
| SQLite database | ~5-10 GB |
| Recommended Azure File Share | 50 GB |

Use Azure App Service **B2 or higher** (2 vCPU, 3.5 GB RAM minimum).

---

## Connecting MCP Clients

### Claude Desktop (`claude_desktop_config.json`)
```json
{
  "mcpServers": {
    "npi-registry": {
      "url": "https://your-app.azurewebsites.net/sse",
      "transport": "sse"
    }
  }
}
```

### Local stdio mode (for dev/testing)
```bash
python main.py
```

---

## Data Source

Data comes from [CMS NPPES](https://download.cms.gov/nppes/NPI_Files.html), the official National Plan and Provider Enumeration System. Updated monthly (full) and weekly (incremental) by CMS.