# Media Converter for AI Agents (FFmpeg) (`ent-e/media-converter-ffmpeg`) Actor

FFmpeg API for AI agents and automations. Send a media URL, get MP3, WAV, Whisper-ready 16 kHz mono WAV, FLAC, OGG, M4A, MP4, WebM, GIF or a JPEG thumbnail back. Trim and batch. No ffmpeg, Docker or server. Works via MCP, n8n, Make, API. Failed files are free.

- **URL**: https://apify.com/ent-e/media-converter-ffmpeg.md
- **Developed by:** [ENT-E](https://apify.com/ent-e) (community)
- **Categories:** AI, Agents, Videos
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 file converteds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Media Converter for AI Agents (FFmpeg)

A pay-per-file **FFmpeg API** for AI agents and automations: send a public audio or video URL and get back an MP3, a Whisper-ready 16 kHz mono WAV, a web-ready MP4, a GIF or a thumbnail, with no ffmpeg install, no Docker and no server to run.

### What this FFmpeg API does

You give it a media URL and a target format. It downloads the file, runs FFmpeg, stores the result in your run's key-value store, and returns one result row per file with a download link (`outputUrl`) and technical metadata.

| Target (`target`) | What you get |
|---|---|
| `wav16k` | Mono 16 kHz WAV, ready for Whisper and other speech-to-text models |
| `mp3`, `wav`, `flac`, `ogg`, `m4a` | Audio extracted from video, or audio transcoded between formats |
| `mp4` | H.264 MP4 with faststart, for web playback (max 1080p) |
| `webm` | VP9 WebM (max 1080p) |
| `gif` | Animated preview, 8 fps, 360 px wide, no audio (billed per output minute like audio/video) |
| `thumbnail` | A JPEG frame: the first frame, or the frame at `startSeconds` |

On top of that:

- **Trim**: set `startSeconds` and `durationSeconds` next to `url` (they also act as the default for every `files` item), or on individual `files` items, to convert only that part.
- **Batch**: pass a `files` array to convert many URLs in one run, each with its own target and trim.
- **Metadata**: each row includes the source's container format, duration, size, video codec and resolution, and audio codec, sample rate and channels (from ffprobe).
- **Failed files are free**: an unreadable, unreachable or rejected file comes back as a `status: "error"` row with an `error` message. You aren't charged for it and the run keeps going.

### Why use it instead of running FFmpeg yourself

- **Nothing to install.** No ffmpeg binary, no Docker image, no codecs to manage, no worker server to keep alive.
- **One call, one outcome.** `{"url": "...", "target": "wav16k"}` returns a Whisper-ready 16 kHz mono WAV. No flag soup.
- **Low risk.** You pay per converted file plus output minutes. No subscription, no idle server, and failed files cost nothing.
- **Works where your automation already lives.** Use it from MCP clients like Claude and Cursor (through Apify's MCP server), n8n, Make, Zapier or a plain HTTP call.
- **Agent-friendly output.** One structured row per file, with a download URL your agent can pass to the next step (transcription, upload, storage).

### Use cases

#### Whisper audio preprocessing: 16 kHz WAV in one call

Speech-to-text models such as Whisper expect 16 kHz mono audio. Convert a recorded call, a webinar video or a podcast to a speech-ready file before you transcribe it.

```json
{
  "url": "https://example.com/recordings/team-call.mp4",
  "target": "wav16k"
}
```

#### Convert video to MP3 / extract audio from video

Pull the audio track out of a video for podcasts, audiograms or archives. Use `m4a`, `ogg` or `flac` if you need a different container or lossless output.

```json
{
  "url": "https://example.com/videos/interview.mp4",
  "target": "mp3"
}
```

#### Video to GIF

Make a short animated preview (8 fps, 360 px) for a social post, a product page or a chat message. Trim it so the GIF covers only the moment you want.

```json
{
  "files": [
    { "url": "https://example.com/videos/demo.mp4", "target": "gif", "startSeconds": 5, "durationSeconds": 6 }
  ]
}
```

#### Video thumbnail generator

Grab a JPEG frame for a catalog, a CMS or a video card. Leave out `startSeconds` to get the first frame.

```json
{
  "files": [
    { "url": "https://example.com/videos/episode-12.mp4", "target": "thumbnail", "startSeconds": 42 }
  ]
}
```

#### Trim audio API

Cut a clip from a long recording, for example the first 10 minutes of a meeting to send to a summarizer. You pay only for the output minutes.

```json
{
  "url": "https://example.com/audio/all-hands.m4a",
  "target": "mp3",
  "startSeconds": 0,
  "durationSeconds": 600
}
```

#### Batch conversion for n8n / Make pipelines (n8n ffmpeg, make ffmpeg)

Convert a whole list in one run. The top-level `target`, `startSeconds` and `durationSeconds` are defaults, and each file can override them. Files are processed one after another.

```json
{
  "target": "wav16k",
  "files": [
    { "url": "https://example.com/podcast/ep-101.mp3" },
    { "url": "https://example.com/podcast/ep-102.mp3" },
    { "url": "https://example.com/podcast/ep-103-trailer.mp4", "target": "thumbnail", "startSeconds": 3 }
  ]
}
```

#### FFmpeg MCP tool for AI agents

Give Claude, Cursor or another MCP client a media tool. Your agent sends a URL and a target and gets a converted file link back. See [Use from MCP](#use-from-mcp-claude-cursor).

```json
{
  "url": "https://example.com/uploads/voice-note.ogg",
  "target": "wav16k"
}
```

#### Web-ready video (MP4 / WebM)

Re-encode uploads into H.264 MP4 with faststart, or VP9 WebM, so they play smoothly in the browser. Video that is already web-ready is copied without re-encoding and billed at the normal media-minute rate. Re-encoding above 720p (1080p-class) is billed per HD re-encode minute; see [Pricing](#pricing).

```json
{
  "url": "https://example.com/uploads/raw-clip.mov",
  "target": "mp4"
}
```

### Pricing

Pay per event. You pay only for successful output:

| Event | Price |
|---|---|
| File converted (per successful output file) | **$0.005** ($5 per 1,000 files) |
| Media minute (per started minute of output audio, GIF, stream-copied video, or video re-encoded at 720p or lower; thumbnails excluded) | **$0.002** |
| HD video re-encode minute (per started minute when `mp4`/`webm` video is actually re-encoded above 720p, i.e. 1080p-class after the 1080p cap; charged *instead of* the media minute, never both) | **$0.04** |
| Actor start (per run, one event per GB of memory, minimum one; default 1 GB = 1 event) | $0.00005 per event |

Failed files are free. Each output file pays exactly one per-minute rate. Every result row shows which one in `minuteEvent`.

**Why HD re-encoding costs more:** encoding 1080p video takes about 8× real time on the default 1 GB run, which costs far more in compute than $0.002 a minute covers. To stay on the cheap rate, send H.264/AAC (for `mp4`) or VP9/Opus (for `webm`) at 1080p or below without trimming, so it's copied rather than re-encoded. You can also downscale to 720p first.

#### Worked cost examples

- **100 one-hour podcasts to Whisper-ready WAV (`wav16k`):**
  - File events: 100 × $0.005 = **$0.50**
  - Media minutes: 100 × 60 min × $0.002 = **$12.00**
  - **Total: $12.50**, or $0.125 per episode (plus $0.00005 actor start for one batch run at the default 1 GB).
  - Minutes are counted per *started* minute of output, so a 60 min 30 s episode bills 61 minutes ($0.127).
- **1,000 video thumbnails:** 1,000 × $0.005 = **$5.00**. Thumbnails have no minute charge.
- **A 6-second GIF preview:** $0.005 + 1 × $0.002 = **$0.007**.
- **One 10-minute podcast to `wav16k`:** $0.005 + 10 × $0.002 = **$0.025**.
- **A 30-second 1080p H.264 MP4 to `mp4` (already web-ready, copied):** $0.005 + 1 × $0.002 = **$0.007**.
- **A 30-second 1080p clip re-encoded to `mp4` or `webm`** (e.g. a MOV/HEVC phone video, a 4K source scaled to 1080p, or any trimmed video): $0.005 + 1 × $0.04 = **$0.045**. A 10-minute 1080p re-encode is $0.005 + 10 × $0.04 = **$0.405**.
- **A 30-second 720p clip re-encoded to `mp4`:** $0.005 + 1 × $0.002 = **$0.007**.
- **Cut costs with trim:** converting only the first 10 minutes of a 1-hour recording bills 10 minutes, not 60.

To cap spend on a run, set a maximum total charge in the run options.

### Input reference

| Field | Type | Default | Description |
|---|---|---|---|
| `url` | string | – | Public URL of one audio/video file. |
| `target` | string | `mp3` | Output format: `mp3`, `wav`, `wav16k`, `flac`, `ogg`, `m4a`, `mp4`, `webm`, `gif`, `thumbnail`. Default for all files in a batch. |
| `startSeconds` | integer | – | Trim start in seconds (for `thumbnail`: the frame time). Applies to `url` and is the default for every `files` item. |
| `durationSeconds` | integer | – | Seconds to keep from `startSeconds`. Applies to `url` and is the default for every `files` item. |
| `files` | array | – | Optional batch. Each item: `url`, and optionally `target`, `startSeconds`, `durationSeconds`. Plain URL strings also work. |
| `maxDurationSeconds` | integer | `10800` (3 h) | Safety cap. Longer inputs are rejected (free) unless `durationSeconds` is set (top-level or on the item). |

Per-file options inside `files` (each falls back to the top-level value when omitted):

| Field | Description |
|---|---|
| `url` | Public URL of the media file. |
| `target` | Overrides the top-level `target` for this file. |
| `startSeconds` | Where to start (trim start, or the thumbnail frame time). Can be fractional, e.g. `12.5`. |
| `durationSeconds` | How many seconds to convert from `startSeconds`. |

Video output (`mp4`, `webm`) is capped at 1080p: larger inputs are scaled down to fit 1920×1080 (or 1080×1920 for portrait), keeping the aspect ratio. Inputs that are already in the target codec (H.264 for `mp4`; VP9, VP8 or AV1 for `webm`), 8-bit 4:2:0 and at most 1080p are remuxed without re-encoding when no trim is set, so quality is unchanged.

Limits: up to 2 GB per file, 3 hours maximum duration by default. Only process media you have the right to use.

### Output reference

One dataset row per input file. The converted files are stored in the run's default key-value store, and `outputUrl` points to the file.

```json
{
  "sourceUrl": "https://example.com/recordings/team-call.mp4",
  "target": "wav16k",
  "status": "ok",
  "outputKey": "57f39f65123e.wav",
  "outputUrl": "https://api.apify.com/v2/key-value-stores/<storeId>/records/57f39f65123e.wav",
  "mime": "audio/wav",
  "outputBytes": 1920078,
  "outputDurationSeconds": 60.0,
  "input": {
    "format": "mov,mp4,m4a,3gp,3g2,mj2",
    "duration": 60.0,
    "sizeBytes": 4821337,
    "video": { "codec": "h264", "width": 1280, "height": 720 },
    "audio": { "codec": "aac", "sampleRate": 44100, "channels": 2 }
  },
  "billedMinutes": 1,
  "minuteEvent": "media-minute",
  "videoReencoded": null
}
```

A failed file has only `sourceUrl`, `target`, `status: "error"` and `error`:

```json
{ "sourceUrl": "https://example.com/missing.mp4", "target": "mp3", "status": "error", "error": "<why it failed, e.g. the HTTP 404 from the download>" }
```

| Field | Description |
|---|---|
| `sourceUrl` | The URL you sent. |
| `target` | The output format used. |
| `status` | `"ok"` for a converted file, `"error"` for a failed one (not charged). |
| `outputKey` | Key of the file in the run's default key-value store. |
| `outputUrl` | Download URL of the converted file. |
| `mime` | MIME type of the output. |
| `outputBytes` | Output file size in bytes. |
| `outputDurationSeconds` | Output duration in seconds. |
| `input` | Probed source metadata: `format`, `duration` (s), `sizeBytes`, `video` (`codec`, `width`, `height`, or `null` if none) and `audio` (`codec`, `sampleRate`, `channels`, or `null` if none). |
| `billedMinutes` | Started minutes of output that were charged (`0` for thumbnails). |
| `minuteEvent` | The per-minute event charged for this file: `media-minute` or `video-reencode-minute` (`null` for thumbnails). |
| `videoReencoded` | For `mp4`/`webm`: `true` if the video was re-encoded, `false` if it was copied without re-encoding; `null` for other targets. |
| `error` | Error message (failed files only). |

### How to use it

#### Use from MCP (Claude, Cursor)

Add Apify's MCP server to your client and load this Actor as a tool:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=ent-e/media-converter-ffmpeg"
    }
  }
}
```

The first connection signs you in to Apify with OAuth. Then ask, for example: *"Convert https://example.com/call.mp4 to a 16 kHz WAV and give me the link."* Because this Actor is pay-per-event, agents can also pay per run through Apify's agentic payments.

#### Use from n8n

Add the **Apify** node (`@apify/n8n-nodes-apify`), choose the **Run an Actor and get dataset** operation, select `ent-e/media-converter-ffmpeg` and paste your input JSON. Each returned item's `outputUrl` can go straight into your transcription or upload step. For long jobs, use **Run an Actor**, then **Get Dataset Items** with the run's `defaultDatasetId`. No community nodes? Use an **HTTP Request** node with the API call below.

#### Use from Make

Add the Apify **Run an Actor** module with **Run synchronously** set to Yes, then **Get Dataset Items** with the run's `defaultDatasetId`, and map `outputUrl` into the next module. Make waits at most 120 seconds for a synchronous run, so for long media use the **Watch Actor Runs** trigger, or an **HTTP** "Make a request" module calling the API below.

#### Use from Zapier

Use the Apify **Run Actor and Fetch Results** action (best for runs under 5 minutes), or **Run Actor** followed by **Fetch Dataset Items**. For long runs, run asynchronously and start the next Zap from the **Finished Actor Run** trigger. Map `outputUrl` into your next step.

#### Use from the API

Run it and get results in one request:

```bash
curl -X POST "https://api.apify.com/v2/acts/ent-e~media-converter-ffmpeg/run-sync-get-dataset-items?token=<APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/talk.mp4", "target": "wav16k"}'
```

Synchronous calls wait up to 5 minutes. For long files or big batches, start an asynchronous run (`POST /v2/acts/ent-e~media-converter-ffmpeg/runs`) and read the dataset when it finishes.

### FAQ

#### Is this an FFmpeg API I can call without installing ffmpeg?

Yes. FFmpeg runs on Apify's infrastructure. You send JSON with a URL and a target and get a download link back. There is nothing to install, containerize or host.

#### How do I prepare audio for Whisper?

Use `"target": "wav16k"`. The output is a mono 16 kHz WAV, the format speech-to-text models such as Whisper expect. It works with video input too, and the audio track is extracted automatically.

#### How do I convert a video to MP3 or extract audio from a video?

Send the video URL with `"target": "mp3"` (or `m4a`, `ogg`, `wav`, `flac`). The audio track becomes the output file.

#### Can I make a GIF or a thumbnail from a video?

Yes. `gif` gives an 8 fps, 360 px animated preview, and `thumbnail` gives a JPEG frame. Use `startSeconds` (with `durationSeconds` for GIFs), at the top level or per file, to choose the moment. GIFs are billed per output minute like audio and video, and thumbnails only per file.

#### Can I use it as an FFmpeg MCP tool in Claude or Cursor?

Yes, through Apify's MCP server at `https://mcp.apify.com`. Add `?tools=ent-e/media-converter-ffmpeg` to load just this tool.

