Cabina MCP

Model Context Protocol — Streamable HTTP (stateless) — https://api.cabina.ai

Overview

Cabina exposes all its AI models — text, image, video, and audio — as MCP tools, alongside tools for retrieval (datastores / RAG) and reusable skills. Any MCP host (Claude Desktop, Claude Code, VS Code Copilot, Cursor, etc.) can call them directly.

The tools are grouped into these areas:

AreaTools
Generationgenerate, get_message, list_models
Attachmentsupload_attachment, list_attachments, delete_attachment
Conversationslist_conversations, get_conversation, delete_conversation
Datastores (RAG)search_datastores, list_datastores, create_datastore, upload_document, add_datastore_document, list_datastore_files, delete_datastore_file
Skillslist_skills, get_skill, read_skill_file, write_skill_file

Every tool also returns a human-readable text summary, so hosts that only render text content still show usable results.

Authentication

Every request must carry a Cabina API token as a Bearer token:

Authorization: Bearer <your-cabina-token>

Tokens are issued by the admin API (POST /admin/user). Missing or invalid tokens return 401 Unauthorized.

Connection

PropertyValue
TransportStreamable HTTP (stateless — no session affinity required)
Endpointhttps://api.cabina.ai/mcp
ProtocolJSON-RPC 2.0 over HTTP POST

Tools — Generation

generate

Generate content with any Cabina model. Returns text for LLMs, CDN URLs for image/video/audio, or transcribed text for transcription models.

Async video: video generation can take several minutes, so generate returns immediately with status: "processing" and a message_id instead of blocking. Poll get_message with that message_id until status becomes success (or error). Text, image, and audio models still return their result synchronously.

Input schema

FieldTypeRequiredDescription
modelstringyesModel ID in provider/model-name format. Use list_models to discover options.
promptstringno*Text prompt. Required for generation, optional for transcription.
systemstringnoSystem prompt (text models only).
conversation_idstring (UUID)noContinue an existing conversation. A new one is created if omitted.
input_attachmentsarraynoInput media: [{"data": "<value>", "type": "url"|"b64_data"|"id"}]. Required for image-to-image, image-to-video, and transcription. For local files, prefer upload_attachment and reference the returned attachment_id with "type": "id" instead of inlining base64.
configobjectnoModel-specific parameters (e.g. size, aspect_ratio, duration, voice).

Output schema

FieldTypeDescription
message_idstring (UUID)ID of the created message. Pass to get_message to poll async results.
conversation_idstring (UUID)ID of the conversation.
statusstringGeneration status: created, processing, success, or error. Returns processing for in-flight video.
textstringGenerated text (LLMs and transcription).
attachmentsarrayGenerated media: [{"content_type": "image/png", "url": "https://..."}]
usageobject{"prompt_tokens", "completion_tokens", "total_tokens"}

Examples

Text GPT-4o chat:

{
  "model": "gpt/gpt-4o",
  "prompt": "Explain quantum entanglement in one paragraph.",
  "system": "You are a concise science writer."
}

Image Flux image generation:

{
  "model": "flux/flux-pro",
  "prompt": "A photorealistic red fox in a snowy forest at golden hour",
  "config": { "aspect_ratio": "16:9" }
}

Video Kling video generation:

{
  "model": "kling/kling-2.5-turbo",
  "prompt": "Camera slowly pans across a misty mountain range at sunrise",
  "input_attachments": [{ "data": "https://example.com/frame.jpg", "type": "url" }]
}

Transcription Audio to text:

{
  "model": "whisper/whisper-large-v3",
  "input_attachments": [{ "data": "https://example.com/audio.mp3", "type": "url" }]
}

get_message

Fetch the current status and result of a message by its ID. Use this to poll for completion after generate returns status: "processing" (e.g. for video).

Input schema

FieldTypeRequiredDescription
message_idstring (UUID)yesThe message_id returned by a previous generate call.

Output schema

Same shape as generate: message_id, conversation_id, status, text, attachments, usage. When status is success, attachments holds the finished media URLs.

{ "message_id": "5f3c…" }

list_models

List all available Cabina models across every modality.

Takes no input. Returns:

{
  "models": [
    { "id": "claude/claude-opus-4-8",    "type": "text"  },
    { "id": "flux/flux-pro",             "type": "image" },
    { "id": "klingimage/kling-v2-master","type": "image" },
    ...
  ]
}

Modality values: text image video audio

Available models

The list below is generated from the same model configuration as list_models, so it always reflects the models currently enabled. Pass any of these as the model parameter in provider/model-name format.

text Text

image Image

video Video

Tools — Attachments

