Docs

Agent MCP server

Connect an AI agent to Doctronic's free AI consult over MCP without credentials, collect intake and terms acceptance, show Doctronic's safety and emergency text verbatim, and hand the person off to doctronic.ai for care.

The Doctronic agent MCP server lets an AI agent run Doctronic's AI consult for the person it's helping. It's the same free AI consult a person starts on doctronic.ai without signing in. The agent connects without an account, API token, or sign-in, and the person stays anonymous. The consult is for adults 18 and over in the United States.

Private beta

The agent MCP server, its endpoints, and its directory listings are in private beta. The production endpoint isn't open yet. Build and test against the staging endpoint.

The rest of these docs cover the Doctronic API, which your backend calls with an API token for your organization's patients. The agent MCP server is separate. It has its own endpoint and doesn't go through the Doctronic API:

Agent MCP serverDoctronic API
CallerAn AI agent acting for one personYour backend, for your organization's patients
CredentialsNoneAn API token for your organization
The person's identityAnonymous until they continue on doctronic.aiMapped to a user ID by your backend
The consultAn anonymous doctronic.ai consultA conversation for one of your users
Care after the consultA one-time link to doctronic.aiAppointments, enabled per organization
ProtocolMCP over Streamable HTTPREST and Server-Sent Events

To run consultations for your own patients inside your product, use the Doctronic API. See get access.

Connect

SettingValue
Endpointhttps://mcp.doctronic.ai/ (private beta, not open yet)
Staging endpointhttps://staging-mcp.doctronic.ai/, for building and testing. Its limits can differ from production.
TransportStreamable HTTP, with JSON responses
AuthenticationNone
SessionsNone. The server keeps no state between requests. The intake_token and consult_id carry it.

The server is the whole host, so the endpoint is the root URL with nothing after it. Add it to your MCP client as a remote HTTP server with no authentication. To use staging, put https://staging-mcp.doctronic.ai/ in place of the production URL.

Claude Code
claude mcp add --transport http doctronic https://mcp.doctronic.ai/
Cursor: .cursor/mcp.json or ~/.cursor/mcp.json
{
  "mcpServers": {
    "doctronic": {
      "url": "https://mcp.doctronic.ai/"
    }
  }
}
Other clients that read an mcpServers file
{
  "mcpServers": {
    "doctronic": {
      "type": "http",
      "url": "https://mcp.doctronic.ai/"
    }
  }
}
  • Claude on the web, desktop, or mobile: add a custom connector in Claude's connector settings, with the endpoint as its remote MCP server URL. Leave the OAuth fields empty.
  • ChatGPT: turn on developer mode, then add the endpoint as a remote MCP server with no authentication.

Client settings screens vary and change over time. Look for the option to add a remote MCP server by URL.

To check the connection from a terminal, list the tools:

curl --fail-with-body --request POST "https://mcp.doctronic.ai/" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json, text/event-stream" \
  --header "User-Agent: ExampleAgent/1.0 (agent)" \
  --data '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'

Name your agent in the User-Agent header. Clients that don't identify as an agent get a lower limit on new consults. See limits.

Run a consult

A consult starts in two steps. start_consult returns the intake questions and the terms. Your agent asks the questions and shows the terms. submit_intake sends the answers and starts the consult.

  1. Call describe_service. Show the person what Doctronic offers.
  2. Ask the person which US state they're in. Call start_consult with that state.
  3. Show the person disclosure once, with the intake questions. Ask each question in questions one at a time, using its prompt. Use the person's answers, not values inferred from other context.
  4. Show the person terms.text word for word, with the terms of service and privacy policy links. When web_consent_required is false, ask whether they accept. When it's true, don't ask in chat. Doctronic asks on its own page. See terms.
  5. Call submit_intake with the intake_token, the person's answers, and whether they were shown and accepted the terms. If the person has already described their concern, send it as initial_message. Keep the consult_id it returns.
  6. If status is consent_pending, the person accepts the terms on doctronic.ai first. See web consent.
  7. Relay the assistant's message to the person. Send each reply with continue_consult until status is assessment_ready or ended.
  8. When status is assessment_ready, call get_assessment and share the result.
  9. Call get_care_options. If the person wants care from a Doctronic physician, follow hand off for care.

If the person describes a possible emergency before Doctronic has replied, show them emergency_text first. See emergency text.

The AI consult is free. describe_service and get_care_options return physician visit prices.

Talk to the person

