Start from the clinical boundary
The first decision was what the server must never do. Every consultation is reviewed in full by an EU-licensed doctor, who decides on medical grounds only (see Safety). No tool available to a patient approves a consultation, issues or changes a prescription, or changes a dose. Those actions are not hidden behind a permission; they are absent. Eligibility checks stay on Hi Doctor’s servers, which run them the same way on every interface. Everything else follows from that line. The assistant’s job in a consultation is to help the patient say what is true, one question at a time, so the questionnaire tools return one question, record one answer, read the answers back, and submit only when asked. The server decides which question comes next, so the model never evaluates a clinical condition itself. Data that could steer a patient towards eligibility does not belong in a model’s context at all. Questionnaire results expose only the fields needed to ask the question and record the answer; answer-evaluation metadata is removed from every questionnaire output rather than accompanied by an instruction to ignore it.Scopes decide what a connection gets
OAuth scopes decide which groups of tools a connection gets: profile, consultations, messages, questionnaires, payment and health tracking, with separate write scopes for changes. A tool whose scope was not granted is not listed. Every tool reaches only what Hi Doctor’s API already lets that account see; the server adds no access of its own.Fewer, clearer tools
Anthropic’s guidance on writing tools for agents and the Claude connector review criteria point the same way: a small set of clearly separated tools, reads separate from writes, and descriptions that state facts rather than instruct the model. We applied that conservatively. Reads and writes stay separate tools, and create, update and delete stay distinct, because a catch-all tool with a hidden destructive branch is worse for safety than one extra entry in the list. Where names were inconsistent, the new name is listed and the old one keeps working for a transition period, so existing clients do not break. Tools would only be merged or hidden if a measured selection test showed real overlap within the same safety class; a tool that is rarely chosen is a candidate for review, not proof that it is redundant. The test did not show that overlap on the look-alike pairs we declared in advance, so the catalog kept the same number of tools and the work went into names, descriptions and schemas. Every tool carries a human title and honest hints: whether it only reads, changes data, is destructive, is safe to repeat, or reaches Stripe. Clients use those hints to decide when to ask the user. Hints are a courtesy to the client, never a substitute for the server’s own checks.A budget for the catalog
The tool list is paid for on every turn. We set a hard budget for the patient catalog: at most 20,000 tokens for the completetools/list response,
counted with the cl100k_base tokenizer (a stated proxy, not any provider’s
billing count), including output schemas.
On 6 October 2026 the patient catalog landed at 19,974 tokens against a budget
of 20,000, which is why the budget is enforced by a test rather than left as a
target. The catalog has grown since, so these figures describe that snapshot;
the test is the current guarantee, and the current list is in the
patient tools reference.
Most of the savings come from schemas, not prose. Repeated output schemas for
the questionnaire tools were the largest single cost. We narrowed schemas
where the data allowed it, but never dropped a required structured result or
weakened validation to hit the number.
A budget for every result
A tool result is also context. Every result, counting both the structured data and its text copy, is capped at 100,000 characters and 20,000cl100k_base tokens, below the limits published for hosted Claude clients and
Claude Code. When a list would exceed the cap, the server returns the longest
complete prefix that fits, says so, and gives the exact offset to continue
from. A single record too large to return becomes an error that explains how
to narrow the request. Nothing is cut in the middle of a value, and totals are
never silently changed.
Before the change, some results were far over that cap. After it, every
result either fits the cap or comes back as a prefix with a continuation
offset, or as an error that explains how to narrow the request.
A cap alone is not enough, though: a bounded error protects the context
window but does not answer the question, so after testing the cap was adjusted
until ordinary reads, such as a single consultation, fit within it.
Continuation that does not lose rows
Lists default to a concise form, because a short summary per row is usually what the next step needs. The earlier concise form showed at most five rows of a page, which made it easy for a model to sum five payments and report them as the total. Concise lists now honour the requested limit, report how many rows came back, whether there are more, and the next offset to request.Errors a model can act on
Validation, conflict and refusal errors come back as tool results with a stablecode, a readable message, and the field or missing fields to fix, so a
model can correct itself or ask the user. Raw error text and upstream traces
are never passed through. Authorization failures are handled at the HTTP
layer, so clients can start sign-in or ask for a missing permission instead of
seeing a generic failure.
How we measured it
Deterministic tests cover the contract: every tool definition, scope enforcement, privacy filters, budgets and continuation. They prove the server behaves as specified; they say nothing about whether a model picks the right tool. For that we also ran real agents on test accounts with synthetic data, checking which tool they chose, whether multi-step tasks ended with the account in the expected state, and how each tool handles invalid input, a missing permission and another account’s ID. The clearest change was the missing-permission case. Before, a missing permission came back as a tool error; now it is an HTTP 403 challenge that names the permission, so a client can ask the person to approve it. These checks use synthetic patients and one agent family, so they describe how this server behaves rather than make a general claim about every model or client.What is not supported?
As of 4 November 2026, the connector does not support the 2026-07-28 version of the MCP specification or client ID metadata documents. Every client we target supports dynamic registration. Changes are recorded in the changelog.Frequently asked questions
Can a Hi Doctor MCP tool approve a consultation or prescribe?
No. Those tools do not exist for patients. Every consultation is reviewed in full by an EU-licensed doctor, who decides on medical grounds only.How does the server limit what an assistant can reach?
OAuth scopes decide which groups of tools a connection gets, and a tool whose scope was not granted is not listed. Every tool reaches only what Hi Doctor’s API already lets that account see.Why does the catalog have a token budget?
The tool list is sent to the model on every turn, so its size is a cost on every request. A test fails if the patient tools/list response grows past 20,000 cl100k_base tokens.What happens when a result is too large?
The server returns the longest complete prefix that fits the result budget, says so, and gives the offset to continue from. Nothing is cut in the middle of a value.How was the server tested?
Deterministic tests cover the contract, and real agents ran tasks on test accounts with synthetic data. The results describe this server, not every model or client.Next steps
Privacy and security of the Hi Doctor MCP
Sign-in, tokens, consent and confidential links.
Patient tools reference
Every patient tool, its scope and its hints.
MCP or REST for healthcare integrations
Which Hi Doctor surface fits your product.
Streamable HTTP
Transport and OAuth reference for client builders.