---
title: "WiseMatch MCP"
description: "Search WiseMatch providers from an AI agent using the Model Context Protocol."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.wisematch.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WiseMatch MCP

WiseMatch exposes a [Model Context Protocol](https://modelcontextprotocol.io)
(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/mcp
```

The 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 `POST` to the MCP endpoint.
- Set both headers on every request:

```http
  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 call `tools/list` or `tools/call` directly, without an
  `initialize` handshake first. Clients that send `initialize` still 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.

```bash
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](/data-types#us-states) 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`](/api/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&lt;enum&gt; | No | Age groups the provider must see: `CHILDREN`, `PRETEENS`, `TEENAGERS`, `ADULTS`, `SENIORS` — the same age bands as the roster's [specialty patient populations](/data-types#specialty-patient-populations), uppercase. Empty means the default adult pool. |
| `clinicalNeeds` | array&lt;filter&gt; | No | What the patient needs help with, e.g. `ANXIETY`, `DEPRESSION`, `TRAUMA`. [Filter objects](#filter-objects). |
| `modalities` | array&lt;filter&gt; | No | Treatment approaches, e.g. `CBT`, `EMDR`, `DBT`. Filter objects. |
| `genderPreferences` | array&lt;enum&gt; | No | `MALE`, `FEMALE`, `NO_PREFERENCE`. |
| `languages` | array&lt;filter&gt; | No | Languages the provider speaks, as full words — `ENGLISH`, `SPANISH`, `MANDARIN_CHINESE`. Filter objects. |
| `siteOfCare` | enum | No | `VIRTUAL` or `IN_PERSON`. |
| `daysOfWeek` | array&lt;enum&gt; | No | Only count availability on these days: `MON`, `TUE`, `WED`, `THU`, `FRI`, `SAT`, `SUN`. |
| `hourRanges` | array&lt;object&gt; | 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:

```json
{
  "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 — `matchScore` runs 0.0 to 1.0 and the first result is
  the best match.
- `providerId` is the same identifier used by [`/slots`](/api/availability)
  and [`/appointments`](/api/appointments).
- `insurances` carries payor codes; map them to display names with
  [`GET /insurance-payers`](/api/insurance-payers). `states` uses the usual
  [US state codes](/data-types#us-states).
- To page through results, pass `pagination.nextPageToken` back as
  `pagination.pageToken` on 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.
- `slotCount` and `slotsThisWeek` — total upcoming slots, and slots in the
  rolling 7-day window starting today (request `timezone`).
- `matchesPreferredWindow` — true when the provider has slots inside the
  requested `daysOfWeek` / `hourRanges`.
- `weeklySlots` — the individual slots, grouped into rolling 7-day windows
  (`weekStart` / `weekEnd` in `YYYY-MM-DD`, request timezone). Each slot
  carries `startTime` (ISO 8601 UTC), `mode` (`VIRTUAL` / `IN_PERSON`),
  `bookingUrl`, and `matchesFilter` (true when it falls inside the requested
  time windows).

> **Create appointments using the bookingUrl**
>
> A slot's `bookingUrl` opens the WiseMatch UI with that provider and slot
> preselected, where the appointment can be booked directly — by the agent
> driving a browser, or by handing the link to a human to finish in theirs.
> Treat the URL as opaque: send it as returned rather than assembling your
> own.

Source: https://docs.wisematch.com/mcp/index.mdx