The server instructions, the tool descriptions, and each next_step carry these rules. The server can't enforce them, so your agent has to follow them.

  • One question at a time. When the person's app can present a question with choices or a short form, use it for the intake questions and for any Doctronic question that offers options. Otherwise ask in plain text. The intake questions are age, sex, and accepting the terms when web_consent_required is false.
  • The person answers. Never answer a question or accept the terms on the person's behalf.
  • Doctronic's words only. Relay Doctronic's questions and replies in Doctronic's words. Add no medical assessment, advice, or emergency instructions of your own. When the person needs safety guidance, the result carries it in safety.text.
  • Verbatim text stays verbatim. Show terms.text, emergency_text, and safety.text when safety.display_verbatim is true exactly as written.
  • The disclosure once. Show disclosure once, with the intake questions.
  • Identifiers stay in tool calls. Never show or read intake_token or consult_id to the person. The code from submit_intake or create_handoff is the one identifier the person sees, with its link.
  • Terms acceptance in chat only without web consent. When web_consent_required is true, the person accepts on a Doctronic page through an accept_terms link. An answer in chat doesn't count.

Tools

ToolPurposeRead-only
describe_serviceDescribes what Doctronic offers, who it's for, prices, limits, the terms and privacy links, Doctronic's emergency text, and how to start.Yes
start_consultChecks the person's state and returns the intake questions, the terms to show, and an intake token. Creates no consult.No
submit_intakeSends the person's answers and terms acceptance, starts the consult, and returns its consult_id.No
continue_consultSends the person's next message and returns the assistant's reply.No
get_assessmentReturns the consult's status, title, differential, SOAP note, and summaries.Yes
get_care_optionsLists care options with prices, availability, and the handoff each one needs.Yes
create_handoffCreates a one-time link and code that move the consult to doctronic.ai, or a new consent link while consent is pending. A book_visit link needs a finished assessment.No
get_handoff_statusReports whether the person has used a consent link or a handoff link.Yes

Read-only tools carry the MCP readOnlyHint annotation. start_consult creates no consult, but it counts toward the new-consult limit, so it isn't read-only. Calling it again returns a new intake token. Errors come back as MCP tool errors with a plain-language message.

start_consult

ArgumentRequiredNotes
stateYesThe person's two-letter US state code, such as NY. DC is accepted.
timezoneNoAn IANA timezone, such as America/New_York. Defaults to UTC. Send the same value to submit_intake.

The call returns a tool error when state isn't a US state code, timezone isn't an IANA timezone name, or the new-consult limit is reached.

Result fieldMeaning
intake_tokenPass it to submit_intake. It works once. Treat it as opaque, and never show it to the person.
expires_atWhen the intake token expires, as Unix seconds (UTC). It lasts 15 minutes.
questionsThe intake questions. Each has a field and a prompt to ask. The sex question also has options.
termsThe terms to show the person. See terms.
web_consent_requiredtrue when Doctronic requires the person to accept the terms on doctronic.ai. See web consent.
emergency_textDoctronic's 911 and 988 text, for the intake. See emergency text.
Representative start_consult result (some fields omitted)
{
  "intake_token": "dct_int_...",
  "questions": [
    { "field": "age", "prompt": "How old are you?" },
    { "field": "sex", "prompt": "What is your sex? (female or male)", "options": ["female", "male"] }
  ],
  "terms": {
    "text": "The exact terms text to show the person.",
    "version": "...",
    "terms_url": "https://www.doctronic.ai/terms-of-service/",
    "privacy_url": "https://www.doctronic.ai/privacy-policy/",
    "display_verbatim": true
  },
  "web_consent_required": false,
  "emergency_text": "If this may be a medical emergency, call 911 or go to the nearest emergency room now. If you are thinking about harming yourself, call or text 988 to reach the Suicide and Crisis Lifeline."
}

Terms

terms has the text to show, its version, the terms_url and privacy_url links, and display_verbatim, which is always true.

Show the terms verbatim

Show terms.text to the person word for word, with links to terms_url and privacy_url. Don't summarize, shorten, or reword it. Use the text from the current result, not a stored copy. Only the person can accept the terms. Never accept them on the person's behalf.

When web_consent_required is false, ask the person whether they accept, and report their answer in submit_intake. When it's true, show the terms but don't ask for acceptance in chat. The person accepts on a doctronic.ai page instead. See web consent.

Doctronic records that the person was shown the terms and accepted them, with the terms version.

submit_intake

