Query NPI Providers
query_npi_providersSearch the NPI registry for healthcare providers by state, specialty, name, city, or ZIP. Returns up to 100 results from the CMS NPPES database.
Instructions
Search the NPI (National Provider Identifier) registry for healthcare providers. Filter by state, specialty, name, city, or ZIP code. Returns up to 100 results per query. Source: CMS NPPES, updated weekly. ~7.2 million providers.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| state | No | Two-letter US state code (e.g. CA, NY, TX) | |
| specialty | No | Provider specialty or taxonomy description (e.g. Cardiology, Family Medicine) | |
| name | No | Provider name (partial match on first or last name, or organization name) | |
| city | No | City name | |
| zip | No | 5-digit ZIP code | |
| limit | No | Maximum number of results to return (default 25, max 100) |
Implementation Reference
- src/tools/npi.ts:69-98 (handler)The async handler function for query_npi_providers that calls the Verilex API endpoint /api/v1/npi with state, specialty, name, city, zip, and limit parameters, then returns formatted results.
async ({ state, specialty, name, city, zip, limit }) => { const res = await apiGet<NpiQueryResponse>("/api/v1/npi", { state, specialty, name, city, zip, limit: limit ?? 25, }); if (!res.ok) { return { content: [ { type: "text" as const, text: `API error (${res.status}): ${JSON.stringify(res.data)}`, }, ], isError: true, }; } const { count, data } = res.data; const summary = `Found ${count} NPI provider(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, - src/tools/npi.ts:31-67 (schema)Schema definition for query_npi_providers tool: title, description, and inputSchema with optional fields state (2-letter code), specialty, name, city, zip (5-digit), and limit (1-100, default 25).
{ title: "Query NPI Providers", description: "Search the NPI (National Provider Identifier) registry for healthcare providers. " + "Filter by state, specialty, name, city, or ZIP code. Returns up to 100 results per query. " + "Source: CMS NPPES, updated weekly. ~7.2 million providers.", inputSchema: { state: z .string() .length(2) .optional() .describe("Two-letter US state code (e.g. CA, NY, TX)"), specialty: z .string() .optional() .describe( "Provider specialty or taxonomy description (e.g. Cardiology, Family Medicine)", ), name: z .string() .optional() .describe( "Provider name (partial match on first or last name, or organization name)", ), city: z.string().optional().describe("City name"), zip: z .string() .optional() .describe("5-digit ZIP code"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum number of results to return (default 25, max 100)"), }, - src/tools/npi.ts:29-99 (registration)Registration of the tool 'query_npi_providers' using server.registerTool() with the name, schema, and handler.
server.registerTool( "query_npi_providers", { title: "Query NPI Providers", description: "Search the NPI (National Provider Identifier) registry for healthcare providers. " + "Filter by state, specialty, name, city, or ZIP code. Returns up to 100 results per query. " + "Source: CMS NPPES, updated weekly. ~7.2 million providers.", inputSchema: { state: z .string() .length(2) .optional() .describe("Two-letter US state code (e.g. CA, NY, TX)"), specialty: z .string() .optional() .describe( "Provider specialty or taxonomy description (e.g. Cardiology, Family Medicine)", ), name: z .string() .optional() .describe( "Provider name (partial match on first or last name, or organization name)", ), city: z.string().optional().describe("City name"), zip: z .string() .optional() .describe("5-digit ZIP code"), limit: z .number() .int() .min(1) .max(100) .optional() .describe("Maximum number of results to return (default 25, max 100)"), }, }, async ({ state, specialty, name, city, zip, limit }) => { const res = await apiGet<NpiQueryResponse>("/api/v1/npi", { state, specialty, name, city, zip, limit: limit ?? 25, }); if (!res.ok) { return { content: [ { type: "text" as const, text: `API error (${res.status}): ${JSON.stringify(res.data)}`, }, ], isError: true, }; } const { count, data } = res.data; const summary = `Found ${count} NPI provider(s).`; const json = JSON.stringify(data, null, 2); return { content: [{ type: "text" as const, text: `${summary}\n\n${json}` }], }; }, ); - src/index.ts:39-39 (registration)Top-level registration call: registerNpiTools(server) invoked during MCP server creation.
registerNpiTools(server); - src/client.ts:44-76 (helper)The apiGet helper function used by the handler to make HTTP GET requests to the Verilex API.
export async function apiGet<T = unknown>( path: string, params?: Record<string, string | number | undefined>, ): Promise<ApiResponse<T>> { const url = buildUrl(path, params); const headers: Record<string, string> = { Accept: "application/json", "User-Agent": "verilex-mcp-server/0.1.0", }; // Forward x402 payment token if present in env (for paid endpoints) const paymentToken = process.env.VERILEX_PAYMENT_TOKEN; if (paymentToken) { headers["X-Payment-Token"] = paymentToken; } const res = await fetch(url, { headers }); const data = (await res.json()) as T; const stale = res.headers.get("X-Data-Stale"); const lastUpdated = res.headers.get("X-Data-Last-Updated"); const ageSeconds = res.headers.get("X-Data-Age-Seconds"); return { ok: res.ok, status: res.status, data, stale: stale === "true", lastUpdated: lastUpdated ?? undefined, ageSeconds: ageSeconds ? Number(ageSeconds) : undefined, }; }