clinic-mcp-server
This MCP server provides an AI agent (like Claude Desktop) with tools to interact with a clinic's knowledge base and appointment system, with safety guards:
search_clinic_docs(query, top_k=5): Hybrid search (pgvector dense similarity + full-text, fused via Reciprocal Rank Fusion) over clinic documents. Returns cited chunks only if above a similarity threshold; otherwise reportsno_relevant_sourcesto prevent fabrication.get_patient_record(patient_id): Retrieves patient details (name, contact, insurance, last visit) and the next confirmed appointment. Errors if patient missing or DB down.list_appointments(date_from, date_to): Lists confirmed appointments in the inclusive date range. Empty list means none found; DB failures raise errors.create_appointment(patient_id, datetime, service): Creates a pending appointment request (status='pending') requiring human approval before being confirmed. Never directly modifies the confirmed calendar.
Safety contract: Read tools are grounded with citations or explicit "no relevant sources"; database errors result in tool errors; the write tool only creates pending requests gated by human approval.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@clinic-mcp-serverDo you accept Delta Dental PPO?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
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.
Related MCP server: vClinic MCP Server
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.
Available Tools
4 toolscreate_appointmentCreate appointment (pending approval)A
Propose a new appointment — does NOT confirm it.
Inserts a row into appointment_requests with status=pending and returns
pending_approval. A human must approve before anything lands on the
confirmed appointments calendar. Calling this twice creates two pending
requests; it never silently books.
| Name | Required | Description | Default |
|---|---|---|---|
| service | Yes | Service to book, e.g. 'Crown consult'. | |
| datetime | Yes | Proposed start time (ISO-8601). Prefer timezone-aware values; naive values use the clinic timezone (America/Los_Angeles). | |
| patient_id | Yes | Existing patient id, e.g. 'jordan-lee'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | |
| message | No | |
| request | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral context beyond annotations: it inserts a row with status=pending, returns pending_approval, requires human approval, and never silently books. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise, uses a short paragraph with a clear first sentence, and each sentence adds unique value. No unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (3 required parameters, approval workflow), the description covers the behavior, return value, side effects, and constraints. The output schema is implied, and the description is sufficient for an AI agent to use correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage with clear parameter descriptions. The tool description does not add further semantics for the parameters, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'propose' and resource 'appointment', clearly distinguishing it from sibling tools like list_appointments which show confirmed ones. It states what it does (inserts a pending request) and what it does not do (confirm).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use it (to propose an appointment requiring approval) and notes that calling it twice creates two pending requests. It implies not for confirmed appointments but does not explicitly state when not to use or name alternatives like list_appointments for checking confirmed ones.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_patient_recordGet patient recordARead-only
Look up a patient by id: name, insurance, last visit, and next confirmed appointment.
Raises a tool error if the patient does not exist or the database is down —
never returns an empty success that could be mistaken for 'no appointments'.
| Name | Required | Description | Default |
|---|---|---|---|
| patient_id | Yes | Stable patient id. Demo patient: 'jordan-lee'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| status | No | |
| patient | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds error behavior (raises error if patient doesn't exist or DB down, never returns empty success) beyond annotations (readOnlyHint, destructiveHint). Provides useful safety context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, no fluff. Efficiently communicates what it does and key behavioral note.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple lookup tool with annotations and output schema, the description adds specific fields returned and error handling. Adequate for the complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear description including a demo value. Description adds no further parameter detail beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Look up a patient by id' and lists specific fields returned. Distinct from siblings: search_clinic_docs, list_appointments, create_appointment are different resources/actions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for retrieving patient info by ID, but no explicit when-to-use or when-not-to-use guidance. Does not mention alternatives despite sibling list being available.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_appointmentsList appointmentsARead-only
List confirmed appointments between date_from and date_to (inclusive).
date_to must be on or after date_from. Empty list with status=ok means no
confirmed appointments in that window — distinct from a database failure,
which raises a tool error.
| Name | Required | Description | Default |
|---|---|---|---|
| date_to | Yes | Inclusive range end (YYYY-MM-DD), clinic local calendar. | |
| date_from | Yes | Inclusive range start (YYYY-MM-DD), clinic local calendar. |
Output Schema
| Name | Required | Description |
|---|---|---|
| count | Yes | |
| status | No | |
| date_to | Yes | |
| date_from | Yes | |
| appointments | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate a read-only, non-destructive tool. The description adds behavioral insight by clarifying that an empty list is distinct from a database error, which helps the agent interpret results correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences front-load the core purpose and critical constraint. Every sentence adds value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists, the description adequately covers the behavior for edge cases (empty vs error). Parameter definitions are fully covered in the schema, and sibling tools are provided for context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both parameters (inclusive range, clinic calendar). The description adds the constraint that date_to must be on or after date_from, but this is a minor addition beyond the schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool lists confirmed appointments within a date range, with inclusive boundaries. Distinguishes from siblings like search_clinic_docs and get_patient_record by focusing on appointment listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes the scenario for use (listing confirmed appointments by date) and specifies that an empty list with status=ok indicates no appointments. However, it does not mention when not to use this tool or provide explicit alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_clinic_docsSearch clinic documentsARead-only
Hybrid-search the clinic knowledge base (pgvector + full-text, RRF-fused).
Returns cited chunks with source filename and scores when the best dense
similarity clears the SIMILARITY_FLOOR gate. Below that floor, returns
status=no_relevant_sources with an empty chunk list — do not fabricate
an answer from weak matches.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Natural-language question about BrightSmile policies, services, insurance networks, pricing, hours, booking rules, or care instructions. | |
| top_k | No | Max chunks to return when the relevance gate passes (default 5). |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | |
| chunks | No | |
| status | Yes | |
| message | No | |
| best_dense_score | Yes | |
| similarity_floor | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and non-destructive. The description adds critical behavioral context: the similarity floor gate and the explicit instruction to not fabricate answers from weak matches. This goes beyond the annotation metadata.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two concise paragraphs. The first sentence immediately states the purpose and method. The second paragraph details return behavior and constraints. No extraneous information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema (as indicated by context signals), so return values are already documented. The description sufficiently covers the search behavior, the relevance gate, and the instruction against fabrication. It is complete for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for both parameters (query and top_k). The description adds no additional meaning beyond what the schema already provides. Baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool performs a 'hybrid-search' of the 'clinic knowledge base' with specific methods (pgvector + full-text, RRF-fused). This distinguishes it from sibling tools like get_patient_record, list_appointments, and create_appointment, which deal with patient data and scheduling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that the tool returns cited chunks only when a similarity floor is met, and otherwise returns status=no_relevant_sources with an empty chunk list. It advises not to fabricate answers from weak matches. However, it does not explicitly state when to prefer this tool over siblings or provide when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
4 tool updates
v0.1.0- First observed
create_appointment - First observed
get_patient_record - First observed
list_appointments - First observed
search_clinic_docs
TDQS
Each tool addresses a distinct task: searching knowledge base, retrieving patient record, listing appointments, and creating appointment requests. No functional overlap exists.
All tools follow a consistent verb_noun snake_case pattern (search_clinic_docs, get_patient_record, list_appointments, create_appointment).
4 tools are well-scoped for a clinic management server, covering search, patient lookup, appointment listing, and appointment creation. Neither too few nor too many.
The set covers basic read and create operations, but lacks tools for updating patient records, confirming/cancelling appointments, or deleting requests, which are notable gaps for a full appointment management workflow.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Connect your team's living knowledge base — docs, data, issues, CRM — to Claude and ChatGPT.
Your office's procedures inside Claude or ChatGPT - verified citations or an honest refusal.
Connect Claude to Fathom meeting recordings, transcripts, and summaries
Medical RAG: semantic search for clinical guidelines, drug interactions, diagnoses & EHR data.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables Claude Desktop to search custom knowledge bases using retrieval-augmented generation via a simple MCP tool.MIT

vClinic MCP Serverofficial
FlicenseNot gradedqualityCmaintenanceEnables AI agents to manage virtual clinic data including patients, visits, diagnoses, treatments, lab/radiology orders, and search medical literature and internal knowledge base.-- FlicenseAqualityDmaintenanceEnables querying a synthetic patient dataset with tools to look up patients by ID, age, disease, name, and get statistics, connecting Claude Desktop to local data.6-
- FlicenseAqualityCmaintenanceEnables Claude to query and manage home-care operations including clients, visits, and compliance, with schema-validated write tools and a tamper-evident audit log.5-
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