# How to use Unoic MCPs

Remote Streamable HTTP endpoint: `https://mcp.unoic.com/mcp`.
This guide is public. Tool calls require an authorized connection. Use `tools/list` and `get_capabilities` as the current source of exact schemas, supported profiles, inventory and limits.

## Transport and client security

Connect directly over HTTPS and validate the server certificate; browser HSTS does not secure a client's first HTTP request. Never put a bearer token in a URL. The current SDK (`1.32.1`) negotiates protocols through `2025-11-25`, also supporting `2025-06-18`, `2025-03-26`, `2024-11-05` and `2024-10-07`. This service does not claim `2026-07-28` support. Use the MCP SDK's initialization and protocol framing for these supported versions.

The transport uses stateless POST requests and JSON responses. Authenticated GET/DELETE requests to `/mcp` return `405`; job updates use `get_job`. A present `Origin` must exactly match an approved Studio/MCP/delivery origin; native clients may omit it and still require authentication. Advertised argument schemas are enforced. Requests also have a maximum JSON depth of 32 and 100,000 values, in addition to byte limits. A disconnect does not cancel an already admitted durable job: recover using its job ID or the original idempotency key.

Operators: the repository file `docs/security/hsts-mcp-hardening.md` describes the prepared HSTS rollout and verification requirements.

## Connect a human-operated app or backend

1. In Studio **Integrations**, create a named connection, choose permissions and hourly limits, and save it.
2. For videos, grant the relevant video/media banks. Interactive sources must already be published; each raw video must also be individually shareable in Studio.
3. In a remote-MCP client, add the endpoint. If it supports OAuth, sign in as an approved Studio owner, select the saved connection, and approve its permissions and banks.
4. For a server or token-capable client, generate a replacement token on the saved active connection. Copy it once, store it securely, and send `Authorization: Bearer <issued token>`.
5. Call `get_capabilities` to verify access. Adding a URL to a document does not install it in an AI client; client menus and MCP Apps preview support vary.

Generating another bearer token invalidates the preceding bearer token. A Studio sign-in manages connections; the MCP client uses its own OAuth authorization or issued connection token. Never embed credentials in iframe HTML, public source code or end-user browser bundles.

Issuing credentials, approving new OAuth access and expanding shared access require a recent authenticator check. Ordinary device/all-device Studio logout keeps AI integrations running. **Secure account and disconnect integrations** revokes Studio sessions and AI credentials, stops pending work and permanently withdraws old exports. Re-enabling a connection requires explicit new credentials/OAuth approval; old credentials and links do not revive.

## Instructions for agents

1. Discover capabilities before choosing a game profile. Follow exact input schemas; do not invent tools, identifiers or output URLs.
2. For each intended creation, use a unique `idempotencyKey` of 1–120 characters. After a transport/queue failure, retry the same key and parameters. A changed request with an existing key returns `IDEMPOTENCY_CONFLICT`.
3. Creation returns a durable `jobId`. Call `get_job` at a sensible interval until `ready`, `needs_review` or `failed`; `queued` and `running` are intermediate states. Closing the client does not cancel an admitted job.
4. Inspect `artifact.reviewStatus` and `artifact.warnings`. Explain review concerns before delivery. Automated checks and content review do not guarantee factual accuracy.
5. Deliver the returned `artifact.url`, `artifact.embedHtml` or `export_asset.downloadUrl`. Games and videos include iframe HTML; diagrams include SVG/JPEG export links.
6. For video requests, discover with `list_banks` and `search_videos` first. Use the returned source type and ID. Source grants and sharing remain required after publication.

Try: “Create a 12 × 12 English Word Search with EARTH, WATER and LIGHT. Check capabilities, create it once, follow its job, and return the hosted URL and iframe HTML.”

## Ten tools

Tool names below are exact. All creation tools take `{ "idempotencyKey": "...", "parameters": { ... } }`; the table describes their `parameters` object. Other rows describe their complete arguments. IDs are UUIDs.

