# Build with Emora Health

Emora connects kids, teens, and young adults (ages 0 to 25 and up) with licensed therapists, psychiatrists, and psychologists. Virtual, evidence-based, insurance-covered, and bookable as early as the next day. Most families start at age 4; autism testing from about age 3. This page describes the surfaces AI agents and developers can use to help people get to the right provider, faster.

## What agents can do

- Match a family to a great provider — by state, specialty, age, insurance, and availability.
- Check real-time appointment slots for a specific clinician.
- Estimate the user's exact copay from their insurance and member ID.
- Read clinically-reviewed editorial content on conditions, specialties, and care.
- Surface the canonical crisis-resource payload (988, 911, Crisis Text Line) the moment a user signals risk.
- Hand the user a pre-filled booking or matching-session URL — they confirm.

## MCP server

`POST https://www.emorahealth.com/api/mcp/v1` — Streamable-HTTP MCP, JSON-RPC 2.0, anonymous.

- Server card: https://www.emorahealth.com/.well-known/mcp/server-card.json
- Manifest (microsites): `/.well-known/mcp.json`

### MCP Apps (interactive UI)

We ship interactive tool views per the MCP Apps spec
(https://github.com/modelcontextprotocol/ext-apps). The
`find_provider` tool registers `_meta.ui.resourceUri =
"ui://emora/find-provider/v1.html"` on `tools/list`, and that
URI is served by the MCP server via `resources/read` with mime
type `text/html;profile=mcp-app`. Hosts that speak MCP Apps
(Claude.ai, Claude Desktop, VS Code Insiders, Goose) render the
HTML in a sandboxed iframe alongside the tool's text result. The
iframe is fed the tool's `structuredContent` via `ui/initialize`
and can call back into the server with `tools/call` for
follow-on tools (e.g. start a booking once a clinician is picked).

Hosts that don't speak MCP Apps see the unknown `_meta` field
and ignore it per the spec — the text envelope still carries the
full result, so nothing breaks.

Test locally with `basic-host` from the ext-apps repo:

```bash
git clone https://github.com/modelcontextprotocol/ext-apps.git
cd ext-apps && npm install && cd examples/basic-host
SERVERS='["https://www.emorahealth.com/api/mcp/v1"]' npm start
# open http://localhost:8080
```

### A2UI / generative UI

The MCP Apps `ui://` resources double as A2UI views — same
iframe-rendered-tool-result pattern, same sandboxing rules. The
server-card advertises this under
`capabilities.experimental['mcp-apps']` and
`capabilities.experimental['a2ui']` so probes that look for
either name find a single source of truth.

## A2A agent card

https://www.emorahealth.com/.well-known/agent-card.json

## Agent skills (v0.2.0)

https://www.emorahealth.com/.well-known/agent-skills/index.json

Conformant to https://schemas.agentskills.io/discovery/0.2.0/schema.json. Each entry references a per-skill SKILL.md plus a sha256 digest.

## OpenAPI 3.1 spec

https://www.emorahealth.com/openapi.json — same surface, OpenAPI flavor. Each operation maps 1:1 to an MCP tool.

## OpenAI plugin manifest

https://www.emorahealth.com/.well-known/ai-plugin.json

## llms.txt

- https://www.emorahealth.com/llms.txt
- https://www.emorahealth.com/llms-full.txt
- https://www.emorahealth.com/providers/llms.txt
- https://www.emorahealth.com/conditions/llms.txt
- https://www.emorahealth.com/insurance/llms.txt
- https://www.emorahealth.com/resources/llms.txt

## RFC 9727 API catalog

https://www.emorahealth.com/.well-known/api-catalog

## Auth

Anonymous read access. Just call.

- OAuth Protected Resource metadata (RFC 9728): https://www.emorahealth.com/.well-known/oauth-protected-resource
- Web Bot Auth directory (RFC 9421): https://www.emorahealth.com/.well-known/http-message-signatures-directory

## Rate limits

Public agent endpoints emit RFC 9598 rate-limit headers on every response: `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` (seconds-until-reset). Legacy `X-RateLimit-*` headers are also emitted for older clients. On 429 responses a `Retry-After` header carries the wait in seconds. Default: 120 requests / minute / IP. Email `hello@emorahealth.com` if you need more.

## Idempotency

Mutation-style endpoints (`POST https://www.emorahealth.com/api/mcp/v1` — every `tools/call`) accept an `Idempotency-Key` request header per the IETF draft `draft-ietf-httpapi-idempotency-key-header`. Send a UUIDv4 (or any `[A-Za-z0-9_-]{8,128}` random string) and the server will replay the same response for 24h if you retry the request. The replay carries `Idempotent-Replay: true` so a client can tell a fresh response from a cached one.

The cache key is `(bucket, Idempotency-Key, sha256(body))` — changing the body voids the cache hit, so an attacker can't replay a different body under the same key. Only 2xx responses are cached.

## Async jobs

MCP mutation tools (`book_appointment`, `book_matching_session`) return a `job_id` and a `job_url` on `_meta`. Poll `GET https://www.emorahealth.com/api/v1/jobs/{job_id}` for the status — `pending`, `succeeded`, or `failed`. Today these mutations complete in a single round-trip (the actual side-effect happens when the user lands on the pre-filled booking URL), so jobs land in `succeeded` state immediately. The endpoint is in place so when we add real async work (server-side eligibility checks, batch booking) the same lifecycle applies. Jobs are retained for 24h.

```http
GET /api/v1/jobs/job_5b8d4c7a-2f1e-4a8b-9c2d-3e1f0a8b7c4d HTTP/1.1
```

```json
{
  "id": "job_5b8d4c7a-2f1e-4a8b-9c2d-3e1f0a8b7c4d",
  "kind": "book_appointment",
  "status": "succeeded",
  "created_at": "2026-05-14T18:21:03.421Z",
  "input": { "provider_id": "abc123", "state": "Florida", "appointment_type": "354092", "date_time": "..." },
  "output": { "booking_url": "https://www.emorahealth.com/book?...", "stage": "intent_recorded" }
}
```

```http
POST /api/mcp/v1 HTTP/1.1
Idempotency-Key: 5b8d4c7a-2f1e-4a8b-9c2d-3e1f0a8b7c4d
Content-Type: application/json
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
  "params": { "name": "book_matching_session", "arguments": {...} } }
```

## Errors

```json
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests.",
    "resolution": "Wait and retry; see Retry-After header.",
    "retry_after": 30
  }
}
```

## Microsites

Our condition-specific microsites — childadhd.ai, teenadhd.ai, childanxiety.ai, teenanxiety.ai, childpsychiatry.ai, teenpsychiatry.ai, psychiatryforkids.com, teentherapy.ai, aprilfeels.com — each expose the same discovery surface scoped to their editorial corpus. Each is its own publisher with its own brand; this server is the canonical source for clinical-care actions.

## Contact

- Email: hello@emorahealth.com
- HTML version of this page: https://www.emorahealth.com/developers
