Skip to main content
Glama
README.md
# transcribe-mcp

Read web pages as clean markdown, transcribe audio and video, and find the silence worth
cutting — from any MCP client.
**No account, no API key, no subscription.** Your agent pays a fraction of a cent per call,
in USDC, straight from a wallet you control.

```json
{
  "mcpServers": {
    "transcribe": {
      "command": "npx",
      "args": ["-y", "transcribe-mcp@latest"],
      "env": { "TRANSCRIBE_MCP_WALLET_KEY": "0x..." }
    }
  }
}
```

On **Windows**, MCP clients can't start `npx` directly, so wrap it:
`"command": "cmd", "args": ["/c", "npx", "-y", "transcribe-mcp@latest"]`.

That is the whole setup. There is nothing to sign up for. It needs **Node 20+**. The
[video skill](#cutting-a-whole-video) also needs ffmpeg.

**One paid call at a time per wallet.** The shop refuses a second paid request while one is
still running (free, with "already in flight"). Call it sequentially, never in parallel.

## Tools

| tool | what it does | price |
|---|---|---|
| `transcribe_url` | a public audio/video `url` **or a local audio `file`** → text, timings, detected language | **$0.05** |
| `find_dead_air` | subtitles or timings (inline, or `from_file` a .json) → the spans worth cutting, and what you'd save | **$0.002** |
| `fetch_page` | a web page → clean markdown, links resolved. `render: true` for JavaScript pages | **$0.005** |
| `shop_info` | prices, limits and how payment works | **free** |

`find_dead_air` eats exactly what `transcribe_url` returns, so the two chain:
transcribe a talk, then cut the silence out of it.

```
"cuts": [{ "from": 2.55, "to": 10.85, "seconds": 8.3, "reason": "silence" }],
"stats": { "sourceSeconds": 20, "speechSeconds": 5.05, "wouldSavePercent": 74.75 }
```

`transcribe_url` and `find_dead_air` take `save_to`: an absolute path to a **new** `.json` file. The full result
goes there and the reply is one line plus the receipt, so an hour of transcripts never floods
your agent's context. It never overwrites a file, and a missing folder is refused before paying.

### Cutting a whole video

For cutting a whole video end to end — split, transcribe, cut, synced subtitles — there is a
ready agent skill in [`skills/dead-air-cutter`](skills/dead-air-cutter/SKILL.md).

## What leaves your machine

- `transcribe_url`: the `url`, or the bytes of the `file` (audio only — `.mp3 .wav .m4a .aac
  .ogg .opus .oga .flac`; a video is refused, extract its audio with ffmpeg first).
- `find_dead_air`: the timings and text — from `from_file`, only `start`, `end`, `text` of each
  segment plus `durationSeconds` are sent, whatever else the file holds. If the file has a
  `vtt` field instead, that subtitle text is sent whole.
- `fetch_page`: the page URL.

This server talks only to `https://transcribe.soboljem.cz`. What the shop does with it, from its
[terms](https://transcribe.soboljem.cz/terms):

- **Audio is never stored.** It is transcribed by Cloudflare Workers AI and passes through
  Cloudflare's infrastructure.
- **The result is kept briefly**, up to about 8 hours. It is replayable for 15 minutes, then
  deleted by a sweep that runs four times a day. The replay is a shop-side safeguard that this
  client cannot use: every call signs a new payment. **After a timeout or a "may have been
  charged" reply, check the wallet. Calling again pays again.**
- **A row per sale is kept with no automatic deletion**: time, price, audio length, word and
  cut counts, the source hostname (never the full URL), and the paying wallet address and
  transaction hash, which are public on Base anyway. Ask via the terms page to have rows
  deleted.
- **Payment** settles through the PayAI facilitator on Base. On each sale, the shop owner
  gets a Telegram notification with the shortened payer address and source hostname.

The private key in `TRANSCRIBE_MCP_WALLET_KEY` never leaves the machine. It only signs.

## Why pay-per-call instead of an API key

Because an agent cannot fill in a signup form. [x402](https://x402.org) is an HTTP-native
payment: the server answers `402 Payment Required` with a price, the client pays it, the
request goes through. No dashboard, no key rotation, no minimum, no monthly bill. If you
never call it, you never pay anything.

Settlement is USDC on **Base** (`eip155:8453`).

## Running it without a wallet

It starts fine. `shop_info` answers, `tools/list` works, and the paid tools tell you what
to set. Look before you fund anything.

## What it will not do

- **It will not overspend.** Every call is filtered through a $0.10 ceiling; a quote above
  it is dropped and the client refuses to pay rather than guessing.
- **It will not charge you for a refusal.** Bad arguments are caught locally and never
  leave your machine. The shop is built not to settle error responses; that was verified on
  testnet (see its terms).
- **It will not tell you "no charge" when it cannot know.** If the connection drops mid-call,
  it says a payment may have gone out and to check the wallet before calling again.
- **It will not lie about a sale.** If the settlement header is missing, it says so
  instead of reporting a payment it cannot prove.

Files are capped at 800 KB. Oversized ones are refused for free, before payment.
A local `file` is sent to the shop as bytes, so nothing has to be hosted first. For anything
long, extract the audio small and split it — mono Opus at 16 kbps fits ~6 minutes per call:

```
ffmpeg -i talk.mp4 -vn -ac 1 -c:a libopus -b:a 16k -f segment -segment_time 360 part%03d.opus
```

## Configuration

| variable | meaning |
|---|---|
| `TRANSCRIBE_MCP_WALLET_KEY` | private key of a wallet holding a little USDC on Base. Required only for the paid tools. |

Use a **dedicated wallet with a few dollars in it**, not your main one. This is true of every
tool you hand a private key to, and it is true here.

## Tests

```
npm test
```

MIT.

TDQS

A4.4/5.0

Scored across 3 tools

Disambiguation5/5

Each tool serves a completely distinct role: transcribe_url handles audio-to-text, find_dead_air post-processes timings to find silence, and shop_info provides pricing metadata. There is zero overlap in purpose.

Naming Consistency4/5

Tool names follow a clear verb_noun pattern (transcribe_url, find_dead_air, shop_info) with snake_case. shop_info deviates slightly from the domain-action style of the others, but it is still predictable and readable.

Tool Count5/5

Three tools is perfectly scoped for this server: a core action (transcribe), a derived analysis (find_dead_air), and informational helper (shop_info). No tool feels extraneous, and the count matches the narrow purpose well.

Completeness4/5

The tool surface covers the key transcription workflow and provides a helpful cost info tool. An obvious gap is the lack of an update or delete operation for transcripts, but for a consumption-oriented service this is reasonable. The surface feels complete for its intended use.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues