clinic-mcp-server
clinic-mcp-server
MCP Server: Company Data as Claude Tools.
Expose a clinic's knowledge base and structured records to Claude Desktop (or any MCP client) as callable tools — with the same grounding discipline as docs-rag-chatbot: read tools grounded with citations; write tools gated behind approval.
That contrast is the pitch. Anyone can wrap a search endpoint. Showing you thought about what happens when an agent can change something is what senior looks like.
Architecture
Claude Desktop (stdio MCP)
│
▼
clinic-mcp-server
├─ search_clinic_docs → hybrid RRF over shared `chunks` (pgvector + tsvector)
│ + SIMILARITY_FLOOR gate → citations or "no relevant sources"
├─ get_patient_record → Postgres `patients` (+ next confirmed appointment)
├─ list_appointments → parameterized date-range query on `appointments`
└─ create_appointment → INSERT into `appointment_requests` (pending only)
NEVER writes confirmed `appointments`Shares DATABASE_URL with docs-rag-chatbot (same Postgres). Retrieval code is local; the RAG chunks table is reused as-is. Clinic tables (patients, appointments, appointment_requests) are additive.
Prerequisites
Postgres/pgvector running for docs-rag-chatbot with docs ingested (
make up && make ingestthere).Python 3.12 + uv.
Quick start (two minutes)
cd clinic-mcp-server
uv sync
cp .env.example .env # DATABASE_URL should match docs-rag-chatbot
# Create clinic tables + seed Jordan Lee et al. (does not touch chunks)
make setup
# Smoke-test over stdio (or point Claude Desktop at it — see below)
make serveClaude Desktop config
Add this to your Claude Desktop claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json). Use absolute paths:
{
"mcpServers": {
"clinic": {
"command": "/Users/leovet/.cargo/bin/uv",
"args": [
"run",
"--directory",
"/Users/leovet/freelance/clinic-mcp-server",
"python",
"-m",
"clinic_mcp"
]
}
}
}Restart Claude Desktop. You should see four tools under the clinic server.
A ready-to-merge example lives at claude_desktop_config.example.json.
Tip: find
uvwithwhich uvif your install path differs.
Demo (~60s)
Open Claude Desktop with the MCP server connected — show the four tools.
Ask: "Do you accept Delta Dental PPO?"
→ Claude callssearch_clinic_docs, answers with a source citation (e.g.06_insurance_faq.md).Ask: "when is Jordan Lee's next appointment?"
→ Claude callsget_patient_recordwithjordan-lee, returns structured data (insurance, upcoming crown consult).Ask: "book Jordan a crown consult next Tuesday"
→ Claude callscreate_appointment; response ispending_approval— nothing committed to the confirmed calendar.Close: "Read tools answer. The write tool proposes and waits for a human."
Tools
Tool | Mode | Behavior |
| read | Hybrid retrieval; below |
| read | Patient row + next confirmed appointment. Missing patient / DB down → tool error (not empty success). |
| read | Confirmed appointments in an inclusive date window (clinic TZ). Empty list is valid; DB failure is an error. |
| write (gated) | Inserts |
Demo patient id: jordan-lee.
Config (.env)
Variable | Purpose | Default |
| Shared Postgres (same as RAG app) |
|
| Dense cosine gate for doc search |
|
| Timezone for date windows / naive datetimes |
|
Makefile
make sync # uv sync --extra dev
make setup # schema + seed
make schema # clinic tables only
make seed # demo patients / appointments
make serve # stdio MCP server
make test # pytestSafety contract
Grounded reads:
search_clinic_docsrefuses weak matches instead of returning noise Claude could cite.Loud failures: DB outages raise
[db_unavailable] …tool errors. Empty appointment lists are only returned when the query succeeded.Guarded writes:
create_appointmentnever inserts intoappointments. A human must approve the pending request before anything is confirmed.Out of scope (intentionally): auth, multi-tenancy, OAuth, remote hosting, MCP resources/prompts. Four tools done well beats twelve half-wired.
Tests
make testCovers tool discovery/schemas, Pydantic validation, retrieval gate + citations, structured errors, patient/appointment lookups, and the invariant that write calls create pending requests only.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/leomengineer/clinic-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server