Skip to main content
Glama
tgdn

healthcare

by tgdn

healthcare-mcp

An MCP server for finding doctors in Romania: by county, speciality, language, name and weekly availability.

Add it to Claude Code

Pick one.

Hosted: a URL and a token

claude mcp add --transport http healthcare https://wonderful.xxxx0.top/mcp \
  --header "Authorization: Bearer <token>"

Other MCP clients need the same two things: the URL https://wonderful.xxxx0.top/mcp and the header Authorization: Bearer <token>.

Local: stdio, with only Docker installed

git clone https://github.com/tgdn/healthcare-mcp.git && cd healthcare-mcp
docker compose up --no-start    # downloads and builds once, starts nothing
claude mcp add healthcare -- docker compose -f "$PWD/docker-compose.yml" run --rm -T stdio

Claude Code starts the server when it needs it, along with a Postgres container that imports the doctors on first use. docker compose down stops Postgres; docker compose down -v also deletes the data.

Then ask Claude something like "I live in Mangalia and need a cardiologist who speaks German on Saturday".

Related MCP server: Doktor MCP Server

Tools

  • ListSpecialities and ListLanguages return what the doctors offer, with counts, optionally for one county.

  • SearchDoctor takes county, speciality, first_name, last_name, language, availability (day, time) and limit, and returns the best rated doctors first.

    • A county is required unless searching by name. Without one, the tool tells the model to ask the user rather than guess.

    • Speciality and language match case-insensitively; an unknown value returns the known ones.

    • Names ignore case and accents. A misspelt name ("Dumitresku") returns the closest spellings, with a note.

    • Availability is regular weekly working hours, not free appointment slots.

    • With no match in the county it searches the neighbouring counties and says so. With no match at all, matches_without counts the results if each filter were dropped.

Design decisions

Why Postgres?

The prompt specifies a production-scale dataset with millions of records, where Postgres is standard practice:

  • Trigram search: GIN trigram indexes make fuzzy ILIKE searches fast and avoid full table scans.

  • Simple ops: Using Postgres for both data storage and search avoids managing extra sync pipelines.

  • Future scale: B-tree indexes handle simple filters, while table partitioning and read replicas scale globally if needed.

Alternatives

  • Elasticsearch: Overkill for basic text matching. Only worth the operational overhead for complex relevance ranking or heavy faceting.

  • SQLite: Fine for the small sample, but fails under concurrent writes in production.

Why MCP over REST?

A REST API forces you to predict every endpoint in advance. MCP gives the model typed tools to compose on the fly, leveraging the existing chat surface instead of building a new UI.

Trade-offs

REST is still easier to cache, version, and rate-limit for non-agent software. If programmatic tools needed access, I would expose the search logic via a light REST API alongside /mcp. Same underlying engine, two different interfaces.

Local HTTP server

docker compose up -d

Serves http://127.0.0.1:3000/mcp with the token local-dev-token. Put MCP_AUTH_TOKEN or MCP_PORT in a .env file to change them (see .env.example).

Deploy

On a hangar host, which runs Traefik and Postgres with a proxied wildcard for *.xxxx0.top, one command from your laptop deploys the committed code:

./deploy/deploy.sh deploy@<host> wonderful.xxxx0.top

The first run creates the database with hangar's new-project and generates the bearer token into /opt/healthcare/.env; later runs keep both and redeploy. The script prints how to read the token. SSH_KEY=<path> picks the SSH key.

Every request to /mcp is logged as one JSON line with the client IP, user agent, MCP client, method and tool (not the arguments):

ssh deploy@<host> docker logs -f healthcare-mcp-mcp-1

Hangar's Dozzle shows the same logs in the browser. deploy/docker-compose.prod.yml works on any host with Traefik on a shared Docker network; its header lists the variables.

Development

Needs Node 22.9 or later.

npm install
cp .env.example .env
npm run db:up      # Postgres on 127.0.0.1:5432, seeded
npm test
npm run dev        # http://127.0.0.1:3000/mcp, reloads on change; stop the mcp container first if it runs

To mount the endpoint in an existing Hono API:

import { createApp } from "./src/app.js";
import { createDb } from "./src/db.js";

api.route("/", createApp({ db: createDb(process.env.DATABASE_URL!), authToken: process.env.MCP_AUTH_TOKEN! }));

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to search the doktor.mx directory for over 56,000 verified doctors and medical specialists across Mexico. It provides tools for verifying professional licenses, finding specialists by symptoms or conditions, and checking medical insurance compatibility.
    10
    25 npm
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables users to manage medical appointments by searching for doctors, checking availability, and booking sessions through a natural language interface. It serves as a reference implementation for advanced MCP features like symptom-based specialist recommendations and multi-step scheduling workflows.
    6 npm
    MIT