Servidor MCP local para Trello hecho con Node.js + TypeScript.
Estado verificado contra código y tests:
- entrypoint MCP por
stdioensrc/index.ts - 15 tools registradas en
src/mcp/registry.ts - 3 resources registrados en
src/mcp/registry.ts - validación de entorno en
src/config/index.ts - suite verde:
npm run test:run→ 184 tests OK - chequeo de tipos verde:
npm run typecheck
src/
├── mcp/ # Registro MCP, handlers, tools y resources
├── application/ # Casos de uso y puertos
├── domain/ # Entidades, invariantes y value objects
├── infrastructure/trello/ # Adapter HTTP, mappers y retry/backoff
├── config/ # Lectura y validación de variables de entorno
└── shared/ # Utilidades transversales
tests/
├── unit/
├── integration/
├── contracts/
└── fixtures/- Node.js >= 20 (
package.json) - credenciales válidas de Trello
- un host compatible con MCP si querés consumirlo desde un cliente externo
Definidas y validadas en src/config/index.ts:
| Variable | Requerida | Descripción |
|---|---|---|
TRELLO_API_KEY |
sí | API key de Trello |
TRELLO_TOKEN |
sí | token de Trello |
TRELLO_DEFAULT_BOARD_ID |
no | board por default cuando no mandás boardId/boardName |
TRELLO_API_BASE_URL |
no | base URL de Trello. Default: https://api.trello.com/1 |
npm install
cp .env.example .envDespués completá tu .env con las credenciales de Trello.
npm installcp .env.example .envCompletá:
TRELLO_API_KEY=tu_api_key
TRELLO_TOKEN=tu_token
TRELLO_DEFAULT_BOARD_ID=opcional
TRELLO_API_BASE_URL=https://api.trello.com/1npm run mcp:startEse script ejecuta tsx src/index.ts (package.json) y el servidor se conecta por stdio (src/index.ts).
Sí: al ejemplo anterior le faltaba el caso concreto de OpenCode con credenciales. Ahora va el tutorial como corresponde, sin fruta.
Camino rápido:
cp opencode.json.example opencode.json
export TRELLO_API_KEY="tu_api_key"
export TRELLO_TOKEN="tu_token"
opencodeSi preferís armarlo a mano, este es el contenido de opencode.json en la raíz del proyecto:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"trello": {
"type": "local",
"enabled": true,
"command": ["npm", "run", "mcp:start"],
"environment": {
"TRELLO_API_KEY": "{env:TRELLO_API_KEY}",
"TRELLO_TOKEN": "{env:TRELLO_TOKEN}"
}
}
}
}Después exportá las variables antes de abrir OpenCode:
export TRELLO_API_KEY="tu_api_key"
export TRELLO_TOKEN="tu_token"
export TRELLO_DEFAULT_BOARD_ID="tu_board_id_opcional"
export TRELLO_API_BASE_URL="https://api.trello.com/1"
opencodeSi querés fijar variables opcionales desde OpenCode, agregalas solo si realmente tienen valor:
{
"environment": {
"TRELLO_API_KEY": "{env:TRELLO_API_KEY}",
"TRELLO_TOKEN": "{env:TRELLO_TOKEN}",
"TRELLO_DEFAULT_BOARD_ID": "{env:TRELLO_DEFAULT_BOARD_ID}",
"TRELLO_API_BASE_URL": "{env:TRELLO_API_BASE_URL}"
}
}No metas esas opcionales porque sí. OpenCode reemplaza variables faltantes por string vacío en config, y src/config/index.ts rechaza TRELLO_DEFAULT_BOARD_ID vacío.
Como el servidor carga dotenv/config en src/config/index.ts, también podés usar este opencode.json más chico y dejar las credenciales en .env:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"trello": {
"type": "local",
"enabled": true,
"command": ["npm", "run", "mcp:start"]
}
}
}Tradeoff:
- Opción A: más explícita y portable para OpenCode, porque no dependés de adivinar de dónde salen las variables.
- Opción B: más corta, pero depende de que el server encuentre correctamente tu
.enval arrancar.
Si no querés meter opencode.json en el repo, podés configurarlo en ~/.config/opencode/opencode.json.
En ese caso conviene usar ruta absoluta con --prefix:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"trello": {
"type": "local",
"enabled": true,
"command": [
"npm",
"--prefix",
"/ruta/absoluta/a/serverMCPTrello",
"run",
"mcp:start"
],
"environment": {
"TRELLO_API_KEY": "{env:TRELLO_API_KEY}",
"TRELLO_TOKEN": "{env:TRELLO_TOKEN}"
}
}
}
}- Abrí OpenCode dentro del repo:
opencode- En otra terminal, verificá que OpenCode vea el server:
opencode mcp list- Ya dentro de OpenCode, probá primero:
use trello y ejecutá bootstrap.status
- Si eso responde bien, seguí con:
trello_list_boardstrello_list_columnstrello_create_card
- Verificado: OpenCode soporta
mcpenopencode.json, servidorestype: "local",commandcomo array yenvironmentcomo objeto (https://opencode.ai/docs/mcp-servers/,https://opencode.ai/docs/config/). - Verificado: este repo hoy está conectado en OpenCode con un comando equivalente a
npm --prefix /home/ignadev/work/serverMCPTrello run mcp:start(opencode mcp list). - Verificado: el server requiere
TRELLO_API_KEYyTRELLO_TOKENensrc/config/index.ts. - Verificado: OpenCode reemplaza env vars ausentes por string vacío en config (
https://opencode.ai/docs/config/), así que no conviene inyectar opcionales vacías porquesrc/config/index.tslas rechaza. - Likely: si usás la opción B,
.envdebería alcanzar porque el server importadotenv/config; aun así, para OpenCode prefiero la opción A porque elimina ambigüedad.
Primero ejecutá la tool diagnóstica:
bootstrap.status
No requiere payload. En la mayoría de los hosts MCP podés ejecutarla sin argumentos; si el cliente te obliga a mandar algo, {} alcanza.
Esa tool devuelve el transporte, la policy publicada, las tools registradas y si las credenciales/default board quedaron configuradas (src/mcp/handlers.ts, src/application/bootstrap.ts).
Orden recomendado:
trello_list_boardstrello_list_columnsconboardIdoboardNametrello_create_cardpara crear una tarjetatrello_add_commentotrello_add_labelssi querés enriquecerla
No requiere input. Si tu host MCP manda un objeto vacío, también es válido:
{}Acepta boardId o boardName (src/mcp/tools/list-columns.ts). Para evitar ambigüedad, usá boardId cuando ya lo tengas de trello_list_boards:
{
"boardId": "tu_board_id"
}También podrías usar:
{
"boardName": "Tareas"
}Ejemplo explícito, indicando board y lista:
{
"name": "Fix login bug",
"boardId": "tu_board_id",
"listName": "To Do",
"pos": "bottom"
}Si omitís listName, el caso de uso usa To Do por default (src/application/create-card.ts). O sea, esto también es válido:
{
"name": "Fix login bug",
"boardId": "tu_board_id"
}Después de crear o ubicar la tarjeta, podés comentarla por cardId:
{
"cardId": "tu_card_id",
"text": "Revisar con QA antes de cerrar"
}Si no tenés cardId, la tool también puede resolver por cardName, pero ahí sí conviene acompañar con boardId o boardName para no meter ambigüedad al pedo (src/types/tool-contract.ts, src/mcp/tools/add-comment.ts).
- arrancá con
bootstrap.status - después ejecutá
trello_list_boards - usá el
boardIdreal de esa respuesta paratrello_list_columnsytrello_create_card - recién después pasá a
trello_add_comment,trello_move_cardo tools de labels
Ese orden reduce errores de input y evita depender de autodiscovery o defaults cuando todavía estás probando el setup.
Resources publicados:
trello://boards/{boardId}/summarytrello://boards/{boardId}/overduetrello://boards/{boardId}/by-label/{labelName}
Ejemplos:
trello://boards/board-1/summarytrello://boards/board-1/overduetrello://boards/board-1/by-label/Bug?limit=10
bootstrap.status
trello_list_boardstrello_list_columnstrello_search_cardstrello_create_cardtrello_move_cardtrello_delete_cardtrello_add_commenttrello_add_labels
trello_change_label_colortrello_list_board_labelstrello_resolve_labeltrello_list_label_cardstrello_search_cards_by_labeltrello_update_label
La selección de board sigue esta precedencia documentada en el README anterior y cubierta por el runtime actual:
boardIdboardNameTRELLO_DEFAULT_BOARD_ID- autodiscovery cuando el usuario tiene un solo board accesible
npm run dev
npm run mcp:start
npm run test
npm run test:run
npm run typechecknpm run lintEse script sigue en pendiente-definir dentro de package.json. No lo vendas como si estuviera listo porque sería fruta.
src/index.tsarrancaMcpServery conectaStdioServerTransportsrc/mcp/registry.tsregistra 15 tools y 3 resourcessrc/mcp/handlers.tspublicabootstrap.statusy el resto de handlers realestests/integration/bootstrap/index.test.tsverificaregisterTool15 veces yregisterResource3 vecesnpm run test:runpasó con 35 archivos / 184 tests OKnpm run typecheckpasó sin errores
AGENTS.mddefine reglas de trabajo y boundariesskills/documenta workflows reutilizables del proyectoopenspec/changes/archive/guarda el historial SDD archivado
MIT (package.json).