ArgumentRequiredNotes
intake_tokenYesThe token from start_consult.
ageYesThe person's age in years. Must be 18 or older.
sexYesfemale or male.
person_shown_termsYestrue only after you showed the person terms.text word for word.
person_accepted_termsYestrue only when the person told you they accept the terms.
initial_messageNoThe person's first message, up to the message length limit.
timezoneNoAn IANA timezone. Defaults to UTC.

The call returns a tool error when:

  • The intake token is invalid, expired, or already used.
  • The person is under 18, or age isn't an age in years.
  • person_shown_terms is false.
  • initial_message is too long, or timezone isn't an IANA timezone name.
  • The daily consult limit is reached.

If the person declines the terms, don't call submit_intake. The consult can't run without them. To let the person read and accept the terms on doctronic.ai instead, set person_accepted_terms to false.

The result has these fields. Which ones are set depends on status.

Result fieldMeaning
consult_idThe handle for this consult. Pass it to every other tool. Never show it to the person.
expires_atWhen the consult_id expires, as Unix seconds (UTC).
statusconsent_pending while the person still has to accept the terms on doctronic.ai. Otherwise gathering, assessment_ready, or ended. See consult status.
messageThe assistant's reply to initial_message, when one was sent.
ctaA suggested next step. See calls to action.
conversation_endedtrue when the assistant ended the conversation.
off_topictrue when Doctronic treated the message as outside the consult.
consent_urlThe doctronic.ai page where the person accepts the terms. null unless status is consent_pending.
codeThe consent link's code. Pass it to get_handoff_status. null unless status is consent_pending.
consent_expires_atWhen the consent link expires, as Unix seconds (UTC). null unless status is consent_pending.
emergency_textDoctronic's 911 and 988 text, for the wait before the person accepts. null unless status is consent_pending. See emergency text.

When the person accepted the terms and Doctronic doesn't require web consent, the consult starts right away. If you sent initial_message, the result carries the assistant's reply. If that first message fails, you still get the consult_id, and next_step tells you to send the message again with continue_consult.

Otherwise, status is consent_pending. See web consent.

Doctronic can require the person to accept the terms on a doctronic.ai page instead of in your agent's conversation. When it does, web_consent_required is true, and submit_intake returns consent_pending whatever person_accepted_terms says. You still show the terms and set person_shown_terms, but you don't ask the person to accept them in chat.

  1. Show the person the consent_url and code. The page shows Doctronic's terms and asks them to accept.
  2. When the person says they're done, call get_handoff_status with the consult_id and code. A status of claimed means they accepted.
  3. Send the person's first message with continue_consult. submit_intake doesn't send initial_message while consent is pending.

If the person describes a possible emergency while they wait, show them emergency_text from the consent_pending result exactly as written, before anything else. Send what they said with continue_consult once they've accepted.

Until the person accepts, continue_consult returns a tool error. Accepting the terms doesn't move the consult, so your consult_id keeps working.

Only the doctronic.ai page can claim a consent code. The page runs Doctronic's bot protection before it records the acceptance, so your agent can't accept the terms for the person by sending the code to the page's web API.

A consent link expires at consent_expires_at, 15 minutes after it's created. If it expires before the person accepts, call create_handoff with purpose set to accept_terms for a new link. Its continue_url is the new consent page. Once the person has accepted, create_handoff refuses that purpose.

continue_consult

ArgumentRequiredNotes
consult_idYesThe handle from submit_intake.
messageYesThe person's next message in their own words, up to the message length limit.
timezoneNoAn IANA timezone. Defaults to UTC.

The result has consult_id, status, message, cta, conversation_ended, and off_topic, as above.

The call returns a tool error when:

  • The person hasn't accepted the terms yet.
  • The consult has ended, moved to doctronic.ai, or doesn't exist.
  • The consult has used all its turns. The error points you to get_assessment and create_handoff.
  • message is empty or too long.
  • Doctronic couldn't finish the reply. The error asks you to try again.

A call refused because consent is pending, or because the consult moved to doctronic.ai, doesn't count as a turn.

Send one message at a time and wait for its result. When a tool error asks you to try again, wait a moment and send the message again. Don't resend a message automatically after a call times out with no result: Doctronic may already have processed it.

get_assessment

The result has status, title, differential, soap_note_markdown, summary, and detailed_summary_markdown.

  • detailed_summary_markdown is the consult's detailed summary for the person. On a symptom consult it lists the likely conditions in rank order, with the tests and treatments to discuss with a physician. This is where the likely conditions are on most consults.
  • differential is the same list in structured form, with a likelihood and the findings for and against each condition. Doctronic only fills it when the consult ran on a flow that publishes one; otherwise it's null, and the detailed summary carries the list. Present either as possibilities to discuss with a clinician, not as a diagnosis.
  • summary is the consult's short summary for the person.
  • summary and detailed_summary_markdown are null while status is gathering.
  • Before the consult is complete, most fields are null.

