grok-media-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@grok-media-mcpmake 2 watercolor images of a lighthouse at sunset"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
grok-media-mcp
A remote MCP server that lets Claude make images, short videos and speech with xAI's Grok media models, with hard spend caps and a short list of things it refuses to make. It runs on one Cloudflare Worker and only lets its owner in: you host your own copy with your own xAI key.
Claude stays the model you talk to. When a chat needs media, Claude calls these tools, looks at the preview, and hands you the file.
Tools
Tool | What it does | Cost (xAI list price, 2026-10-19) |
| 1-4 images from a prompt, with small previews Claude can look at | $0.04 per image, $0.05 at |
| Edit or combine 1-5 images given by file id | Same |
| Start a 1-15 s video (480p or 720p); returns a job id | $0.02, $0.05 or $0.08 per second |
| Pending, done (with link), failed or expired | Free |
| Read text aloud with one of xAI's built-in voices | $15 per million characters |
| Transcribe an uploaded audio file | $0.10 per hour |
| Armed or not, spend today, this month and this session, caps | Free |
| Recent files with fresh links | Free |
No chat, search, code execution or generic file upload: only media.
Related MCP server: @lweight/xbrush-api-mcp
How it keeps you safe
Only you get in. claude.ai connects with OAuth. The Worker is the authorization server, Cloudflare Access is the login, and one email is allowed. Dynamic client registration is off: only Claude's published client identity and its exact redirect URI are accepted, and the consent page is shown every time with a warning to allow it only right after you clicked Connect yourself. A sign-in opened from any site other than claude.ai is refused. The Access ID token is checked for signature, issuer, audience, expiry, not-before and email. Access tokens last an hour and refresh tokens 30 days, rotating on use.
Nothing spends until you arm it. Paid tools refuse unless you have armed the server on its /inbox page, which
lasts two hours and asks you to confirm the work is not for children. Reading tools always work.
Hard caps, kept exactly. One Durable Object holds the ledger, so caps hold however many chats call at once. Defaults: $1.50 per call, $3 per arming session, $5 a day, $25 a month, 6 calls a minute. Each call reserves its quoted cost first and settles to xAI's reported cost after. A repeat of the same request within 10 minutes returns the earlier result for free. Your prepaid xAI balance with auto top-up off is the last cap that no bug can pass.
Content rules. Before any call to xAI, prompts are checked for children and teens, ages under 18, names on your private family list, sexual content, gore, weapon instructions, logos and trademarked characters, and real people. It is a word-and-pattern tripwire, not a classifier: Claude's judgment and xAI's moderation come first, and you look at anything before it goes public. Never use this for anything a child or teen uses.
Only your files go to xAI. Tool inputs are file ids, never URLs or raw data: files the server made, or ones you
uploaded on /inbox. Uploaded images are decoded and re-encoded, which removes location and camera data.
Files stay private. Media lives in your R2 bucket for 30 days. Links are HMAC-signed, last an hour (previews 15
minutes), always download as attachments, and are served with nosniff and a sandboxing CSP. Only image, video and
audio types are served. xAI's own temporary URLs are never returned.
Nothing sensitive in logs. Workers Logs get the tool, status and cost, never prompts, arguments, tokens, the key or xAI's error bodies.
Host your own copy
You need a Cloudflare account with a domain on it and an xAI account. Everything personal (your hostname, your email, your family-name list and every key) is set in the Cloudflare dashboard, never in this repo.
Generate secrets on your own machine and paste them straight into the dashboard. Never paste a key into a chat.
1. xAI
Make a separate xAI team for this server.
Use prepaid credits only. Leave the invoiced limit at $0 and turn auto top-up off (or cap it low).
Make an API key limited to the media models (image, video, speech) with a low requests-per-minute limit.
2. Cloudflare Access (Zero Trust)
Login method: Google or GitHub, with two-factor sign-in turned on at that provider.
OIDC app for the connector login: Access > Applications > Add an application > SaaS > OIDC. Redirect URL
https://<your-host>/callback, scopesopenid email profile, PKCE on. Policy: Allow, Include, Emails, your one address. Session duration 24 hours. Note the Client ID, Client secret and Issuer.Self-hosted app for the inbox: Access > Applications > Add an application > Self-hosted. Domain
<your-host>, pathinbox. The same one-email policy and 24-hour session. Under cookie settings keep SameSite Lax and HttpOnly on. Note the Application Audience (AUD) tag.
3. The Worker
Workers & Pages > Create > Import a repository, pick your copy of this repo. Production branch
main; turn builds for other branches off. The first deploy creates the KV namespace and R2 bucket for you.Worker > Settings > Domains & Routes > Add > Custom domain:
<your-host>. Theworkers.devaddress and preview URLs are off inwrangler.jsonc, and the Worker refuses any other host.Worker > Settings > Variables and Secrets. Add each of these as type Secret:
Secret | Value |
|
|
| The one email allowed in |
| Names the server must refuse, comma-separated (can be empty) |
| The media-only xAI key |
| From the OIDC app |
| From the OIDC app |
| From the OIDC app, for example |
| The AUD tag of the self-hosted inbox app |
| 32+ random characters, for example |
| 32+ random characters, different from the one above |
Until every required secret is set, the Worker answers 503 to everything.
R2 > your bucket > Settings: keep public access off and the
r2.devURL disabled, and add an object lifecycle rule that deletes objects after 30 days. (The Worker also deletes them itself; the rule is the backstop.)Security > WAF:
A custom rule that blocks requests to your host for
/mcpand/tokenunless they come from Anthropic's published egress range (160.79.104.0/21when this was written; check Claude's connector docs).A rate-limiting rule on
/f/,/authorize,/tokenand/callback, for example 30 requests a minute per IP. Don't skip it: every visit to/authorizewrites to KV, and the free KV write allowance is what keeps your sign-ins refreshing.
Set a Cloudflare billing notification. The Images binding (previews and inbox re-encoding) has a free monthly allowance of unique transformations; normal use stays well inside it.
4. Connect Claude
Check discovery first:
https://<your-host>/.well-known/oauth-protected-resource/mcpandhttps://<your-host>/.well-known/oauth-authorization-servershould load, and the second should show"client_id_metadata_document_supported": trueand noregistration_endpoint.In claude.ai: Settings > Connectors > Add custom connector, URL
https://<your-host>/mcp. Sign in with Access and allow on the consent page. Never allow a consent page you didn't just open from claude.ai.When claude.ai asks about tool permissions, choose "always allow" only for
media_budget,video_statusandlist_media.Where claude.ai lets you, turn the connector off in projects where it must never be used (anything for kids, work projects), and say so in those projects' instructions.
Open
https://<your-host>/inbox, arm the server, and ask Claude for a test image.
Rotating secrets
Secret | How |
| Make a new key in xAI, replace the secret, then delete the old key |
| Regenerate in the OIDC app, then replace the secret |
| Replace; open inbox forms stop working until reloaded |
| Replace; existing links stop working ( |
All connector sessions | Clear the |
Settings you can change
CAP_PER_CALL_USD, CAP_PER_SESSION_USD, CAP_PER_DAY_USD, CAP_PER_MONTH_USD, CALLS_PER_MINUTE and
ARM_HOURS are in wrangler.jsonc. Model ids and prices are in src/config.ts; media_budget warns when the
price table is more than 90 days old.
Development
npm ci
npm run typecheck
npm test # runs in workerd with xAI and Access mocked: no account, no spendDependencies are pinned exactly. Update them through Dependabot PRs reviewed by hand.
License
This server cannot be deployed
Maintenance
Related MCP Connectors
Use AI models for chat, image, and video generation from Claude Code and other MCP hosts.
MCP server for QPost — lets AI agents publish video and image posts to YouTube, TikTok, Instagram.
MCP server for Google Veo AI video generation
Hosted X (Twitter) MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
1
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server for AI-powered image, audio, and video generation, enabling media creation directly from Claude, Cursor, and other MCP clients.1119 npmMIT
- AlicenseAqualityCmaintenanceMCP server for the XBrush AI media generation API, enabling image, video, audio generation, editing, and more directly from Claude Code via async polling.2114 npmMIT
- FlicenseNot gradedqualityBmaintenanceMCP server for managing video pipelines, integrating media processing (TTS, STT, image generation) and video editing, with a structured plugin system and tunnel to Claude AI Web.-
- FlicenseNot gradedqualityCmaintenanceRemote MCP server for Claude to generate images and videos using Higgsfield AI. Supports photo, reference-based image, and video generation.-