Input attachments let you send a file (image, audio, or video) to a model — for image-to-image, image-to-video, or transcription. Upload the file once with upload_attachment, then reference the returned attachment_id from one or more generate calls via input_attachments: [{"type": "id", "data": "<attachment_id>"}] — this avoids re-sending large base64 payloads on every request. Attachments are capped at 100 MB.

upload_attachment

Upload an input media file once and get back an attachment_id to reference in generate.

ParameterTypeRequiredDescription
datastringyesBase64-encoded file bytes. Accepts a raw base64 string or a data URI (data:<content-type>;base64,<payload>).
filenamestringnoOriginal filename; helps detect the content type and sets the CDN extension.
content_typestringnoContent-type hint (e.g. image/png) used when data is raw base64 without a data URI.
size_bytesintegernoDeclared file size in bytes. When provided it is validated against the 100 MB limit up front, so oversized uploads are rejected before the data is decoded.

Returns: { "attachment_id": "att_123", "url": "https://...", "content_type": "image/png" }

Then reference it in generate:

{
  "model": "flux/flux-pro",
  "prompt": "Restyle this photo as an oil painting",
  "input_attachments": [{ "type": "id", "data": "att_123" }]
}

list_attachments

List the input attachments you have uploaded. Takes no input. Returns:

{
  "attachments": [
    { "attachment_id": "att_123", "filename": "photo.png", "content_type": "image/png", "url": "https://...", "created_at": "2026-06-26T..." },
    ...
  ]
}

delete_attachment

Delete a previously uploaded input attachment by its attachment_id.

ParameterTypeRequiredDescription
attachment_idstringyesThe attachment_id returned by upload_attachment.

Returns: { "deleted": true }

Tools — Conversations

Every generate call belongs to a conversation. Omit conversation_id on the first call to start a new one (the returned conversation_id can be passed back to continue it). These tools let you browse history, read a whole thread, and delete threads you no longer need.

list_conversations

List your conversations, most recently updated first. Takes no input. Returns:

{
  "conversations": [
    { "conversation_id": "5f3c…", "title": "Quantum physics chat", "last_message_text": "Thanks!", "updated_at": "2026-06-26T..." },
    ...
  ]
}

get_conversation

Fetch a whole conversation by its ID: its title and every message in order, including roles, models, statuses, and any attachment URLs.

ParameterTypeRequiredDescription
conversation_idstring (UUID)yesThe conversation ID returned by generate or list_conversations.

Returns:

{
  "conversation_id": "5f3c…",
  "title": "Quantum physics chat",
  "created_at": "2026-06-26T...",
  "messages": [
    { "message_id": "a1…", "role": "user", "text": "Explain entanglement", "status": "user", "created_at": "..." },
    { "message_id": "b2…", "role": "assistant", "text": "Entanglement is...", "model": "gpt-4o", "status": "success",
      "attachments": [], "created_at": "..." }
  ]
}

delete_conversation

Delete a conversation and all of its messages by conversation_id. This cannot be undone.

ParameterTypeRequiredDescription
conversation_idstring (UUID)yesThe conversation ID to delete.

Returns: { "deleted": true }

Tools — Datastores (RAG)

A datastore is a searchable knowledge base. The typical workflow is: create_datastoreupload_document (returns a file_id, indexed in the background) → add_datastore_document (attach the file) → search_datastores. Use list_datastore_files to check indexing status before searching.

search_datastores

Perform semantic search across one or more Cabina datastores. Returns matching document excerpts with confidence scores.

ParameterTypeRequiredDescription
datastore_idsstring[]yesIDs of the datastores to search across.
querystringyesThe search query text.
top_kintegernoMaximum number of results to return. Uses the datastore default when omitted.

Returns:

{
  "raw": "Formatted context string ready for injection into a prompt",
  "results": [
    { "content": "Matched document excerpt...", "confidence_score": 0.92 },
    ...
  ]
}

list_datastores

List all datastores you have access to. Takes no input. Returns:

{
  "datastores": [
    { "id": "ds_123", "name": "Support docs", "created_at": "2026-01-15T..." },
    ...
  ]
}

create_datastore

Create a new datastore you can add documents to and search.

ParameterTypeRequiredDescription
namestringyesName for the new datastore.

Returns: { "id": "ds_123", "name": "Support docs" }

upload_document

Ingest a text or PDF document into your library from inline text or a URL. Returns a file_id; indexing runs in the background. Then call add_datastore_document to attach it to a datastore.

ParameterTypeRequiredDescription
namestringyesDocument name.
textstringno*Inline text content. Provide either text or url, not both.
urlstringno*URL of a text or PDF document to fetch and ingest.

Returns: { "file_id": "file_789", "url": "https://..." }

