# Clarion: MCP server for AI agents

The agent turns Uzbek audio and video into text or subtitles over MCP. Streamable HTTP transport, stateless.

Endpoint: `https://api.uzasr.uz/mcp`

## Authentication

OAuth 2.1 with PKCE. On first connect the agent opens a browser: the user signs in to Clarion and allows access, no key needed. Agents can be disconnected in the dashboard under “API keys”.

## Connect

### Claude Code

```bash
claude mcp add --transport http clarion-mcp https://api.uzasr.uz/mcp
```

### Codex

```bash
codex mcp add clarion-mcp --url https://api.uzasr.uz/mcp
codex mcp login clarion-mcp
```

### Plugin

```bash
/plugin marketplace add rustammdev/clarion-mcp
/plugin install clarion-mcp@clarion-mcp
```

After the command, open `/mcp` in Claude Code, pick `clarion-mcp` → Authenticate and click “Allow” in the browser. In Codex, `codex mcp login clarion-mcp` starts the sign-in, and the plugin opens the browser on its first call. Connected agents are listed in your dashboard under “API keys”.

## CI and headless

Without a browser, send an API key `uzasr_live_…` in the `Authorization: Bearer <key>` header. Use a separate key per client.

### Claude Code

```bash
claude mcp add --transport http clarion-mcp https://api.uzasr.uz/mcp \
  --header "Authorization: Bearer $UZASR_API_KEY"
```

### Codex

```toml
[mcp_servers.clarion-mcp]
url = "https://api.uzasr.uz/mcp"
bearer_token_env_var = "UZASR_API_KEY"
```

## Agent workflow

1. `create_upload(file_path)` returns an `upload_id` and a ready curl command.
2. The agent runs the command in a shell: the file goes to `PUT /v1/uploads/{id}`.
3. `transcribe(upload_id, model, format)` waits ~40 s for the result. If it is not ready, it returns a `job_id`.
4. `get_transcription(job_id, format)` fetches the result. `job_id` equals `upload_id`.

## Tools

| Tool | Arguments | What it does |
| --- | --- | --- |
| `list_models` | — | Available models: `uzasr-large` is the main one, `uzasr-base` is cheaper. |
| `create_upload` | file_path | Returns an `upload_id` and a curl command for the upload. |
| `transcribe` | upload_id, model, format | Defaults to `model="uzasr-large"`, `format="text"`. Waits ~40 s, otherwise returns a `job_id`. |
| `get_transcription` | job_id, format | Fetches the finished result. |

## Formats

| format | Contents |
| --- | --- |
| `text` | Continuous text with punctuation, Latin script. |
| `segments` | Lines with start and end timestamps. |
| `srt` | SubRip subtitles: frames from word timestamps, up to 6 s and 84 characters. |
| `vtt` | WebVTT subtitles, same frame rules. |

## Limits

| Limit | Value |
| --- | --- |
| File size | up to 256 MB |
| Audio duration | up to 3 hours |
| Upload link | single-use, 15 minutes |
| Uploads awaiting `transcribe` per key | up to 10 |

Compress videos larger than 256 MB to audio first:

```bash
ffmpeg -i input.mp4 -vn -ac 1 -ar 16000 -c:a libopus -b:a 32k output.ogg
```

## Privacy

- **Audio.** Kept on the server briefly and deleted right after recognition.
- **Transcript.** Deleted after 7 days.
- **Result.** Goes to the agent as a tool response, which means to the agent's LLM provider too. That choice stays yours.