| Tool | Arguments or creation parameters | Required access |
| --- | --- | --- |
| `get_capabilities` | `{}`; returns games, schemas, profiles, inventory, assets, videos and limits | `catalog:read` |
| `create_game` | `gameId` plus the game's fields below | `games:create` |
| `generate_svg` | Required `prompt` (1–4,000 chars); optional `title` (1–120), `size`, `language` | `assets:create` |
| `get_job` | `{ "jobId": "..." }` | Same connection; a ready artifact also requires its relevant permission |
| `get_artifact` | `{ "artifactId": "..." }` | Same connection and the artifact's relevant permission |
| `export_asset` | `{ "artifactId": "...", "format": "svg" }`; format is `svg` or `jpeg` | `assets:read` and `assets:create` |
| `list_banks` | Optional `limit` (1–50; default 20), `cursor` | `videos:read`; explicitly granted owner banks only |
| `search_videos` | Optional `bankId`, `query` (1–160 chars), `sourceType` (`interactive` or `raw`), `limit`, `cursor` | `videos:read`, bank grant, published/shared sources |
| `get_video_embed` | Required `sourceType` (`interactive` or `raw`), `videoId` | Same video access as search |
| `compose_video` | Required `sourceType`, `videoId`, `title`, `durationSeconds`, `cues`; optional `description`, `subtitles`, `subtitleLabel` | Same video access as search |

Pass discovery results' `nextCursor` unchanged as `cursor`; `null` means there is no next page. The artifact permission is `games:create` for games, `assets:create` for diagrams and `videos:read` for videos.
Diagrams use sizes `720x720` (default), `1280x720` or `720x1280`, and languages `en` (default), `hi` or `gu`. Exports are SVG and JPEG with an opaque white background. Fetch the returned download URL through the integrating platform's backend to import an asset.

## Seven games through create_game

All accept an optional `title` (1–120 chars). Where supported, `seed` is a string of 1–120 chars; a seed does not guarantee successful bounded generation.

| `gameId` | Inputs and limitations |
| --- | --- |
| `word-search` | Supply `words` (1–32 strings, each ≤160 chars) or `theme` (1–120 chars). Explicit words take precedence. `rows`/`cols`: 5–24 (default 12); `language`: `en`/`hi`/`gu` (default `en`); `difficulty`: `easy`/`medium`/`hard` (default `easy`). `minCells`: English 5, Hindi/Gujarati 3 or 5 (default 3). Entire explicit list must fit. Supports `seed`. |
| `kakuro` | `height`/`width`: 4–22 (default 4); `difficulty`: `beginner`/`easy`/`medium`/`hard`/`expert` (default `beginner`); `symmetry`: `none`/`half-turn` (default `none`). Only listed size/difficulty profiles are supported. Supports `seed`; may return `NO_MATCH`. |
| `calcudoku` | `size`: 3–9 (default 4); `tier`: 1–4 (default 1); `mode`: `MIXED`/`ADD_ONLY`/`ADD_SUB`/`MUL_ONLY`/`MUL_DIV` (default `MIXED`); `load`: `Gentle`/`Standard`/`Extended` (default `Gentle`). Only listed full profiles are supported. Provisional ratings; supports `seed`; may return `NO_MATCH`. |
| `futoshiki` | `n`: 3–9 (default 4); `preset`: `beginner`/`easy`/`smallChallenge`/`medium`/`hard`/`expert` (default `beginner`). Medium requires 4+, Hard/Expert 6+, smallChallenge only 3–4. Reserves existing certified inventory; no automatic refill. No seed. |
| `hidato` | `side`: 5–25 (default 5); `preset`: `easy`/`medium` (default `easy`). Reserves existing certified inventory; no new catalog generation. Hard/Expert unavailable. No seed. |
| `cryptogram` | Required `statement`, `keywords`, `concept`, `alternative`, `explanation`; details and example below. Author-supplied content, no AI rewriting or factual verification; `needs_review`. |
| `find-differences` | Required `images` and `differences`; details below. Author-supplied JPEGs, regions and answers; no image generation or automatic comparison; `needs_review`. |

