Skip to main content
Glama

Trello MCP Server

Servidor MCP (Model Context Protocol) para o Trello, em Flask. Multiusuário: cada pessoa conecta a própria conta do Trello por um painel web e recebe um connector token para configurar no Claude.

Setup

python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env

Gere a chave mestra e coloque em APP_SECRET_KEY no .env:

python -c "import secrets; print(secrets.token_urlsafe(48))"

Trocar a APP_SECRET_KEY depois torna as credenciais já salvas ilegíveis — os usuários precisarão reconectar a conta.

Suba o servidor:

python run.py

Related MCP server: Trello MCP Server

Conectar uma conta

Há dois caminhos. Ambos provam a posse da conta do mesmo jeito: você apresenta um par API Key + Token válido do Trello.

A) OAuth (Claude Desktop / claude.ai)

Adicione um conector customizado apontando só para a URL:

https://trello-mcp.olimpo-services.com.br/mcp

O cliente descobre o restante sozinho (metadata, registro dinâmico), abre /oauth/authorize no navegador, você cola API Key + Token do Trello e autoriza. O cliente recebe um access token renovável — sem header manual.

B) Connector token manual (Claude Code / CLI)

  1. Abra http://localhost:8000/panel.

  2. Cole a API Key e o Token gerados em trello.com/app-key.

  3. O servidor valida as credenciais direto no Trello — isso prova que a conta é sua.

  4. Guarde o connector token exibido (só aparece uma vez) e configure no Claude:

claude mcp add --transport http trello http://localhost:8000/mcp --header "Authorization: Bearer SEU_TOKEN"

Reconectar a mesma conta gera um token novo e revoga o anterior.

OAuth 2.0

O próprio servidor é o authorization server. O /mcp aceita como Bearer tanto um connector token manual quanto um access token OAuth.

Endpoint

RFC

Papel

/.well-known/oauth-protected-resource (+ /mcp)

9728

Diz qual é o authorization server

/.well-known/oauth-authorization-server (+ /mcp)

8414

Metadata: endpoints, PKCE S256, grants

POST /oauth/register

7591

Dynamic Client Registration (aberto)

GET/POST /oauth/authorize

6749

Usuário prova a conta do Trello → code

POST /oauth/token

6749

