NPI MCP Server
title: NPI MCP Server emoji: 🩺 colorFrom: blue colorTo: green sdk: docker pinned: false app_port: 8000
NPI MCP Server
An MCP server that wraps the public
NPPES NPI Registry API (version 2.1, no
authentication) and exposes it over streamable HTTP at /mcp.
It does more than proxy the registry. Three tools pass NPPES queries through; three add logic the registry does not provide — offline checksum validation, a composite referral-eligibility assessment, and a plain-English specialty search that maps everyday clinical words onto NUCC taxonomy codes.
Tools
Direct NPPES access:
Tool | Use it when |
| You know the provider's name. |
| You already hold an exact 10-digit NPI. |
| You only need the provider's NUCC taxonomies. |
Derived intelligence, not available from NPPES:
Tool | Use it when |
| Cheap offline pre-flight. Runs the CMS Luhn checksum over |
| "Can I refer a patient to this provider?" Five ordered checks: checksum → registry lookup → active enumeration → declared primary taxonomy → complete practice address. Returns an actionable concern per failed check. |
| The user describes a kind of provider — "a cardiologist", "peds", "skin". Maps the phrase to NUCC codes, searches, then filters out the registry's text-match noise. |
Supported specialty keywords: cardiology, dermatology, family medicine,
neurology, oncology, orthopedic, pediatrics, psychiatry — plus common synonyms
such as heart, peds, mental health, skin, cancer and primary care.
The three derived tools never raise. A mistyped NPI, an unknown NPI, an NPPES outage or an unrecognized keyword each return a structured result explaining what happened, so the calling model can recover instead of seeing an exception. An upstream outage is reported as inconclusive rather than "no such provider".
Endpoints
Path | Purpose |
| MCP streamable HTTP endpoint. |
|
|
| Server name, version and MCP endpoint path, so a platform root probe gets 200. |
Configuration
Variable | Meaning |
| Comma-separated public hostnames to trust for DNS-rebinding protection. |
| Bind address. The container defaults to |
| Default |
The public hostname is runtime configuration, never compiled in, so one image
serves both deployment targets. The resolved allowed_hosts are logged at
startup.
Set MCP_ALLOWED_HOSTS for any non-local deployment. Without it, requests
arriving with a public Host header are rejected with HTTP 421.
Deploy
Hugging Face Spaces (Docker SDK)
The frontmatter above configures the Space; app_port: 8000 matches the
Dockerfile's EXPOSE. Add a Space variable MCP_ALLOWED_HOSTS set to the
Space hostname, e.g. your-name-npi-mcp.hf.space. The MCP endpoint is then
https://your-name-npi-mcp.hf.space/mcp.
Cloudflare tunnel
docker build -t npi-mcp .
docker run -d -p 8000:8000 -e MCP_ALLOWED_HOSTS="<your-tunnel-host>.trycloudflare.com" npi-mcp
cloudflared tunnel --url http://localhost:8000A quick tunnel's hostname changes every run, so pass the new one via
MCP_ALLOWED_HOSTS and restart the container. Multiple hosts are accepted, so a
stable named tunnel and a Space hostname can be trusted at the same time.
Local development
pip install -e .
npi-mcp # http://0.0.0.0:8000
mcp dev src/npi_mcp/server.pymcp dev loads server.py by file path, so the module has no parent package —
every intra-package import is absolute (from npi_mcp.models import ...).
The SDK is pinned to mcp[cli]>=1.0,<2: the 2.x SDK renames FastMCP to
MCPServer and changes the API.