Skip to main content
Glama
fmilioni
by fmilioni

Agents Board

A project board for coding agents, shared over MCP.

Agents Board gives Codex, Claude Code and Cursor a real project-management system — cards, sprints, comments and docs — as queryable state over MCP, instead of spec Markdown files that grow without bound and go stale. A clean Nuxt UI mirrors the same board for humans, in real time.

It ships a single plugin package for Codex, Claude Code and Cursor — two skills and the MCP connection. Install it from your client's repository marketplace and the board becomes available together with the local MCP connection.

License: MIT Node pnpm Docker MCP

WARNING

Early stage — not yet stable. Agents Board is under active development and not production-stable yet. Right now we're focused on stabilizing the skills (agents-board and plan), so their behavior and the tool surface may still change between versions. Expect breaking changes and upgrade the plugin deliberately through Codex's /plugins browser or CLI, Claude Code's plugin marketplace, or Cursor's Customize page.


Why

A long-running coding agent has no memory between sessions. The usual fix — piling plans and decisions into ever-growing .md files — rots fast: the files drift from reality, contradict each other, and bloat the context window.

Agents Board flips that. What to do (the active sprint, cards, backlog, comments, decisions, docs) lives in a database the AI queries on demand through MCP tools, and edits as work progresses. The agent orients itself at the start of every session by reading the board — not by re-reading stale prose. You watch the same board, drag cards, and leave comments the agent reads back.

Related MCP server: kanban-mcp

Highlights

  • 🗂️ A real board — projects, sprints, stories and sub-tasks, blockers, tags, priorities. Drag-and-drop UI with live WebSocket updates.

  • 🤖 Built for the agent — every entity is a typed MCP tool; prefixed IDs (prj_, crd_, spr_…) tell the AI what it's holding at a glance.

  • 💬 Comments as the decision log — the agent records why on the card; you reply, it reads your unread comments back next session.

  • 🔗 Commits attached to cards — each card keeps the diff that delivered it, captured outside the AI's context (no tokens spent reading patches).

  • 📚 Docs that don't rot — architecture, ADRs and patterns live as project docs the agent reads before reinventing.

  • 🔎 Search by meaning — cards, comments and docs are searchable with a hybrid of Postgres full-text and in-process embeddings (a multilingual model in-container, no external API), fused by rank (RRF).

Setup

Requires Node 24+, pnpm 9+, and Docker.

1. Bring up the stack

Postgres + migrations + API + UI + MCP, in one shot:

git clone https://github.com/fmilioni/agents-board.git
cd agents-board
cp .env.example .env
docker compose up -d --build

cp .env.example .env already ships working defaults for local Docker; the values worth knowing:

POSTGRES_USER=agents_board
POSTGRES_PASSWORD=agents_board
POSTGRES_DB=agents_board
POSTGRES_PORT=5544                       # host port (in-container is 5432)
API_PORT=4400
NUXT_PUBLIC_API_URL=http://127.0.0.1:4400
# MCP_HTTP_PORT=4402                      # MCP port (Streamable HTTP at /mcp)
# MCP_PUBLIC_URL=http://127.0.0.1:4402    # public URL clients reach the MCP at

Migrations run automatically before the API and MCP start, and a one-shot backfill then (re)builds the semantic-search vectors for any content missing them. The embedding model loads in its own embedding service; the API and MCP call it over HTTP and fall back to lexical search if it's down. Postgres data persists under ./docker/data/agents-board-postgres. Out of the box the board is open (no login) — see Authentication to turn sign-in on.

Upgrade from Claude Organizer

Export a backup from the Claude Organizer UI, then import it from the Agents Board UI. There is no automatic database migration between the two projects.

2. Install the plugin for your coding agent

One plugin package serves all three clients: the same host-neutral skills plus the MCP registration, read through each host's own manifest.

Codex

Add this repository as a Codex marketplace, then install its plugin:

codex plugin marketplace add fmilioni/agents-board
codex plugin add agents-board@agents-board

