medical-mcp-toolkit

ruslanmv/medical-mcp-toolkit

3.2

If you are the rightful owner of medical-mcp-toolkit and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.

The Medical MCP Toolkit is a production-ready server that provides clinical tools for IBM watsonx Orchestrate agents, facilitating efficient healthcare operations.

Tools
8
Resources
0
Prompts
0

medical-mcp-toolkit

Production-ready MCP-style server that exposes clinical tools for IBM watsonx Orchestrate agents.

What it is: a clean MCP server exposing 12 medical tools via both:

  • An HTTP API (FastAPI) for quick testing & service integration.
  • MCP transports (SSE/STDIO) for LLM multi-agent orchestration.

✨ Features

  • 12 tools: patient, vitals, profile, clinical calculators, drug info / interactions / contraindications / alternatives, symptom triage, KB search, scheduling, patient 360.
  • FastAPI HTTP endpoints: /health, /schema, /tools, /invoke.
  • Bearer token authentication (set BEARER_TOKEN).
  • uv-managed Python environment (uv sync, .venv).
  • Containerized (Dockerfile). Structured logs to stdout.
  • Postman collection for one-click testing.
  • Mermaid architecture (kept exactly as provided below). PostgreSQL backend with production-ready schema aligned to the JSON Schema, seeded demo data, Dockerfile.db, and Makefile DB helpers (db-up, db-down, db-logs, db-reset).

🧠 System Context

graph TD
    %% === STYLES ===
    classDef agent fill:#eefaf0,stroke:#1a7f37,stroke-width:2px
    classDef tool fill:#f3e8fd,stroke:#8e44ad,stroke-width:1px
    classDef external fill:#f8f9fa,stroke:#666,stroke-width:1px,stroke-dasharray: 5 5

    %% === ORCHESTRATION AGENTS ===
    subgraph WXO[IBM watsonx Orchestrate]
        direction TB
        Coordinator[Medical Coordinator Agent]:::agent
        Triage[Emergency Triage Agent]:::agent
        GenMed[General Medicine Agent]:::agent

        subgraph Specialists
            direction LR
            Cardiology[Cardiology]:::agent
            Pediatrics[Pediatrics]:::agent
            Oncology[Oncology]:::agent
            Endocrinology[Endocrinology]:::agent
        end

        %% Agent Handoffs
        Coordinator -->|delegates| Triage
        Coordinator -->|routes| GenMed
        GenMed -->|refers| Specialists
    end

    %% === BACKEND SERVICES & TOOLS ===
    subgraph BackendServices [Backend Services]
        direction TB
        subgraph MCPToolkit[Medical MCP Toolkit]
            direction TB
            T1[getPatient]:::tool
            T2[getPatientVitals]:::tool
            T3[getPatientMedicalProfile]:::tool
            T4[calcClinicalScores]:::tool
            T5[getDrugInfo]:::tool
            T6[triageSymptoms]:::tool
            T7[searchMedicalKB]:::tool
            T8[scheduleAppointment]:::tool
        end

        subgraph ExternalRuntimes [External Runtimes]
            MCPServer[Medical MCP Server<br/>FastMCP/SSE]:::external
            WatsonxAI[watsonx.ai Foundation Models]:::external
        end
        
        MCPToolkit -.->|runtime API calls| MCPServer
        MCPServer -.->|LLM calls| WatsonxAI
    end

    %% === CONNECTIONS ===
    WXO -->|All agents use| MCPToolkit

Companion Multi-Agent Repository (Orchestrate): https://github.com/ruslanmv/Medical-AI-Assistant-System This repo: https://github.com/ruslanmv/medical-mcp-toolkit


πŸš€ Quickstart (uv)

# 1) Clone and enter the repo
git clone https://github.com/ruslanmv/medical-mcp-toolkit
cd medical-mcp-toolkit

# 2) Create your environment file
cp .env.example .env
# Edit .env and set BEARER_TOKEN, and (optionally) DATABASE_URL

# 3) (Optional) Start Postgres DB with schema + seed data
make db-up
# Verify: make db-logs   or   docker ps

# 4) Create venv and install deps (uv-managed)
make install   # or: make uv-install

