mcp server
forward
Keep UI design and backend docs in sync, inside your git repo. A design canvas, API/infra/data-model docs, and an MCP server + CLI so AI agents document as they build.
Set up
Runs on your computer. Pick your agent and operating system.
Before you start
- Node.js 20 or newer
{
"mcpServers": {
"dsasante1-forward": {
"command": "npx",
"args": [
"-y",
"forward-mcp"
]
}
}
}same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12
Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs
README
synced Nov 1, 2026Forward
Keep UI design and backend documentation in sync, inside your repository.
Designers draw UI on a visual canvas. Backend developers, and the AI agents working with them, attach API docs, infrastructure, data-model and flow documentation to those design elements. A history timeline and a catch-up digest show frontend developers exactly which endpoints to integrate, change or remove.
- Lives in git. The whole project is plain JSON in
.forward/, one file per record. It is versioned, reviewed and merged with the code it describes. No server and no account are needed. - AI-agent first. Claude Code, Codex, Cursor, Copilot or any MCP client gets 42 tools with full
parity with the canvas. Agents without MCP use the same tools through the
forwardCLI. - GitHub native. One workflow validates
.forward/on pull requests, posts a catch-up digest as a PR comment, and publishes a read-only canvas to GitHub Pages. - Open source under the Apache 2.0 license.
Quick start
Run this in the root of your repository. Node 22 or newer is required.
npx -y -p forward-mcp forward init # creates .forward/, agent configs and the GitHub workflow
npx -y -p forward-mcp forward serve # opens the canvas editor on .forward/ at http://127.0.0.1:4747
git add .forward AGENTS.md CLAUDE.md .mcp.json .cursor .github && git commit -m "Add Forward"
forward serve writes straight to .forward/. An agent editing through MCP at the same time
shows up on the canvas within a couple of seconds, and the History view reads your git log.
AI agents
forward init (or forward agents later) writes the agent wiring into your repository:
| File | For |
|---|---|
AGENTS.md | Instructions every agent reads: when and how to document endpoints, infra and schema |
CLAUDE.md | Imports AGENTS.md for Claude Code |
.mcp.json | Registers the forward MCP server for Claude Code |
.cursor/mcp.json | Registers it for Cursor |
.vscode/mcp.json | Registers it for VS Code / Copilot (forward agents --vscode) |
Codex reads AGENTS.md. Register the server in ~/.codex/config.toml:
[mcp_servers.forward]
command = "npx"
args = ["-y", "forward-mcp"]
env = { FORWARD_AGENT = "codex" }
Any other MCP client runs npx -y forward-mcp over stdio from the repository root. No
configuration is needed: the server finds the nearest .forward/ and works on those files.
Without MCP, the CLI calls the very same tool code in-process:
forward tools # list all 42 tools
forward tools write_documentation # one tool's arguments
forward find_element --query "login button"
forward write_documentation --element-id el_123 --title "POST /login" --description "Body: email, password"
forward call write_infra_node '{"kind":"cache","label":"Redis"}'
forward diff origin/main # what this branch changed, as Markdown
Good first calls for an agent are project_info, find_element, write_documentation,
validate_project and get_changes_since_ref. Writes are stamped with your git user.name, plus
via <agent> when FORWARD_AGENT is set.
Images
Drop or paste an image onto the canvas (or right-click → Image…) and it becomes a rectangle
with an image fill; any rectangle, ellipse or frame can take one from the inspector or the
right-click menu, clipped to its corners. The inspector sets the fit (cover, contain, fill) and alt
text. Agents use set_element_image with a file path.
The bytes are stored once in .forward/assets/, named by their SHA-256, and the element only holds
that name, so checkpoints, history and the PR digest never copy them, the same image used twice is
one file, and two branches adding it don't conflict. PNG, JPEG, WebP, GIF and AVIF are accepted up
to 5 MB (SVG is refused: it can carry script). The canvas downscales to 4096 px and re-encodes,
and the store strips EXIF/XMP from every JPEG and PNG, so a photo's GPS position never reaches git.
forward init marks assets/ binary in .forward/.gitattributes; teams with many large images
can add git lfs track ".forward/assets/**".
Removing an image or deleting its element keeps the file (undo and checkpoints may need it).
forward assets lists what's stored, forward assets prune deletes what no element or checkpoint
uses, and forward validate warns about missing or unused images and fails on a file whose bytes
don't match its name. forward capture --images fetches the page's <img>s into drafts instead
of grey placeholders.
Designs from frontend code
Ideally the frontend is built from the design. When a screen was built first, Forward can draw it for you: it renders the running app, reads back what the browser actually painted (position, size, colours, borders, corners, fonts, text, stacking) and turns it into canvas elements: one frame per route, a box for everything that paints, text for every run of text. Wrappers that paint nothing are dropped, so the layer tree stays readable. React dev builds also report which component rendered each node, so repeated components become a component plus instances.
forward capture --browsers # which browsers it can use here
forward capture http://localhost:5173 / /login /settings --dry-run
forward capture http://localhost:5173 / /login /settings
forward capture http://localhost:5173 /account --auth state.json --viewport 390x844
forward capture http://localhost:5173 / --browser edge # or chrome, brave, chromium, vivaldi, opera, a path
Live capture uses the browser you already have. Any Chromium-based browser works: Chrome, Edge,
Brave, Chromium, Vivaldi or Opera. Nothing is installed or downloaded. The browser runs headless
with a fresh, temporary profile (it never sees your own cookies, logins or extensions). It's
controlled over a pipe, so nothing listens on the network, and it's closed and its profile deleted
when the capture ends. If the project has Playwright, that is used first; --browser picks one
explicitly and FORWARD_BROWSER sets the default.
No Playwright and no Chromium browser (a server, a container, some CI)? forward capture then runs
its companion package, forward-capture, at the same version
(npx -y forward-capture@<version>). It brings Playwright and downloads Playwright's headless
Chromium once, about 100 MB, into Playwright's shared cache; npx -y forward-capture install
fetches it ahead of time. FORWARD_NO_DOWNLOAD=1 forbids both downloads. forward-mcp itself
stays free of dependencies.
Firefox and Safari can't be driven this way. In those (or any browser), forward capture --script
prints a snippet to paste into the DevTools console. It downloads forward-snapshot.json, which
forward capture --from forward-snapshot.json imports. Agents call the same thing as
import_design_from_code.
Generated elements are drafts, marked "from code" on the canvas:
- Re-running a capture updates drafts in place, and API docs attached to a draft are kept. An
element keeps its identity by its
data-testid,id, the JSX line that rendered it (React dev builds) or itsaria-label. Failing those, by its position under the nearest element that has one. When the page around a draft changes (a banner inserted above, say), drafts are re-matched by type, name or text, size and what they contain, as long as the match is unambiguous. API docs never move on a guess: if a documented draft can't be matched for certain, it stays where it was (stale, docs intact) and the capture reports it. Test ids on repeated or generic elements make identity certain. - A draft someone has edited (moved, restyled, renamed) is never overwritten. The import reports it as a conflict.
- Adopt draft (inspector or right-click menu) turns a draft into an ordinary design element that imports never touch again.
- Deleting a draft remembers it in
.forward/dismissed/, so the next capture doesn't bring it back.--restorebrings deleted drafts back. - Drafts the code no longer renders are reported as stale.
--pruneremoves them, but never one that is documented, edited, adopted, or holds something that stays. Pruning also forgets deleted drafts the code no longer renders. --anchorsadds// @adc <id>markers above each component's declaration in your JS/TS source, soresolve_anchorslinks code to design. It edits source files, so it is off by default; every capture says how many anchors it would add.- Adopting a draft isn't listed as a design change in the PR digest. The digest reports it on its own "Adopted from code" line instead.
- A capture records what the page shows, so run it against development or seed data, not real customer data. Password fields are always masked.
GitHub
forward init adds .github/workflows/forward.yml, which uses
this repository's composite action:
- On pull requests it runs
forward validate, annotating schema errors inline. It then posts one comment, updated on every push, listing new, changed and removed endpoints with doc diffs and a per-layer summary of everything else. - On the default branch it builds a static, read-only canvas with
forward exportand deploys it to GitHub Pages. Turn Pages on with Source: GitHub Actions.
Teams that want an AI to write the docs on every pull request can add the bring-your-own-AI
pipeline in apps/docs-ci. Its repo-mode template commits the generated .forward/
changes back to the PR branch.
How it works
designers backend devs AI agents GitHub
│ │ │ │
[ canvas ] [ VS Code extension ] [ MCP server · CLI ] [ Action · Pages ]
│ │ │ │
└───────────────────────┴──────── forward-core/api ─┴────────────────────────┘
│
.forward/ files in your git repo
Every surface speaks one REST contract, forward-core/api. A router in forward-core/repo
serves that contract from the files in .forward/: in-process for the MCP server, CLI, extension
and CI, and over a local HTTP server that forward serve runs for the canvas. There is no central
server, database or account. Git is the sync, the history and the access control.
The .forward/ directory
| Path | Holds |
|---|---|
forward.json | Project manifest: id, name, format version |
design/<id>.json | Design elements, each with its optional apiBinding docs |
history/<elementId>/<ts>-<n>.json | Append-only API-doc history, one file per version |
infra/nodes, infra/edges, infra/flows | Infrastructure graph and narrated flows |
data/entities, data/relations | ER data model |
agents/agents, agents/servers | Agents and the MCP servers they call |
tasks/<id>.json | Task tracker |
checkpoints/<id>.json | Named, restorable snapshots of design and infra |
dismissed/<id>.json | Code drafts someone deleted, so capture doesn't recreate them |
assets/<sha256>.<ext> | Image bytes for image fills, named by their hash |
One file per record keeps merges clean and PR diffs readable. History entries are separate files,
so two branches that both document endpoints merge without conflicts. The project activity feed is
built from git log, so commit messages show up in the History timeline. forward validate checks
schemas, ids and cross-layer links.
Seven data layers, one contract
The data model is deliberately layered. The design is the primary artefact and exists on its own;
everything else is optional and attaches (or links) to it. All shapes live once in
packages/shared (forward-core) as Zod schemas + TypeScript types, so every surface
stays in sync.
| Layer | What it is | Attaches to |
|---|---|---|
| Design | DesignElements a designer draws — frames, rectangles, ellipses, text, components/instances — with absolute geometry, parentId hierarchy and style | — (stands alone) |
| API binding | An optional { title, description } doc note a backend dev attaches to a design element. Docs-first and framework-agnostic (REST, GraphQL, gRPC, a job…) — an endpoint is never a first-class canvas object | one design element |
| Infrastructure | A project-scoped graph of InfraNodes + InfraEdges (frontend, backend, db, cache, queue, service, devops, external, group), rendered as an overlay | project |
| Flows | Narrated InfraFlows — ordered hops over the infra nodes — that serialize to a Mermaid sequenceDiagram and can tie a hop to an endpoint | infra graph |
| Entities (ER/UML) | A project-scoped data model of Entity tables + crow's-foot EntityRelations, serialized to a Mermaid erDiagram | project |
| Tasks | A work tracker (Task: status/priority/type, assignees, start/due dates, dependsOn, activity feed) that optionally links into a design element / flow / endpoint, with a timeline (Gantt) view | project (soft links) |
| Checkpoints | Named, restorable snapshots of the whole canvas (design + infra) — a deliberate save with a note | project |
On top of these sits the History timeline: a per-element append-only API-doc history
(version_timeline) plus a unified project event feed, rendered as a git-graph with expandable
"git-diff for API docs" and a catch-up digest ("since this baseline, here's what to integrate /
modify / remove") for a returning frontend dev.
Monorepo layout
npm workspaces (Node >= 22.12 to develop; .nvmrc pins 22).
| Path | Package | What it is |
|---|---|---|
| packages/shared | forward-core | The contract: Zod schemas + types, timeline/diff/infra/entity helpers, the api-rest client (forward-core/api) and the repo-mode store, router and git helpers (forward-core/repo) |
| apps/mcp | forward-mcp | The agent surface: the MCP server (forward-mcp) and the forward CLI (init, serve, validate, diff, export, capture, agents, every tool). Also builds the companion forward-capture (live capture with Playwright) |
| apps/canvas | forward-canvas | The design editor, shipped standalone with the CLI (host/) and embedded in the VS Code extension |
| apps/extension | forward-vscode | VS Code extension. Works on the workspace's .forward/ automatically |
| apps/docs-ci | forward-docs-ci | Bring-your-own-AI CI step that applies an agent-written plan to a project |
| apps/site | forward-site | The website: landing page, docs and a live read-only demo, deployed on Vercel |
Development
npm install && npm run build # build packages/shared first, then every app
npm test # all Vitest suites
npm run typecheck
npm run dev:host -w apps/canvas # hack on the standalone canvas host with Vite
node apps/mcp/dist/cli.js serve # run your local build of the CLI against a repo with .forward/
npm run dev -w apps/site # the website (landing page + docs) with Vite
See CONTRIBUTING.md for the workflow, conventions and governance, and CHANGELOG.md for what changed in each release.
Publishing
Releases are tags. mcp-v* publishes forward-mcp to npm with trusted publishing, so no npm token
is stored anywhere. v* publishes the VS Code extension. Both re-run the full verification first,
and forward-mcp is smoke-tested as the installed tarball. See docs/releasing.md,
including the one-time manual first publish.
npm version 0.3.0 -w apps/mcp --no-git-tag-version # land it through a PR, then:
git tag mcp-v0.3.0 && git push origin mcp-v0.3.0