You can inspect or manage it interactively with /plugins in Codex CLI. Start a new Codex task after installation so its bundled skills and tools are loaded. The agents-board tools point at local Docker (http://127.0.0.1:4402/mcp) by default.

Claude Code

Add the same repository through Claude Code's marketplace and install the plugin:

/plugin marketplace add fmilioni/agents-board
/plugin install agents-board@agents-board

Start a new Claude Code session after installation. The tracked CLAUDE.md forwards to the shared AGENTS.md, so every client follows the same repository rules and board conventions.

Cursor

There is no CLI install. For local development, symlink the plugin directory then reload the window:

ln -s "$(pwd)/plugins/agents-board" ~/.cursor/plugins/local/agents-board

A team can import this repository as a Cursor marketplace (Dashboard → Plugins; it reads .cursor-plugin/marketplace.json) and install agents-board from Customize. The agents-board tools point at local Docker (http://127.0.0.1:4402/mcp) by default; a remote URL is the plugin variable AB_MCP_URL under Plugins → Configure.

3. Configure the MCP for a remote host

Local Docker is the default — nothing to do: the bundled plugin already registers an agents-board server at http://127.0.0.1:4402/mcp.

To use a board on another machine, point the MCP client at it. Reach it over a stable hostname (a Tailscale MagicDNS name like host.tailnet.ts.net, a LAN host, or a remote domain). Pair it with AB_API_URL (default http://127.0.0.1:4400) pointed at the same host — the helper scripts (attach-commit / attach-worktree-diff / attach-image) post to the API directly, so without it they'd hit the client machine's own localhost and fail.

  • Claude CodeAB_MCP_URL (the bundled .mcp.json reads it).

  • Cursor — set the plugin variable AB_MCP_URL in Plugins → Configure.

  • Codex — a second named server (use a name other than agents-board, which belongs to the bundled plugin):

export AB_API_URL=http://host.tailnet.ts.net:4400
codex mcp add agents-board-remote --url http://host.tailnet.ts.net:4402/mcp

For a repository-scoped Codex connection instead of a user-level one, add it to the trusted project's .codex/config.toml:

[mcp_servers.agents-board-remote]
url = "https://mcp.<domain>/mcp"

Each server gets its own tool namespace, OAuth session and projects; the skills pick the one whose project matches the repo and never mix them.

Usage

Talk to the board in plain language (any language) — the skills trigger on their own:

$agents-board what's next?
$plan break GitHub authentication into cards

Skill

What it does

Triggers when…

agents-board

How to use the board: find the project (record projectId + auth flag in .agents-board.local.md), read cards/sprints/backlog, search cards and docs semantically, move a card through its statuses, comment, write docs, work the inbox.

you read or write anything on the board — "let's continue", "what's next?", "move AB-42 to review".

plan

Turn a fuzzy new demand into structured work (sprint → stories → cards): clarify what's ambiguous, offer research on the stack or the domain, clarify again with what it surfaced, get the design approved, then write cards a zero-context agent can execute.

you describe something new to build, before it's broken down.

No workflow is imposed on how you write code. The plugin ships no implementation, review or worktree machinery — bring your own skills and process. What the board asks for is only that the card be moved to in_progress, land in review with a test-plan comment you can tick off, and reach done only when you approve it.

Inbox

Got an idea mid-flight but don't want to plan it yet? Drop it in the inbox — a one-line demand captured without breaking it into cards. The agent reads pending inbox items when it orients and offers to plan them; the plan skill turns a demand into the right sprint/stories/tasks and marks it planned. It keeps raw intake out of the board until it's actually structured work.

Authentication

Auth is built on better-auth and is off by default — the open board above, no login, an open MCP the plugin connects to as-is. Turn it on from the first-boot setup on the login screen; the first account becomes the admin, and after that sign-in is required.

  • Methods — email+password is the zero-config base; GitHub OAuth is optional and only appears when GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET are set (callback https://api.<domain>/api/auth/callback/github). No host is forced to register an OAuth app.

  • Access — users get roles and per-project access; admins manage who can see what.

  • MCP — with auth on, /mcp is an OAuth 2.1 resource server and compatible MCP clients obtain a bearer automatically. With auth off, /mcp is open, mirroring the open board.

Relevant env (see .env.example):

Var

Purpose

BETTER_AUTH_SECRET

Signs sessions/tokens — required in production.

BETTER_AUTH_URL

Public URL of the API (where better-auth is mounted).

AUTH_TRUSTED_ORIGINS

Origins allowed to call auth (CSRF) — also the API's CORS allow-list.

AUTH_COOKIE_DOMAIN

Parent domain to share the session cookie across subdomains (remote only).

MCP_ACCESS_TOKEN_TTL / MCP_REFRESH_TOKEN_TTL

Lifetime in seconds of the OAuth tokens the MCP login issues (default 7 days / 30 days). Shorten both when the board is exposed to the internet.

GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET

Enable GitHub sign-in.

Local gotcha: the web (:4401) and API (:4400) are different origins, and the session cookie is SameSite=Lax + host-bound. Locally, reach both on the same host — use 127.0.0.1, not localhost — or the cookie won't be sent. Behind the reverse proxy, AUTH_COOKIE_DOMAIN removes this constraint across the subdomains.

Remote deployment (reverse proxy)

A versioned overlay puts the three services behind one TLS edge (Caddy, ports 80/443), a subdomain each (app./api./mcp.<domain>):

cp .env.prod.example .env   # set *_DOMAIN, ACME_EMAIL, BETTER_AUTH_SECRET, public URLs
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build

Point DNS for the three subdomains at the host; Caddy issues/renews TLS (ACME). Set NUXT_PUBLIC_API_URL=https://api.<domain> before building (it's baked into the SPA) and AUTH_COOKIE_DOMAIN=<domain> to share the session cookie. Details: deploy/Caddyfile, .env.prod.example.

Signing in from a terminal-only box (WSL, SSH, headless)

With auth on, the MCP client runs the OAuth flow by opening a browser and waiting on a local loopback callback (http://localhost:<random-port>/…). In a terminal-only environment that stalls — no browser opens (the client prints the URL instead — open it yourself), and the loopback redirect must be able to reach back into the box (WSL2 forwards localhost by default; over SSH, forward the port with ssh -L <port>:localhost:<port> …). Keep one host throughout — don't mix localhost and 127.0.0.1, or the login won't stick.

The reliable escape hatch: auth is off by default and an open board needs no login at all. For a local/WSL dev box, leave auth off and skip the loopback flow entirely; turn auth on where a browser-reachable login exists — e.g. a remote deployment behind the reverse proxy, reached over normal https://. The loopback dance depends on the MCP client and your box's networking; Agents Board is a standard OAuth 2.1 resource server and can't shortcut it server-side.

Architecture

Coding agent ─HTTP──▶ MCP (:4402/mcp) ──┐
                                        ├─▶ core ──▶ Postgres 16
Browser (SPA) ──HTTP──▶ API (:4400) ────┘   (+ WebSocket /ws for real-time)
                             └─ core ──HTTP──▶ Embedding service (:4403) ──▶ model

A pnpm monorepo under packages/:

Package

Role

shared

Shared TypeScript types.

db

Drizzle schema + migrations.

core

Zod-validated use-cases — the single source of truth.

auth

better-auth setup (email+password, GitHub, OAuth for the MCP).

mcp

The MCP server (Streamable HTTP).

api

Fastify REST + WebSocket.

embedding-service

Loads the embedding model once and serves it over HTTP (api/mcp are thin clients).

web

Nuxt 4 SPA (the UI talks only to the API, never the MCP).

Prefixed nanoid IDs (prj_, crd_, spr_…) let the agent recognize an entity's type from the ID alone.

Development (without Docker)

pnpm install
pnpm db:up                       # Postgres on :5544
pnpm db:migrate
pnpm dev:api                     # :4400
pnpm dev:web                     # :4401
pnpm dev:mcp                     # :4402/mcp
pnpm dev:embedding               # :4403 (semantic search; omit for lexical-only)

Also handy: pnpm typecheck, pnpm lint, pnpm test, and pnpm db:generate after schema changes.

License

MIT © Felipe Milioni

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for is.team, enabling AI agents to interact with project boards, tasks, cards, sprints, integrations, and real-time notifications.
    100
    14 npm
    1
    MIT
  • A
    license
    B
    quality
    F
    maintenance
    An MCP server that provides a database-backed kanban board with 40+ tools for AI agents to track issues, features, todos, epics, and diary entries across projects, including status workflows, relationships, and semantic search.
    45
    83
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server for agent-first Kanban board management, enabling agents to create, move, comment, and claim pebbles (cards) across statuses like requested, code_creation, testing, validation, and complete, with support for blocking, context feedback, and HIL (human-in-the-loop) transitions.
    -