An ended consult's assessment stays readable until its consult_id expires.

get_care_options

The result has options and an insurance note. Each option has option, label, description, price_usd, availability, requires_handoff, and handoff_purpose.

optionhandoff_purposeWhat it is
video_visitbook_visitA video visit with a licensed Doctronic physician, who reviews the consult first. Bookable once the assessment is ready.
prescription_refillrefillA refill of an existing prescription after physician review, in states that allow asynchronous telehealth visits. Controlled substances aren't prescribed.
save_consultsave_consultKeeps the consult on doctronic.ai. Free.

Show the person the prices and availability from the result. insurance says which options take insurance. Doctronic confirms coverage on doctronic.ai.

Consult status

statusMeaningWhat to do
consent_pendingThe person hasn't accepted the terms on doctronic.ai yet.Show the consent_url. Continue once get_handoff_status reports claimed.
gatheringThe assistant is still asking questions.Relay its message and send the person's answer with continue_consult.
assessment_readyThe consult is complete.Call get_assessment, then get_care_options.
endedThe conversation is over, for example after a safety event.Show any safety text first. Send no more messages for this consult. get_assessment still returns what it produced. If the person wants to go on, start a new consult.

What every result carries

Every tool result includes three fields:

FieldContentsWhat your agent does
disclosureA fixed statement that Doctronic is an AI health tool, not a physician, that the consult isn't a diagnosis, and to call 911 in an emergency.Show it to the person once, with the intake questions.
safetyThe safety state of this result. See safety.Check it before anything else in the result.
next_stepOne sentence about what to do next.Use it to choose your next call. It's written for your agent, not for the person.

Safety

Representative safety field in an emergency
{
  "level": "emergency",
  "text": "If this may be a medical emergency, call 911 or go to the nearest emergency room now. If you are thinking about harming yourself, call or text 988 to reach the Suicide and Crisis Lifeline.",
  "display_verbatim": true
}
levelMeaningtext
noneNo safety condition.null
cautionDoctronic flagged a safety concern.A message for the person.
emergencyThe person may need emergency care.The 911 and 988 instructions above, sometimes after a message about the person's situation.

Show safety text verbatim

When display_verbatim is true, your agent displays text to the person word for word, before anything else from that result. Don't summarize, shorten, reword, or leave it out.

When level is emergency:

  • Show the safety text first, and stop the routine flow. Don't offer care options, booking, or other next steps in the same reply.
  • Don't send another message for the person automatically.

The server doesn't contact emergency services. The safety text tells the person how to get help.

Decide from the safety field, not from the assistant's wording.

Emergency text

Before Doctronic has replied to the person, no result carries safety.text. For that stretch, these results carry emergency_text, the same 911 and 988 text an emergency safety result ends with:

Resultemergency_text
describe_serviceAlways set, so your agent has it before it asks the person anything.
start_consultAlways set.
submit_intakeSet when status is consent_pending. Otherwise null.

If the person describes a possible emergency during the intake, or while they wait to accept the terms, show them emergency_text exactly as written, before anything else. Then go on:

  • During the intake, send what they said as initial_message with submit_intake.
  • While they wait to accept the terms, send what they said with continue_consult once they've accepted. The intake is already spent.

Once Doctronic has replied, the safety field carries any emergency guidance. Add none of your own.

Calls to action

cta has a kind and an optional text label. kind is null when there's no call to action.

kindMeaning
see_doctorA visit with a physician may help. Offer a book_visit handoff once status is assessment_ready.
see_doctor_in_personAn in-person visit may help. Show text when present.
emergency_roomEmergency care may be needed. Treat it like an emergency safety result.
refillA prescription refill may fit. Offer a refill handoff.
saveOffer a save_consult handoff.
otherAnother next step. Show text when present.

When safety.level is emergency, the safety text takes precedence over any call to action.

The consult_id

