# Studio in Claude Desktop: the local MCP server

> Make a Praeko Studio video with an agent that has no terminal (Claude Desktop, Cursor, Codex, Gemini CLI, opencode): installing `@praeko/studio-mcp`, the 14 tools, the upload to Praeko and the split with the remote MCP that publishes.

Source: https://praeko.app/docs/en/studio/mcp

Node 22 or newer · stdio · Never publishes · Remotion is not MIT

[Praeko Studio](https://praeko.app/docs/en/studio) is normally operated by an agent **with a terminal**. `@praeko/studio-mcp` is an MCP server that runs on **your machine** and exposes the same steps as tools, so an agent **without a terminal** (Claude Desktop, for example) can create the episode, write the script, make the voice, render, make the cover and upload the video to Praeko. It runs the Studio CLI underneath, over stdio: no port is opened.

> **Live on npm** `@praeko/studio-mcp` (0.1.1, checked on 11/08/2026) is published: the commands below work as written. It does not replace your machine: it needs Node, Chrome/Remotion to render and your own keys, all on your computer.

> **End-to-end guide** To go from zero to publishing with an agent, step by step, see [Get started with your AI agent](https://praeko.app/docs/en/get-started-with-agent): it covers the path without a terminal (`studio_upload` and then `create_post`) and the one with a terminal.

## Two servers, two roles

|  | `praeko` (remote) | `praeko-studio` (local) |
|---|---|---|
| Where it runs | `https://praeko.app/mcp`, in Praeko's cloud | On your machine, over stdio (`npx -y @praeko/studio-mcp`) |
| Does | Channels, media, posts (create, schedule, edit, cancel), insights, docs | Create the episode, script, voice, compile, render, cover, check, package and upload the files |
| Publishes? | Yes, **always in two steps** (preview and `confirm`) | **Never.** It creates no post, schedules nothing, has no queue and no account |
| Your key | OAuth sign-in or a key you put in the client | The Praeko and ElevenLabs keys stay on your machine (Keychain, secrets file or variable); the agent **never** sees them |

The names do not collide: the client prefixes each tool with the server name. You can keep both on at the same time.

## The flow without a terminal

### 1. Create

`studio_brief_read` and `studio_brief_write` (brand and rules), `studio_new_episode`, `studio_write_script`, `studio_voice` in `draft` (silent and free voice), `studio_compile` and `studio_check`.

### 2. Render

`studio_voice` in `final` (spends ElevenLabs characters: preview and confirmation code), `studio_render`, `studio_cover` and `studio_package`. Slow steps become jobs: follow them with `studio_job`.

### 3. Upload

`studio_upload` sends the video (`out/<episode>.mp4`) and the cover (`out/<episode>-cover.png`) to your Praeko media library and returns only the `mediaId`s. In two steps: the first call shows the files, sizes and destination and gives a `confirmation_code`; only the second, with `confirm`, uploads. **It creates no post and publishes nothing.**

### 4. Publish (on the remote server)

With the [remote `praeko`](https://praeko.app/docs/en/mcp) server on, the agent uses the `mediaId`s in `create_post` (or `schedule_post`): `media: { video: <id>, cover: <id> }`. That tool has its own preview and only publishes after your "yes".

## Install

Create the project once (`npx @praeko/studio init my-channel`: the command ends by printing the two install lines of this server with the right folder). Then point the server at the project folder, the one with `brand.json`; use the **absolute** path.

**Claude Code (one line)**

```bash
claude mcp add praeko-studio -- npx -y @praeko/studio-mcp --project <folder>
```

**Equivalent JSON**

```json
{
  "command": "npx",
  "args": [
    "-y",
    "@praeko/studio-mcp",
    "--project",
    "<folder>"
  ]
}
```

## One block per client

The formats below were checked on the vendors' pages on 08/11/2026; where that was not possible, the page says so.

### Claude Code

One command registers the server (the `--` separates Claude's own options from the server command). By default it is saved for you only, in this project; `--scope user` applies to every project.

**Terminal**

```bash
claude mcp add praeko-studio -- npx -y @praeko/studio-mcp --project <folder>
```

**.mcp.json (alternative, in Git)**

```json
{
  "mcpServers": {
    "praeko-studio": {
      "command": "npx",
      "args": [
        "-y",
        "@praeko/studio-mcp",
        "--project",
        "<folder>"
      ]
    }
  }
}
```

> **Source** Checked on 08/11/2026 at `code.claude.com/docs/en/mcp`: syntax `claude mcp add [options] <name> -- <command> [args...]`; an entry with no `type` in `.mcp.json` is read as a stdio server.

### Claude Desktop

In Settings, Developer tab, click Edit Config. The file is `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS), `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/.config/Claude/claude_desktop_config.json` (Linux). Paste the block, **quit Claude Desktop completely and open it again**. Use the absolute path of the folder.

**claude_desktop_config.json**

```json
{
  "mcpServers": {
    "praeko-studio": {
      "command": "npx",
      "args": [
        "-y",
        "@praeko/studio-mcp",
        "--project",
        "<folder>"
      ]
    }
  }
}
```

> **Source** Checked on 08/11/2026 at `modelcontextprotocol.io/docs/develop/connect-local-servers` (the page uses Claude Desktop as its example). This is the **local** server path; the custom connector for the [remote Praeko](https://praeko.app/docs/en/agents/claude-desktop) is a different thing.

### Cursor

In the project's `.cursor/mcp.json`, or in `~/.cursor/mcp.json` for every project. A local server takes `type: stdio`.

**.cursor/mcp.json**

```json
{
  "mcpServers": {
    "praeko-studio": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "@praeko/studio-mcp",
        "--project",
        "<folder>"
      ]
    }
  }
}
```

> **Source** Checked on 08/11/2026 at `cursor.com/docs/context/mcp`.

### Codex

One command (the `--` separates the server command) or the `[mcp_servers.<name>]` table in `~/.codex/config.toml` (or `.codex/config.toml` of a trusted project).

**Terminal**

```bash
codex mcp add praeko-studio -- npx -y @praeko/studio-mcp --project <folder>
```

**~/.codex/config.toml**

```toml
[mcp_servers.praeko-studio]
command = "npx"
args = ["-y","@praeko/studio-mcp","--project","<folder>"]
```

> **Source** Checked on 08/11/2026 in the Codex MCP documentation (OpenAI, `learn.chatgpt.com/docs/extend/mcp`).

### Gemini CLI

In the project's `.gemini/settings.json`, or in `~/.gemini/settings.json` for every project.

**settings.json**

```json
{
  "mcpServers": {
    "praeko-studio": {
      "command": "npx",
      "args": [
        "-y",
        "@praeko/studio-mcp",
        "--project",
        "<folder>"
      ]
    }
  }
}
```

> **Transition to Antigravity CLI** Checked on 08/11/2026 at `geminicli.com/docs/tools/mcp-server`, which says Gemini CLI was replaced by Antigravity CLI on Jun 18, 2026 for free and Google One accounts. The `gemini mcp add` command exists, but we do not show it: Gemini's own options and the server's arguments (`-y`) can get mixed up. For Antigravity: check the client's documentation.

### opencode

In `opencode.json` (or `opencode.jsonc`); a local server uses `type: local` and the whole command as a list.

**opencode.json**

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "praeko-studio": {
        "type": "local",
        "command": [
          "npx",
          "-y",
          "@praeko/studio-mcp",
          "--project",
          "<folder>"
        ]
      }
    }
  }
}
```

> **Check the client's documentation** The opencode page of 08/11/2026 (`opencode.ai/docs/mcp-servers`) shows servers inside `mcp.servers`; older versions used `mcp.<name>` directly. We could not check the exact file name or the version where the format changed: check the client's documentation, or use `opencode mcp add`.

### Other client (generic)

Any client that runs a local MCP server over stdio takes the same trio: command, arguments and (if needed) environment variables. Field names vary by client: check the client's documentation.

**JSON block (the most common shape)**

```json
{
  "mcpServers": {
    "praeko-studio": {
      "command": "npx",
      "args": [
        "-y",
        "@praeko/studio-mcp",
        "--project",
        "<folder>"
      ]
    }
  }
}
```

**The three values**

```text
command: npx
args:    ["-y","@praeko/studio-mcp","--project","<folder>"]
server:  stdio (no port, no URL)
```

## The 14 tools

| Tool | What it does |
|---|---|
| `studio_status` | Checks the environment (Node, ffmpeg, Chrome, fonts, voice accounts without keys, license) and warns if the Praeko key is admin. |
| `studio_docs` | Lists or returns the Studio documentation topics. |
| `studio_brief_read`, `studio_brief_write` | Reads and writes `brief.md`, `playbook.md` and `brand.json` (validated, with `.bak`). |
| `studio_new_episode` | Creates `episodes/<name>/`. |
| `studio_write_script` | Writes `script.txt` or `episode.yaml` (the YAML is validated). |
| `studio_voice` | `draft`: silent voice, free. `final`: spends ElevenLabs characters and is **two-step** (a preview with the script characters, account and balance, a warning if the balance is not enough, and a `confirmation_code`). |
| `studio_compile`, `studio_check` | Compiles `episode.yaml` and checks the episode. |
| `studio_render`, `studio_cover`, `studio_package` | Background jobs (`jobId`): video, cover and publishing texts. For an image post (`studio_new_episode` with `format: image`), `studio_render` renders the slide to `out/<episode>-slide-01.jpg` (1080x1350, JPEG) and `studio_cover` is refused. |
| `studio_job` | Status, log or cancel of a job. One job at a time per project. |
| `studio_upload` | Uploads the episode's video and cover (or, for an image post, the JPEG as `type: image`) to the Praeko media library, in **two steps**, and returns only the `mediaId`s. It creates no post. |

> **A write key, not admin** `studio_upload` uses your Praeko key (`PRAEKO_KEY`, the macOS Keychain or the secrets file, like the rest of Studio). It only needs to send files: create a key with the **`write`** scope for Studio under API keys. If the key found is `admin`, `studio_status` and `praeko studio doctor` show a warning (not an error). The service address does not come from `brand.json`, so text written by the agent can never redirect the key.

## Safety

| Guarantee | How |
|---|---|
| Stdio only | No port open, nothing reachable over the network. |
| No free-form command | The tools call the Studio CLI with fixed arguments; what the agent writes never becomes a command line. Episode names follow `^[a-z0-9][a-z0-9-]*$` and every path stays inside the project. |
| Keys | No answer, log or error shows a key: values are masked (`sk_…3e`). |
| Project text is data | `script.txt`, `brief.md` and CLI output come back marked `untrusted`: the server does not obey what is written in them. |
| Spending only with your yes | `studio_voice` final and `studio_upload` are two-step: the code is short, bound to the arguments (and the files), valid for 10 minutes and works once. |
| Resources | One job at a time per project, a maximum time per job, cancellation. No telemetry. |

> **Remotion license** The package is MIT, but **Remotion** (the default video and cover engine) is **not**: free for individuals, non-profits and companies of up to 3 employees; larger companies need the Company License ([remotion.pro/license](https://www.remotion.pro/license)). The license belongs to whoever installs and runs it. Details in [Praeko Studio](https://praeko.app/docs/en/studio).

## Troubleshooting

| Symptom | Likely cause | What to do |
|---|---|---|
| The server does not show up in the client | The client was not restarted, or the JSON has an error. | Quit and reopen the client completely, check the JSON and run the command by hand in a terminal. |
| `has no brand.json` | `--project` does not point at the project folder. | Use the absolute path of the folder with `brand.json` and `src/index.ts`. |
| `no Praeko key found` | `studio_upload` did not find the key. | Save a `write` key (`PRAEKO_KEY` in the server's environment, or `praeko studio schedule --via praeko --key` in a terminal). Never paste the key in the chat. |
| `reason: expired`, `unknown_code` or `arguments_changed` | 10 minutes passed, the code was already used, the server restarted, or the file/script changed after the preview. | Ask for a new preview and confirm without changing anything. |
| `INSUFFICIENT BALANCE` in the voice preview | No account with a key has enough characters for the script. | Add credit or another account (`praeko studio voice account add`) and ask for the preview again. |
