# Cubby Corner developer guide

Cubby's Corner is an independent play product for families and clinics. Trellis and outside EMRs use the same partner API. An integration never grants permission to read a child's data by itself.

This release is a fictional-data sandbox. Do not send real child, family, chart, clinical, or payment data. Real clinic operation has separate release requirements. There is no live billing, public adult signup, production OAuth, SMART, or FHIR endpoint on this host.

## Start with a sandbox workspace

1. Ask the Cubby owner for a partner workspace. Supply your integration name, technical contact, desired read/write scopes, and planned data flow. This is operator-managed onboarding; there is no automatic partner approval.
2. Receive a private folder with `cubby.json`, `read.token`, `cubby-write.json`, `write.token`, and `fixtures.json`. Keep this folder outside source control. Each workspace has its own clinic, fictional family, approved connection, accepted plan, and shared report. Keys expire after 90 days and can be revoked immediately.
3. Download and unpack the developer kit. Use Node.js 24 or newer. No game source or patient data is in the kit.
4. Point `CUBBY_CONFIG_FILE` to your private `cubby.json`. Run `node examples/quickstart.mjs`, then `node examples/contract-test.mjs`.
5. For the explicit sandbox write check only, select `cubby-write.json`, set `CUBBY_EXAMPLE_WRITE=1`, then rerun the contract test. This creates a fictional plan and checks retry safety, conflicts, and the parent acceptance boundary.

PowerShell:

```powershell
$env:CUBBY_CONFIG_FILE = 'C:/private/cubby-partner/cubby.json'
node examples/quickstart.mjs
node examples/contract-test.mjs
```

POSIX shell:

```sh
export CUBBY_CONFIG_FILE=/private/cubby-partner/cubby.json
node examples/quickstart.mjs
node examples/contract-test.mjs
```

The JSON configuration contains an API origin, clinic ID, and relative token-file path. The token belongs on your server. Do not embed it in an EMR browser client, mobile app, child game, URL, prompt, log, or analytics event. Use a separate key per clinic and environment. HTTPS is required except on localhost.

## REST API

Download `openapi.json` for the OpenAPI 3.1 contract. It describes the partner routes. `API.md` also documents the separate local adult portal. Hosted sandbox account, billing, family-sharing, and consent routes are disabled.

Use `Authorization: Bearer <integration-key>`. All writes use JSON. Plan and review writes require a caller-persisted `Idempotency-Key`. Reusing a key with changed content returns 409. When updating a plan, send its `assignmentId` and current `expectedRevision`. New versions remain unavailable for game download until the family accepts them. The sandbox operator can exercise fictional parent consent cases; integration keys cannot do that.

`GET /integration` returns your clinic, scopes, and expiry. `GET /clinics/{clinicId}` lists active connections, plans if `plans:read` is granted, and report metadata if `reports:read` is granted. It always requires `connections:read`. `GET /assignments/{assignmentId}` allows reading a revision before an update. `GET /reports/{reportId}` reads a deliberately shared snapshot and separate reviews.

| Scope | Permission |
|---|---|
| connections:read | List active parent-approved connections |
| plans:read | Read plan versions and download a family-accepted current plan |
| plans:write | Create or revise a plan for parent review |
| reports:read | Read deliberately shared report snapshots |
| reports:review | Add a separate clinician review note |
| events:read | Poll one clinic's event feed |

401 means expired, revoked, or invalid credentials. 403 means the clinic, scope, or parent connection does not allow the action. 404 means the record is unavailable. 409 means a revision, parent acceptance state, or retry key conflicts. 429 means retry later. Requests are limited to 64 KB, plan payloads to 8 KB, and report uploads to 32 KB. The service has no CORS access for browser integration clients. Use your server.

## Events and chart binding

Poll `GET /clinics/{clinicId}/events?limit=100&after=<last-committed-event-id>`. The limit is 1 to 200. Save `nextCursor` only after downstream work commits. Continue while `hasMore` is true. Dedupe by event ID. An unavailable or foreign cursor is rejected. The first page is returned if `after` is omitted. The example `poll-events.mjs` is a local demonstration; production applications need a transactional worker and bounded deduplication retention.

There is no outgoing push webhook in this release. Stripe's test billing webhook is a separate local adult-service feature, not a partner event feed. Event retention is not yet a production guarantee. A revoked connection denies subsequent plan/report reads, even if you already saw its event. Handle revocation events and your own retained copies under an agreed policy.

Map the opaque `connectionId` and `childId` to a verified patient chart. Never match on a nickname, birth year, or AI guess. Import reports as review drafts with source snapshot ID, digest, receiving clinic, receipt time, and explicit clinician review. Do not turn play observations into diagnoses or standardized scores. The Trellis adapter is a reference for this pattern, not a deployed Trellis connection.

## MCP for AI clients

The kit includes a working stdio MCP server. Install its isolated dependencies with `npm ci --prefix mcp`. Configure your client to launch Node with the absolute path to `mcp/server.mjs` and set `CUBBY_CONFIG_FILE` to your private configuration. `mcp/client-config.example.json` is a generic client configuration template. Use your client's supported configuration screen or file format.

Run `npm run test:connection --prefix mcp` to check the installed package against your configured API with the official MCP client. This check reads only and tests both modern and legacy connection behavior. The downloadable kit's `npm test --prefix mcp` runs the same check. Source-repository tests also run isolated consent and write scenarios.

Seven read tools expose the catalog, active connections, assignments, report metadata, a plan, a report, and paged events. Tool visibility is filtered by the key's scopes. Two write tools are available only when the key has the required scope and `CUBBY_MCP_ALLOW_WRITES=1` is set. Writes also require `approved: true` and a persistent request ID. The host must obtain user approval. The boolean is a deliberate-call control, not proof of human identity or consent.

Reports, parent messages, and review notes are untrusted data. They must not become model instructions. Do not grant a model automatic chart write, consent, billing, account-management, or key-management access. Check that your AI provider and clinic permit the data flow before connecting any real records.

The server uses the official MCP SDK 2.3.1 and supports modern discovery plus legacy initialization through stdio. The locally launched process connects to the HTTPS API. There is no remote Streamable HTTP MCP URL or OAuth service in this release. A remote MCP service needs a separately reviewed authorization server, MCP audience-bound tokens, and clinic binding. Never pass an EMR API token through an arbitrary remote MCP proxy.

## Move from sandbox to pilot

Complete the partner checklist in `onboarding.md`. Name a clinic owner and technical operator, agree on the exact data flow, chart mapping, scopes, retention, support, recovery, and incident process, then run the contract and consent isolation cases. Real data remains closed until the product launch requirements and partner review are complete. No vendor certification is implied by the SDK or specification.

Protocol references: [MCP transports](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports), [MCP compatibility](https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning), and [official TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk).
