Skip to main content
Glama

clinic-mcp

Эталонный сервер Model Context Protocol для записи на прием и первичного осмотра в клинике. Написан на TypeScript со строгой типизацией, структурированными ошибками и изоляцией арендаторов, обеспечиваемой на уровне данных. Данные являются синтетическими. Это не медицинское программное обеспечение.

Цель состоит в том, чтобы показать, как выглядит MCP-сервер производственного уровня для вертикали, требующей изоляции данных и обоснованных результатов: это та же структура кода, которую я пишу в Rentive, но с фиктивными данными и другой предметной областью, чтобы шаблоны можно было изучить, не раскрывая ничего проприетарного.

Зачем нужен MCP

Приложения на базе LLM продолжают изобретать одни и те же способы взаимодействия: специальные определения функций для каждого провайдера, индивидуальный парсинг аргументов, отсутствие общего транспорта, отсутствие согласованной модели ошибок. MCP — это небольшой открытый протокол, который исправляет уровень взаимодействия. Сервер предоставляет список типизированных инструментов через stdio (или HTTP), и любой клиент, поддерживающий MCP (Claude Desktop, интеграции с IDE, пользовательские агенты), может обнаруживать и вызывать их с помощью одного и того же механизма.

Для бэкендов предметной области это означает, что вы пишете инструменты один раз, и они работают везде. Для разработчиков агентов это означает, что вы перестаете вручную создавать схемы инструментов и начинаете компоновать серверы.

Related MCP server: tenant-scoped-crm

Архитектура

flowchart LR
    Client["MCP client<br/>(Claude Desktop, custom agent)"]
    Server["clinic-mcp server"]
    Tools["Tools<br/>find_available_slot<br/>book_appointment<br/>record_intake<br/>search_protocols<br/>escalate_to_oncall"]
    Store["ClinicStore<br/>tenant-scoped accessors"]
    Seed[("seed.json<br/>synthetic clinics, providers,<br/>patients, protocols")]

    Client -->|stdio JSON-RPC| Server
    Server --> Tools
    Tools --> Store
    Store --> Seed

Каждый инструмент принимает clinic_id, и хранилище гарантирует, что все операции чтения и записи ограничены этой клиникой. Доступ между арендаторами вызывает TenantMismatchError, а не молчаливый возврат неверной строки. Это отражает шаблон безопасности на уровне строк, который производственное развертывание обеспечивало бы в Postgres, представленный здесь в коде приложения, чтобы гарантию можно было проверить в одном файле (src/store/index.ts).

Запуск локально

Требуются Node 20+ и pnpm.

git clone https://github.com/dominikstefanski/clinic-mcp.git
cd clinic-mcp
pnpm install
pnpm test          # 29 tests
pnpm typecheck
pnpm dev           # boots the server on stdio

Сервер считывает src/store/seed.json при запуске и обслуживает две синтетические клиники: clinic_north (общая практика, кардиология, дерматология) и clinic_west (педиатрия, общая практика).

Подключение к Claude Desktop

Добавьте это в конфигурацию Claude Desktop (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json). Замените путь на ваш локальный клон.

{
  "mcpServers": {
    "clinic-mcp": {
      "command": "npx",
      "args": ["-y", "tsx", "/absolute/path/to/clinic-mcp/src/server.ts"]
    }
  }
}

Перезапустите Claude Desktop. Пять инструментов появятся в меню подключений. Попробуйте запрос вроде "Найди свободное время для общей практики в clinic_north в следующий понедельник утром."

Справочник инструментов

Все инструменты возвращают { ok: true, ...result } в случае успеха или { ok: false, error: { code, message } } в случае ошибки. Входные данные проверяются с помощью zod; ошибки аргументов на уровне MCP возвращаются как ошибки validation с деталями по полям.

find_available_slot

Поиск свободных слотов для записи по специальности в диапазоне дат, пропуская конфликты.

Поле

Тип

Примечания

clinic_id

string

Обязательно

specialty

enum

general_practice

pediatrics

cardiology

dermatology

from_iso

string

Включительно, начало ISO 8601

to_iso

string

Исключительно, конец ISO 8601

duration_minutes

int

от 15 до 120, по умолчанию 30

limit

int

от 1 до 50, по умолчанию 10

book_appointment

Создание записи на прием. Требует предоставленный вызывающим объектом idempotency_key; повторные вызовы возвращают исходную запись вместо создания дубликата. Голосовые агенты будут повторять попытки, поэтому это поле обязательно.

Поле

Тип

Примечания

clinic_id

string

Обязательно

provider_id

string

Должен принадлежать clinic_id

patient_id

string

Должен принадлежать clinic_id

start_iso

string

ISO 8601

duration_minutes

int

от 15 до 120, по умолчанию 30

reason

string

от 1 до 500 символов

idempotency_key

string

от 8 до 128 символов, предоставляется вызывающим

Возвращает { appointment, idempotent_replay }.

record_intake

Сохранение структурированной заметки о первичном осмотре и назначение уровня сортировки (triage).

Поле

Тип

Примечания

clinic_id

string

Обязательно

patient_id

string

Должен принадлежать clinic_id

symptoms

string[]

от 1 до 20 записей

severity

int

от 1 до 10, со слов пациента

onset_iso

string

ISO 8601

notes

string

Необязательно, макс. 2000 символов

Правило сортировки: тяжесть >= 8 — urgent (срочно), >= 5 — elevated (повышенная), в противном случае — routine (планово).

search_protocols

Поиск по ключевым словам в библиотеке протоколов клиники. Возвращает ранжированные фрагменты, на которые модель может ссылаться при ответе.

Поле

Тип

Примечания

clinic_id

string

Обязательно

query

string

от 1 до 500 символов

limit

int

от 1 до 20, по умолчанию 5

Текущая реализация — это простой TF-скоринг с весом заголовка (3x). Он существует, чтобы продемонстрировать интерфейс инструмента поиска; в производственных развертываниях бэкенд был бы заменен на векторный поиск (см. примечания по проектированию).

escalate_to_oncall

Пометка существующей записи как срочной и переназначение ее на дежурного врача клиники.

Поле

Тип

Примечания

clinic_id

string

Обязательно

appointment_id

string

Должен принадлежать clinic_id

reason

string

от 1 до 500 символов, добавляется к причине записи

Возвращает { appointment, on_call_provider, reassigned }.

Примечания по проектированию

Изоляция арендаторов обеспечивается в хранилище, а не в инструменте. Инструменты принимают clinic_id и передают его дальше. Хранилище проверяет право собственности при каждом доступе и выбрасывает TenantMismatchError при несовпадении. Если вы добавите новый инструмент завтра, вы не сможете случайно допустить утечку между клиниками; хранилище не позволит этого сделать.

Идемпотентность при записи. book_appointment требует idempotency_key. Реальные вызывающие стороны (голосовые агенты, циклы повторных попыток, сетевые сбои) будут повторять запросы, а система здравоохранения, которая реагирует на повторные попытки созданием дубликатов записей, — это система, которая теряет доверие с первого дня.

Структурированные ошибки вместо выброшенных строк. Каждая ошибка предметной области является типизированным подклассом DomainError со стабильным code. Обертка MCP превращает их в { ok: false, error: { code, message } }. Клиенты могут выполнять ветвление по code вместо использования регулярных выражений для message.

Инструмент поиска является временным решением. search_protocols использует TF-скоринг в памяти, поэтому репозиторий работает без внешних сервисов. В производстве это место, где вы подключаете Pinecone, pgvector или выбранный вами бэкенд поиска. Контракт ввода/вывода инструмента остается прежним.

Обработка времени упрощена. Рабочие часы провайдера интерпретируются в UTC для ясности. Реальное развертывание учитывало бы часовой пояс каждой клиники (уже есть в схеме). Я указываю на это явно, чтобы рецензенты знали, что это намеренно, а не недосмотр.

Чем это не является

  • Не является медицинским программным обеспечением. Правило сортировки — игрушечное, а корпус протоколов — написанная вручную проза. Не используйте его для чего-либо, что касается реальных пациентов.

  • Не соответствует требованиям HIPAA. Данные поддельные, хранилище находится в оперативной памяти, журнал аудита отсутствует. Для производства потребовалось бы все это и многое другое.

  • Не является полноценным EMR или бэкендом планирования. Цель состоит в том, чтобы показать форму MCP-сервера, а не поставлять систему для клиники.

Лицензия

MIT. См. LICENSE.

Available Tools

5 tools
book_appointmentBook an appointmentB

Create an appointment for a patient with a provider. Requires an idempotency_key; repeated calls with the same key return the original appointment instead of double-booking.

ParametersJSON Schema
NameRequiredDescriptionDefault
clinic_idYes
provider_idYes
patient_idYes
start_isoYesAppointment start, ISO 8601
duration_minutesNo
reasonYes
idempotency_keyYesCaller-supplied key. Repeated calls with the same key return the original appointment instead of double-booking.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses idempotency behavior (returns original on repeat), which is useful for safe retries, but omits other behavioral traits like required permissions, side effects, or error states.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences: one states the core purpose, the other adds critical idempotency detail. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 7 parameters, no output schema, and zero annotations, the description is incomplete. It does not explain return value, error handling, or scheduling constraints like business hours.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 29% (2/7 params described). The description does not add meaning for undocumented parameters (e.g., clinic_id, provider_id, patient_id, duration_minutes, reason) beyond their names, failing to compensate for low coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool creates an appointment for a patient with a provider, distinguishing it from sibling tools like find_available_slot (which finds slots) and record_intake (which records intake).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide guidance on when to use this tool versus alternatives like find_available_slot, nor does it specify prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

escalate_to_oncallEscalate an appointment to the on-call providerC

Mark an existing appointment as urgent and reassign it to the clinic's on-call provider.