Cryptogram: statement ≤3,000 chars and 12–240 playable Latin letters; optional `greek: true` enables case-sensitive Greek. Protect literal notation with `[[double brackets]]`. Supply 1–6 distinct exact keywords (≤80 chars each), correct `concept` and incorrect `alternative` (≤120 each), and post-choice `explanation` (≤800). Keep the correct concept out of visible wording and keywords. Optional `context` ≤80, `preset` (`guided`, `standard`, `hard`, `expert`; default `standard`), `showRemainingCounts` (default false), and private `seed` (default server randomness). Never share the seed with learners.

```json
{"name":"create_game","arguments":{"idempotencyKey":"photosynthesis-cryptogram-001","parameters":{"gameId":"cryptogram","statement":"Plants use sunlight to make sugar and release oxygen.","keywords":["sunlight","sugar"],"concept":"Photosynthesis","alternative":"Evaporation","explanation":"Photosynthesis uses light energy to make sugars.","preset":"standard"}}}
```

Find Differences: `images: { "A": "data:image/jpeg;base64,...", "B": "data:image/jpeg;base64,..." }`. Each decoded JPEG file is ≤256 KiB and each raster ≤1,000,000 pixels. Dimensions must exactly match the chosen `aspect`: `1:1` (default), `3:4`, `16:9`, `9:16`. No remote image URLs. Images are sanitized and copied to immutable artifact files.
Supply 1–16 `differences`, each `{ "regions": { "A": rect, "B": rect }, "prompt": "...", "correctAnswer": "...", "distractors": ["..."] }`. Prompt ≤1,000 chars; correct answer and 1–3 distinct distractors ≤500 chars each. A rectangle is `{ "x": 0.2, "y": 0.2, "width": 0.2, "height": 0.2 }`: normalized coordinates within 0–1, width/height ≥0.0001, and the full rectangle inside the image. Hit tolerance is 15% of its shorter side; ambiguous overlaps are not guessed. `mode`: `interleaved` (default) or `all-first`. No seed.
Answer data and private puzzle state stay server-side. Browser progress is unranked practice, not authoritative examination scoring.

## Compose an interactive video

Composition publishes new checkpoints/captions over an authorized frozen video copy; it leaves Studio sources unchanged. It does not splice/render video bytes, accept arbitrary video URLs, or make AI calls. Supplied checkpoints replace source checkpoints; omitted `subtitles` produces no captions.
Required: `sourceType`, discovered `videoId`, `title` (1–240 chars), `durationSeconds` (>0, ≤86,400), `cues` (1–500). Optional: `description` ≤12,000 chars, `subtitleLabel` ≤120, `subtitles` ≤10,000. Entire normalized parameters, including lab HTML, must fit within **56,000 UTF-8 bytes**.
Cue `{ id, atSeconds, kind: "quiz", questions }` contains 1–20 questions. Each question requires `{ id, prompt, options, correctOptionId, explanation, onCorrect, onIncorrect }`. Prompt 1–4,000 chars; explanation 0–4,000; 2–8 options `{ id, text }` with text 1–1,000 chars and distinct trimmed/case-insensitive text. All cue/question/option/subtitle IDs must be globally unique, each 1–100 chars.
Outcomes: `{ "mode": "continue", "targetSeconds": null }`, or `mode: "jump"`/`"offer-replay"` with a numeric target within the video's duration. Cue timestamps must also be within the duration.
Lab cue: `{ "id": "lab-1", "atSeconds": 30, "kind": "lab", "questions": [], "lab": { "title": "...", "html": "..." } }`. Lab title 1–160 chars; HTML 1–100,000 chars, also subject to the overall 56,000-byte limit. Labs run in an opaque sandboxed iframe with scripts and signal completion with `window.UnoicLab.complete()`.
Subtitle: `{ "id": "caption-1", "start": 0, "end": 3, "text": "Plain caption text" }`; text 1–4,000 chars, `0 ≤ start < end ≤ durationSeconds`.
Interactive sources require the same duration as their published source. Raw-source durations are supplied by the caller and produce `needs_review`; preview timing before sharing.