#### How much does video conversion cost?

It depends on whether the video has to be re-encoded. Copying already web-ready video (H.264 to `mp4`, VP9/VP8/AV1 to `webm`, at most 1080p, no trim), audio, GIFs and re-encodes at 720p or lower cost $0.005 per file plus $0.002 per output minute. Re-encoding to `mp4`/`webm` above 720p costs $0.005 per file plus $0.04 per output minute instead, because 1080p encoding needs much more compute. A 30-second 1080p re-encode is $0.045. The `minuteEvent` and `videoReencoded` fields in each result show what was charged.

#### What happens if a file fails?

It's returned as a row with `status: "error"` and an `error` message. Failed files are not charged, and the rest of the batch continues.

#### Which URLs work?

Public, directly downloadable audio or video file URLs, up to 2 GB and 3 hours by default (raise `maxDurationSeconds` or trim with `durationSeconds` for longer media).

### ENT-E media toolkit

Every tool takes a public file URL, needs nothing installed, charges per file, doesn't charge for failures, and works from MCP, n8n, Make, Zapier and the API.

- **[Media Converter for AI Agents (FFmpeg)](https://apify.com/ent-e/media-converter-ffmpeg)**: audio/video to MP3, Whisper-ready 16 kHz WAV, MP4, WebM, GIF or thumbnails, with trim and batch.
- **[Image Converter & Compressor](https://apify.com/ent-e/image-converter-compressor)**: convert to WebP or AVIF, compress to a target file size, resize, strip EXIF/GPS.
- **[Podcast Loudness Normalizer](https://apify.com/ent-e/podcast-loudness-normalizer)**: normalize to -16, -14, -23 or -24 LUFS with a true-peak ceiling, plus a before/after report.
- **[Video to Captions](https://apify.com/ent-e/video-to-captions-whisper)**: SRT, VTT, TXT and word-level JSON from any video or audio URL, with Whisper.
- **[Video to Shorts](https://apify.com/ent-e/video-to-shorts-captions)**: vertical 9:16 clips with burned-in animated captions for TikTok, Reels and Shorts.

# Actor input Schema

## `url` (type: `string`):

Direct, publicly downloadable URL of ONE audio or video file (http/https; redirects followed). Any FFmpeg-readable format: mp4, mov, mkv, webm, avi, mp3, wav, m4a, ogg, flac, opus... Max 2 GB. Must be the file itself, not a YouTube/web page. Example: https://download.samplelib.com/mp4/sample-5s.mp4

## `target` (type: `string`):

Output format, applied to `url` and to any `files` item without its own target. Default: mp3. Audio: mp3 (VBR ~190 kbps), wav (16-bit PCM, original rate), wav16k (mono, 16 000 Hz, 16-bit PCM - use this before Whisper/speech-to-text), flac (lossless), ogg (Vorbis), m4a (AAC 192 kbps). Video: mp4 (H.264 + AAC, web/faststart), webm (VP9 + Opus). Image: gif (animated, 8 fps, 360 px wide, no audio), thumbnail (single JPEG frame at startSeconds, default first frame). Audio targets need an input audio stream; video/gif/thumbnail need a video stream.

## `startSeconds` (type: `integer`):

Optional trim start in whole seconds from the beginning of the input, e.g. 30. For target=thumbnail this is the frame time (default: first frame). Applies to `url` and acts as the default for every `files` item; a `files` item's own startSeconds overrides it (and may be fractional, e.g. 12.5).

## `durationSeconds` (type: `integer`):

Optional length in whole seconds to keep from startSeconds, e.g. 600 for 10 minutes. Billing is per started minute of OUTPUT, so trimming lowers cost; also lets inputs longer than maxDurationSeconds be processed. Applies to `url` and is the default for every `files` item; per-item durationSeconds overrides it.

## `files` (type: `array`):

Optional batch, processed sequentially. Array of objects: {"url": string (required), "target": one of the target values (optional, falls back to top-level target), "startSeconds": number (optional, seconds from start to begin, e.g. 30; falls back to top-level startSeconds), "durationSeconds": number (optional, seconds to keep, e.g. 60; falls back to top-level durationSeconds)}. Example: \[{"url":"https://example.com/talk.mp4","target":"wav16k"},{"url":"https://example.com/clip.mov","target":"gif","startSeconds":5,"durationSeconds":4}]. Plain URL strings are also accepted. Failed items return status=error and are not charged.

## `maxDurationSeconds` (type: `integer`):

Safety cap in seconds on input duration (default 10800 = 3 hours). Longer inputs are rejected with status=error (not charged) unless durationSeconds is set (top-level or on the item) to trim. Billing is per started minute of OUTPUT, so trimming also lowers cost.

## Actor input object example

```json
{
  "url": "https://download.samplelib.com/mp3/sample-3s.mp3",
  "target": "mp3",
  "files": [
    {
      "url": "https://download.samplelib.com/mp4/sample-5s.mp4",
      "target": "gif"
    }
  ],
  "maxDurationSeconds": 10800
}
```

# Actor output Schema

## `results` (type: `string`):

One dataset row per input URL with status, a download URL (outputUrl) of the converted media file, metadata, or an error message.

## `files` (type: `string`):

Key-value store holding the converted output files.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "url": "https://download.samplelib.com/mp3/sample-3s.mp3",
    "files": [
        {
            "url": "https://download.samplelib.com/mp4/sample-5s.mp4",
            "target": "gif"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ent-e/media-converter-ffmpeg").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "url": "https://download.samplelib.com/mp3/sample-3s.mp3",
    "files": [{
            "url": "https://download.samplelib.com/mp4/sample-5s.mp4",
            "target": "gif",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("ent-e/media-converter-ffmpeg").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "url": "https://download.samplelib.com/mp3/sample-3s.mp3",
  "files": [
    {
      "url": "https://download.samplelib.com/mp4/sample-5s.mp4",
      "target": "gif"
    }
  ]
}' |
apify call ent-e/media-converter-ffmpeg --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ent-e/media-converter-ffmpeg"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0OM0IE8aOh5MrzQYI/builds/Hjw5uqm4sxomD2Vuz/openapi.json
