Documentation / MCP
The MCP server
HyperCRM exposes its API over the Model Context Protocol as one streamable-HTTP JSON-RPC endpoint, so an MCP client can work with patients, appointments, billing, forms, files and reporting — under the same practice scoping and role gates as the REST API.
Breaking changes in 0.2.0
Three tools were renamed when the write_* convention landed, and there are no aliases: create_patient and update_patient are now write_patient with action=create or update, and add_patient_note is write_patient_note with action=create. Two ways to do one thing measurably hurts tool selection, so the old names are gone rather than deprecated.
Which plan this needs
The REST API and the MCP server are included on the Complete plan and are not available on Essential. The pricing page lists every band. An OAuth client is not created in settings: it registers itself the first time it connects, and an owner on Complete approves it, with a verified email address and a sign-in from the last ten minutes. An approval lasts 90 days and is then asked for again. Settings, Account, Connected apps is where you see what is connected and disconnect it.
What you get
75 tools — 47 reads, 28 writes, across patients, appointments, billing and invoices, forms, files, the catalogue (chairs, locations, services, tags), practice and people, analytics and search, notifications, the website builder, and for a dental practice the dental chart. Every one is backed by the same services, validation and permissions the REST API uses, so an agent cannot reach anything a signed-in member of your practice could not.
No MCP resources or prompts are exposed — resources/list and prompts/list both return empty. Tools are the whole surface.
Connecting
One endpoint, POST /api/v1/mcp, speaking JSON-RPC 2.0 over streamable HTTP:
{
"mcpServers": {
"hypercrm": {
"type": "http",
"url": "https://your-hypercrm-origin/api/v1/mcp"
}
}
}
OPTIONS /api/v1/mcp answers CORS preflight. The endpoint sets no Access-Control-Allow-Credentials header, which is safe precisely because every call needs an explicit bearer token rather than an ambient cookie — a cross-origin page cannot ride a signed-in user's session onto it.
Authorisation
Every tool call requires Authorization: Bearer <token>. The server implements the MCP authorisation spec: OAuth 2.1 with mandatory PKCE (S256), protected-resource and authorisation-server metadata documents, and dynamic client registration. A Firebase ID token is also accepted, which is the simpler path if you already have one.
Access tokens last about an hour and refresh tokens 30 days; the refresh token is rotated on every use, so a leaked one is single-use. Tokens are opaque random strings, never JWTs, and only their hash is stored.
Practice scoping
practiceId is always taken from the token and never from tool arguments. No tool's input schema even declares it, and the write paths strip any practiceId a client sends before it reaches a service. That is enforced by a test across all 75 tools rather than left to reviewer attention, because a single tool accepting a practice id would turn the whole server into a cross-tenant read.
Role gates
MCP enforces the same owner-only rules as the REST API. Reports, the audit log, practice settings, invitations, staff changes, and every website write are owner-only; patients, appointments, files, notifications, the catalogue reads and the form reads are open to any practice member. One tool is split: write_form needs the owner's role for every action except create_link, because handing a patient a form is reception's job and deciding what the form asks is not. The tool catalogue marks each one, and the reasoning is worth stating plainly: without matching gates, MCP would be a way around permissions the REST API enforces.
Errors
A tool that fails still returns HTTP 200 with a valid JSON-RPC envelope. The failure is reported inside the result:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"isError": true,
"structuredContent": {
"status": 400,
"ok": false,
"error": {
"code": "validation_failed",
"message": "Request validation failed.",
"details": [{ "path": ["firstName"], "message": "firstName is required" }]
}
}
}
}
That is the same error shape the REST API returns, so one error handler covers both surfaces. Transport-level problems — malformed JSON, an unknown method, bad tools/call arguments — return HTTP 400 with a JSON-RPC error object (-32700, -32600, -32601, -32602, -32603).
The one exception is a missing, invalid or expired credential: per the MCP authorisation spec that gets HTTP 401 with a WWW-Authenticate header pointing at the metadata document, which is what lets a client start the OAuth flow on its own.
What is deliberately not exposed
| Not available over MCP | Why |
|---|---|
| The OAuth endpoints | Circular — they are how a client gets its token in the first place. |
| Passkey/WebAuthn ceremonies | Browser-only, and revoking a credential risks locking an account out. |
| Public booking, public form submission, the contact form | Unauthenticated widgets. An agent-driven contact-form submitter is a spam vector. |
| Accepting a staff invitation | A browser redemption flow belonging to the invited person, not the caller. |
| File and asset uploads | The bytes go browser-to-storage directly and never pass through the server. |
| CSV export | Tools always return JSON. |
The OAuth flow, end to end
What a client does the first time it connects, and what your user sees while it happens.
Discover
The client calls the endpoint with no token, receives a 401 naming the protected-resource metadata document, and fetches that and the authorisation-server metadata.
Register
The client registers itself with a name and its redirect URIs, and receives a client id. No secret is issued — MCP clients are public clients.
Ask the user
The client opens a browser at the authorisation endpoint with PKCE parameters. After signing in, your user sees a consent screen naming the client and the account it would act as, with Approve and Deny.
Approve
Approving mints a one-time authorisation code and redirects back to the client with it.
Exchange
The client exchanges the code plus its PKCE verifier for an access token (about an hour) and a refresh token (30 days).
Refresh
On expiry the client exchanges the refresh token for a new pair. The old refresh token is invalidated on use, so each one works exactly once.
Next
All 75 tools
Every tool by domain, with its arguments, whether it writes or deletes, whether it reaches outside HyperCRM, and which role can call it.
REST API reference
The same capabilities over HTTP, with full field-level reference for patients and appointments.
Patient tools
Ten tools for the patient record, its clinical notes, files, billing entries and invoices.
Appointment tools
Four tools for bookings, chair blocks and computed availability.
Billing tools
Five tools for the billing ledger and the invoices issued from it.
Form tools
Five tools for intake and consent forms and their submissions. Building a form is the owner's; reading and sending one is not.
File tools
Two tools: read a file with a signed link, or delete one permanently.
Analytics tools
Six tools for dashboard figures, the three reports, the audit log and search.
Notification tools
Two tools for the calling user's own inbox.
Practice and people tools
Eight tools for the practice profile, its members and staff invitations.
Website tools
Ten tools for the practice website and its blog, including the one that publishes it.
Catalogue tools
Seven tools for chairs, locations, services and patient tags.
Dental chart tools
Six tools for the dental chart and gum chart exams. Only a dental practice has them.
Common questions
Patient records are encrypted, both where they are stored and on their way to your screen. Files are private, and a link to one stops working after a short time. Changes to patient records are recorded, with who made them and when. There is no shared practice password: everyone has their own account. On the Complete plan, the practice owner can also require two-step sign-in for the whole team.
No. The practice is resolved from the token, never from a tool argument, and no tool's input schema accepts a practice id — a test asserts that across all 75. An agent connected to your practice reaches exactly what a signed-in member of it could reach, and nothing else.
Every tool declares MCP annotations and tools/list returns them, so a client can tell reads from writes, and writes from deletes, without calling anything. Twenty tools can delete or void data and five reach outside HyperCRM: sending an invitation email, emailing an invoice, publishing the website, minting a public form link, and filing a bug report with us.
No. create_patient, update_patient and add_patient_note were removed in 0.2.0 rather than aliased, because offering two ways to do one thing measurably degrades a model's tool selection. Use write_patient and write_patient_note with an action argument.
Not today. Both resources/list and prompts/list return empty, and tools are the entire surface. A resource- or prompt-shaped view of your practice data is not something the server exposes today, so every integration goes through the tool list.