clinic-frontdesk-mcp

clinic-frontdesk-mcp

Enables MCP-compatible clients to act as an AI receptionist for a small medical clinic, handling appointment booking and rescheduling, patient registration, intake, reminders, and FAQ answers.

Category
访问服务器

README

clinic-frontdesk-mcp

Give your LLM a front desk.

CI Python 3.11+ License: MIT MCP tests

An open-source MCP server that turns any MCP-compatible client — Claude Desktop, Claude Code, or your own agent — into an AI receptionist for a small medical clinic.

It handles the front desk: booking and rescheduling appointments, registering patients, taking pre-visit intake, sending reminders, and answering questions about timings, fees and location. The LLM is the brain; this server is the hands.

You:    Book Mr. Shah with Dr. Mehta tomorrow evening for a diabetes follow-up.
Claude: Dr. Mehta has 6:00, 6:30 and 7:00 PM open tomorrow. Which suits him?
You:    6 PM.
Claude: Booked — Rajesh Shah with Dr. Anjali Mehta on Mon 25 Jan 2027 at 6:00 PM,
        for diabetes follow-up. A reminder goes out 24 hours before. Reference #12.

You:    He's had a headache for three days, should he take something?
Claude: I can't advise on that one — it's best discussed with the doctor. Dr. Mehta
        has 11:20 AM free on Tuesday if you'd like to bring the visit forward.

You:    Cancel it, actually.
Claude: That's Rajesh Shah with Dr. Mehta, Mon 6:00 PM, diabetes follow-up.
        Shall I cancel it?          ← nothing has happened yet

Behind those four turns: a patient lookup, a live availability check, a transactional booking, a queued reminder, a clinical question routed away from the model's own opinion, and a destructive action held back for confirmation.

Why it's not just a CRUD wrapper

A calendar with tool descriptions bolted on gets the happy path right and the other paths wrong. The interesting work here is in the failure modes:

The awkward bit How it's handled
Two agents grab the same slot at once Overlap check + insert in one BEGIN IMMEDIATE transaction, behind a partial unique index — details
Clocks jump forward and back Non-existent wall-clock slots skipped, ambiguous ones offered once, durations measured in real elapsed time
"Should he take something for the headache?" A curated clinical vocabulary short-circuits to the doctor redirect — a rule, not a similarity score that can drift
The FAQ has no good answer Returns match: none so the agent escalates instead of inventing clinic policy
The requested slot is gone Returns the nearest alternatives, not a bare error, so the conversation keeps moving
Logs are patient records too Names collapse to initials, phone numbers are masked, before anything is written

What it will not do

This server handles logistics only. It has no clinical knowledge and is not a medical device.

  • No clinical advice. Medical questions return the clinic's standard "please discuss this with the doctor" response, with an offer to book an appointment. This is enforced in code, not left to the model's judgement — see Clinical safety.
  • No diagnoses stored. Intake records what the patient said, in their words.
  • Confirmation before destructive actions. cancel_appointment does nothing without an explicit confirm=true; called without it, it returns a preview to read back to the caller.

Privacy

Patient data stays on the machine running the server, in a single SQLite file. There are no external calls in v1 unless you explicitly configure the optional Twilio adapter.

Logs go to stderr only (stdout is the MCP transport) and PII is redacted before anything is written: phone numbers are masked and names collapse to initials. The audit_log table records every write action in the same redacted form.

The database is not encrypted at rest. Store CLINIC_DB_PATH on an encrypted volume and treat that file as you would any other patient record.

Requirements

  • Python 3.11 or newer
  • Nothing else. SQLite is created and seeded on first run.

Install

Not yet on PyPI. Until the first release, install from source with the git forms below. After publication, uvx clinic-frontdesk-mcp will be the one-line install.

# Run directly from the repository, no clone needed
uvx --from git+https://github.com/prashant-cr/Clinic-front-desk-MCP-server clinic-frontdesk-mcp

# Or clone and install
git clone https://github.com/prashant-cr/Clinic-front-desk-MCP-server
cd Clinic-front-desk-MCP-server
uv pip install -e .

# With the optional SMS adapter
uv pip install -e '.[twilio]'

Connect it to Claude Desktop

