RunComfy MCP
Servidor MCP oficial remoto para a API Serverless da RunComfy (ComfyUI): gerencie implantações de GPU e execute inferência assíncrona de imagem/vídeo.
Documentação
RunComfy MCP
Servidor MCP para a plataforma RunComfy — API Serverless (ComfyUI), API de Modelos e API de Treinamento. Gerencie implantações, execute modelos hospedados, treine LoRAs e recupere resultados de assistentes de IA como Claude, Cursor e Windsurf.
Endpoint: https://mcp.runcomfy.com/mcp
Documentação: docs.runcomfy.com/mcp
O que faz
31 ferramentas espelhando a documentação do RunComfy 1:1, em três produtos além do saldo da sua conta.
API Serverless (ComfyUI) — seus próprios fluxos de trabalho em endpoints dedicados
Documentação: docs.runcomfy.com/serverless
| Categoria | Ferramentas |
|---|---|
| Gerenciamento de implantação | list_deployments, get_deployment, create_deployment, update_deployment, delete_deployment |
| Inferência | submit_request, get_request_status, get_request_result, cancel_request |
| Avançado | call_instance_proxy |
API de Modelos — modelos hospedados do catálogo, sob demanda
Documentação: docs.runcomfy.com/model-apis
| Categoria | Ferramentas |
|---|---|
| Catálogo | list_models, get_model, list_model_categories |
| Inferência | run_model, get_model_request_status, get_model_request_result, cancel_model_request |
Sem necessidade de gerenciar implantação e cobrança por requisição. list_models navega pelo
catálogo por palavra-chave ou capacidade (category=image-to-video), get_model
retorna o esquema de entrada de um modelo — tipos de propriedade, padrões, enums e
intervalos — e run_model o executa. Assim, um assistente pode ir de "crie um
vídeo" a uma requisição válida sem sair das ferramentas ou adivinhar um parâmetro.
As entradas também carregam description, base_price_usd por price_unit e um
model_url para a página do modelo.
model_id é o identificador exibido na página do modelo em
runcomfy.com/models, incluindo barras — por exemplo,
blackforestlabs/flux-1-kontext/pro/edit. Entradas de arquivo devem ser URLs HTTPS públicas.
API de Treinamento — conjuntos de dados e treinamento de LoRA com AI Toolkit
Documentação: docs.runcomfy.com/trainer-apis
| Categoria | Ferramentas |
|---|---|
| Conjuntos de dados | create_dataset, list_datasets, get_dataset_status, delete_dataset |
| Uploads de conjuntos de dados | upload_dataset_file_from_url, upload_dataset_text_file, get_dataset_upload_urls |
| Trabalhos de treinamento | submit_training_job, get_training_job_status, get_training_job_result, cancel_training_job, resume_training_job, edit_training_job |
Fluxo típico: crie um conjunto de dados → envie mídia e legendas .txt correspondentes →
consulte até READY → envie um trabalho com uma configuração YAML do AI Toolkit → consulte o status
→ baixe os checkpoints do resultado.
Como o servidor roda remotamente, ele não consegue ler arquivos locais. Envie mídia que ele
possa acessar via HTTP com upload_dataset_file_from_url, escreva legendas inline
com upload_dataset_text_file e, para arquivos locais ou maiores que 150 MB, use
get_dataset_upload_urls e PUT os bytes para a URL assinada você mesmo.
Conta
| Categoria | Ferramentas |
|---|---|
| Saldo | get_balance |
Uma única carteira financia os três produtos. get_balance informa o que resta, em
balance_usd para leitura e balance_microdollars (milionésimos de dólar)
para verificações exatas de limite. É servido a partir de api.runcomfy.net em vez de
espelhado por produto, porque há apenas um valor a informar.
Integração entre eles
Um LoRA treinado roda sem qualquer implantação: passe o model_id do modelo base
para run_model e o LoRA como entrada, por exemplo,
{"lora": {"path": "my_first_lora_3000.safetensors"}} — seja um nome dos seus
Ativos de LoRA ou uma URL
pública, como um checkpoint de get_training_job_result. Para um endpoint
dedicado com hardware escolhido, implante-o e use as ferramentas Serverless.
Configuração rápida
Todo cliente autentica com um token de API RunComfy da sua página de Perfil. Duas formas de fornecê-lo:
- Cabeçalho de token de API — funciona em qualquer cliente Streamable HTTP. É o mais simples e a única opção para clientes sem fluxo OAuth no navegador.
- OAuth no navegador — sem token em arquivo de configuração. Suportado por Claude.ai, Cursor e clientes locais que registram um callback de loopback, como Claude Code.
Claude Code
Cabeçalho de token (um comando, nada mais a fazer):
claude mcp add --transport http runcomfy https://mcp.runcomfy.com/mcp --header "Authorization: Bearer YOUR_RUNCOMFY_TOKEN"
Ou OAuth no navegador — omita o cabeçalho e execute /mcp dentro do Claude Code e escolha
Autenticar:
claude mcp add --transport http runcomfy https://mcp.runcomfy.com/mcp
--transport http é o transporte Streamable HTTP. streamable-http não é um
valor aceito pelo Claude Code, e -transport / -header com um único hífen também não
são — ambas as formas falham antes mesmo de o servidor ser contatado.
Verifique com claude mcp list, que deve mostrar runcomfy: connected.
Claude.ai
Adicione https://mcp.runcomfy.com/mcp em Configurações → Conectores → Adicionar conector
personalizado e selecione Conectar. O Claude descobre os endpoints OAuth 2.1
do RunComfy, abre uma página de consentimento do RunComfy e solicita um dos tokens de API
exibidos no seu Perfil RunComfy. O token
é validado pelo RunComfy e criptografado dentro da concessão de autorização MCP; ele
nunca é retornado ao Claude.
Cursor
.cursor/mcp.json:
{
"mcpServers": {
"runcomfy": {
"url": "https://mcp.runcomfy.com/mcp",
"headers": { "Authorization": "Bearer YOUR_RUNCOMFY_TOKEN" }
}
}
}
VS Code (Copilot)
.vscode/mcp.json:
{
"servers": {
"runcomfy": {
"type": "http",
"url": "https://mcp.runcomfy.com/mcp",
"headers": { "Authorization": "Bearer YOUR_RUNCOMFY_TOKEN" }
}
}
}
Windsurf
Configurações → MCP:
{
"mcpServers": {
"runcomfy": {
"serverUrl": "https://mcp.runcomfy.com/mcp",
"headers": { "Authorization": "Bearer YOUR_RUNCOMFY_TOKEN" }
}
}
}
Qualquer outro cliente
- URL:
https://mcp.runcomfy.com/mcp - Transporte: Streamable HTTP
- Autenticação:
Authorization: Bearer <token>em cada requisição, ou OAuth 2.1 com um URI de redirecionamento de loopback ou um callback de cliente suportado exato
Solução de problemas
| Sintoma | Causa |
|---|---|
401 com RunComfy rejected this API token | O token está errado, expirado ou truncado ao copiar. Gere um novo em Perfil — o corpo da resposta indica a correção. |
401 sem error_description | Nenhum cabeçalho Authorization chegou ao servidor. Verifique se o cabeçalho está entre aspas como um único argumento: --header "Authorization: Bearer ...". |
invalid_client_metadata durante OAuth | O cliente registrou um callback fora da lista de permissões de loopback e clientes exatos. Use um callback suportado ou o cabeçalho de token. |
invalid_target durante OAuth | A URL configurada deve ser exatamente https://mcp.runcomfy.com/mcp — sem barra final. O RFC 8707 vincula o token a esse recurso exato. |
503 com Retry-After | A API do RunComfy não pôde ser acessada para verificar o token. Tente novamente. |
429 | Mais de 600 requisições autenticadas por token por minuto a partir de um único IP. |
Revogue o acesso regenerando o token no seu Perfil RunComfy. Isso invalida o cabeçalho de token e qualquer concessão OAuth baseada nele, porque cada requisição MCP revalida o token upstream.
Arquitetura
MCP Client ──RunComfy API token──┐
│ Cloudflare Worker (/mcp)
MCP Client ──MCP OAuth token─────┤ validates the credential, resolves
│ it to one user's RunComfy token
▼
Cloudflare Container
(Python FastMCP app)
│ request-scoped RunComfy credential
┌───────────────┼───────────────┐
▼ ▼ ▼
api.runcomfy.net model-api. trainer-api.
(Serverless) runcomfy.net runcomfy.net
(Model) (Trainer)
Um único token RunComfy autentica os três produtos, então a mesma resolução de credencial cobre todas as ferramentas.
Ambos os tipos de credencial convergem para o mesmo cabeçalho de identidade com escopo de requisição
antes de o contêiner ser acessado. Eles são diferenciados pela forma: tokens de acesso OAuth
são sempre userId:grantId:secret, e um token de API RunComfy nunca
contém dois-pontos.
- Cloudflare Worker (
src/index.ts) — servidor de autorização OAuth 2.1 e limite de recurso protegido. Credenciais ausentes, inválidas, expiradas ou com público errado são rejeitadas antes da inicialização do MCP ou da descoberta de ferramentas. - Token de API direto (
src/index.ts) — um token de Perfil RunComfy apresentado comoAuthorization: Beareré revalidado contraapi.runcomfy.netem cada requisição, com limite de taxa por IP de origem, e nunca é encaminhado como está. - Consentimento OAuth (
src/oauth-bridge.ts) — valida um token de Perfil RunComfy existente, armazena-o apenas em dados de concessão OAuth criptografados e emite um token de acesso MCP separado vinculado ao público. O registro dinâmico de clientes aceita callbacks de loopback (Claude Code e outros clientes locais), uma lista exata de callbacks de clientes hospedados e o callback legado exato do Cursor. O Cursor registracursor://anysphere.cursor-mcp/oauth/callback,https://www.cursor.com/agents/mcp/oauth/callbackehttp://localhost:8787/callbackjuntos; todos os três devem ser aceitos mesmo quando o redirecionamento ativo usa localhost. Protocolos personalizados arbitrários e variantes de callback permanecem rejeitados, e S256 PKCE é obrigatório. - Contêiner Python (
server.py) — aplicativo FastMCP com 31 ferramentas nas APIs Serverless, Model e Trainer. Ele não tem credencial compartilhada/de operador e falha de forma segura, a menos que a borda autenticada forneça o token RunComfy com escopo de requisição do usuário atual. - Cloudflare Container inicia automaticamente na primeira requisição e dorme após 10 minutos de inatividade.
Estrutura do projeto
.github/workflows/deploy.yml CI: typecheck, test, deploy to Cloudflare
src/index.ts Cloudflare Worker entrypoint
src/oauth-bridge.ts OAuth consent and RunComfy token validation
server.py MCP tool definitions (31 tools)
runcomfy_client.py RunComfy API clients (serverless, model, trainer)
container_app.py ASGI middleware (request IDs, token forwarding)
container_entrypoint.py Uvicorn startup
container_runtime.py Env validation, structured logging
wrangler.jsonc Cloudflare Worker + Container config
Dockerfile Container image
.env.example Local dev config
Desenvolvimento local
# Python 3.11+
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
python -m container_entrypoint
Endpoints locais:
http://127.0.0.1:8000/healthzhttp://127.0.0.1:8000/mcp
O endpoint Python local intencionalmente não tem credencial de fallback compartilhada. Chamadas de ferramentas protegidas devem passar pelo limite do Worker autenticado.
Implantação
Enviar para main implanta automaticamente via .github/workflows/deploy.yml:
verificação de tipos, testes do Worker e testes do contêiner devem passar; então
wrangler deploy --containers-rollout immediate envia o Worker e o
contêiner Python juntos. Pull requests executam as mesmas verificações sem
implantar. O fluxo de trabalho também pode ser executado manualmente na aba Actions.
Um segredo de repositório é necessário:
| Segredo | Finalidade |
|---|---|
CLOUDFLARE_API_TOKEN | Um token com permissão Editar Cloudflare Workers na conta em wrangler.jsonc |
CLOUDFLARE_ACCOUNT_ID | Opcional. account_id já está commitado em wrangler.jsonc; defina isso apenas para implantar sob uma conta diferente. |
Para implantar manualmente (requer plano Cloudflare Workers Paid com Containers habilitados):
npm install
npm run check
npm test
npx wrangler deploy --containers-rollout immediate
O endpoint MCP fica disponível em https://mcp.runcomfy.com/mcp (domínio personalizado configurado em wrangler.jsonc).
Variáveis de ambiente e bindings
Não há deliberadamente nenhum segredo compartilhado de chave de API RunComfy. O estado OAuth é mantido
no binding OAUTH_KV e cada requisição upstream está vinculada ao usuário que
autorizou a concessão OAuth.
Variáveis do Worker (em wrangler.jsonc)
| Nome | Padrão | Descrição |
|---|---|---|
CONTAINER_INSTANCE_NAME | runcomfy-unified | Nome da instância do Durable Object |
CONTAINER_STARTUP_TIMEOUT_MS | 15000 | Espera máxima para início do contêiner |
CONTAINER_PORT_READY_TIMEOUT_MS | 30000 | Espera máxima para porta pronta |
MCP_MAX_BODY_BYTES | 1048576 | Tamanho máximo do corpo da requisição |
OPENAI_APPS_CHALLENGE | Token de submissão atual | Token público de verificação de domínio da OpenAI, servido literalmente em GET /.well-known/openai-apps-challenge; não definido ou vazio retorna 404. Verifique a propriedade de qualquer token existente antes de substituí-lo. |
MCP_DIRECT_TOKEN_RATE_LIMITER | 600 / 60s | Limite por IP em requisições /mcp autenticadas por token de API |
RUNCOMFY_SERVERLESS_BASE_URL | https://api.runcomfy.net | URL base da API Serverless |
RUNCOMFY_MODEL_API_BASE_URL | https://model-api.runcomfy.net | URL base da API de Modelos |
RUNCOMFY_TRAINER_API_BASE_URL | https://trainer-api.runcomfy.net | URL base da API de Treinamento |
Desenvolvimento Python local (arquivo .env)
| Nome | Obrigatório | Descrição |
|---|---|---|
RUNCOMFY_SERVERLESS_BASE_URL | Não | Substitui a URL base Serverless (padrão: https://api.runcomfy.net) |
RUNCOMFY_MODEL_API_BASE_URL | Não | Substitui a URL base da API de Modelos (padrão: https://model-api.runcomfy.net) |
RUNCOMFY_TRAINER_API_BASE_URL | Não | Substitui a URL base da API de Treinamento (padrão: https://trainer-api.runcomfy.net) |
RUNCOMFY_MCP_MOUNT_PREFIX | Não | Prefixo de caminho para montagem do MCP (padrão: vazio) |