tasks-mcp-poc

tasks-mcp-poc

A generic task manager (like Monday, Jira, Trello) with MCP as its only interface, enabling task and user management via natural language through Claude.

Category
访问服务器

README

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.

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.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选