Skip to content

Repository files navigation

ModelArk Seed Multimodal MCP Server

A Python Model Context Protocol server built on FastMCP that exposes BytePlus multimodal generation through a typed, safe tool surface.

What It Does

The server provides a conditional MCP tool surface across three BytePlus products plus artifact access and an optional media upload helper:

Product Tools Description
Seed Audio seed_audio_generate, seed_audio_generate_variations Full-scene audio generation through Seed Speech
Seedream seedream_generate_image, seedream_edit_image, seedream_generate_image_variations Image generation and editing through ModelArk
Seedance seedance_create_task, seedance_create_task_variations, seedance_get_task, seedance_list_tasks, seedance_cancel_or_delete_task Async video generation and task management through ModelArk
Artifacts seed_media_get_artifact Retrieve persisted media inline by artifact ID
TOS (optional) media_upload Upload Base64 or local-file media to BytePlus TOS, return a presigned HTTPS URL for use as a reference

Key features:

  • Durable artifacts — all generated media is persisted locally so MCP resources remain usable after provider URLs expire (2h audio, 24h image/video)
  • Parallel variations — generate N independent variations in a single call with asyncio.gather, partial failures captured per variation
  • Per-variation seeds — Seedream supports reproducible generation with base_seed + index deterministic seeds
  • Typed inputs — Pydantic models validate all inputs before spending quota; unsupported combinations are rejected at the MCP layer
  • Model capability registry — logical model families map to operator-configured model IDs; validates resolutions, formats, and batch support per model
  • Security — DNS-pinned SSRF-safe downloads, tenant/principal ownership, scoped JWT auth for network HTTP, Host/Origin protection, and body limits
  • Runtime controls — shared provider/principal concurrency, daily budget reservations, safe retries, task ownership, readiness, metrics, and tracing
  • 459 offline tests — unit, contract, integration, HTTP security, E2E, and MCP conformance with 88.08% branch coverage

Supported Input Modalities

All input media is validated through an SSRF-safe URL policy and size-checked Base64 before reaching the provider. The table below shows what each tool accepts as reference input:

Tool Modality URL Base64 Speaker ID Roles Max Constraints
seedream_generate_image Image reference 10 PRO / 14 LITE·4X
seedance_create_task Image first_frame · last_frame · reference_image 9
seedance_create_task Video reference_video 3 URL only
seedance_create_task Audio reference_audio 3 Not sole input
seed_audio_generate Audio 3 Exclusive w/ image
seed_audio_generate Image 1 Exclusive w/ audio

The _variations siblings (seedream_generate_image_variations, seedance_create_task_variations, seed_audio_generate_variations) accept the same input modalities as their base tools.

Note

Video references must be pre-hosted. seedance_create_task accepts video references as a public HTTPS URL only — there is no inline Base64 option. Use the media_upload tool to upload Base64 or a local file path (stdio only) to BytePlus TOS and receive a presigned HTTPS GET URL you can pass directly to seedance_create_task. Alternatively, host the video on your own accessible HTTPS endpoint (S3, TOS, etc.). The URL must resolve to a public IP (private/loopback/link-local addresses are rejected by the SSRF policy). media_upload requires TOS_ACCESS_KEY / TOS_SECRET_KEY / TOS_BUCKET env vars; see Configuration.

Architecture

The server uses two provider gateways behind one normalized domain layer, a lifespan-owned runtime for concurrency/budget/ownership, and a durable artifact store. See docs/architecture.md for the full overview.

Components

flowchart TB
  subgraph Client["MCP clients"]
    CD[Claude Desktop]
    CX[Codex CLI]
    OC[OpenCode]
    TR[TRAE IDE]
  end
  subgraph Server["ModelArk MCP Server (FastMCP)"]
    Tools["Tools<br/>Seedream · Seedance · Seed Audio · Artifacts · TOS upload"]
    Domain["Domain layer<br/>models · capability registry · errors"]
    Runtime["Runtime services<br/>concurrency · budget · ownership · retry"]
    Store["Artifact store<br/>filesystem + .meta.json"]
    Sec["Security<br/>JWT · SSRF-safe downloads · body limits"]
    Obs["Observability<br/>structured logs · metrics · traces"]
  end
  subgraph Providers["BytePlus"]
    MA["ModelArk gateway<br/>Bearer auth"]
    SS["Seed Speech gateway<br/>X-Api-Key"]
  end
  Client <-->|"stdio / HTTP"| Tools
  Tools --> Domain
  Tools --> Runtime
  Tools --> Store
  Domain --> Providers
  Sec -. guards .-> Tools
  Obs -. observes .-> Tools
