Skip to main content
Glama
0-to-1-Labs

Tracker MCP Server

by 0-to-1-Labs

Tracker is a collaborative Kanban board — boards → lists → cards, drag-and-drop, synced live across every connected client. What makes it different is who counts as a user: an AI agent is an actor exactly like a human — it can be a board member, be @mentioned, have cards delegated to it, work them in a legible session, and ask a human when it's stuck. Every mutation flows through one shared domain function that authorizes once, writes Postgres, appends an append-only Activity row, and fans the event out over Redis. REST handlers, the WebSocket gateway, the MCP tools, and outbound webhooks are all thin adapters over that single spine — a contract test proves REST and MCP hit the identical path. Build for one surface and you've built for all four.

Feature tour

Board experience. Boards → lists → cards with fluid drag-and-drop (dnd-kit), optimistic and instant. Cards carry a markdown description, due date, priority, labels, assignees, comments, checklists, attachments, and custom fields. Human-readable card keys (TRK-42) resolve anywhere. A command palette (⌘K) drives every action from the keyboard, and a global search (Postgres full-text + structured filters, saved as personal or shared views) spans every board you can read.

Real-time, done right. Optimistic UI renders the change immediately; the server reconciles over the WebSocket with the authoritative state. Fractional indexing on card/list positions means concurrent drags from different clients never fight over integer ranks, and every optimistic mutation carries a client_mutation_id so a retry or a reconciliation is exact, never doubled. Live presence shows who else is on the board.

Agents as first-class principals. An agent authenticates with a scoped API token and drives the board over REST or MCP (same domain functions, proven equivalent by a contract test) or reacts to signed webhooks. Cards are assigned to humans and delegated to agents. A delegated (or @mentioned) agent works the card in an agent session — a glanceable state machine (queued → working ⇄ awaiting_input → done | error) with an append-only event trail — and when it hits a fork it calls ask_human, which routes the question to an accountable human and renders one-click answer buttons. Agent work is legible, not a black box.

MCP, consolidated. The MCP server ships a tight, method-parameterized tool catalog (board_read / board_write / card_read / card_write / session_read / session_write / my_work / automation_read / automation_write) — 7 tools, ~44% less schema context than the flat predecessor at strictly larger coverage. Connect over Streamable HTTP with a Bearer token, via OAuth 2.1 (claude.ai-style Connectors, no pre-shared token), or through a stdio proxy for desktop agents. Compact markdown board/card resources let an agent read a board for ~15 tokens/card.

Custom fields & attachments. Per-board custom field definitions (typed, validated) attach structured data to cards and are searchable. Cards take file attachments behind a pluggable storage driver — zero-config local disk for self-hosting, or presigned S3 (any S3-compatible backend, MinIO included) for production, with server-enforced size, count, and content-type caps.

Rules engine (agent-authorable). Boards carry Butler-style trigger → filters → actions rules that run automatically on board events. The twist: an agent can draft them from a plain description over MCP. Rules run as a visibly non-human "Automation" actor, with depth-1 loop guards, per-rule rate limits, and a ReDoS-proof safe-regex subset.

GitHub / GitLab integration. Link a repo to a board through card keys — a branch named trk-42-fix-login, a PR titled TRK-42: …, or a fixes TRK-42 magic word links the card. The integration emits vcs.* events (pr_opened, pr_merged, …) onto the same event path the rules engine watches, so a PR's lifecycle moves the card with no manual status updates. Each linked card shows a state-colored PR chip.

Admin console. A settings UI covers the operational surface: mint scoped API tokens with a live scope-implication preview and one-time secret reveal; manage webhooks with a per-delivery log, manual redelivery, and dead-letter re-enable; and run the agent roster — capability toggles (delegatable / mentionable), credential scopes, and recent activity per agent.

Security model. Human passwords are Argon2; agent tokens are SHA-256-hashed at rest, returned in plaintext exactly once, and carry an explicit scope set (broad scopes imply narrower ones; administrative scopes never implied). A board leash (board:<id>) confines a token to a single board. Tokens can only mint strictly-weaker tokens. Authorization is enforced once, in the domain layer — no adapter has a privileged path. Webhooks are HMAC-signed (v2, replay-protected). Per-token rate limits are shared across REST and MCP.

Related MCP server: mcp-kanban

60-second quickstart

Requires Docker.

git clone https://github.com/0-to-1-Labs/tracker.git
cd tracker
cp .env.example .env          # set SESSION_SECRET for anything non-local
docker compose up             # builds + runs web + api + mcp + postgres + redis

The api applies its Drizzle migrations on start, then serves. Seed a known login + demo board + agent token (idempotent, re-runnable):

