> Public copy of the ViewStream developer guide (also for AI agents). All guides: https://www.viewstream.co.il/developers/guide/index.md · API reference: https://api.viewstream.co.il/docs/

# MCP server (AI assistants)

ViewStream runs a remote **MCP server** (Model Context Protocol) at

```
https://api.viewstream.co.il/mcp
```

With it an AI assistant — Claude, ChatGPT, Cursor, or any MCP client — can work with your ViewStream account in
plain language: *"what is on air on our main channel now?"*, *"find last week's programmes about the European
championship and summarise them"*, *"which videos were watched most yesterday?"*, *"cut a clip of the first five
minutes of the 20:00 news"*. The assistant calls ViewStream **tools** on your behalf, with an API key you give it.

## How it works

- **Transport:** MCP Streamable HTTP, protocol revision `2025-06-18` (`2025-11-25` and `2025-03-26` are also
  negotiated). The client POSTs JSON-RPC 2.0 messages to `/mcp` and gets one JSON response per request. The server
  is stateless: it issues no `Mcp-Session-Id` and opens no server-initiated stream (`GET /mcp` answers `405`).
- **Authentication:** an API key of your tenant, sent as `Authorization: Bearer <key>` — the same keys, scopes and
  rate limit (20 requests/second per key, burst 100) as the REST API. OAuth sign-in is not offered; a Studio login
  cookie is not accepted on `/mcp`.
- **Same rules as the API:** every tool calls the public `/v1` API inside the server *as your key*, so it sees only
  your tenant's data, only what the key's scopes allow, and is validated, rate-limited and audited exactly like a
  direct API call. Each tool call is also recorded in the audit log as `mcp.tool_call` (tool name and a summary of
  the arguments — long texts such as a support message are stored only as their length).
- **Output:** Hebrew titles, summaries and subtitles are returned as they are (UTF-8). A tool result is capped at
  about 60 KB; longer lists are shortened and marked `_truncated` — ask for a smaller `limit` or a shorter range.
- **Errors:** a failed tool returns a result with `isError: true` and the API's problem detail (type, status,
  detail), so the assistant can explain or correct the call.

## Create an API key for the assistant

In Studio go to **Integrations → API keys → New key** and give the key only the scopes the assistant needs:

| You want the assistant to… | Scopes |
|---|---|
| Read channels, EPG, catch-up, programmes, service status and alerts | `channels:read` |
| Read the library, AI summaries and subtitles | `assets:read` |
| Read viewing statistics | `stats:read` |
| Cut clips | `clips:write` |
| Open support requests | `support:write` |
| Regenerate AI summaries | `assets:write` |

A read-only assistant needs `channels:read`, `assets:read` and `stats:read`. The assistant only *sees* the tools its
key can use (`tools/list` is filtered by scope). Treat the key like a password: anyone who has it can do what its
scopes allow. Revoke it in the same screen when you stop using the assistant.

## Tools

Read tools (no changes to your data):

| Tool | What it does | Scope |
|---|---|---|
| `list_channels` | Channels with id, slug, title, state, encoder feeds, DVR window, retention, live URL | `channels:read` |
| `channel_status` | One channel now: on air / next, feed and recording health, alerts firing on it | `channels:read` |
| `search_catchup` | Search recorded programmes (title, guide text, AI summary, presenters, topics — and what was said, with the moments) on one or all channels | `channels:read` |
| `get_programme` | One programme: times, guide text, channel, recording status, VOD, playback URLs; with `assets:read` also its summary and subtitle languages | `channels:read` |
| `get_epg` | The programme guide of a channel between two times (default: 3 hours ago to 21 hours ahead, at most 7 days) | `channels:read` |
| `search_library` | Search or list library videos (title, description, external id, AI summary) | `assets:read` |
| `get_asset` | One video: status, publication, duration, renditions, playback, summary, subtitle languages | `assets:read` |
| `get_subtitles` | Subtitles of a programme, video or clip as a timestamped transcript (`text`) or WebVTT, in pages | `assets:read` |
| `get_summary` | The Hebrew AI summary of a programme or video (summary, presenters, topics, status) | `assets:read` |
| `stats_overview` | Audience and quality overview of a period with a comparison period | `stats:read` |
| `stats_top` | Top videos, clips or channels; or a channel's programmes by audience (`entity: programmes`) | `stats:read` |
| `list_alerts` | Monitoring alerts, newest first | `channels:read` or `stats:read` |
| `service_status` | Service health per layer (streaming, delivery, origin, QoE) and the AI services | `channels:read` or `stats:read` |
| `search_docs` | Search the Studio manual (English and Hebrew), this guide and the API reference | any key |

Write tools (they change data — a good assistant asks you before calling them):

