Skip to main content
Glama

Query NPI Providers

query_npi_providers

Search 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

TableJSON Schema
NameRequiredDescriptionDefault
stateNoTwo-letter US state code (e.g. CA, NY, TX)
specialtyNoProvider specialty or taxonomy description (e.g. Cardiology, Family Medicine)
nameNoProvider name (partial match on first or last name, or organization name)
cityNoCity name
zipNo5-digit ZIP code
limitNoMaximum number of results to return (default 25, max 100)

Implementation Reference

  • 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}` }],
      };
    },
  • 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);
  • 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,
      };
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description provides useful behavioral details: returns up to 100 results, source is CMS NPPES updated weekly, and covers ~7.2 million providers. Could add pagination or rate limit info, but current details are above average.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: first covers action and filters, second adds source and scale. No wasted words, front-loaded with key information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description lacks explicit return value details, but the tool's purpose (search) implies a list of providers. The source and size info add context. Could mention typical response fields, but still adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, baseline 3. The description adds minor value by noting 'partial match' for name parameter, but other filters are already clear from schema. No major additional meaning beyond what schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches the NPI registry for healthcare providers with specific filters (state, specialty, name, city, ZIP). This distinguishes it from siblings like lookup_npi (single lookup) and npi_stats (statistics).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for searching providers with filters, but does not explicitly state when to use this over alternatives like lookup_npi or when not to use it. No exclusions or context for when this tool is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/carrierone/verilexdata-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server