Skip to content
Conduit

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.

dsasante1/forwardcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "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, 2026

Forward

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 forward CLI.
  • 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:

FileFor
AGENTS.mdInstructions every agent reads: when and how to document endpoints, infra and schema
CLAUDE.mdImports AGENTS.md for Claude Code
.mcp.jsonRegisters the forward MCP server for Claude Code
.cursor/mcp.jsonRegisters it for Cursor
.vscode/mcp.jsonRegisters 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 its aria-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. --restore brings deleted drafts back.
  • Drafts the code no longer renders are reported as stale. --prune removes them, but never one that is documented, edited, adopted, or holds something that stays. Pruning also forgets deleted drafts the code no longer renders.
  • --anchors adds // @adc <id> markers above each component's declaration in your JS/TS source, so resolve_anchors links 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 export and 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

PathHolds
forward.jsonProject manifest: id, name, format version
design/<id>.jsonDesign elements, each with its optional apiBinding docs
history/<elementId>/<ts>-<n>.jsonAppend-only API-doc history, one file per version
infra/nodes, infra/edges, infra/flowsInfrastructure graph and narrated flows
data/entities, data/relationsER data model
agents/agents, agents/serversAgents and the MCP servers they call
tasks/<id>.jsonTask tracker
checkpoints/<id>.jsonNamed, restorable snapshots of design and infra
dismissed/<id>.jsonCode 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.

LayerWhat it isAttaches to
DesignDesignElements a designer draws — frames, rectangles, ellipses, text, components/instances — with absolute geometry, parentId hierarchy and style— (stands alone)
API bindingAn 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 objectone design element
InfrastructureA project-scoped graph of InfraNodes + InfraEdges (frontend, backend, db, cache, queue, service, devops, external, group), rendered as an overlayproject
FlowsNarrated InfraFlows — ordered hops over the infra nodes — that serialize to a Mermaid sequenceDiagram and can tie a hop to an endpointinfra graph
Entities (ER/UML)A project-scoped data model of Entity tables + crow's-foot EntityRelations, serialized to a Mermaid erDiagramproject
TasksA 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) viewproject (soft links)
CheckpointsNamed, restorable snapshots of the whole canvas (design + infra) — a deliberate save with a noteproject

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).

PathPackageWhat it is
packages/sharedforward-coreThe 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/mcpforward-mcpThe 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/canvasforward-canvasThe design editor, shipped standalone with the CLI (host/) and embedded in the VS Code extension
apps/extensionforward-vscodeVS Code extension. Works on the workspace's .forward/ automatically
apps/docs-ciforward-docs-ciBring-your-own-AI CI step that applies an agent-written plan to a project
apps/siteforward-siteThe 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

License

Apache License 2.0. See LICENSE and NOTICE.

↑↓ navigate openesc close