Sign inSign up

yomrishon/mcp-sora

By yomrishon

•Updated 7 months ago

Model Context Protocol (MCP) server for OpenAI Sora 2 video generation

Image
Integration & delivery
API management
Machine learning & AI
0

10K+

yomrishon/mcp-sora repository overview

⁠YomRishon MCP Sora

A production-ready Model Context Protocol (MCP) server for OpenAI Sora 2 video generation.

Exposes Sora 2 video workflows as MCP tools so AI clients can generate, edit, extend, and manage videos safely and reliably.


⁠Setup

⁠Prerequisites
  • Node.js ≥ 20
  • An OpenAI API key with Sora 2 access
⁠Install
git clone <repo-url> && cd yomrishon-mcp-sora
npm install
npm run build
⁠Configure
cp .env.example .env
# Edit .env and set OPENAI_API_KEY
VariableRequiredDefaultDescription
OPENAI_API_KEYstdio—OpenAI API key (required in stdio mode; optional in HTTP mode)
OPENAI_BASE_URLNohttps://api.openai.com/v1API base URL
SORA_DEFAULT_MODELNosora-2Default model for generation
SORA_MAX_POLL_SECONDSNo300Max polling duration
SORA_POLL_INTERVAL_MSNo5000Polling interval
SORA_DEBUGNofalseEnable debug logging
SORA_ALLOWED_UPLOAD_DIRSNo/tmpComma-separated allowed upload directories
MCP_TRANSPORTNostdioTransport mode: stdio or http
MCP_HTTP_PORTNo3000HTTP listen port (HTTP mode only)
MCP_HTTP_HOSTNo127.0.0.1HTTP listen host (HTTP mode only)
⁠Run
# Stdio mode (default)
node dist/index.js

# HTTP mode
MCP_TRANSPORT=http node dist/index.js
⁠Docker
# Build
docker build -t yomrishon-mcp-sora .

# Run
docker run -e OPENAI_API_KEY=sk-... yomrishon-mcp-sora
⁠CI/CD

A GitHub Actions workflow at .github/workflows/docker-publish.yml automatically builds and pushes the Docker image to Docker Hub on:

  • Push to main
  • Version tags (v*)
  • Manual dispatch

Required GitHub repo secrets:

SecretDescription
DOCKERHUB_USERNAMEYour Docker Hub username
DOCKERHUB_TOKENDocker Hub access token

⁠MCP client configuration

⁠Claude Desktop / VS Code

Add to your MCP settings (e.g., claude_desktop_config.json or VS Code MCP settings):

