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

# Connect AI agents with the MCP server

> Connect Claude Code, claude.ai, or any MCP client to Rendobar over OAuth, then submit jobs, upload files, and chain job outputs from the chat.

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
__html: JSON.stringify({
  "@context": "https://schema.org",
  "@type": "TechArticle",
  "@id": "https://rendobar.com/docs/mcp-server/#article",
  "headline": "Connect AI agents with the MCP server",
  "description": "Connect Claude Code, claude.ai, or any MCP client to Rendobar over OAuth, then submit jobs, upload files, and chain job outputs from the chat.",
  "datePublished": "2026-06-22",
  "dateModified": "2026-07-26",
  "author": { "@type": "Organization", "@id": "https://rendobar.com/#organization" },
  "publisher": { "@type": "Organization", "@id": "https://rendobar.com/#organization" },
  "isPartOf": { "@id": "https://rendobar.com/#website" }
})
}}
/>

The MCP server at `https://api.rendobar.com/mcp` gives any MCP client 10 tools: submit a job, upload a file, poll status, and chain a completed job into the next one. Connect it with one command over OAuth, no API key to copy.

## Connect

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport http rendobar https://api.rendobar.com/mcp
    ```

    Your browser opens once to approve access.
  </Tab>

  <Tab title="claude.ai">
    Settings, Connectors, Add custom connector. Paste the URL and approve in the browser prompt.

    ```text theme={null}
    https://api.rendobar.com/mcp
    ```
  </Tab>

  <Tab title="Other MCP clients">
    Any client that speaks Streamable HTTP with OAuth 2.1 connects the same way: point it at the URL below and approve in the browser that opens.

    ```text theme={null}
    https://api.rendobar.com/mcp
    ```

    Clients without OAuth support can authenticate with an API key instead: header `Authorization: Bearer rb_...`, from [Settings, API keys](https://app.rendobar.com) on the dashboard.
  </Tab>
</Tabs>

## What you can do

Call `list_job_types` first. It returns every active job type fresh, so it never goes stale like a hardcoded list would.

| Tool              | What it does                                                                                                                              | Returns                                  |
| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| `list_job_types`  | Every active job type: use cases, what it chains with, a params digest, and an example payload.                                           | `{ jobTypes[], guidance }`               |
| `submit_job`      | Submit a job. `inputs` accepts a URL string, `{ url }`, `{ content }` (inline text), or `{ job: "job_..." }` for chaining.                | `{ jobId, status }`                      |
| `get_job`         | Check status and results. `wait: true` blocks up to 45 seconds instead of polling. A completed video job includes an inline poster image. | `{ id, status, output?, cost?, error? }` |
| `list_jobs`       | Recent jobs, filterable by `status` and `type`.                                                                                           | `{ jobs[], total }`                      |
| `probe_media`     | Run ffprobe against a media URL as an async job. Poll `get_job` for the normalized summary and full report.                               | `{ jobId, status }`                      |
| `get_account`     | Credit balance, plan limits, active jobs, and rate limit usage.                                                                           | `{ balance, plan, limits }`              |
| `cancel_job`      | Cancel a job still `waiting` or `dispatched`.                                                                                             | `{ id, status: "cancelled" }`            |
| `upload_media`    | Open an upload session. Presigned URLs for shell-capable callers, or a `pageUrl` for the user to upload from their own device.            | `{ session, pageUrl, files[] }`          |
| `complete_upload` | Finalize an asset after its bytes land in storage.                                                                                        | `{ asset: { id, url, status } }`         |
| `get_upload`      | Check an upload session's progress. `wait: true` blocks up to 45 seconds.                                                                 | `{ status, assets[] }`                   |

`{ job: "job_..." }` inside `submit_job`'s `inputs` chains a completed job straight into the next one today for `ffmpeg` inputs. For any other job type, pass the prior job's output URL (from `get_job`) as a plain URL input instead.

A failed call returns `isError: true` with `{ error: { code, message, retryable } }` instead of throwing, so the agent can react to it. See the [error catalogue](/docs/support/errors) for codes.

## From your phone

A phone has no filesystem the agent can reach, so a media file routes through a page you open yourself.

<Steps>
  <Step title="Connect on claude.ai mobile">
    Settings, Connectors, Add custom connector, paste `https://api.rendobar.com/mcp`, approve.
  </Step>

  <Step title="Ask for the edit">
    "Trim this video to the first 10 seconds and burn in captions." Claude calls `list_job_types`, then `upload_media` with no files declared, since it can't read anything off your phone.
  </Step>

  <Step title="Tap the upload link">
    `upload_media` returns a `pageUrl`. Claude sends it to you in the chat. Open it, pick the file from your camera roll, and it uploads.
  </Step>

  <Step title="Get the result in chat">
    Claude polls `get_upload({ wait: true })` until the asset is ready, calls `submit_job` with its URL, then `get_job({ wait: true })`, and replies with the finished clip.
  </Step>