Loading

Layered view

flowchart LR
  L1["Transport<br/>stdio · Streamable HTTP"] --> L2["Server<br/>FastMCP tools · resources · routes"]
  L2 --> L3["Domain<br/>typed models · capability registry"]
  L3 --> L4["Provider gateways<br/>ModelArk · Seed Speech"]
  L4 --> L5["BytePlus<br/>Seedream · Seedance · Seed Audio"]
  L2 -.-> X["Cross-cutting<br/>security · runtime · observability · artifacts"]
Loading

Request sequence (a billable generate call)

sequenceDiagram
  participant C as MCP Client
  participant T as Tool handler
  participant R as Runtime services
  participant P as Provider gateway
  participant B as BytePlus
  participant A as Artifact store
  C->>T: call tool (Pydantic inputs)
  T->>T: validate inputs + capability registry
  T->>R: reserve budget + acquire provider/principal semaphores
  R-->>T: budget reservation
  T->>P: call_with_retry(provider request)
  P->>B: HTTPS (Bearer / X-Api-Key)
  B-->>P: media URL (2h audio / 24h image·video)
  P-->>T: provider result
  T->>A: persist artifact (durable copy)
  A-->>T: seed-media://artifacts/{id}
  T->>R: commit budget
  T-->>C: ArtifactRef (stable resource URI)
Loading

Quick Start

# Clone the repository
git clone <repo-url> modelark-mcp
cd modelark-mcp

# Install dependencies
uv sync

# Configure credentials
cp .env.example .env
# Edit .env and fill in your BytePlus API keys

# Run the server
make start

# Or run the verification script to test your credentials
uv run python scripts/verify_phase0.py

Configuration

Edit .env with your BytePlus credentials:

BYTEPLUS_MODELARK_API_KEY=your_modelark_key
BYTEPLUS_SEED_AUDIO_API_KEY=your_seed_audio_key  # pragma: allowlist secret
SEEDREAM_DEFAULT_MODEL=dola-seedream-5-0-pro-260628
SEEDANCE_DEFAULT_MODEL=dreamina-seedance-2-0-260128

If a credential is absent, the server skips registering that product's tools. seed_media_get_artifact is always available, provider tools appear only when their credentials are configured, and media_upload appears only when TOS credentials are configured.

See Configuration for the full environment variable reference.

Using with MCP Clients

The server runs as a stdio process. Configure it in your MCP client:

Claude Desktop

{
  "mcpServers": {
    "modelark-seed": {
      "command": "uv",
      "args": ["--directory", "/path/to/modelark-mcp", "run", "python", "-m", "modelark_mcp"],
      "env": {
        "BYTEPLUS_MODELARK_API_KEY": "your_modelark_key",
        "BYTEPLUS_SEED_AUDIO_API_KEY": "your_seed_audio_key"
      }
    }
  }
}

Codex CLI

Codex reads MCP servers from ~/.codex/config.toml (global) or .codex/config.toml (project-scoped, trusted projects). The format is TOML with one [mcp_servers.<name>] table per server:

[mcp_servers.modelark-seed]
command = "uv"
args = ["--directory", "/path/to/modelark-mcp", "run", "python", "-m", "modelark_mcp"]

[mcp_servers.modelark-seed.env]
BYTEPLUS_MODELARK_API_KEY = "your_modelark_key"
BYTEPLUS_SEED_AUDIO_API_KEY = "your_seed_audio_key"

OpenCode

OpenCode reads MCP servers from opencode.json / opencode.jsonc at the project root, or ~/.config/opencode/opencode.json globally. Use the top-level mcp key with type: "local" and command as an array:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "modelark-seed": {
      "type": "local",
      "command": ["uv", "--directory", "/path/to/modelark-mcp", "run", "python", "-m", "modelark_mcp"],
      "enabled": true,
      "environment": {
        "BYTEPLUS_MODELARK_API_KEY": "your_modelark_key",
        "BYTEPLUS_SEED_AUDIO_API_KEY": "your_seed_audio_key"
      }
    }
  }
}

TRAE IDE

TRAE uses the standard mcpServers JSON shape, added either via Settings → MCP → Add → Manual in the IDE, or declared in a project-level .trae/mcp.json (enable project-level MCP in Settings → MCP). The ${workspaceFolder} variable resolves to the project root:

{
  "mcpServers": {
    "modelark-seed": {
      "command": "uv",
      "args": ["--directory", "${workspaceFolder}", "run", "python", "-m", "modelark_mcp"],
      "env": {
        "BYTEPLUS_MODELARK_API_KEY": "your_modelark_key",
        "BYTEPLUS_SEED_AUDIO_API_KEY": "your_seed_audio_key"
      }
    }
  }
}