ParametersJSON Schema
NameRequiredDescriptionDefault
clinic_idYes
appointment_idYes
reasonYes

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It only states 'mark as urgent and reassign' without detailing side effects (e.g., notifications, status changes) or reversibility.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence is efficient but omits critical details; adequate but could include a brief second sentence without losing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Lacks output description and any mention of consequences or constraints (e.g., irreversibility), leaving the agent uninformed for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, and description adds no parameter details beyond names. 'reason' is not explained as the reason for urgency; clinic_id/appointment_id are self-evident but lack any validation context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('mark as urgent and reassign') and resource ('existing appointment'), and clearly distinguishes from sibling tools like book_appointment or find_available_slot.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool vs alternatives, no prerequisites (e.g., appointment must exist), and no conditions to avoid (e.g., already escalated).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_available_slotFind available appointment slotsB

Return open appointment slots for a given specialty in a date range. Filters by clinic_id and skips conflicts with existing appointments.

ParametersJSON Schema
NameRequiredDescriptionDefault
clinic_idYes
specialtyYes
from_isoYesInclusive start of the search window, ISO 8601
to_isoYesExclusive end of the search window, ISO 8601
duration_minutesNo
limitNo

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses that it 'skips conflicts with existing appointments,' indicating a read-only, availability-checking behavior. However, it does not mention whether it requires authentication, whether it is idempotent, or any side effects. The behavioral disclosure is partial but not misleading.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the main action. Every word serves a purpose: what it returns, the key filters, and the conflict avoidance. No fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite moderate complexity (6 params, no output schema), the description omits important details: return format (list of slot times?), ordering, pagination, error conditions. The sibling 'book_appointment' suggests a workflow, but no linkage is provided. The description is too sparse for complete agent understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is low (33%, only from/to have descriptions). The description adds meaning for specialty and date range, and mentions clinic_id filtering. But it does not explain duration_minutes or limit parameters. Given low coverage, the description partially compensates but leaves gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Return open appointment slots' with specific constraints ('given specialty in a date range', 'Filters by clinic_id'). This distinguishes it from sibling tools like 'book_appointment' (booking) and 'record_intake' (recording). The verb and resource are immediately clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide any guidance on when to use this tool versus alternatives, such as before booking an appointment or when an immediate slot is needed. It describes what it does but lacks explicit context for selection among siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

record_intakeRecord patient intakeB

Persist a structured intake note (symptoms, severity, onset) for a patient and assign a triage level (routine / elevated / urgent).

ParametersJSON Schema
NameRequiredDescriptionDefault
clinic_idYes
patient_idYes
symptomsYes
severityYesPatient-reported severity, 1 (mild) to 10 (worst imaginable)
onset_isoYesWhen symptoms began, ISO 8601
notesNo

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations; description only states it persists and assigns triage level, but fails to disclose side effects, authorization needs, or how triage is determined.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence of 15 words, no redundancy, efficient and direct.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, no description of return value (e.g., triage level or record ID), insufficient to fully specify tool behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Description mentions 'symptoms, severity, onset' but omits 'clinic_id', 'patient_id', and 'notes'. Schema coverage is 33%, leaving param gaps unaddressed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('persist') and the resource ('structured intake note') with key fields, distinguishing it from sibling tools like 'book_appointment'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives. No mention of prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_protocolsSearch clinic protocol documentsB

Keyword search over the clinic's protocol library. Returns ranked snippets the model can cite when answering.

ParametersJSON Schema
NameRequiredDescriptionDefault
clinic_idYes
queryYes
limitNo

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Without annotations, the description carries full burden. It discloses that the tool returns ranked snippets that can be cited, which is informative, but lacks details on side effects, authentication, or rate limits. The behavior is adequately described for a simple read-only search.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with two front-loaded sentences, each adding value: it states the action and the return format. No extraneous words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of output schema and parameter descriptions, the description is incomplete. It does not specify return structure beyond 'snippets', nor does it clarify the role of clinic_id. The tool requires more context for reliable use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description does not explain any parameters (clinic_id, query, limit). The agent must infer semantics solely from the parameter names and constraints, which is insufficient.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs keyword search over the clinic's protocol library and returns ranked snippets for citation, making its purpose distinct from sibling tools that handle appointments, escalation, slot finding, and intake recording.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for searching protocols via keyword, but does not provide explicit guidance on when to use this tool versus alternatives or when not to use it.

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.

  1. 5 tool updatesv0.1.0
    • First observedbook_appointment
    • First observedescalate_to_oncall
    • First observedfind_available_slot
    • First observedrecord_intake
    • First observedsearch_protocols

TDQS

A3.5/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: booking appointments, escalating to on-call, finding slots, recording intake, and searching protocols. No two tools overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case, making it easy to predict the action and resource for each tool.

Tool Count5/5

With exactly 5 tools, the server is well-scoped for a clinic domain, covering core patient-facing and administrative workflows without being overly heavy or thin.

Completeness3/5

The set covers appointment creation, urgent escalation, slot availability, intake recording, and protocol search. However, it lacks read/update/delete for appointments and any patient or provider management, which are notable gaps.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    A reference MCP server demonstrating safe agent access to multi-tenant CRM data with tenant isolation enforced in the data layer, role-based permissions, and human confirmation on writes.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server reference implementation adding enterprise layers (identity, authorization, audit) around MCP, with sample shipment status and delayed shipment tools over a stateless transport.
    Apache 2.0