code+PKCE ou refresh_token → access token

  • PKCE S256 obrigatório. plain é recusado.

  • Clientes públicos (token_endpoint_auth_method: none) e confidenciais (client_secret_post / client_secret_basic) são aceitos.

  • Auth code: uso único, TTL OAUTH_CODE_TTL (10 min). Access token: OAUTH_ACCESS_TOKEN_TTL (30 dias). Refresh: OAUTH_REFRESH_TOKEN_TTL (180 dias), rotacionado a cada uso — o par antigo morre na hora.

  • Só o hash SHA-256 de codes e tokens é persistido.

  • Revogar todos os acessos de uma conta: desconecte pelo /panel — o usuário e todos os seus tokens/codes são apagados juntos.

  • Access-Control-Allow-Origin: * nos endpoints OAuth, /mcp e /.well-known/* para os clientes web (claude.ai).

Tools

11 tools, desenhadas para poucas chamadas e muito poder por chamada.

Tool

Tipo

O que faz

list_boards

leitura

Lista boards; include já traz listas/labels/membros junto

get_board_snapshot

leitura

Board inteiro numa chamada: listas, labels, membros, cards, checklists e comentários

search

leitura

Busca global; aceita a sintaxe do Trello (@me, due:week, label:red) + filtros estruturados

get_activity

leitura

Histórico de board/card/membro, com resumo em texto por ação

manage_cards

escrita

create, update, move, archive, unarchive, duplicate, get — em lote

manage_checklists_and_comments

escrita

Checklists, itens e comentários — em lote

manage_board_structure

escrita

Boards, listas e labels; create_board monta o board inteiro de uma vez ou copia um board (source_board, keep_cards); update_list renomeia, reordena e move a lista para outro board (target_board)

manage_attachments

escrita

Anexa link ou arquivo (base64, até 10 MB), lista anexos e controla a capa — em lote

read_attachment

leitura

Lê ou baixa um anexo de card de qualquer tipo (texto, PDF, imagem, zip, docx/xlsx/pptx, vídeo, áudio...) com as credenciais do servidor

manage_members

escrita

Membros de board e atribuição em cards (produto membros × cards)

manage_powerup_checklists

escrita

Checklists do Power-Up (itens com início, fim e responsável), padrões do board e predecessoras entre itens de qualquer card, inclusive de outros boards (TI/II/TT/IT + defasagem, como no MS Project) — em lote

delete_items

destrutiva

Remoções permanentes, com dry_run

read_attachment: ler arquivos anexados

As URLs de anexos do Trello exigem autenticação, então um agente não consegue abri-las sozinho. read_attachment baixa o arquivo com as credenciais do usuário autenticado e devolve o conteúdo:

{"card": "<id, shortLink ou nome>", "attachment": "<id ou nome, ex.: roteiro-v1.pdf>", "board": "<opcional>",
 "mode": "auto | info | download", "offset": 0, "part": 1, "length": 98304, "entry": "<arquivo dentro de um .zip>"}

Tipo

Retorno

Limite

.txt .md .json .csv

texto (UTF-8)

60 KB; acima disso vem cortado e marcado TRUNCADO

PDF

texto extraído (pypdf; se vier vazio, um extrator mínimo de (texto) Tj)

arquivo até 10 MB, 60 páginas, 60 KB de texto

PNG / JPG

bloco MCP image (base64 + mimeType)

5 MB

.zip

lista o conteúdo (nome, tamanho, avisos) sem extrair

arquivo até 30 MB, 500 entradas

.docx .xlsx .pptx

texto extraído (parágrafos; planilhas em TSV; slides)

arquivo até 30 MB, 60 KB de texto

vídeo, áudio e demais

metadados (nome, tipo, tamanho, id) e instruções de download

—

link externo

erro claro

—

Baixar qualquer arquivo (mode: "download"): devolve JSON com data (base64), offset, length, next_offset, done, total_bytes e sha256_da_parte. Repita com offset = next_offset (ou part 2, 3...) até done: true e junte as partes. Parte padrão de 96 KB (máx. 512 KB por chamada); o arquivo é lido até 64 MB. mode: "info" devolve só os metadados, sem baixar. entry lê (ou, com download, baixa em partes) um arquivo de dentro de um .zip.

Proteções: nada é gravado em disco (tudo em memória, com limites); entradas de zip com caminho ../absoluto são sinalizadas (unsafe_path) e nunca extraídas; descompactação em streaming com teto de 20 MB por entrada e aviso de zip-bomb por taxa de compressão; docx/xlsx/pptx com DTD/entidades são recusados; os retornos nunca trazem a URL do anexo nem credenciais. Observação prática: cada parte em base64 passa pelo contexto do agente, então para arquivos grandes (vídeos) o uso realista é metadados/tamanho; baixe por partes só o que for necessário.

  • O anexo é procurado só entre os anexos do card informado; id de outro card é recusado. O card é resolvido com as credenciais do usuário, então vale a mesma autorização das demais tools.

  • Com vários anexos de mesmo nome (versões reenviadas), vale o mais recente.

  • Só baixa de https://*.trello.com; as credenciais nunca seguem para outro host (redirects para storage assinado vão sem o header). Somente leitura (readOnlyHint).

  • Anexos que são só link (isUpload: false) não são baixados.

Princípios de design

Nomes valem como ids. Todo parâmetro que identifica algo (board, list, card, labels, members, checklist, item) aceita id ou nome — casa exato, depois prefixo, depois substring. Nomes ambíguos retornam erro listando os candidatos, então a IA se corrige sozinha.

Lote com relatório por item. As tools de escrita recebem operations: [...]. Uma falha não aborta as demais; o retorno traz summary e um results[i] com status: ok|error por operação.

Datas flexíveis. due/start/since/before aceitam ISO, today, tomorrow, yesterday, now e offsets (+3d, -2w, +6h). String vazia limpa o campo.

Alterações incrementais. labels e members aceitam uma lista (substitui tudo) ou {add, remove, set}.

Resposta enxuta por padrão. Ids viram nomes, payloads viram contadores. include_desc, desc_max_chars, max_cards e include_raw controlam o tamanho.

Autorização por tool

As tools declaram annotations MCP (readOnlyHint, destructiveHint) em tools/list, e o cliente decide o que exige confirmação. Por isso as remoções permanentes ficam isoladas em delete_items (única marcada destructiveHint: true): dá para liberar as tools de escrita normais e exigir aprovação só nas destrutivas. archive (reversível) mora em manage_cards, não ali.

Arquitetura

Arquivo

Responsabilidade

run.py

Entrypoint

trello_mcp/__init__.py

App factory, registro de blueprints, init do banco

trello_mcp/config.py

Configuração via .env

trello_mcp/crypto.py

Fernet para credenciais em repouso + hash do connector token

trello_mcp/db.py

SQLite: tabela users

trello_mcp/auth.py

Conectar conta, resolver Bearer (connector token ou access token) → credenciais

trello_mcp/oauth.py

Lógica do OAuth: metadata, DCR, PKCE, emissão/rotação de token

trello_mcp/oauth_routes.py

Endpoints /.well-known/*, /oauth/register, /oauth/authorize, /oauth/token

trello_mcp/panel.py + templates/

Painel web (/panel) e telas do OAuth

trello_mcp/mcp_server.py

Endpoint JSON-RPC /mcp e dispatch das tools

trello_mcp/trello_client.py

Wrapper HTTP da API do Trello

trello_mcp/tools/common.py

Resolvers com cache, filtros de card, batch runner

trello_mcp/tools/*.py

Uma tool (ou grupo) por arquivo (read_attachment.py: leitura de anexos)

Modelo de segurança

  • Key e Token do Trello são criptografados (Fernet) antes de ir para o banco.

  • Do connector token e dos tokens OAuth só o hash SHA-256 é persistido.

  • Todo POST /mcp exige Authorization: Bearer <token> (connector token ou access token OAuth).

  • Erros de tool voltam como isError: true no resultado (não como erro de protocolo), para o modelo ler a mensagem e se corrigir.

Deploy (Docker + Traefik)

Host de produção: trello-mcp.olimpo-services.com.br

Na VPS, dentro do diretório do projeto, crie o .env com a chave mestra:

echo "APP_SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_urlsafe(48))')" > .env

PORT, DATABASE_PATH, PUBLIC_BASE_URL e FLASK_DEBUG já vêm do docker-compose.yml — o .env precisa conter apenas a APP_SECRET_KEY. Suba:

docker compose up -d --build

Confira: https://trello-mcp.olimpo-services.com.br/health deve responder {"status":"ok"}.

Notas de infraestrutura

Volume nomeado, não bind mount. O container roda como usuário não-root (uid 1000). Um bind mount ./data seria criado pelo Docker como root e o container não conseguiria escrever o SQLite. O volume nomeado trello-mcp-data herda o dono de /app/data definido na imagem. Backup:

docker run --rm -v trello-mcp-data:/data -v $(pwd):/backup alpine tar czf /backup/trello-mcp-backup.tar.gz -C /data .

A APP_SECRET_KEY é o dado mais crítico do deploy. Ela descriptografa as credenciais do Trello de todos os usuários. Perdê-la ou trocá-la obriga todo mundo a reconectar a conta no painel. Faça backup dela junto com o volume.

3 workers do gunicorn sobre um SQLite. O banco roda em modo WAL (leituras concorrentes com uma escrita) e as conexões têm timeout=10. Escrita só acontece quando alguém conecta uma conta no painel — o caminho quente (/mcp) é só leitura no banco. Ajuste com WEB_CONCURRENCY se precisar.

Workers gthread (3 × 8 threads). O trabalho é espera de I/O na API do Trello; com workers sync, três chamadas lentas ocupavam todos os workers e o initialize/tools/list de outro cliente ficava na fila (o OpenClaw estourava o limite de 1,5 s). initialize, ping e tools/list não chamam o Trello nem fazem I/O além da checagem do token. Ajuste com WEB_CONCURRENCY e WEB_THREADS.

Timeouts. Chamadas ao Trello: conexão 10 s / leitura 15 s; upload de anexo: leitura 90 s; download de anexo: 30 s por leitura e 45 s no total. Leituras (GET) repetem uma vez em falha de rede; escritas não (evita anexo duplicado: o erro avisa para conferir com list). Erros de rede não exibem key/token. Corpo de requisição limitado a MAX_REQUEST_BYTES (64 MB).

--timeout 120 no gunicorn. Um lote grande de operações encadeia várias chamadas à API do Trello (cada uma com até 15s de timeout); o default de 30s mataria requisições legítimas.

Testes

Suíte offline (sem credenciais, contra um fake da API do Trello):

.venv\Scripts\python.exe tests/run_all.py
  • tests/test_auth.py — banco, criptografia, rotação de token, /mcp sem auth

  • tests/test_tools.py — as tools, filtros, lotes parciais e mensagens de erro

  • tests/test_mcp.py — handshake MCP, tools/list, tools/call, tratamento de erros

  • tests/test_attachment_types.py — read_attachment para qualquer tipo: info, download em partes, zip (listar/entrada/zip-bomb/path traversal), docx/xlsx/pptx, mídia

  • tests/test_read_attachment.py — read_attachment (texto, PDF, imagem, limites, autorização), robustez do base64, timeouts/segredos do cliente HTTP e velocidade do handshake

Os testes precisam de APP_SECRET_KEY e, de preferência, de um banco descartável: APP_SECRET_KEY=teste DATABASE_PATH=/tmp/t.sqlite3 python tests/run_all.py.

Suíte contra a API real (opcional, exige credenciais no ambiente):

TRELLO_API_KEY=... TRELLO_TOKEN=... .venv/Scripts/python.exe tests/test_real_api.py

Sem as variáveis, ela se pula sozinha. A parte de leitura só consulta um board existente; a de escrita cria um board descartável (ZZ TESTE MCP (apagar)), exercita tudo dentro dele e o apaga no fim — nenhum board existente é modificado. Se a limpeza falhar, o id do board é impresso para remoção manual.

Notas sobre a API do Trello

Comportamentos confirmados contra a API real, que explicam decisões do código:

Atribuição de membro é idempotente aqui, não lá. O Trello devolve 400 member is already on the card ao reatribuir alguém que já está no card (e not on the card no caso inverso). Como o efeito desejado já vale, manage_members trata isso como sucesso e marca already_applied: true — a IA reatribui por garantia o tempo todo.

Rate limit: 300 req/10s por API key, 100 req/10s por token. Lotes grandes podem estourar. O cliente reage a 429 com até 3 tentativas e backoff (respeitando Retry-After); depois disso o erro sugere dividir o lote.

GET /boards/{id}/checklists aceita checkItems/checkItem_fields embora a documentação oficial não liste esses params para esse endpoint. É o que permite o depth='full' sem uma chamada por card. Se parar de funcionar, o fallback é iterar /cards/{id}/checklists.

A busca ignora queries de 1 caractere. query: "a" retorna zero resultados — não é bug do servidor.

GET /cards/{id}/actions não documenta limit. Funciona na prática, mas a paginação oficial ali é por page (50 por página).

Status

  • Infraestrutura Flask + endpoint MCP JSON-RPC

  • Multiusuário com token por sessão + painel web

  • 11 tools do Trello + suíte de testes

  • read_attachment (v0.2.0) para qualquer tipo de arquivo (v0.3.0); handshake sem I/O e workers gthread

  • Deploy Docker + Traefik

  • Validado contra a API real do Trello (57 verificações, leitura e escrita)

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables interaction with Trello boards, lists, and cards through the Trello REST API. Supports board management, card operations, member management, labels, and checklists through natural language.
      121 npm
      1
      ISC
    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides seamless integration with Trello's API to manage boards, lists, and cards through natural language. It supports full CRUD operations, card movement, and the ability to load Trello resources directly into an LLM's context for analysis.
      MIT