The same mcpServers JSON can be pasted directly into TRAE's Manual configuration window if you already run this server in another IDE.

TRAE Work

TRAE Work is the standalone AI-native workspace (web, desktop, mobile) with Work and Code dual modes. It reads the same mcpServers JSON shape as TRAE IDE and resolves ${workspaceFolder} to the project root. On the desktop app you also pick a runtime environment本地 (local) or 云端 (cloud) — when adding the server.

Add the server via Avatar → Settings → MCP → Create → Manual configuration, then paste:

{
  "mcpServers": {
    "modelark-seed": {
      "command": "uv",
      "args": ["--directory", "${workspaceFolder}", "run", "python", "-m", "modelark_mcp"],
      "env": {
        "BYTEPLUS_MODELARK_API_KEY": "your_modelark_key",
        "BYTEPLUS_SEED_AUDIO_API_KEY": "your_seed_audio_key"
      }
    }
  }
}

Runtime environment. Pick 本地 to run the server on your machine (the repo must be cloned locally, as above). Pick 云端 to run it in a TRAE-managed cloud sandbox; in that case sync the repository to the cloud environment first (for example via the GitHub integration) so ${workspaceFolder} resolves to a path that actually contains the project. See the official TRAE Work MCP guide.

Cursor, VS Code, MCP Inspector

See the Integration Guide for configuration snippets for Cursor IDE, VS Code MCP extension, and the MCP Inspector.

Available Make Targets

make help          # Show all targets
make install       # Install dependencies from uv.lock
make start         # Run the server over stdio
make start-http    # Run the server over Streamable HTTP (localhost:3000)
make dev           # Run in dev mode with auto-reload
make test          # Run the test suite
make lint          # Lint with ruff
make typecheck     # Type-check with mypy
make inspect       # Launch FastMCP inspector
make check-env     # Validate environment configuration

Documentation

Document Description
Getting Started Installation, configuration, and first run
Architecture System structure, two-gateway domain layer, request flow
Configuration Full environment variable reference
Integration Guide MCP client setup (Claude, Cursor, VS Code, Inspector)
API Reference Complete tool schemas, inputs, outputs, and examples
Use Cases Common scenarios with example tool calls
Tools Tool reference with input/output tables
Security Consolidated security model (auth, SSRF, body limits)
Runtime Concurrency, budget, ownership, retry
Observability Structured logging, metrics, tracing
Models Model capability registry and validation
Artifacts Durable artifact lifecycle and store
Transports stdio vs HTTP deployment
Deployment Container, Kubernetes, and remote HTTP deployment
Troubleshooting Common errors and fixes

Project Layout

modelark-mcp/
├── src/modelark_mcp/
│   ├── server.py              # Deterministic FastMCP factory and registration
│   ├── __main__.py            # Entry point (truststore injection)
│   ├── runtime.py             # Lifespan-owned stores, limits, budgets, ownership
│   ├── config/                # Pydantic Settings, model capability registry
│   ├── domain/                # ArtifactRef, errors, media, models
│   ├── providers/             # ModelArk + Seed Speech gateways and adapters
│   ├── tools/                 # 9 tool handlers + parallel helpers + cost estimation
│   ├── artifacts/             # Tenant-aware filesystem artifact store
│   ├── observability/         # Structured logging and Prometheus metrics
│   └── security/              # JWT, URL/media policy, safe downloader, HTTP limits
├── tests/
│   ├── unit/                  # Model validators, URL policy, media policy, helpers
│   ├── contract/              # Provider gateway + adapter contract tests
│   ├── integration/           # Tool handler, HTTP security, MCP conformance
│   └── e2e/                   # In-process FastMCP client tests
├── docs/                      # User and contributor documentation
├── plans/                     # Implementation plans
├── scripts/                   # Verification and smoke test scripts
├── fastmcp.json               # Declarative server configuration
├── Makefile                  # Task runner
└── pyproject.toml             # Project metadata and dependencies

Tech Stack

License

See the project configuration for license details.

Status

All three provider surfaces and both transports are implemented. The local release gate passes 459 offline tests at 88.08% branch coverage, Ruff formatting and lint, strict mypy, Bandit/secret scans, and package build. Dependency audit and container health are enforced by CI. Remote HTTP requires JWT configuration and is intentionally fail-closed.

About

Python MCP server exposing BytePlus models Seed Audio, Seedream, and Seedance via tools

Resources

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages