# FronyBoard

**Category:** 🗄️ Databases  
**Repository:** https://github.com/Cafelatte1/FronyBoard  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/fronyboard

## Description
Project tracker for AI agents: roadmap, periods, tasks and a validation gate, in one SQLite file

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "fronyboard": {
    "command": "npx",
    "args": ["-y","fronyboard"]
  }
}
```

## Documentation & README

# FronyBoard

An MCP server that gives AI agents (Claude Code and friends) a first-class project
tracker.

Where Jira is an issue tracker for humans behind a web UI, FronyBoard replaces each
part with something an agent can use natively:

| Jira | FronyBoard |
|---|---|
| Database | One SQLite file in a dedicated data directory |
| Records | JSON documents (roadmap, period) + Markdown |
| API | MCP tools |
| Workflow engine | Schema + rule validation, run as a gate before every write |
| State transition | An MCP tool call (`transition_task`) |

The schema and operating rules were extracted from a real product's management system
(31 tasks shipped through it), then generalized.

## Install

Requires [uv](https://docs.astral.sh/uv/). One line registers FronyBoard in Claude Code;
`uvx` fetches the package from PyPI on first use and caches it:

```powershell
claude mcp add FronyBoard -- uvx fronyboard
```

Any MCP client that can launch a stdio command works the same way — the command is
`uvx fronyboard`. It is also listed in the
[MCP Registry](https://registry.modelcontextprotocol.io) as `io.github.Cafelatte1/fronyboard`.
From a clone, point at the checkout instead (this needs `git`):

```powershell
git clone https://github.com/Cafelatte1/fronyboard
claude mcp add FronyBoard -- uv run --directory <path-to-clone>\backend fronyboard
```

This is the local (stdio) mode: the client starts the server as a child process and
talks to it over a pipe. No HTTP, no network, no credentials — `web.py` and
`fauth.py` are never called. Data is written to `%LOCALAPPDATA%\Frony\FronyBoard\data`
(`~/.Frony/FronyBoard/data` where `LOCALAPPDATA` is unset); set `AIRA_DATA_DIR` to
relocate it. Logs (JSON Lines, one line per MCP tool call plus server events) go to
the sibling `logs` folder — `FRONYBOARD_LOG_DIR` overrides.

To share one FronyBoard between several machines, or to use it from the Claude and
ChatGPT apps, run it as an HTTP server instead — see
[docs/self-hosting.md](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/self-hosting.md).

## Project setup

Connecting the MCP server gives every session the tools and the general workflow
(delivered as server instructions). What it cannot know is **which FronyBoard project
a codebase belongs to** — declare that in the codebase itself by adding this section
to its `CLAUDE.md` (create the file if the project has none):

```markdown
## FronyBoard

This project is tracked by FronyBoard (project key: DLY).
Manage tasks through the FronyBoard MCP tools, following the FronyBoard server instructions.
```

Replace `DLY` with the project's key (register one first with `create_project`).
The section is also the opt-in signal: a codebase without it is treated as not
FronyBoard-managed.

## Model

```
fronyboard.db
├── projects   one row per project (key e.g. DLY): the roadmap record —
│              yearly overview (goal / now / target / checklist) + quarterly milestones
└── periods    one row per opened period (e.g. 2026Q3): tasks ({KEY}-001, ...)
               + `result` (retrospective, written when the period closes)