add_datastore_document

Attach a previously uploaded document (by file_id) to a datastore so it can be searched.

ParameterTypeRequiredDescription
datastore_idstringyesID of the datastore to attach the file to.
file_idstringyesFile ID returned by upload_document.

Returns: { "success": true }

list_datastore_files

List the documents in a datastore, including each document's processing status.

ParameterTypeRequiredDescription
datastore_idstringyesID of the datastore whose files to list.

Returns:

{
  "files": [
    { "file_id": "file_789", "name": "handbook.pdf", "status": "indexed" },
    ...
  ]
}

delete_datastore_file

Remove a document from a datastore by file_id.

ParameterTypeRequiredDescription
datastore_idstringyesID of the datastore to remove the file from.
file_idstringyesID of the file to remove.

Returns: { "success": true }

Tools — Skills

Skills are reusable, file-based bundles (a SKILL.md plus optional scripts/assets) that you can discover, download, and run locally — or author yourself. Global skills are shared and read-only; user skills are private and writable.

These tools are only present when the server is configured with a skills backend.

list_skills

List all skills available to you (global skills plus your own). Call this first to discover skills. Takes no input. Returns:

{
  "global_skills": [ { "name": "pdf-fill", "description": "Fill PDF forms" } ],
  "user_skills":   [ { "name": "my-report", "description": "..." } ]
}

get_skill

Fetch a full skill: its file tree and the base64-encoded contents of every file, so you can save it into your local skills/ directory and run it yourself.

ParameterTypeRequiredDescription
skill_namestringyesName of the skill to fetch.

Returns the skill name, description, and a files array of { path, content_b64, content_type, size, is_dir }.

read_skill_file

Read a single file from a skill (base64-encoded). Use when you don't need the whole skill bundle.

ParameterTypeRequiredDescription
skill_namestringyesName of the skill.
pathstringyesFile path relative to the skill root, e.g. SKILL.md.

Returns: { "content_b64": "...", "content_type": "text/markdown" }

write_skill_file

Write a single file into one of your skills (creates the skill if it doesn't exist). Build a skill file-by-file, or patch individual files. Global skills are read-only.

ParameterTypeRequiredDescription
skill_namestringyesName of your skill to write to (user-private skills only).
pathstringyesFile path relative to the skill root, e.g. SKILL.md or run.py.
contentstringyesPlain text file content. Pass raw text — do not base64-encode it.

Returns: { "path": "SKILL.md" }

Quickstart

MCP Inspector

npx @modelcontextprotocol/inspector
  1. Transport: Streamable HTTP
  2. URL: https://api.cabina.ai/mcp
  3. Add header: Authorization: Bearer <your-token>
  4. Connect, then call list_models to see all available models.

Claude Desktop

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "cabina": {
      "url": "https://api.cabina.ai/mcp",
      "headers": {
        "Authorization": "Bearer <your-cabina-token>"
      }
    }
  }
}

Claude Code

Register via the CLI (one-time):

claude mcp add --transport http cabina https://api.cabina.ai/mcp \
  --header "Authorization: Bearer <your-cabina-token>"

Or add to .claude/settings.json (project) / ~/.claude/settings.json (global):

{
  "mcpServers": {
    "cabina": {
      "type": "http",
      "url": "https://api.cabina.ai/mcp",
      "headers": {
        "Authorization": "Bearer <your-cabina-token>"
      }
    }
  }
}

OpenCode

Add to opencode.json (project root) or ~/.config/opencode/opencode.json (global):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "cabina": {
      "type": "remote",
      "url": "https://api.cabina.ai/mcp",
      "headers": {
        "Authorization": "Bearer <your-cabina-token>"
      }
    }
  }
}

To avoid storing the token in plaintext use the {env:VAR} syntax: "Bearer {env:CABINA_TOKEN}".

OpenClaw

Add to ~/.openclaw/openclaw.json:

{
  "mcp": {
    "cabina": {
      "transport": "streamable-http",
      "url": "https://api.cabina.ai/mcp",
      "headers": {
        "Authorization": "Bearer <your-cabina-token>"
      }
    }
  }
}

Then run openclaw mcp reload to pick up the change without restarting.

Hermes Agent

Add to ~/.hermes/config.yaml:

mcp_servers:
  cabina:
    url: "https://api.cabina.ai/mcp"
    headers:
      Authorization: "Bearer <your-cabina-token>"

Use environment variable interpolation to avoid hardcoding the token: "Bearer ${CABINA_TOKEN}".

Error handling

HTTP statusMeaning
401Missing or invalid bearer token.
500 (in tool result)Model generation failed. The error message is returned in the tool result's text content with isError: true.