submit_intake returns a consult_id that begins with dct_cons_. Pass it to every other tool.

  • It's state, not identity. It names one anonymous consult. It doesn't identify the person, and it isn't a credential for anything else at Doctronic.
  • Treat it as opaque. Its contents are encrypted. Don't parse it or build one.
  • Keep it in tool calls. Never show or read it to the person. The same goes for the intake_token.
  • Keep it with the person's conversation. Anyone who holds it can continue and read that consult. Use one per person, keep it out of logs, and don't share it.
  • It expires after 24 hours. After that, tools return an error, and the person needs a new consult. To keep the consult, create a save_consult handoff before it expires.
  • A claimed handoff ends agent access. Once the person confirms a book_visit, refill, or save_consult handoff, the consult belongs to their Doctronic account. The consult_id stops working for it. get_handoff_status still answers. Accepting the terms at a consent link doesn't end agent access.

Hand off for care

The MCP server doesn't book visits, take payment, or handle prescriptions. doctronic.ai does, after a one-time handoff.

  1. Call get_care_options and show the person the options, their prices, and their availability.
  2. When the person picks one, call create_handoff with its handoff_purpose.
  3. Show the person the continue_url and code from the result. Tell them the page will ask them to sign in to Doctronic, or create a free account, and to confirm the consult is theirs. The result also has the code's expires_at and instructions for your agent.
  4. The person opens the link, signs in, and confirms. Doctronic moves the consult to their account and opens it on doctronic.ai, and your consult_id stops working.
  5. To see whether they've used the link, call get_handoff_status. It returns pending, claimed, or expired.
purposeWhere the person lands on doctronic.ai
book_visitThe booking flow, with this consult, to book a video visit with a licensed Doctronic physician. If booking can't start, the consult opens instead.
refillThe consult, where they can request a prescription refill.
save_consultThe consult, saved to their account.

Booking needs a finished assessment

create_handoff refuses book_visit until the consult's status is assessment_ready, because booking a visit needs the consult's SOAP note. The refusal creates no code and tells your agent to keep the consult going with continue_consult. If the person wants to see a doctor now, send that in their words, so Doctronic can wrap up. If the consult ended before the assessment was ready, the person needs a new consult to book from.

A handoff code works like a ticket:

  • One use. The first person to open the link and confirm claims the consult. Show the link only to the person in the consult.
  • Short-lived. An unused code expires after 15 minutes. If it expires, create a new one.
  • No identity. The code doesn't identify the person, and it grants nothing once claimed or expired.
  • For the person only. The doctronic.ai page completes a bot check before it claims a code. Your agent can't claim a code itself, whether to continue a consult or to accept the terms.

Every expires_at in a tool result is in Unix seconds (UTC). The doctronic.ai pages behind consent_url and continue_url read the code through their own web API, which reports times in ISO 8601. Your agent doesn't need that API. It can't claim a code through it either, because a claim needs the page's bot check.

Limits

LimitCurrent valueWhen it's reached
Requests per client IP address120 per minuteHTTP 429 with a Retry-After header
New consults per client IP address10 per hour, or 3 per hour for clients that don't identify as an agentstart_consult returns a tool error
New consults per day, across all agents2,000 per UTC daysubmit_intake returns a tool error until the next UTC day
Intake tokenOne use, 15 minutessubmit_intake returns a tool error. Call start_consult again.
Turns per consult60, including a first message sent with submit_intakecontinue_consult returns a tool error. Hand off or start a new consult.
Message length1,152 characters. describe_service reports the current value.The tool returns a tool error
consult_id lifetime24 hoursTools return a tool error. Start a new consult.
Unused consent or handoff code lifetime15 minutesget_handoff_status returns expired. Create a new code.

These are the production defaults. Staging can differ, and limits can change during the private beta. Wait for Retry-After before you retry a 429. Its body is a JSON-RPC error with code -32002.

A refused call comes back as a tool result with isError: true and a short reason. Some MCP clients prefix that text with Error executing tool <name>:. Show the reason to the person when it asks for something only they can do, such as accepting the terms.

When the server is turned off, every request returns HTTP 503 with JSON-RPC error code -32001:

503 Service Unavailable
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32001,
    "message": "The Doctronic agent surface is not enabled."
  },
  "id": null
}

What the server doesn't do

  • No booking, payment, or prescriptions. These need a handoff to doctronic.ai.
  • No account access. The server can't sign anyone in or read a Doctronic account, past consults, or records.
  • No identity. The tools take no name, date of birth, or contact details. Leave them out of consult messages too.
  • No consent on the person's behalf. The person answers the intake questions and accepts the terms. Your agent relays what they said.
  • No emergency dispatch. The server doesn't contact emergency services. It returns emergency text for your agent to display verbatim.
  • No consults for minors or for people outside the United States.
  • No access to your organization's data. It runs its own anonymous consults and can't reach the users or chats you create with the Doctronic API.

On this page