# 5) Run the HTTP server (FastAPI on port 9090)
make run-api   # (equivalent to: uv run uvicorn server:app --host 0.0.0.0 --port 9090)

Typical startup log (example):

2025-10-15 12:16:46,272 INFO [mcp_server] [registry] 12 tools registered: calcClinicalScores, getDrugAlternatives, getDrugContraindications, getDrugInfo, getDrugInteractions, getPatient, getPatient360, getPatientMedicalProfile, getPatientVitals, scheduleAppointment, searchMedicalKB, triageSymptoms
INFO:     Started server process [23217]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:9090 (Press CTRL+C to quit)

βœ… Smoke Test (bash)

Health is plain text (ok), so use jq -R .:

curl -sS http://localhost:9090/health | jq -R .
# "ok"

Invoke a tool:

curl -sS -X POST "http://localhost:9090/invoke" \
  -H 'Authorization: Bearer dev-token' \
  -H 'Content-Type: application/json' \
  -d '{
    "tool": "triageSymptoms",
    "args": {
      "age": 45,
      "sex": "male",
      "symptoms": ["chest pain","sweating"],
      "duration_text": "2 hours"
    }
  }' | jq

Example result:

{
  "ok": true,
  "tool": "triageSymptoms",
  "result": {
    "acuity": "urgent",
    "advice": "call emergency services",
    "rulesMatched": ["chest pain", "diaphoresis"],
    "nextSteps": ["ECG", "troponin", "aspirin if not contraindicated"]
  }
}

If you see jq parse errors, you’re probably piping non-JSON. /health is text/plain; /invoke is JSON. Add -i to curl to review HTTP status/headers.


πŸ”Œ HTTP API

  • GET /health β†’ ok (text/plain)

    • JSON-view trick: curl -sS /health | jq -R -r . β†’ ok
  • GET /schema (auth) β†’ Components JSON Schema (from schemas/components.schema.json)

  • GET /tools (auth) β†’ {"tools": ["..."]}

  • POST /invoke (auth) β†’ {"ok": true, "tool": "<name>", "result": ...}

Auth: set BEARER_TOKEN in the server environment. If unset, auth is disabled (dev mode). Send: Authorization: Bearer <token> for /schema, /tools, /invoke.


🧰 Available Tools (12)

  • Patient: getPatient, getPatientVitals, getPatientMedicalProfile
  • Calculators: calcClinicalScores (BMI, BSA, CrCl, eGFR)
  • Drugs: getDrugInfo, getDrugInteractions, getDrugContraindications, getDrugAlternatives
  • Triage & KB: triageSymptoms, searchMedicalKB
  • Scheduling & P360: scheduleAppointment, getPatient360

Use GET /tools to list names, and GET /schema for typed input/output.


πŸ§ͺ More Examples

List tools:

curl -sS "http://localhost:9090/tools" \
  -H 'Authorization: Bearer dev-token' | jq

Get schema:

curl -sS "http://localhost:9090/schema" \
  -H 'Authorization: Bearer dev-token' | jq

Drug info:

curl -sS -X POST "http://localhost:9090/invoke" \
  -H 'Authorization: Bearer dev-token' \
  -H 'Content-Type: application/json' \
  -d '{"tool":"getDrugInfo","args":{"drug":"lisinopril"}}' | jq

🧡 MCP Transports (SSE / STDIO)

The same tools are exposed via MCP for LLM agents.

SSE transport (port 9090):

uv run python -c "import asyncio; \
from medical_mcp_toolkit.mcp_server import run_mcp_async; \
asyncio.run(run_mcp_async('sse', host='0.0.0.0', port=9090))"

STDIO transport:

uv run python -c "import asyncio; \
from medical_mcp_toolkit.mcp_server import run_mcp_async; \
asyncio.run(run_mcp_async('stdio'))"

Note: The HTTP API is served by uvicorn server:app. The SSE/STDIO MCP runner is separate (from mcp_server.py). Choose the mode you need.


πŸ—„οΈ Database (Dockerized PostgreSQL)

What you get:

  • Dockerfile.db β€” production-grade Postgres image builder.
  • db/10_init.sql β€” full schema (patients, vitals, conditions, allergies, meds; drugs, interactions; appointments; audit).
  • db/20_seed.sql β€” demo data (patients demo-001, demo-002, and basic drug KB).
  • Makefile helpers: db-up, db-down, db-logs, db-reset.

