Skip to main content
Glama

tasks-mcp-poc

Prueba de concepto de un gestor de tareas genérico (al estilo Monday, Jira o Trello) cuya única interfaz es MCP: no hay frontend tradicional, solo modelo de datos persistido en Postgres, reglas de negocio y un servidor MCP que expone todo como herramientas para ser usadas por Claude, tanto local (vía stdio) como desplegado en la nube (vía HTTP).

Dominio

Gestión simple de usuarios y tareas:

  • Usuarios: admin o member.

  • Tareas: título, descripción, estado (pendiente | en_progreso | completada) y usuario asignado.

  • El estado persiste en Postgres (Neon) vía Drizzle ORM — ver Persistencia.

Related MCP server: Taskmaster

Reglas de negocio

  • Toda operación (salvo login) requiere un token de sesión válido obtenido con login.

  • Las sesiones expiran a la hora de creadas.

  • Solo admin puede: listar/crear/eliminar usuarios, eliminar tareas, gestionar dependencias.

  • delete_user no permite eliminar el propio usuario ni uno con tareas asignadas o creadas por él (hay que reasignarlas o eliminarlas primero); sus sesiones y registros de tiempo sí se eliminan en cascada.

  • Cualquier usuario puede crear tareas (create_task): un admin puede asignarlas a cualquier usuario; un member solo puede asignarlas a sí mismo o a otro member (no a un admin).

  • Un member solo puede ver y actualizar el estado de las tareas que tiene asignadas.

  • admin puede ver y actualizar cualquier tarea.

  • Una tarea puede depender de otras (add_task_dependency): mientras alguna dependencia no esté completada, la tarea no puede salir de pendiente. No se permiten dependencias circulares.

  • Un usuario solo puede tener un registro de tiempo activo a la vez: si inicia el timer de una tarea mientras tiene otra corriendo, la anterior se pausa automáticamente.

  • Al pausar (stop_task_timer) se puede indicar una razón y, opcionalmente, crear una tarea de seguimiento asignada a otra persona (ej. "pausa porque espero respuesta de Juan") — esta creación puntual no requiere rol admin, cualquier sesión válida puede reportar un bloqueo.

Autenticación

Autenticación simple usuario/contraseña:

  • Contraseñas guardadas con hash scrypt + salt (nunca en texto plano).

  • login(username, password) devuelve un token opaco (UUID) que debe pasarse en el resto de las herramientas, simulando una sesión.

  • logout(token) invalida la sesión.

Usuario semilla (solo para esta PoC):

username

password

rol

admin

admin123

admin

El resto de los usuarios (member) se crean con create_user una vez logueado como admin.

Persistencia

  • Base de datos Postgres gestionada en Neon, acceso vía drizzle-orm/neon-http.

  • Schema en src/db/schema.ts (tablas users, tasks, task_dependencies, task_time_entries, sessions).

  • Migraciones con Drizzle Kit:

    npm run db:generate   # genera SQL a partir de src/db/schema.ts
    npm run db:migrate    # aplica migraciones pendientes contra DATABASE_URL
    npm run db:seed       # crea el usuario admin semilla (idempotente)
    npm run db:studio     # UI de Drizzle Studio para inspeccionar los datos
  • DATABASE_URL se lee de .env en desarrollo (nunca commitear ese archivo) y de un secret de la plataforma de hosting en producción — ver Deploy.

Transporte MCP

El servidor de tools (src/mcp.ts) es el mismo en ambos casos; solo cambia el transporte:

Entry point

Transporte

Uso

src/server.ts

StdioServerTransport

Local, spawneado por Claude Code (claude mcp add)

src/httpServer.ts

StreamableHTTPServerTransport

Remoto, servido vía Express en /mcp (deploy en Fly.io)

Herramientas MCP expuestas

Herramienta

Rol requerido

Descripción

login

público

Autenticarse y obtener token

logout

sesión válida

Cerrar sesión

whoami

sesión válida

Ver datos del usuario actual

list_users

admin

Listar usuarios

create_user

admin

Crear usuario

delete_user

admin

Eliminar usuario (no el propio, ni uno con tareas asignadas/creadas)

list_tasks

sesión válida

Listar tareas (propias o todas si es admin)

create_task

sesión válida

Crear tarea; member solo puede asignarla a sí mismo u otro member

update_task_status

dueño de la tarea o admin

Cambiar el estado de una tarea (bloqueado si tiene dependencias sin completar)

start_task_timer

dueño de la tarea o admin

Iniciar registro de tiempo (pausa automáticamente cualquier otro timer activo del usuario)

stop_task_timer

dueño de la tarea o admin

Detener/pausar el timer activo; opcionalmente crea una tarea de seguimiento para otra persona