</Steps>

## From an agent with shell access

An agent that can run shell commands skips the upload page and PUTs bytes directly.

<Steps>
  <Step title="Declare the file">
    Pass the filename and size. A known size gets you a presigned URL right away: a single PUT under 100 MB, part URLs above it.

    ```text theme={null}
    upload_media({ files: [{ filename: "clip.mp4", size: 8421312 }] })
    ```
  </Step>

  <Step title="PUT the bytes">
    ```bash theme={null}
    curl -sS -X PUT --upload-file clip.mp4 "https://<presigned-url-from-upload_media>"
    ```
  </Step>

  <Step title="Finalize the asset">
    ```text theme={null}
    complete_upload({ assetId: "asset_8f2a1c" })
    ```

    Returns the ready asset, including its stable `url`. For a multipart upload, pass `parts: [{ partNumber, etag }]` collected from each part's PUT response.
  </Step>

  <Step title="Submit the job">
    ```text theme={null}
    submit_job({
      type: "ffmpeg",
      inputs: { "clip.mp4": "https://api.rendobar.com/assets/asset_8f2a1c/content" },
      params: { command: "ffmpeg -i clip.mp4 -vf scale=1280:720 -c:v libx264 -crf 23 out.mp4" }
    })
    ```

    Returns `{ jobId: "job_9c31", status: "waiting" }`.
  </Step>

  <Step title="Chain a second job off the first">
    Pass the completed job's id as the next job's input. No download, no re-upload.

    ```text theme={null}
    submit_job({
      type: "ffmpeg",
      inputs: { "out.mp4": { job: "job_9c31" } },
      params: { command: "ffmpeg -i out.mp4 -vf drawtext=text='done':x=10:y=10 final.mp4" }
    })
    ```
  </Step>

  <Step title="Wait for the result">
    ```text theme={null}
    get_job({ jobId: "job_a71f", wait: true })
    ```

    Blocks up to 45 seconds, then returns `output.file.url`.
  </Step>
</Steps>

## Run the local server for direct disk access

The hosted server can't read your disk, so even a shell-capable agent goes through the presigned-URL handshake above. `@rendobar/mcp`, the local stdio server, skips that: its `upload_file` tool reads a file off disk and uploads it in a single call.

Get an API key at [app.rendobar.com](https://app.rendobar.com), Settings, API keys.

<Tabs>
  <Tab title="Claude Code">
    ```bash theme={null}
    claude mcp add rendobar -s user --env RENDOBAR_API_KEY=rb_... -- npx -y @rendobar/mcp
    ```
  </Tab>

  <Tab title="Claude Desktop">
    Edit the config file, then restart Claude Desktop.

    * macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
    * Windows: `%APPDATA%\Claude\claude_desktop_config.json`

    ```json theme={null}
    {
      "mcpServers": {
        "rendobar": {
          "command": "npx",
          "args": ["-y", "@rendobar/mcp"],
          "env": { "RENDOBAR_API_KEY": "rb_..." }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Other clients">
    Cursor, Cline, Windsurf, Zed, and Continue all run the same `npx -y @rendobar/mcp` command with the `RENDOBAR_API_KEY` env var. Only the config file and the top-level key name differ (`mcpServers` for most, `context_servers` for Zed).
  </Tab>
</Tabs>

<Info>Needs Node 20.10 or later. The server checks at startup and exits with a clear message if it's older.</Info>

## See also

* [FFmpeg reference](/docs/jobs/ffmpeg): the job type `submit_job` calls in every example on this page
* [How a job works](/docs/concepts/job): the job lifecycle and the `output` shape
* [Error codes](/docs/support/errors): every code behind an `isError` response
* [Plan limits](/docs/support/limits): file size caps and concurrency by plan
