Qencode MCP

Qencode lets AI assistants transcode, analyze, edit, optimize, and deliver video using natural language, powered by a cloud video processing platform.

Documentation

qencode-mcp

Model Context Protocol (MCP) server for the Qencode Transcoding API.

Connect any MCP-compatible AI client — Claude, Cursor, ChatGPT, Grok, Gemini — to your Qencode account and let it submit, monitor, and reason about transcoding jobs on your behalf.

Quick example

Once your client is connected (see Connect a client), ask your agent in plain English:

Transcode https://example.com/input.mp4 as an HLS ladder at 1080/720/540/360. Put it in my R2 bucket videos/demo/.

The agent picks the hls_abr recipe, fills in the per-rendition encoding params, submits via start_encode2_raw, and polls until the job is done.

Prerequisites

  • A Qencode portal account with at least one project — sign in at the portal for your environment: https://portal.qencode.com (production) or https://portal-qa.qencode.com (QA). You select the project during the OAuth consent step.
  • An MCP-compatible client (Claude, Cursor, ChatGPT, Grok, Gemini, or any custom client).

There are no API keys to copy into client config — authentication is browser-based OAuth.

How it works

The connector uses standard OAuth 2.1 — no API keys in client config. On first use, your client opens a browser, you sign in to your Qencode portal account, pick a project, and approve the requested scopes. The client stores the token; subsequent calls are silent until the token expires.

Scopes the client should request at authorize time (published via Protected Resource Metadata):

ScopePurpose
openidOIDC identity
profileDisplay name
emailAccount email
offline_accessRefresh token
transcoding:readget_job_status, wait_for_job, docs tools
transcoding:writetranscode_video, start_encode2_raw

The RS enforces transcoding:read and transcoding:write on access tokens at the transport layer.

Your Qencode API keys never leave the portal. The MCP server derives a short-lived session token per request via an internal portal endpoint.

Environments

The same connector is deployed in two environments. Each has its own domains, accounts, projects, and credentials — sign in to the portal that matches the endpoint you connect to.

RoleProductionQA (testing)
MCP endpoint (connect here)https://mcp.qencode.com/mcphttps://mcp-qa.qencode.com/mcp
Portal (sign in / projects)https://portal.qencode.comhttps://portal-qa.qencode.com
Authorization serverhttps://auth.qencode.comhttps://auth-qa.qencode.com
Qencode APIhttps://api.qencode.comhttps://api-qa.qencode.com

The instructions below use the production endpoint. To test against QA, swap in the QA URL and sign in at the QA portal.

Connect a client

Endpoint: https://mcp.qencode.com/mcp — same for every client below. Sign in to your Qencode account when the browser opens and approve access.

QA (internal testing): use https://mcp-qa.qencode.com/mcp and sign in at the QA portal instead.

ClientWhere to add itMCP URL / config
Claude (chat)Message box → + → Connectors → Add connectorhttps://mcp.qencode.com/mcp
Claude CodeTerminalclaude mcp add --transport http qencode https://mcp.qencode.com/mcp
ChatGPTApps → search Qencode → Connect; or Developer Mode → Build appConnector URL: https://mcp.qencode.com/mcp
Gemini~/.gemini/settings.jsonmcpServers"httpUrl": "https://mcp.qencode.com/mcp" — then /mcp auth qencode in the CLI
CursorSettings → Tools & MCP → New MCP Server (or ~/.cursor/mcp.json)"url": "https://mcp.qencode.com/mcp" — restart Cursor after saving

Cursor (mcp.json):

{
  "mcpServers": {
    "qencode": { "url": "https://mcp.qencode.com/mcp" }
  }
}

Gemini (settings.json):

{
  "mcpServers": {
    "qencode": {
      "httpUrl": "https://mcp.qencode.com/mcp",
      "timeout": 30000,
      "trust": false
    }
  }
}

Tip: sign in to portal.qencode.com in your browser before connecting — OAuth goes smoother.

What the connector exposes

Tools

Transcoding & jobs

ToolDescription
transcode_videoSubmit a job from a source URL to one or more outputs. Convenience wrapper — auto-injects encoder_version: 2 (or 1 for VMAF) when omitted.
start_encode2_rawEscape hatch — submit a job with the full query JSON exactly as the Qencode API expects.
get_job_statusOne-shot status snapshot by task_token.
get_job_status_detailedFull, authoritative job status, including per-rendition progress and output details.
wait_for_jobPoll until terminal state, timeout, or internal poll cap. Do not call in parallel with other tools in the same client batch.
search_qencode_docsSearch the built-in knowledge base of recipes and reference docs.
fetch_qencode_docFetch the full content of a knowledge-base resource by qencode:// URI (tool-based counterpart to resources/read).

Media Storage

Bucket management and ingest for Qencode Media Storage. These ride the same OAuth grant as the transcoding tools — no extra scope and no re-consent.