list_task_time_entries

sesión válida

Listar los registros de tiempo (inicio/fin/motivo) de una tarea

add_task_dependency

admin

Marcar que una tarea depende de que otra esté completada

remove_task_dependency

admin

Quitar una dependencia previamente creada

list_task_dependencies

sesión válida

Listar las tareas que bloquean a una tarea dada

delete_task

admin

Eliminar una tarea

Uso

npm install
npm run build

Probar con el smoke test incluido

Ejercita todo el flujo (login, permisos denegados, CRUD de tareas) contra el servidor real vía stdio:

npm run build
npm run smoke

Registrar el servidor en Claude Code

claude mcp add admin-poc -- node /Users/ckastli/gm2/mcp-poc/dist/server.js

Luego, desde Claude, se puede pedir por ejemplo:

"Inicia sesión como admin (admin/admin123), crea un usuario member nuevo y asígnale una tarea."

Claude usará las herramientas MCP (login, create_user, create_task, etc.) para completar el pedido, respetando las reglas de negocio y permisos definidos en el servidor.

Desarrollo

npm run dev        # corre src/server.ts (stdio) directo con tsx, sin compilar
npm run dev:http   # corre src/httpServer.ts (Streamable HTTP) en localhost:8080

Deploy

El servidor está desplegado en Fly.io usando el transporte HTTP (src/httpServer.ts), con Docker (Dockerfile) y config en fly.toml.

fly deploy -a tasks-mcp-poc

Seguridad: MCP_API_KEY

Como el endpoint HTTP queda expuesto públicamente en internet (a diferencia del modo stdio, que solo corre localmente spawneado por Claude Code), src/httpServer.ts exige un bearer token en todas las requests antes de llegar a la lógica de negocio propia del MCP (login, tokens de sesión, etc. — esto es una capa extra, no un reemplazo):

Authorization: Bearer <MCP_API_KEY>

Si la variable de entorno MCP_API_KEY no está seteada, el middleware no se activa (uso solo aceptable en desarrollo local). En producción siempre debe estar seteada como secret de la plataforma, nunca en .env commiteado ni en el código.

Generar/rotar el valor:

# 1. Generar un valor aleatorio nuevo
API_KEY=$(node -e 'console.log(require("crypto").randomUUID())')

# 2. Cargarlo como secret en Fly (esto reinicia las máquinas automáticamente para aplicarlo)
fly secrets set MCP_API_KEY="$API_KEY" -a tasks-mcp-poc

# 3. Guardar $API_KEY en un gestor de secretos (1Password, Doppler, etc.) —
#    Fly no permite volver a leer el valor de un secret ya seteado.

Rotarlo periódicamente o ante sospecha de filtración es solo repetir esos tres pasos; no requiere cambios de código ni un nuevo fly deploy.

Estructura

src/
  types.ts                 tipos del dominio (derivados del schema de Drizzle)
  crypto-utils.ts           hashing de contraseñas
  auth.ts                   login/logout/verificación de sesión y rol
  mcp.ts                    factory createMcpServer(): registra las herramientas
  server.ts                 entry point stdio (uso local con Claude Code)
  httpServer.ts              entry point Streamable HTTP (uso remoto, Fly.io)
  db/
    schema.ts                tablas de Drizzle (users, tasks, task_dependencies, task_time_entries, sessions)
    client.ts                 cliente Drizzle sobre el driver HTTP de Neon
    seed.ts                    usuario admin semilla (idempotente)
  services/
    userService.ts            reglas de negocio de usuarios
    taskService.ts             reglas de negocio de tareas (incluye dependencias)
    timeTrackingService.ts      registro de tiempo trabajado por tarea
drizzle/
  *.sql                       migraciones generadas por drizzle-kit
scripts/
  smoke-test.ts                cliente MCP que ejercita el flujo completo (vía stdio)

Limitaciones (a propósito, es una PoC)

  • Las sesiones (tabla sessions) no se purgan automáticamente al expirar, solo al ser usadas.

  • Sin rate limiting, recuperación de contraseña, ni auditoría.

  • MCP_API_KEY es un único secreto compartido (no hay múltiples API keys ni scopes por cliente).

  • Las sesiones de transporte MCP viven en memoria del proceso (src/httpServer.ts): si la máquina de Fly se duerme por inactividad o se hace un fly deploy, esas sesiones se pierden y el cliente tiene que reconectar (el token de login, en cambio, persiste en Postgres). Es una decisión deliberada para mantener las cosas simples en esta PoC — la alternativa (persistir sesiones MCP en la base) es un cambio real de código, no de configuración.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cizar/tasks-mcp-poc'

If you have feedback or need assistance with the MCP directory API, please join our Discord server