Adding local audio transcription to Cursor and Claude Desktop via MCP

Install @speechweave/mcp and transcribe files and urls from Cursor, Claude Desktop, Claude Code, or Windsurf

By David Rae · 4 min read

Cursor and Claude Desktop are good at reading code and text. Drop a 45-minute sprint recording into the repo and the model has nothing to chew on until something turns that file into text.

@speechweave/mcp is the official Model Context Protocol server for that gap. You pass an absolute filesystem path or a public HTTPS URL. The server uses the same job workflow as our SDK simply create the job, then wait or poll until it finishes.

1. Install

Requires Node 18+ and a SpeechWeave API key (sk_live_…).

Cursor

Project file .cursor/mcp.json, or the global Cursor MCP config:

{
  "mcpServers": {
    "speechweave": {
      "command": "npx",
      "args": ["-y", "@speechweave/mcp"],
      "env": {
        "SPEECHWEAVE_API_KEY": "sk_live_..."
      }
    }
  }
}

Restart Cursor (or reload MCP) so the tools show up.

Claude Desktop

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

Same mcpServers block as above, and restart Claude Desktop. (If the server never starts on macOS, Claude often cannot find npx when Node was installed. Put the full path from which npx in command instead of npx.)

Env vars:

Variable Default Purpose
SPEECHWEAVE_API_KEY (required) Bearer key
SPEECHWEAVE_JOB_WAIT_MS 3600000 (1 hour) Max wait for wait-first tools before they return a job_id and tell you to poll

Model is a per-call argument (core or max, default core).

You can also run it by hand to confirm the process starts:

export SPEECHWEAVE_API_KEY="sk_live_..."
npx -y @speechweave/mcp

2. The six tools

Wait-first tools block the turn until the transcript is ready (or until timeout_ms / SPEECHWEAVE_JOB_WAIT_MS). Async tools return a job id immediately. Default service_mode is standard. Pass deferred for the cheaper background queue, which is usually what you want for long audio.

Tool Mode Input Use when
transcribe_file Wait-first Absolute local path Short/medium clip, blocking wait for results
transcribe_url Wait-first Public https:// URL Same, file already on the internet
start_job_file Async Absolute local path Long recording, poll for results
start_job_url Async Public https:// URL Long URL, poll for results
get_job_status Poll job_id Until completed / failed / cancelled
cancel_job Control job_id Queued or processing jobs

Shared arguments on the create / wait-first tools:

  • model: core (default) or max
  • service_mode: standard (default) or deferred
  • language: optional ISO code (en, es, …). Ignored when task is translate.
  • task: transcribe (default) or translate (English text, regardless of source language)
  • prompt: spelling / vocabulary hint for the first ~30 seconds, max 2000 characters

transcribe_file, transcribe_url, and get_job_status also take response_format: text, srt, vtt, or verbose_json. Omit it for the default plain transcript. verbose_json includes timestamped segments.

Wait-first tools take optional timeout_ms. On timeout you get the job_id and a hint to call get_job_status. That is success, not a hard failure.

Paths: relative paths are rejected. ./standups/aug_17.m4a will error. /Users/you/project/standups/aug_17.m4a works. Ask the agent to resolve the workspace file to an absolute path, Cursor and Claude Desktop can do that.

URLs: https:// only. No http://, no signed URLs that expire before the job runs.

Never paste raw audio into the prompt or into a tool argument.

3. Prompts that actually exercise the tools

Short clip, wait-first:

Transcribe /Users/me/recordings/standup.mp3 with SpeechWeave and list action items by owner.

The agent should call transcribe_file with that absolute path and then read transcript.

Long file, do not block the turn:

Start a SpeechWeave job for /Users/me/recordings/three_hour_offsite.m4a with service_mode: "deferred", then poll until it completes and summarize decisions.

That is start_job_file followed by get_job_status. Pass deferred explicitly. Without it the tools use the higher-priority (and more expensive) standard path.

Public URL:

Start a SpeechWeave job for https://cdn.example.com/interview.mp3 with service_mode: "deferred" and check back until it finishes.

Translate to subtitles:

Translate /Users/me/recordings/spanish_interview.mp3 into English SRT using SpeechWeave.

That is transcribe_file with task: "translate" and response_format: "srt".

Checkout-friction research (still one tool call, then the model’s own reasoning):

Transcribe /Users/me/research/user_interview_04.mp3 with SpeechWeave. Quote every place the user mentions checkout, and turn those into a prioritized issue list.

4. What happens under the hood

For a local file the server:

  1. Rejects a relative path or a missing file.
  2. Calls jobs.create({ file: absolutePath, model, service_mode, ... }) on @speechweave/node, which presigns, PUTs the bytes, and creates the job. Oversized files are rejected before upload (413 FILE_TOO_LARGE) with a hint to use service_mode: "deferred" when the sync cap is the problem.
  3. Wait-first: polls until terminal or timeout.
  4. Returns a JSON summary (id, status, transcript, …) into the model’s context. It does not write a .txt next to your audio, so nothing extra lands in git unless the agent decides to.

You are billed at the same Core / Max × sync / deferred rates as any other job.

Account limits still apply (typical self-serve max is 250 MB). GET /v1/limits on your key if a large file 413s.

5. When MCP is the wrong tool

Use the Node or Python SDK in app code when you need webhooks, a database write, or a user-facing upload button. MCP is for the editor and for agents sitting on your laptop.

Docs: speechweave.com/docs/mcp. Package: @speechweave/mcp on npm.