npi_mcp / app.py
Humanlearning's picture
feat: add debug tab with connectivity diagnostics using httpx and curl.
86e211c
import gradio as gr
from typing import List, Optional
import os
import sys
# Ensure src is in python path
sys.path.append(os.path.join(os.path.dirname(__file__), "src"))
from npi_mcp_server.tools import search_providers, get_provider_by_npi
from npi_mcp_server.schemas import ProviderSummary, ProviderDetail
async def search_providers_tool(query: str, state: str = None, taxonomy: str = None) -> List[dict]:
"""
Search for healthcare providers via the NPI API.
Args:
query: Name (first/last) or organization name.
state: Two-letter state code.
taxonomy: Taxonomy code or description.
Returns:
List of ProviderSummary objects as dictionaries.
"""
results = await search_providers(query, state, taxonomy)
return [r.model_dump() for r in results]
async def get_provider_by_npi_tool(npi: str) -> Optional[dict]:
"""
Retrieve details for a specific provider by NPI.
Args:
npi: 10-digit NPI string.
Returns:
ProviderDetail object as dictionary or None if not found.
"""
result = await get_provider_by_npi(npi)
if result:
return result.model_dump()
return None
with gr.Blocks() as demo:
gr.Markdown("# NPI Registry MCP Server")
gr.Markdown("This interface exposes NPI Registry tools as an MCP server.")
with gr.Tab("Search Providers"):
with gr.Row():
query_input = gr.Textbox(label="Query", placeholder="Name or Organization")
state_input = gr.Textbox(label="State", placeholder="2-letter code (e.g., CA)")
taxonomy_input = gr.Textbox(label="Taxonomy", placeholder="Taxonomy code")
search_btn = gr.Button("Search")
search_output = gr.JSON(label="Results")
search_btn.click(
fn=search_providers_tool,
inputs=[query_input, state_input, taxonomy_input],
outputs=search_output
)
gr.Examples(
examples=[
["SHELLEY AKEY", "AZ", "363LN0000X"],
["KATHERYN ALIOTO", "CA", "101YA0400X"],
["Counselor", "CA", ""],
["Physical Therapist", "WA", "225100000X"],
],
inputs=[query_input, state_input, taxonomy_input],
label="Try Examples"
)
with gr.Tab("Get Provider by NPI"):
npi_input = gr.Textbox(label="NPI", placeholder="10-digit NPI")
get_btn = gr.Button("Get Details")
get_output = gr.JSON(label="Provider Details")
get_btn.click(
fn=get_provider_by_npi_tool,
inputs=[npi_input],
outputs=get_output
)
with gr.Tab("Debug"):
gr.Markdown("## Connectivity Test")
debug_btn = gr.Button("Run Diagnostics")
debug_output = gr.Textbox(label="Logs", lines=20)
async def run_diagnostics():
import httpx
import subprocess
import json
from npi_mcp_server.config import NPI_API_BASE_URL
logs = []
logs.append(f"Base URL: {NPI_API_BASE_URL}")
url = f"{NPI_API_BASE_URL.rstrip('/')}/search_providers"
payload = {
"query": "SHELLEY AKEY",
"state": "AZ",
"taxonomy": "363LN0000X"
}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
}
# Test 1: Python httpx
logs.append("\n--- Test 1: Python httpx ---")
try:
async with httpx.AsyncClient() as client:
response = await client.post(url, json=payload, headers=headers, timeout=30.0)
logs.append(f"Status: {response.status_code}")
logs.append(f"Response: {response.text}")
except Exception as e:
logs.append(f"Error: {e}")
# Test 2: System curl
logs.append("\n--- Test 2: System curl ---")
try:
cmd = [
"curl", "-v", "-X", "POST", url,
"-H", "Content-Type: application/json",
"-H", f"User-Agent: {headers['User-Agent']}",
"-d", json.dumps(payload)
]
result = subprocess.run(cmd, capture_output=True, text=True)
logs.append(f"Return Code: {result.returncode}")
logs.append(f"Stdout: {result.stdout}")
logs.append(f"Stderr: {result.stderr}")
except Exception as e:
logs.append(f"Curl Error: {e}")
return "\n".join(logs)
debug_btn.click(fn=run_diagnostics, outputs=debug_output)
if __name__ == "__main__":
demo.launch(mcp_server=True)