pnpm --filter @kanban/api db:seed
# → human login  demo@kanban.local / demo1234
#   "Demo Board" with To Do / In Progress / Done
#   a demo agent + Bearer token (printed once) for driving the same board via REST/MCP

Log in at http://localhost:8080 with demo@kanban.local / demo1234, or register a fresh account.

Agent quickstart

An agent goes from zero to driving the board in three steps. Full guide: docs/agents/quickstart.md.

1. Mint a scoped token (as a logged-in human, or grab the one db:seed printed):

curl -s -X POST http://localhost:3000/api/tokens \
  -H 'content-type: application/json' -b "$SESSION_COOKIE" \
  -d '{ "label": "research-agent",
        "scopes": ["boards:read", "cards:write", "comments:write", "sessions:write"] }'
# → { "token": "kbt_…" }   ← shown once; copy it now

2. Connect over MCP (Streamable HTTP, Bearer token):

POST http://localhost:3001/mcp
Authorization: Bearer kbt_…

...or drive REST directly. Either way it's the same domain layer, same scopes.

3. Create your first card:

# MCP:  card_write { "method": "create", "params": { "listId": "…", "title": "Investigate flaky test" } }
# REST:
curl -H "Authorization: Bearer kbt_…" -H 'content-type: application/json' \
  -X POST http://localhost:3000/api/lists/$LIST_ID/cards \
  -d '{"title": "Investigate flaky test", "clientMutationId": "0f3c-…"}'

From there: pick up delegated work (my_work { method: "delegated_to_me" }), open a session, post progress, ask_human when unsure, and complete with a summary. The MCP handshake ships server instructions (actor model, delegation-vs-assignment, the ?since poll contract, idempotency) so you start legible with no extra reads. A runnable reference agent lives in examples/session-agent/.

Architecture

One domain core; four thin adapters; a single Zod contract layer shared by all of them.

flowchart TB
  subgraph shared["packages/shared — the contract layer"]
    zod["Zod schemas = single source of truth<br/>every DTO / contract + the scope model"]
  end

  subgraph adapters["thin adapters (no privileged path)"]
    rest["REST routes"]
    ws["WebSocket gateway"]
    mcp["MCP tools"]
    hooks["outbound webhooks"]
  end

  subgraph core["apps/api/src/domain/* — the spine"]
    domain["domain functions: (ctx, validatedInput)<br/>authorize once · write Postgres · append Activity · publish"]
  end

  pg[("Postgres<br/>source of truth")]
  redis[("Redis pub/sub<br/>event fan-out")]

  zod -.imported by.-> rest & ws & mcp & hooks
  rest --> domain
  ws --> domain
  mcp --> domain
  hooks --> domain
  domain --> pg
  domain --> redis
  redis --> ws
  redis --> hooks

Every mutation authorizes once, writes Postgres, appends an Activity row (the audit trail + webhook payload source + agent poll history), and publishes to Redis. Because Redis already fans events out, scaling 1→N api instances needs no code change. IDs are UUID v7 minted in the app; deletes are soft (an archived flag) so the Activity log is never rewritten.

Monorepo (pnpm workspaces):

Package

What it is

packages/shared

Zod entity + DTO schemas and the scope model — the contract layer.

packages/core

The domain spine shared by the api and the standalone MCP server.

apps/api

Fastify: REST + WS + MCP + webhooks over the domain layer; Drizzle/Postgres; ioredis.

apps/web

React + Vite SPA: TanStack Query (optimistic mutations), Zustand, dnd-kit, Tailwind.

packages/plugin-sdk

Webhook verification + helpers for building reactive agents.

e2e

Playwright cross-client drag-and-drop E2E.

Stack: TypeScript (strict) · Fastify · Drizzle ORM + Drizzle Kit · Zod · ioredis · @modelcontextprotocol/sdk · Argon2 / SHA-256 · React + Vite · TanStack Query · Zustand · dnd-kit · Tailwind (VS Code "Dark High Contrast" tokens) · Vitest · Playwright · Postgres · Redis · Docker Compose.

Documentation

Contributing

Contributions are welcome — see CONTRIBUTING.md for dev setup, the test gate, the TDD convention, and the DCO sign-off requirement. Please also read our Code of Conduct. Security issues: see SECURITY.md.

License

Tracker is licensed under the GNU Affero General Public License v3.0 — see LICENSE.


Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for task management that enables AI agents to read, create, update tasks, and track work sessions, allowing agents and humans to collaborate on the same task board.
    6 npm
    9
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    An AI-native kanban board MCP server where agents pull tasks via the Model Context Protocol. It provides tools for task discovery, claiming, progress updates, and review workflows.
    4
    MIT