MCP Server (@dentolize/plugin-mcp)
The first-party Model Context Protocol server for the Dentolize plugin platform. If you are building an AI agent — a WhatsApp booking bot, a Claude/Cursor workflow, a voice assistant — you do not need to hand-wrap our REST API: run this server and your agent gets curated, scope-aware tools for the whole patient journey (lookup → book → invoice → collect → reply).
It is a thin, stateless wrapper over the same REST API described in REST API: every tool call is a normal authenticated API request, subject to your granted scopes, rate limits, IP allowlist and audit logging. Nothing bypasses the platform.
What it is
- One server instance = one installation. It boots with a single plugin token and serves that token's scope surface.
- Scope-aware tool registry. On startup it calls
GET /pingand registers only the tools the token's scopes allow. An agent with a read-only token physically cannot see or call the write tools — no prompt-injection path to a booking or an invoice. - ~20 curated tools, not 100 auto-generated operations: descriptions are written for LLM consumption and precise about side effects ("the message IS actually sent to the patient's phone").
- Reference docs as MCP resources: the authentication and webhooks guides plus the full scope and event catalogs ship inside the package (
dentolize://docs/authentication,.../webhooks,.../scopes,.../events).
Running it
Stdio (what Claude Desktop / Claude Code / Cursor spawn):
DENTOLIZE_TOKEN=dtz_live_... npx @dentolize/plugin-mcp
mcp.json:
{
"mcpServers": {
"dentolize": {
"command": "npx",
"args": ["-y", "@dentolize/plugin-mcp"],
"env": { "DENTOLIZE_TOKEN": "dtz_live_..." }
}
}
}
Streamable HTTP for shared/remote deployments (stateless /mcp endpoint):
DENTOLIZE_TOKEN=dtz_live_... npx @dentolize/plugin-mcp --http 8808
Configuration: DENTOLIZE_TOKEN (required, environment only), DENTOLIZE_BASE_URL or --base-url (defaults to production https://api.dentolize.com/api/v1; point it at your sandbox with a dtz_test_… token while developing).
Tools
| Tool | Kind | Scope(s) |
|---|---|---|
lookup_patient |
read | patients:read |
get_patient |
read | patients:read |
get_clinic_profile |
read | clinic:read |
list_branches |
read | clinic:read |
list_practitioners |
read | practitioners:read |
list_procedures |
read | procedures:read |
find_available_slots |
read | availability:read |
list_appointments |
read | appointments:read |
get_appointment |
read | appointments:read |
list_conversation_messages |
read | conversations:read |
list_events |
read | webhooks:manage |
create_patient |
write | patients:write |
update_patient |
write | patients:write |
create_appointment |
write | appointments:write |
reschedule_appointment |
write | appointments:write |
cancel_appointment |
write | appointments:write |
create_invoice |
write, money path | invoices:write |
create_payment_link |
write, money path | paymentlinks:write |
send_message |
write | communications:send |
reply_conversation |
write | conversations:write |
Read tools carry the MCP readOnlyHint annotation so hosts can auto-approve them; write tools spell out their side effects and the mutating ones carry destructiveHint. Every POST-backed write sends an automatic Idempotency-Key — a transport retry can never double-book or double-invoice.
Errors surface as MCP tool errors containing the standard platform envelope (code, message, status, requestId, structured details such as pendingAmount), so an agent can recover ("offer the pending amount instead").
A typical booking-bot session: lookup_patient(phone) → (create_patient if unknown) → list_practitioners(isDoctor: true) → find_available_slots → create_appointment → after the visit create_invoice → create_payment_link → reply_conversation.
Security notes
- Token via environment only. There is deliberately no
--tokenflag (argv leaks into process listings), and the server never writes the token to any log or error. Inject it from a secret manager. - stdout is protocol-clean in stdio mode; all diagnostics go to stderr.
- Least privilege beats prompt hygiene. Grant the agent's installation only the scopes its job needs — ungrated tools are never registered, which is a far stronger guarantee than instructing the model not to use them.
- IP allowlisting (Authentication & Scopes) applies to the server's outbound API calls like any other plugin backend — pin the token to your infrastructure's egress IPs.
- HTTP mode has no auth of its own: whoever reaches the port acts with the token's scopes. Bind to localhost or front it with your own authenticated proxy; prefer stdio when the agent runs on the same host.
- Use
dtz_test_…tokens against the sandbox while iterating on prompts and flows; production rejects test tokens.