Start DB:

make db-up
# or direct script:
scripts/create_db.sh

Manage DB:

make db-logs    # tail logs
make db-down    # stop & remove container
make db-reset   # recreate fresh DB (drops data)

Default DSN (matches .env.example):

postgresql://mcp_user:mcp_password@localhost:5432/medical_db

πŸ”§ Scripts

  • scripts/mcp_curl_demo.sh β€” cross-platform demo for both HTTP and SSE JSON-RPC.

Examples:

# HTTP mode (health, tools, invoke)
MODE=http TOKEN=dev-token ./scripts/mcp_curl_demo.sh

# SSE JSON-RPC mode (initialize, tools/list, tools/call triage)
MODE=sse TOKEN=dev-token CALL_TOOL=triageSymptoms ./scripts/mcp_curl_demo.sh

πŸ› οΈ Development

Environment (uv-managed):

make install       # or: make uv-install
make fmt           # ruff format + black
make lint          # ruff check
make test          # pytest

Run HTTP API (dev):

export BEARER_TOKEN=dev-token
make run-api
# (equivalent to: uv run uvicorn server:app --host 0.0.0.0 --port 9090)

Run MCP SSE (dev):

uv run python -c "import asyncio; from medical_mcp_toolkit.mcp_server import run_mcp_async; asyncio.run(run_mcp_async('sse', host='0.0.0.0', port=9090))"

🐳 Docker

Build & run:

make docker-build
BEARER_TOKEN=prod-secret make docker-run
# Server will listen on container port 9090 and be mapped to localhost:9090

Logs & stop:

make docker-logs
make docker-stop

Build DB image directly (optional):

docker build -t medical-db -f Dockerfile.db .
docker run -d --name medical-db-container \
  -e POSTGRES_USER=mcp_user \
  -e POSTGRES_PASSWORD=mcp_password \
  -e POSTGRES_DB=medical_db \
  -p 5432:5432 \
  medical-db

βš™οΈ Configuration (env)

  • BEARER_TOKEN β€” required for auth in non-dev environments.

  • DATABASE_URL β€” PostgreSQL DSN (optional; if unset, the demo uses in-memory data).

    • Default (see .env.example): postgresql://mcp_user:mcp_password@localhost:5432/medical_db
  • MCP_LOG_LEVEL β€” log level for MCP parts (INFO, DEBUG, …).

  • UVICORN_LOG_LEVEL β€” log level for Uvicorn (info, debug, …).

  • (Adapters, when you wire real systems)

    • DRUG_API_BASE, DRUG_API_KEY
    • KB_BASE
    • SCHED_BASE

πŸ“¬ Postman

Import postman/medical-mcp-toolkit.postman_collection.json. Set variables:

  • baseUrl β†’ http://localhost:9090
  • token β†’ your bearer token (e.g., dev-token)

🧩 What You Can Do With This Repo

  • Plug-and-play medical tools for multi-agent systems (watsonx Orchestrate, etc.).
  • Call tools over HTTP for rapid prototyping, dashboards, or RPA glue.
  • Run MCP transports so LLM agents can invoke the same functions natively.
  • Swap demo adapters with real EHR/Drug-DB/KB/Scheduling systems while keeping typed contracts (Pydantic models + JSON Schema).
  • Ship to prod with Docker and lightweight operational footprint.

🧯 Troubleshooting

  • jq: parse error ... on /health: that route returns text/plain. Use:

    curl -sS http://localhost:9090/health | jq -R -r .
    
  • 401 Unauthorized on /invoke: start the server with BEARER_TOKEN and pass the same in Authorization: Bearer ....

  • You started the SSE MCP runner but are calling HTTP endpoints: SSE mode doesn’t serve /invoke. Use uvicorn server:app for the HTTP API.

  • Check port binding:

    ss -ltnp | grep 9090   # or: sudo lsof -i :9090
    

πŸ“œ License

Apache 2.0 β€” see LICENSE.


🀝 Acknowledgments

Built with ❀️ for clinical AI prototyping at production quality. Optimized for IBM watsonx Orchestrate multi-agent systems and compatible LLM runtimes.