{
  "mcpServers": {
    "sora": {
      "command": "node",
      "args": ["/absolute/path/to/yomrishon-mcp-sora/dist/index.js"],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
⁠With npx (if published)
{
  "mcpServers": {
    "sora": {
      "command": "npx",
      "args": ["yomrishon-mcp-sora"],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
⁠HTTP transport (remote / multi-client)

When MCP_TRANSPORT=http, the server starts a Streamable HTTP endpoint instead of using stdio. Each request carries its own API key via the Authorization header, so a single server instance can serve many clients with different OpenAI accounts.

⁠Start the server
MCP_TRANSPORT=http MCP_HTTP_PORT=3000 node dist/index.js

Or with Docker:

docker run -p 3000:3000 \
  -e MCP_TRANSPORT=http \
  -e MCP_HTTP_HOST=0.0.0.0 \
  yomrishon-mcp-sora
⁠Client configuration (HTTP)

Point your MCP client at the HTTP endpoint:

{
  "mcpServers": {
    "sora": {
      "url": "http://localhost:3000/mcp",
      "headers": {
        "Authorization": "Bearer sk-..."
      }
    }
  }
}
⁠Endpoints
MethodPathDescription
POST/mcpMCP JSON-RPC endpoint (requires Authorization: Bearer <key>)
GET/mcpSSE stream for server-initiated messages
DELETE/mcpSession close (no-op in stateless mode)
GET/healthHealth check — returns {"status":"ok"}
GET/download/:tokenProxy download — streams video content using a short-lived token (no API key needed)
⁠Security considerations for HTTP mode
  • The server runs stateless — no session tokens or cookies are stored.
  • Always deploy behind a TLS-terminating reverse proxy (nginx, Caddy, etc.) in production.
  • MCP_HTTP_HOST defaults to 127.0.0.1 (loopback only). Set to 0.0.0.0 to accept remote connections.
  • If OPENAI_API_KEY is set alongside HTTP mode, it acts as a fallback when clients omit the header.

⁠Tools reference

⁠sora_describe_capabilities

Call this first to understand what parameters are valid.

{}

Returns supported models, sizes, durations, and feature flags.


⁠sora_create_video

Create a new video generation job.

{
  "prompt": "A golden retriever runs through a sunlit meadow at dawn. Slow tracking shot from the side, golden hour light streaming through tall grass. Cinematic, shallow depth of field, 35mm film grain.",
  "model": "sora-2",
  "size": "1920x1080",
  "seconds": 10
}

With image reference:

{
  "prompt": "The same landscape transforms from winter to spring. Time-lapse style, static camera.",
  "input_reference": {
    "type": "image_url",
    "url": "https://example.com/winter-landscape.jpg"
  },
  "seconds": 15
}

With characters:

{
  "prompt": "Luna the astronaut floats through the space station corridor. Close-up tracking shot, blue ambient lighting.",
  "characters": [
    { "id": "char_abc123", "name": "Luna" }
  ],
  "seconds": 10
}

⁠sora_get_video

Check a job's status.

{
  "video_id": "vid_abc123"
}

⁠sora_wait_for_video

Block until the job completes or times out.

{
  "video_id": "vid_abc123",
  "poll_interval_ms": 5000,
  "max_wait_seconds": 120
}

⁠sora_list_videos

List recent jobs with optional filters.

{
  "status": "completed",
  "model": "sora-2",
  "limit": 10
}

⁠sora_download_video_content

Get a download URL for a completed video. Returns a proxy URL that can be used directly without an API key.

{
  "video_id": "vid_abc123"
}

Returns:

{
  "download_url": "http://localhost:3000/download/<token>",
  "content_type": "video/mp4",
  "expires_in_seconds": 600
}

The download_url is single-use and expires after 10 minutes. Call the tool again to get a fresh URL.


⁠sora_edit_video

Edit an existing video with a new prompt.

{
  "source_video_id": "vid_abc123",
  "prompt": "Change the lighting to a warm sunset tone and slow the camera movement.",
  "model": "sora-2"
}

⁠sora_extend_video

Extend a completed video with additional footage.

{
  "video_id": "vid_abc123",
  "prompt": "The camera continues to pan right, revealing a hidden waterfall behind the trees.",
  "seconds": 10
}

⁠sora_create_character

Upload a character for cross-shot consistency.

{
  "name": "Luna",
  "file_path": "/tmp/luna-reference.mp4",
  "description": "Female astronaut, short dark hair, blue flight suit"
}

Or from a previously uploaded file:

{
  "name": "Luna",
  "file_id": "file_abc123",
  "description": "Female astronaut, short dark hair, blue flight suit"
}

⁠sora_get_character
{
  "character_id": "char_abc123"
}

⁠sora_remix_video

Deprecated — use sora_edit_video instead.

{
  "source_video_id": "vid_abc123",
  "prompt": "Same scene but in anime style.",
  "model": "sora-2"
}

⁠sora_help_prompt

Get a structured prompt brief from a rough idea. Does not call the API.

{
  "idea": "a cat exploring a neon-lit Tokyo alley at night",
  "style": "cyberpunk",
  "constraints": ["no text", "single take"]
}

Returns a framework with sections (subject, action, setting, camera, lighting, style, continuity) plus composition tips and an example.


⁠Capability registry

All model capabilities are defined in src/capabilities.ts. When Sora 2 capabilities change:

  1. Edit only src/capabilities.ts
  2. Update model sizes, durations, feature flags as needed
  3. Rebuild: npm run build

The capability file is extensively commented. Do not scatter capability checks throughout the codebase.


⁠Error categories

CategoryDescription
ValidationErrorInvalid user input (missing fields, bad types)
CapabilityErrorUnsupported operation for selected model
OpenAIAPIErrorUpstream API call failed
RateLimitErrorOpenAI rate-limited the request
AssetErrorFile/asset issue (missing, wrong type, expired)
TimeoutErrorPolling timed out before completion
NotFoundErrorRequested resource not found

All errors include a category, message, and optional details with allowed values.


⁠Troubleshooting

"OPENAI_API_KEY environment variable is required"
Set the key in your environment or MCP client config's env block.

"Size X is not supported for model Y"
Call sora_describe_capabilities to see valid sizes for your model.

"Video did not reach terminal status within Ns"
Video generation can take minutes. Increase max_wait_seconds or use sora_get_video to poll manually.

"File path is outside allowed upload directories"
Set SORA_ALLOWED_UPLOAD_DIRS to include your upload directory.

Debug mode
Set SORA_DEBUG=true to see full request/response bodies in stderr logs (API keys are still redacted).


⁠Security notes

  • API keys are loaded from environment variables only and never logged
  • Authorization headers are redacted in all log output
  • File uploads are restricted to explicitly configured directories (SORA_ALLOWED_UPLOAD_DIRS)
  • File extension validation prevents uploading non-video files as characters
  • No arbitrary URL fetching — remote references go directly to OpenAI's API
  • Video download URLs use single-use, time-limited tokens (10-minute expiry) — the upstream API key is never exposed to clients
  • In HTTP mode, deploy behind a TLS-terminating reverse proxy; MCP_HTTP_HOST defaults to loopback (127.0.0.1)

⁠License

MIT

Tag summary

Content type

Image

Digest

sha256:c437e4474…

Size

60.4 MB

Last updated

7 months ago

docker pull yomrishon/mcp-sora