MCP server for Open Dental — dental practice management API. Read patients, appointments, providers, procedures, recalls. Write commlogs (phone calls, messages) back to the patient chart.
Open Dental MCP has solid naming conventions (all tools start with action verbs: get_, find_, create_, update_, list_, log_) and comprehensive parameter descriptions. However, output schemas are not documented, tools return JSON strings without declaring the structure of returned objects. Error handling is present but generic (catches OpenDentalError base class). Parameter validation is minimal; several tools accept free-form JSON strings (updates_json, appointment_json, comm_datetime) without format constraints or examples. Descriptions are adequate (avg ~150 chars) but lack dependency hints and recovery guidance. No tool annotations (readOnlyHint, destructiveHint) despite clear risk levels (READ_ONLY vs WRITE). Pagination is implemented (limit params) but no cursor/offset or total count returned.
Create a new appointment. ``appointment_json`` is a JSON object string with at minimum: ``PatNum``, ``AptDateTime``, ``ProvNum``, ``Op``, ``AppointmentTypeNum``. See Open Dental API docs for the full schema.
List appointments with optional filters. Use ``date=YYYY-MM-DD`` for a single day, or ``date_start`` + ``date_end`` for a range. Filter by ``patnum``, ``provnum``, or ``clinicnum``.
Search for patients by name / phone / email / DOB. Returns matching records. At least one criterion must be provided. Use this to find a patient's PatNum before calling ``get_patient`` or other record-specific tools.
List procedure log entries (treatments performed). Filterable.
Fetch a single appointment by AptNum.
Output schemas not documented. Tools return JSON strings (via _json() helper) but callers cannot see the structure of returned objects (patient fields, appointment fields, etc.). LLMs cannot plan downstream tool calls or extract specific fields without trial-and-error.
Free-form JSON string parameters (updates_json, appointment_json, comm_datetime) lack format constraints, examples, or validation guidance. LLMs cannot infer the required JSON structure without external documentation. No regex patterns or enum constraints.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | <=2025-11-25 | v2 |
Fetch a single patient by PatNum (Open Dental's internal patient ID).
List appointment type definitions (cleaning, filling, exam, etc.).
List clinics (offices) accessible to this developer account.
List operatories (treatment rooms). Optionally filter by clinic number.
List all providers (dentists + hygienists) in the practice.
Log a phone call, email, text, or other communication to a patient's chart.
Update fields on an existing patient record. ``updates_json`` is a JSON object string of fields to change, e.g. ``'{"Email": "[email protected]", "WkPhone": "5551234567"}'``. Only fields included in the object will be modified.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk levels declared in metadata (READ_ONLY vs WRITE). LLMs cannot distinguish safe reads from destructive writes without explicit hints.
Error handling is generic. Catches OpenDentalError base class and formats via _format_error(), but does not provide recovery guidance. E.g., 'Resource not found' does not suggest calling find_patients() first.
Pagination implemented (limit params) but no cursor, offset, or total count returned. find_patients returns {count, patients} but find_appointments, find_procedurelogs do not document whether results are truncated or if more pages exist.