> ## Documentation Index
> Fetch the complete documentation index at: https://developer.hooper.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Use the Hooper API from Claude, Cursor and other AI assistants.

Hooper runs a [Model Context Protocol](https://modelcontextprotocol.io) server, so an AI assistant can submit games and read back sessions, shots and highlights for you. Ask things like *"analyze this Veo match"* or *"show me every made three from last night"* and the assistant calls the API.

The server is a thin client of `/v1`. It holds no credentials: every tool call is made with **your** API key, so billing, rate limits and organization scoping are exactly what the API enforces.

## What it can do

Once connected, you talk to the assistant in plain language and it picks the right [tools](#tools):

> **Analyze a game**
>
> *"Analyze this game:* `https://app.veo.co/matches/…`*"*
>
> Checks your balance, submits the video, and tells you the session id and what it will cost.

> **Check on processing**
>
> *"Is my last game done yet?"*
>
> Looks up the session's status and gives you a link to watch it in the Hooper Hub. Processing takes minutes to an hour depending on length.

> **Shot analysis**
>
> *"Break down every three-pointer in that game. Who made them and from where?"*
>
> Pages through every shot with time, result, court location, scorer, assister and rebounder.

> **Name your players**
>
> *"Analyze this game. We're Acme: #23 Ana Silva, #7 Cleo Dias."*
>
> Sends your roster with the game, so shots and highlights come back credited to your players. See [Rosters](#rosters).

> **Highlights**
>
> *"Give me links to all the made shots from the second half."*
>
> Returns clips with playable video and preview image URLs.

> **Analyze a file on your computer**
>
> *"Analyze* `~/Videos/game.mp4`*"*
>
> In assistants that can run commands (Claude Code, Cursor), uploads the file and submits it. See [Local files](#local-files).

> **History and credits**
>
> *"How many games have I processed this month, and how many credits do I have left?"*
>
> Lists your sessions and reads your available and held credits.

Only `analyze_video` spends credits.

## Connect

You need an API key (`hk_prod_…`, see [Authentication](/authentication)). The server is at:

```
https://mcp.hooper.gg/mcp
```

It speaks Streamable HTTP; send your key in the `Authorization` header.

**Claude Code**

```bash theme={null}
claude mcp add --transport http hooper https://mcp.hooper.gg/mcp \
  --header "Authorization: Bearer hk_prod_…"
```

Run `/mcp` inside Claude Code to confirm `hooper` is connected.

**Cursor**

Add to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):

```json theme={null}
{
  "mcpServers": {
    "hooper": {
      "url": "https://mcp.hooper.gg/mcp",
      "headers": { "Authorization": "Bearer hk_prod_…" }
    }
  }
}
```

**Claude Desktop**

Claude Desktop reaches remote servers with a pasted key through the [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) bridge (requires Node.js). Add to `claude_desktop_config.json` and restart the app:

```json theme={null}
{
  "mcpServers": {
    "hooper": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.hooper.gg/mcp", "--header", "Authorization:${HOOPER_AUTH}"],
      "env": { "HOOPER_AUTH": "Bearer hk_prod_…" }
    }
  }
}
```

The key goes in `env` rather than `args` because some platforms mangle spaces inside arguments.

> [!WARNING]
>
> These config files hold your key in plain text, and the key can spend credits. Use a dedicated key for assistants so you can revoke it on its own.

> [!NOTE]
>
> **claude.ai** custom connectors (Claude on the web and mobile) require OAuth sign-in rather than a pasted key, which isn't supported yet. Use one of the clients above.

## Tools

| Tool | Calls | What it returns |
| - | - | - |
| `create_upload` | `POST /v1/uploads` | An `upload_id` and a ready-to-run `curl` command that sends a local file. Free. |
| `analyze_video` | `POST /v1/sessions` | A new session in `queued` state, from a link or an `upload_id`, with optional [rosters](#rosters). **Costs credits.** |
| `get_session` | `GET /v1/sessions/{id}` | Status, shot and highlight counts, and a `hub_url` to watch it in the Hooper Hub |
| `list_sessions` | `GET /v1/sessions` | Your sessions, newest first, cursor-paged |
| `list_shots` | `GET /v1/sessions/{id}/shots` | Every shot: time, result, points, court position, scorer / assister / rebounder |
| `list_highlights` | `GET /v1/sessions/{id}/highlights` | Clips with playable video and preview URLs |
| `list_players` | `GET /v1/sessions/{id}/players` | Who each `plr_` id is: jersey, name, team and your metadata |
| `get_balance` | `GET /v1/balance` | Available and held credits, and the hourly rate |

Every tool except `create_upload` and `analyze_video` is read-only. Session ids can be given as `sess_18234` or just `18234`.

### Differences from the REST API

The tools are shaped for a model's context window, so a few things differ from calling `/v1` directly:

* **Sessions are summarized.** `get_session` and `list_sessions` return `shot_count` and `highlight_count` instead of the embedded lists. Page through them with `list_shots` and `list_highlights`. Each session also carries a `hub_url` for watching it in the Hooper Hub.
* **No box scores.** Sessions leave out `totals` and players leave out `stats`. Players are told apart by jersey number, and without numbers by appearance, so per-player stats can be misleading. `list_players` is there to say who the `plr_` ids on shots and highlights are. For box scores, call the [API](/sessions) directly.
* **Shots carry the court position only.** `list_shots` returns `court_location` (the shot chart point) instead of the `location` object, and leaves out `excitement_score`.
* **Highlights carry two renditions.** `list_highlights` returns the default and horizontal cuts plus the preview image, not every resolution.
* **Uploads need a shell.** Video never passes through the assistant or the MCP server. `create_upload` hands back a `curl` command and the assistant runs it on your machine, so local files work only in assistants that can run commands. See [Local files](#local-files).
* **No webhooks.** The assistant polls with `get_session`. Processing takes minutes to an hour depending on length.

## Rosters

Hooper tells players apart by the jersey numbers it reads. Give the assistant each team's numbers, and names if you like, and it passes them to `analyze_video` as [`rosters`](/sessions#rosters). The detected players then come back with your names and your own ids in `metadata`, so *"show me Ana's made threes"* works and follows her from game to game.

Without a roster, the `plr_` ids on shots and highlights are Hooper's best guess within that one game. They're unnamed, a `null` means Hooper couldn't tell who it was, and one person is sometimes split into two players. Rosters need jersey numbers to be read, so leave `jerseys` on `auto` or set it to `enabled`.

## Local files

The video never goes through the MCP server or the assistant itself. The assistant asks for an upload, then sends the file with a command on your machine:

**1. Reserve an upload**

The assistant measures the file (for example `wc -c < game.mp4`) and calls `create_upload` with its exact size and path. This is free.

**2. Send the file**

`create_upload` returns a command like the one below, and the assistant runs it. It streams the file straight to Hooper's storage, so a long game can take a while on a slow connection.

```bash theme={null}
curl -sS --fail -X PUT -T '/Users/you/Videos/game.mp4' -H 'Content-Type: video/mp4' 'https://storage.googleapis.com/…'
```

**3. Submit**

The assistant calls `analyze_video` with the `upload_id`. Submitting before the file has finished uploading returns `409 upload_incomplete`.

This works in assistants that can run commands, such as Claude Code and Cursor's agent. Claude Desktop can't run commands, so there you give it a public link instead, or [upload with the API](/sessions#sources) yourself. The upload URL accepts the file for 7 days.

## Credits and retries

`analyze_video` is billed like `POST /v1/sessions` (see [Billing](/billing)). The server derives the [`Idempotency-Key`](/sessions#idempotency) from the tool's arguments, so if an assistant retries a call after a timeout it gets the original session back instead of paying twice.

The flip side: submitting the **same URL with the same options within 24 hours** returns the earlier session rather than starting a new run. To deliberately reprocess, change an option or add a `metadata` entry.

Tool calls count toward your key's [rate limit](/authentication#error-codes) of 60 requests per minute.

## Errors

API errors reach the assistant as a readable tool error with the code, message and `Request-Id`, for example:

```
Hooper API error 402 (insufficient_credits): Not enough credits to process this video [needed_cents: 752] [available_cents: 100] [Request-Id: req_…]
```

A missing or malformed `Authorization` header fails every tool call with `Missing Hooper API key`. Check the header is set in your client's config. See [Errors](/errors) for every code.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.