Add this to claude_desktop_config.json, then restart Claude Desktop.

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "clinic-frontdesk": {
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/prashant-cr/Clinic-front-desk-MCP-server",
        "clinic-frontdesk-mcp"
      ],
      "env": {
        "CLINIC_DB_PATH": "/Users/you/clinic-data/clinic.db",
        "CLINIC_NAME": "Demo Family Clinic",
        "CLINIC_TIMEZONE": "Asia/Kolkata"
      }
    }
  }
}

Once published to PyPI, args simplifies to ["clinic-frontdesk-mcp"]. If you cloned the repo instead, use "command": "/path/to/repo/.venv/bin/clinic-frontdesk-mcp" with "args": [].

Use an absolute path for CLINIC_DB_PATH — Claude Desktop does not launch the server from your project directory, so a relative path lands somewhere unexpected.

The server also ships a receptionist_system prompt. Select it in your client to put the model into a warm, careful receptionist persona with the safety rules already in place.

Try it: a five-step demo

Start a conversation with the server connected and try these in order. The first run seeds a demo clinic with three doctors, four patients and a FAQ.

  1. "Who are the doctors at the clinic and when do they work?" → list_doctors. Dr. Mehta (general practice, split morning/evening shifts), Dr. Iyer (pediatrics, 20-minute slots), Dr. Sheikh (dermatology, 45-minute consultations).

  2. "What's open with Dr. Mehta next Monday evening?" → check_availability. Returns real bookable slots in clinic-local time, past ones excluded.

  3. "Book Mr. Shah with Dr. Mehta tomorrow evening for a diabetes follow-up." → find_patient, then book_appointment. Read back the confirmation. A reminder is queued for 24 hours before. Try booking the same slot again — you will get the nearest alternatives instead of a bare failure.

  4. "He's been tired in the afternoons for about two months, takes metformin 500mg twice daily, allergic to penicillin." → submit_intake. Then ask "what will the doctor see?" → get_intake returns a one-paragraph brief a doctor can read in ten seconds.

  5. "Actually, can we move that to Wednesday morning? And what are your consultation fees?" → reschedule_appointment (old → new summary, reminder re-queued) and answer_faq.

Then try the guardrails:

  • "He's had a bad headache for three days — should he take something for it?" → the doctor redirect, not advice.
  • "Cancel his appointment." → a preview and a request to confirm. Nothing is cancelled until you say yes.
  • "What's the wifi password?" → match: none, so the agent offers to check with the front desk rather than inventing an answer.

Tools

Read

Tool What it does
list_doctors Doctors with specialty and usual weekly hours
check_availability Open slots for a doctor; falls back to the next three openings when a day is full
find_patient Partial search by name or phone. Returns all matches — never guesses
get_appointments Filter by patient, doctor, date and status
get_intake Intake form plus the ten-second doctor_brief
answer_faq Best FAQ match with a confidence level, or match: none to escalate
daily_summary Per-doctor view of a day: appointments, merged free blocks, pending intakes, unsent reminders

Write

Every write appends a PII-redacted row to audit_log.

Tool What it does
register_patient Creates a patient, or returns the existing record for that phone number
book_appointment Validates and books, queues a 24-hour reminder, returns a read-back confirmation
reschedule_appointment Moves the appointment and re-queues the reminder
cancel_appointment Requires confirm=true. Without it, returns a preview
submit_intake Stores intake and regenerates the doctor brief. Re-submitting replaces it
send_reminder Sends one reminder immediately
process_due_reminders Sends every reminder that has come due. Run periodically
add_faq Lets staff grow the FAQ through the agent

Configuration

All settings are environment variables, all with defaults — the server starts with no configuration at all.

Variable Default Purpose
CLINIC_DB_PATH ./clinic.db SQLite file. Created and seeded on first run
CLINIC_NAME Demo Family Clinic Name used in confirmations and reminders
CLINIC_TIMEZONE Asia/Kolkata IANA zone. All tool input and output is in this zone
CLINIC_SEED true Load demo data when the database is first created
CLINIC_LOG_LEVEL INFO Log verbosity (stderr)
TWILIO_ACCOUNT_SID – All three needed for SMS; otherwise reminders print to stderr
TWILIO_AUTH_TOKEN –
TWILIO_FROM_NUMBER –