| Tool | What it does | Scope |
|---|---|---|
| `create_clip` | Cut a clip (at most 6 h) from a channel's recording between two times; `segment` precision is ready at once, `frame` is finalised by a background job. Channel clips only. | `clips:write` |
| `create_support_request` | Open a support request with Interhost (`contact_email` required; at most 10 per tenant per hour) | `support:write` |
| `regenerate_summary` | Make a new AI summary of a programme or video from its Hebrew subtitles (replaces the stored one, including an edit) | `assets:write` |

Channels can be given by id or slug (`main`, `news`). Times are RFC 3339 (`2026-10-06T20:00:00+03:00`).

**Resources** (documents an assistant can read): `viewstream://docs/{lang}/{topic}` — pages of the Studio manual and
of this guide, `lang` = `en` or `he`, e.g. `viewstream://docs/he/catch-up`, `viewstream://docs/en/api-recipes`;
`viewstream://openapi` — every API operation with its required scope; `viewstream://openapi/{operationId}` — one
operation in full. **Prompts:** `daily_report` (yesterday's viewing report) and `find_programme` (find a programme
and summarise it).

## Connect an assistant

Replace `<key>` with your API key in each example.

### Claude Code

```bash
claude mcp add --transport http viewstream https://api.viewstream.co.il/mcp \
  --header "Authorization: Bearer <key>"
```

Then ask, for example: *"Using viewstream, what is on air on all channels right now?"* Check the connection with
`claude mcp list`.

### Claude Desktop and claude.ai

Custom connectors in Claude Desktop and on claude.ai (**Settings → Connectors → Add custom connector**) sign in with
OAuth, which this server does not offer yet. Until it does, connect Claude Desktop through the `mcp-remote` bridge,
which adds the header (needs Node.js). In `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "viewstream": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.viewstream.co.il/mcp",
               "--header", "Authorization:${AUTH_HEADER}"],
      "env": { "AUTH_HEADER": "Bearer <key>" }
    }
  }
}
```

### Cursor

In `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project — do not commit the key):

```json
{
  "mcpServers": {
    "viewstream": {
      "url": "https://api.viewstream.co.il/mcp",
      "headers": { "Authorization": "Bearer <key>" }
    }
  }
}
```

### Other clients

Any client that supports remote MCP servers over Streamable HTTP with a custom header works: use the URL above and
the `Authorization` header. Clients that only support the older HTTP+SSE transport can use `mcp-remote` as above.

## Raw JSON-RPC with curl

```bash
KEY=<key>
MCP=https://api.viewstream.co.il/mcp
H=(-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream")

# 1. handshake
curl -s "${H[@]}" "$MCP" -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
  "params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
curl -s "${H[@]}" -H "MCP-Protocol-Version: 2025-06-18" "$MCP" -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# 2. the tools this key may call
curl -s "${H[@]}" -H "MCP-Protocol-Version: 2025-06-18" "$MCP" -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

# 3. call a tool
curl -s "${H[@]}" -H "MCP-Protocol-Version: 2025-06-18" "$MCP" -d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
  "params":{"name":"search_catchup","arguments":{"q":"אליפות אירופה","limit":5}}}'
```

A tool result looks like this (shortened):

```json
{"jsonrpc":"2.0","id":3,"result":{
  "content":[{"type":"text","text":"{\"q\":\"אליפות אירופה\",\"items\":[…]}"}],
  "structuredContent":{"q":"אליפות אירופה","items":[{"id":"0192c8a0-…","title":"חמש","start_at":"2026-10-04T17:00:00Z",
    "status":"recorded","match":{"field":"summary","snippet":"…להעפיל לאליפות אירופה 2028…"},"channel":{"id":"…","slug":"main"}}],
    "truncated":false,"channels_searched":1}}}
```

## Errors

| HTTP | When |
|---|---|
| `401` + `WWW-Authenticate: Bearer` | No key, or the key is malformed, unknown or revoked |
| `403` | The request came from a web page whose `Origin` is not allowed (protection against DNS rebinding), or the key has no tenant |
| `400` | `MCP-Protocol-Version` names a revision the server does not speak |
| `405` | `GET /mcp` (no server-initiated stream) or another method than POST |
| `406` / `415` | `Accept` excludes `application/json`, or the body is not `application/json` |
| `429` | Rate limit (`Retry-After` says when to retry) |

Inside a `200` answer, protocol problems are JSON-RPC errors (`-32601` unknown method, `-32602` unknown tool or bad
parameters, `-32002` unknown resource), and tool failures are results with `isError: true` carrying the API's
problem type: `insufficient_scope` (the key lacks the tool's scope), `not_found` (no such channel or programme *in
your tenant*), `validation_error`, `rate_limited`, `feature_disabled`.

## Limits and notes

- Catch-up search covers titles, guide texts and AI summaries; subtitle text itself is not searched.
- `create_clip` cuts channel recordings only (no clips from library videos); the clip has no separate draft or
  publish state.
- Times in answers are UTC; the assistant converts them to Israel time when you ask.
- The server is for one tenant per key. Operator (Interhost admin) functions are not available through MCP.
