WiseMatch exposes a Model Context Protocol
(MCP) server so an AI agent on your platform can search WiseMatch providers as
a tool call. The search_providers tool finds providers that match a
patient’s state, insurance, care type, and preferences, and returns ranked
provider records with availability summaries.
The intended workflow: the agent searches for a provider and a slot that fit
the patient, then booking happens in the WiseMatch UI — every slot in the
results carries a bookingUrl that opens WiseMatch with that provider and
slot preselected. From there the booking is completed directly, either by the
agent driving a browser or by handing the link to a human.
Endpoint
https://pluto.wisematch.com/mcpThe MCP endpoint is at /mcp on the API host, not under /api/v1.
Transport
The server speaks JSON-RPC 2.0 over stateless Streamable HTTP.
-
Send every message as an HTTP
POSTto the MCP endpoint. -
Set both headers on every request:
Content-Type: application/json Accept: application/json, text/event-stream -
The server is stateless. It does not issue or require an
Mcp-Session-Id, so you can calltools/listortools/calldirectly, without aninitializehandshake first. Clients that sendinitializestill work.
Any MCP client that supports the Streamable HTTP transport can connect. Point it at the endpoint URL above.
search_providers
Only state and timezone are required, and insurance is highly
recommended for an accurate match. Everything else narrows or re-ranks the
results. For anything the structured filters don’t capture — “a warm
therapist who works with new parents” — put it in freeText, which refines
the ranking semantically.
curl -X POST https://pluto.wisematch.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "search_providers",
"arguments": {
"state": "CA",
"timezone": "America/Los_Angeles",
"insurance": "aetna",
"careType": "THERAPY",
"clinicalNeeds": [{ "id": "ANXIETY", "required": true }],
"genderPreferences": ["FEMALE"],
"daysOfWeek": ["MON", "TUE"],
"hourRanges": [{ "startHour": 8, "endHour": 12 }],
"pagination": { "pageSize": 5 }
}
}
}'Arguments
| Field | Type | Required | Description |
|---|---|---|---|
state |
enum | Yes | Two-letter US state the patient will receive care in. |
timezone |
enum | Yes | IANA zone used to interpret hourRanges and the weekly availability windows: America/New_York, America/Chicago, America/Denver, or America/Los_Angeles. |
insurance |
enum | No | Highly recommended for an accurate match. Canonical payor code (e.g. aetna) — the same insurancePayer codes returned by GET /insurance-payers. |
careType |
enum | No | THERAPY (default) or MED_MANAGEMENT. |
therapyType |
enum | No | COUPLES. INDIVIDUAL is accepted but treated as no filter — every provider offers individual therapy. The field is also ignored for MED_MANAGEMENT, and COUPLES is ignored when patientPopulations includes a minor band; stale combinations are dropped rather than rejected. |
patientPopulations |
array<enum> | No | Age groups the provider must see: CHILDREN, PRETEENS, TEENAGERS, ADULTS, SENIORS — the same age bands as the roster’s specialty patient populations, uppercase. Empty means the default adult pool. |
clinicalNeeds |
array<filter> | No | What the patient needs help with, e.g. ANXIETY, DEPRESSION, TRAUMA. Filter objects. |
modalities |
array<filter> | No | Treatment approaches, e.g. CBT, EMDR, DBT. Filter objects. |
genderPreferences |
array<enum> | No | MALE, FEMALE, NO_PREFERENCE. |
languages |
array<filter> | No | Languages the provider speaks, as full words — ENGLISH, SPANISH, MANDARIN_CHINESE. Filter objects. |
siteOfCare |
enum | No | VIRTUAL or IN_PERSON. |
daysOfWeek |
array<enum> | No | Only count availability on these days: MON, TUE, WED, THU, FRI, SAT, SUN. |
hourRanges |
array<object> | No | Preferred time-of-day windows in timezone, e.g. { "startHour": 8, "endHour": 12 }. startHour is 0–23; endHour is a half-open bound from 1–24 (24 means end of day) and must be greater than startHour. |
pagination |
object | No | { "pageSize": ..., "pageToken": ... }. pageSize is 1–100, default 20. To fetch the next page, pass the previous result’s nextPageToken as pageToken. |
freeText |
string | No | Semantic free-text query used for ranking, e.g. a sentence describing what the patient is looking for. |
Filter objects
clinicalNeeds, modalities, and languages each take a list of
{ "id": <code>, "required": <bool> } objects. required defaults to
false:
"required": true— hard filter; providers without the attribute are excluded."required": false— preference; matching providers rank higher but non-matching ones still appear.
When you send exactly one clinical need or exactly one language, it is treated as required — a lone filter has nothing to be preferred over.
Example response
The result arrives as JSON text in the tool result’s content; parsed, it’s
a results array of ranked providers plus a pagination object:
{
"results": [
{
"providerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"displayName": "Jane Sample, LMFT",
"states": ["CA"],
"languages": ["ENGLISH", "SPANISH"],
"specialties": [{ "id": "ANXIETY", "label": "Anxiety" }],
"modalities": ["CBT", "EMDR"],
"siteOfCare": ["VIRTUAL"],
"genders": ["FEMALE"],
"insurances": ["aetna", "cigna"],
"availabilitySummary": {
"nextSlotAt": "2026-10-05T16:00:00Z",
"slotCount": 12,
"slotsThisWeek": 4,
"matchesPreferredWindow": true,
"weeklySlots": [
{
"weekStart": "2026-10-02",
"weekEnd": "2026-10-08",
"slots": [
{
"startTime": "2026-10-05T16:00:00Z",
"mode": "VIRTUAL",
"bookingUrl": "https://app.wisematch.com/wisematch/start?pid=3fa85f64-5717-4562-b3fc-2c963f66afa6&i=2026-10-05T16%3A00%3A00Z&mode=VIRTUAL",
"matchesFilter": true
}
]
}
]
},
"matchScore": 0.92
}
],
"pagination": { "pageSize": 5, "nextPageToken": "5" }
}The parts that matter most:
- Results are ranked —
matchScoreruns 0.0 to 1.0 and the first result is the best match. providerIdis the same identifier used by/slotsand/appointments.insurancescarries payor codes; map them to display names withGET /insurance-payers.statesuses the usual US state codes.- To page through results, pass
pagination.nextPageTokenback aspagination.pageTokenon the next call; it’s null on the last page.
Availability summary
availabilitySummary is where to look for whether the patient can actually
get in:
nextSlotAt— the next open slot; null when there are none.slotCountandslotsThisWeek— total upcoming slots, and slots in the rolling 7-day window starting today (requesttimezone).matchesPreferredWindow— true when the provider has slots inside the requesteddaysOfWeek/hourRanges.weeklySlots— the individual slots, grouped into rolling 7-day windows (weekStart/weekEndinYYYY-MM-DD, request timezone). Each slot carriesstartTime(ISO 8601 UTC),mode(VIRTUAL/IN_PERSON),bookingUrl, andmatchesFilter(true when it falls inside the requested time windows).