Seeding happens only when the database file is created. Restarting never duplicates demo rows or resurrects deleted records. Set CLINIC_SEED=false to start empty for a real clinic.

How it works

  caller ──▶ Claude Desktop / Claude Code / your agent      ← the brain: language, judgement
                       │  MCP over stdio
                       ▼
             ┌───────────────────────┐
             │ server.py             │  14 tools, thin — no logic lives here
             ├───────────────────────┤
             │ scheduling  patients  │  slot maths, conflicts, intake
             │ faq         notifs    │  matching, clinical routing, reminders
             ├───────────────────────┤
             │ db.py  → clinic.db    │  SQLite on your disk. UTC in, local out
             └───────────────────────┘  every write mirrored to a redacted audit_log
                       │
                       └─▶ stderr (redacted logs)   ·   Twilio SMS (optional, off by default)

Nothing leaves the machine unless you configure the Twilio adapter yourself.

Time

Every timestamp is stored in UTC and every tool input and output is in clinic-local time. scheduling.py is the single conversion boundary — nothing above it touches UTC, nothing below it touches local time.

Slots come from a weekly template in schedules, overridden per-day by schedule_exceptions (a holiday closes the day; a time override replaces that day's windows). Slots that would run past the end of a window are dropped, so a 10:00–12:30 window in 20-minute slots ends at 12:20.

DST is handled explicitly: a slot at a wall-clock time that does not exist (spring forward) is skipped, and an ambiguous hour (fall back) is offered once. Slot durations are real elapsed time, so consecutive slots never overlap across a transition.

No double-booking

Two layers, because SQLite has no exclusion constraint:

  1. A partial unique index on (doctor_id, starts_at_utc) for active appointments.
  2. An overlap check and the insert inside one BEGIN IMMEDIATE transaction, which closes the check-then-insert race the index alone cannot cover for partial overlaps.

Clinical safety

Routing medical questions to the doctor is a rule, not a similarity score. Scoring failed it in both directions during development: "I have a bad headache for 3 days" fell below the escalation floor purely for being a long sentence, while the generic keyword take pulled "do you take insurance?" toward the medical entry.

A curated CLINICAL_TERMS vocabulary in faq.py now short-circuits to the redirect entry, which the seed marks with the reserved keyword medical. You can reword that answer for your clinic — just keep the keyword on it.

Development

uv venv
uv pip install -e '.[dev]'

uv run pytest -q                 # 248 tests
uv run ruff check . && uv run ruff format --check .
uv run mypy src/

Inspect the server with the MCP Inspector, pointing it at the installed entry point — the same command Claude Desktop runs:

# Interactive browser UI
npx @modelcontextprotocol/inspector .venv/bin/clinic-frontdesk-mcp

# Or drive it from the terminal
npx @modelcontextprotocol/inspector --cli .venv/bin/clinic-frontdesk-mcp --method tools/list
npx @modelcontextprotocol/inspector --cli .venv/bin/clinic-frontdesk-mcp \
  --method tools/call --tool-name list_doctors

Note that mcp dev src/clinic_frontdesk_mcp/server.py:mcp does not work here: it loads the file as a standalone module, which breaks the package-relative imports. Point the Inspector at the entry point instead, as above — it also exercises the real console script rather than a special-cased import.

Layout

src/clinic_frontdesk_mcp/
├── server.py         # MCP tool definitions only — thin, delegates everything
├── scheduling.py     # slot maths, conflict detection, the local<->UTC boundary
├── patients.py       # patient records and intake
├── faq.py            # FAQ matching and clinical-question detection
├── notifications.py  # reminder delivery adapters
├── db.py             # schema, migrations, seeding, redacted audit log
├── models.py         # domain dataclasses
└── config.py         # environment configuration

Business logic lives in the domain modules and is testable without MCP. If a tool body in server.py grows past a screen, the logic belongs somewhere else.

Not in v1

No web UI, no authentication or multi-tenancy, no real WhatsApp integration (the adapter interface is there), no EMR/FHIR integration, no payments, no multi-clinic support.

License

MIT — see LICENSE.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选