ToolDescription
list_bucketsList the Media Storage buckets available to the account.
create_bucketCreate a new bucket. Called only on an explicit request — not to satisfy a missing destination.
list_objectsBrowse the contents of a bucket.
get_download_urlReturn a time-limited download URL for an existing object.
download_url_to_bucketServer-side copy of a public URL into a bucket (ingest, no transcoding).

Resources

The server ships a knowledge base of recipes and reference docs, exposed as MCP resources so the agent can fetch only what it needs. Notable URIs:

  • qencode://docs/best-practices — composition defaults the agent applies automatically
  • qencode://docs/storage — destination compatibility matrix (Qencode S3, R2, AWS S3, Azure, B2, FTP/SFTP)
  • qencode://docs/error-codes — error code → cause → fix
  • qencode://docs/gotchas — non-obvious API quirks
  • qencode://schema/digest — full attribute reference for start_encode2
  • qencode://recipe/<slug> — one per feature flow: hls_abr, mp4_ladder, audio_outputs, thumbnails, speech_to_text, subtitles, stitching, drm_widevine_ezdrm, drm_fairplay_ezdrm, drm_playready_ezdrm, drm_aes128, drm_buydrm, drm_expressplay, codec_av1, per_title_encoding, incremental_abr, refresh_abr_playlist, callbacks, reliability, video_metadata

Use search_qencode_docs to discover the right recipe URI for a goal.

Prompts (slash commands)

In clients that surface MCP prompts, 21 one-shot templates are available. Each tells the agent to read the matching qencode://recipe/... resource and submit via start_encode2_raw.

ABR / packaging: encode_hls_abr, encode_dash_abr, encode_mp4_ladder, encode_incremental_rung, encode_refreshing_playlist

Codecs / quality: encode_av1, tune_per_title

Audio / images / text: extract_audio, generate_thumbnails, transcribe, add_subtitles

Probe / stitch: get_video_metadata, stitch_videos

Production hooks: enable_callbacks, enable_reliability

DRM: encode_aes128_hls, encode_widevine_ezdrm, encode_playready_ezdrm, encode_fairplay_ezdrm, encode_drm_buydrm, encode_drm_expressplay

Source URL rules

transcode_video and start_encode2_raw accept source values with schemes https://, http://, s3://, or tus:. FTP/SFTP and private/metadata URLs are rejected at the tool boundary (SSRF defence). See docs/security/THREAT_MODEL.md for limitations.

Security

Authentication is OAuth 2.1 only — there is no static-API-key mode. Your Qencode API keys never leave the portal; the server derives a fresh, short-lived session token per request via an internal portal endpoint. Source URLs are validated at the tool boundary (SSRF defence — see Source URL rules).

Full threat model and adversarial test coverage: docs/security/THREAT_MODEL.md.

Development

uv venv && uv pip install -e ".[dev]"
NO_NETWORK=1 pytest -q              # offline L1 + L2 + L5 (~540 tests)
pytest -m protocol                # MCP wire conformance only
pytest -m unit                    # per-tool logic (FakeQencode)
pytest -m security                # OWASP MCP Top 10 adversarial suite

Protocol tests run fully offline (mocked Authorization Server, portal, and Qencode API). CI is the Jenkins job mcp_automated_tests (Jenkinsfile.manual): manual checkboxes for any layer, nightly L3 cron, weekly L4 cron.

Supported MCP protocol versions

Clients negotiate a version at initialize. This server targets MCP 2025-11-25 as the primary version. CI also runs conformance tests against 2025-06-18 because JSON-RPC batching behavior differs between earlier revisions. We do not claim support for 2025-03-26 or older wire semantics beyond what the underlying SDK negotiates.

VersionSupportNotes
2025-11-25PrimaryStreamable HTTP, resumable SSE where used
2025-06-18CI matrixRegression guard for mid-2025 clients
2025-03-26Not targetedBatching semantics differ from 2025-06-18

More docs

Versioning policy

The connector follows SemVer applied to the MCP surface — tools, prompts, resources, OAuth scopes, and supported protocol versions. Qencode HTTP API changes are out of scope (they are the API's own concern, not the connector's).

  • MAJOR — a breaking surface change: a tool/prompt/resource is removed or renamed, a previously optional argument becomes required, an OAuth scope is added or tightened in a way that forces re-consent, or a supported MCP protocol version is dropped.
  • MINOR — a backward-compatible addition: a new tool/prompt/resource, a new optional argument, or a newly supported protocol version.
  • PATCH — no change to the surface shape: tool/prompt description rewordings, knowledge-base/doc updates, and bug fixes.

Surface changes are guarded by snapshot tests under tests/protocol/. When you change the surface, regenerate the snapshots (python scripts/regen_tools_snapshot.py) and bump the version in the same PR: pyproject.toml, src/qencode_mcp/__init__.py, server.json, and a new CHANGELOG.md entry must all agree.

Links