```

A project is two kinds of records — the roadmap, and one record per period. Both are
JSON documents; the schema and the rules that guard it are in
`backend/src/fronyboard/validation.py`.

- **Task ids are a project-global sequence** (`DLY-042`) — they keep counting across
  periods and are never reused. They are the only link between FronyBoard and a codebase:
  use them in branch names (`feat/DLY-042/short-desc`) and record the branch on the task.
- **A task is a title** (v0.33.0, AIR-086) plus status, tags, `depends_on`, branch and two
  one-line notes of at most 300 characters each. Agents read titles and status; the 25-line
  body nobody read, and the month/week slots that only existed to schedule it, are gone.
  Time is `meta.completed_at`.
- **The two notes answer different questions at different moments** (v0.38.0, AIR-090).
  `content` is written at create time and says **why** the task exists — the pressure behind
  it, or the scope deliberately left out. The approach chosen is not part of it (AIR-092):
  agents wrote it here and again in the commit, so it lives in the commit only. `check` is required by
  `transition_task(status="done")` and says **what proves it done** — the command and its
  output, or an observable a reader can go and see. One free note asked before the work can
  only restate the plan: in a 12-session benchmark every task an agent wrote paraphrased its
  own title, because the note was fixed at create time and `update_task` was never called.
  Reopening a task drops its `check`; nothing is proven any more.
- **Reference chain**: `period → roadmap milestone` (the quarter). That is the only one.
- **Statuses** — milestones: `planned | active | done`;
  tasks: `todo | in_progress | done | blocked | cancelled`.
- **`cancelled` is the soft delete** — there is no hard delete. Cancelling requires a
  reason, keeps the record (and its id) forever, and hides the task from queries by
  default (`list_tasks` takes `include_cancelled`). `blocked` = may resume,
  `cancelled` = will not happen; transitioning a cancelled task restores it.
- **Carry-over**: a task that outlives its period is not moved — recreate it in the next
  period under a new id and note the mapping in the closing retrospective.
- **`get_status` is the whole resume** — the overview, each period's open tasks, and
  `recent_done`: the ten most recently finished tasks with their `content`, their `check`
  and when they completed. What is already built is what a cold session needs most, and
  nobody makes a second call to find it (AIR-090). It is still a record of claims: the
  board says what an agent reported, the code is the evidence.
- **`depends_on`** on a task lists the earlier tasks it builds on (other projects allowed).
  It points backwards only — there is no forward index, because storing one direction and
  deriving the other read as inverted often enough to be worth dropping (v0.36.0, AIR-089).
  The field was `follows` until v0.37.0; the boot migration renames it. It is a pointer,
  not a lock: `list_tasks` and `get_status` flag the entries not yet done as `waiting_on`,
  and nothing is ever blocked.
- **Timestamps** (`meta.created_at` / `updated_at` / `started_at` / `completed_at`) are
  stamped by the server in naive UTC — `started_at` on the first `in_progress` transition,
  `completed_at` on `done` (and removed again if the task leaves `done`). Agents never
  write them.
- **The `result` field closes a period** — the rest of the file holds only current
  state, so the "why it turned out this way" lives there: judgment and reasons,
  not counts. Its presence is what marks a period closed.

## Tools

| Area | Tools |
|---|---|
| Projects | `create_project`, `update_project`, `list_projects`, `get_roadmap`, `get_status`, `validate` |
| Roadmap | `set_overview`, `set_check`, `upsert_milestone` |
| Periods | `open_period`, `close_period`, `get_retrospective` |
| Planning | `create_task`, `update_task`, `transition_task` |
| Queries | `list_tasks`, `get_task`, `search_tasks`, `recent_activity` |

`update_task` and `transition_task` derive the project from the task id prefix
(`DLY-042` → `DLY`), so their `key` parameter is optional. Re-calling
`close_period` on a closed period rewrites its retrospective.

Typical flow:

```
create_project → set_overview → upsert_milestone → open_period
→ create_task
→ transition_task in_progress (with branch) → ... → transition_task done
→ close_period (retrospective)
```

Every mutation is validated before anything is written; invalid changes are rejected
with the full error list. `close_period` refuses while tasks are still `todo` or
`in_progress`. Writes are serialized per project, so concurrent clients cannot
collide on ids or lose updates.

## Self-hosting

The same package also runs as an always-on HTTP server (`fronyboard serve`): MCP over
streamable HTTP for every machine on your network, a read-only web dashboard for
humans, API keys per device, and OAuth for the hosted Claude / ChatGPT apps.
Authentication is delegated to [FronyAuth](https://github.com/Cafelatte1/project-auth),
a separate service. None of it is needed for the stdio install above.
To see the dashboard on your own machine without any of that, run `fronyboard serve --local`
(loopback only, no login) and open http://127.0.0.1:8642.
[docs/self-hosting.md](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/self-hosting.md) covers the setup;
[docs/operations.md](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/operations.md) is the day-2 runbook.

## Development

```powershell
uv run --directory backend pytest      # backend
cd frontend; npm test                  # dashboard
```

The repo is a monorepo. `backend/src/fronyboard/` — `store.py` (SQLite, data root),
`validation.py` (schema gate), `service.py` (operations), `auth.py` (bearer
middleware) + `fauth.py` (FronyAuth client), `log.py`, `web.py` (JSON API + static
serving), `server.py` (MCP tool surface + CLI). `frontend/` — the dashboard (React +
Vite), built to static files that the backend serves; its build output
`frontend/dist` is committed so a server needs no Node toolchain.

The three docs under [docs/](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/) cover what the code cannot tell you — running
this on your own machines:

- [docs/self-hosting.md](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/self-hosting.md) — running FronyBoard as a shared server: clients, dashboard, hosted apps, deploy
- [docs/operations.md](https://github.com/Cafelatte1/FronyBoard/blob/HEAD/docs/operations.md) — home server runbook