The UUID below is an example only: replace it with an actual `search_videos` result and use the source's real duration/timing.

```json
{"name":"compose_video","arguments":{"idempotencyKey":"fractions-checkpoint-001","parameters":{"sourceType":"raw","videoId":"11111111-1111-4111-8111-111111111111","title":"Fractions checkpoint","durationSeconds":60,"cues":[{"id":"cue-1","atSeconds":30,"kind":"quiz","questions":[{"id":"q-1","prompt":"Which fraction equals one half?","options":[{"id":"a","text":"2/4"},{"id":"b","text":"1/4"}],"correctOptionId":"a","explanation":"Two quarters equal one half.","onCorrect":{"mode":"continue","targetSeconds":null},"onIncorrect":{"mode":"jump","targetSeconds":20}}]}]}}}
```

Examples are MCP `tools/call` params, not standalone HTTP bodies. Use an MCP SDK/client for initialization and protocol framing. For status call `get_job` with `{ "jobId": "<returned UUID>" }`; for an image call `export_asset` with `{ "artifactId": "<returned UUID>", "format": "jpeg" }` or `"svg"`.

## Permissions, limits and revocation

`catalog:read` is always included. Enable the relevant scopes above. OAuth approval snapshots scopes and banks: removals take effect immediately; additions require reconnection and renewed approval. Static bearer tokens follow the connection's current settings. Queued jobs retain their submission-time authorization ceiling; later grants do not expand them.
Owner ceilings across connections: **2 queued/running jobs**, **60 admitted game jobs/hour**, **10 admitted diagram jobs/hour**. Connection hourly limits may be lower. Admitted jobs count even if they later fail; rejected validation/admission requests do not consume hourly job quota. Video jobs share concurrency, with no separate hourly creation ceiling.
All MCP traffic is limited to **120 requests/connection/minute**. MCP request bodies are capped at **1 MiB**; composition has its stricter 56,000-byte parameter cap. Video sources are MP4/WebM/Ogg, ≤50 MiB. Discovery pages default to 20 and allow 1–50 results.
Published links are unlisted: anyone receiving one can view it until revoked. Revoking a publication, pausing its connection, removing the relevant scope/bank, or withdrawing a video source permanently withdraws affected existing exports. Restoring access permits new publications; old URLs do not revive. Every delivery rechecks access. Already downloaded/buffered content cannot be recalled.

## Errors and recovery

Tool failures return `isError: true` and `{ "error": { "code": "...", "message": "...", "retryable": false } }`. Job failures expose `error` through `get_job`.

| Error or result | Next action |
| --- | --- |
| Authentication failure / `FORBIDDEN` | Check active connection, token rotation, scope, bank grant and source sharing. Reconnect OAuth after expanding access. |
| `INVALID_INPUT` / `PROFILE_UNAVAILABLE` | Read current schemas/profiles and correct the request; do not silently substitute content or difficulty. |
| `NO_MATCH` / exhausted certified inventory | Explain the unavailable result; choose an available profile with the user. A seed does not guarantee a match. |
| `IDEMPOTENCY_CONFLICT` | Restore the original parameters or use a new key for a new intended output. |
| `CONCURRENCY_LIMIT` / `QUOTA` / `OWNER_QUOTA` | Let jobs finish or wait for the rolling hourly window; check lower connection limits. |
| `RATE_LIMITED` | Wait one minute and reduce polling. |
| `QUEUE_UNAVAILABLE` | The job may be saved; retry the same key and parameters. Recovery also re-enqueues stranded jobs. |
| `needs_review` | Read warnings and inspect authored/generated content before teaching or sharing. |
| Provider uncertainty/failure | Inspect the failed job. Do not automatically make another paid request; a deliberate new attempt needs a new key. |
| Published URL returns 404 | Check revocation, connection state, scope/bank removal and source withdrawal. A new publication is required after restoration. |
