Skip to main content
Glama

Ferry is an MCP server that lets AI agents build animated, narrated presentations of codebase changes. The presentations open in your browser and update live while the agent builds them.

Ferry demo: an agent builds a deck live, then walks a sequence diagram and a stepped diff

▶ Watch the full demo (1:50): the agent builds the deck live, walks the behavior, architecture and code, then applies a review comment from the viewer.

Ferry carries reviewers from the old code to the new. It's built on a few ideas that make change explainers easy to follow:

  • Maximum stability. Code keeps its identity between steps. Only changed lines enter or leave. Lines that only change indentation glide sideways instead of being deleted and re-added.

  • Behavior before code. Sequence diagrams play the broken behavior, then replay the fix in the same slots. After that, a stepped diff shows the change that causes it.

  • Interruptible motion. Every channel is a closed-form spring. Retargeting keeps the current position and velocity, so pressing ← mid-transition reverses smoothly instead of jumping.

  • Plans, not pixels. Agents send declarative JSON. The server validates it, resolves git, highlights code with Shiki, and returns actionable warnings.

Install with your agent

Paste this into Claude Code, Codex, Cursor, or any agent that can run shell commands:

Install the Ferry MCP server for me. Clone https://github.com/danowicz/ferry-mcp into ~/.ferry-mcp (or pull if it's already there), then follow ~/.ferry-mcp/INSTALL.md: check Node ≥ 22.18, run npm install and npm test, and register Ferry with the MCP clients I use. Tell me when it's ready and what I need to restart.

INSTALL.md holds the steps the agent follows: prerequisites, verification, and config snippets for each client.

Related MCP server: MCP Walkthrough

Install by hand

git clone https://github.com/danowicz/ferry-mcp.git ~/.ferry-mcp
cd ~/.ferry-mcp && npm install   # Node ≥ 22.18

Claude Code

claude mcp add ferry --scope user -- node ~/.ferry-mcp/bin/ferry.js

Claude Desktop / Cursor / any MCP client (use the absolute path; clients don't expand ~)

{
  "mcpServers": {
    "ferry": { "command": "node", "args": ["/Users/you/.ferry-mcp/bin/ferry.js"] }
  }
}

Then ask your agent something like:

Explain the changes on this branch with a Ferry presentation.

The explain_changes prompt walks the agent through the whole flow. The viewer starts automatically at http://localhost:4747 (set FERRY_PORT to change it). Decks are stored in ~/.ferry/decks (set FERRY_HOME to change it).

Tools

Tool

What it does

authoring_guide

Slide types, JSON shapes, storytelling rules

inspect_changes

Changed files, churn, and numbered changes (blocks of added, removed, or re-indented lines)

create_deck / update_deck

Deck metadata and theme

add_slides / update_slide / remove_slides / reorder_slides

Edit the deck; warnings flag unmatched callouts, unknown ids, folded targets

get_deck / list_decks

Read back authoring JSON and outlines

delete_deck

Deletes a deck with its change plan and chat

draft_deck_from_git

Skeleton deck: title with stats, file map, one stepped diff per significant file

open_deck

Opens the live viewer

wait_for_feedback

Waits until you send a plan from the viewer, then returns it to implement (outline and slide JSON)

get_feedback

Returns what's pending without waiting

resolve_feedback

Closes a sent plan with a reply shown in the viewer

reply_feedback

Asks you a question in the viewer

export_deck

One self-contained HTML file (fonts and code inlined, works offline)

Review, plan, then implement

Ferry splits a review into three steps, all in the viewer:

  1. Review the change through the deck the agent built: behavior, architecture, then the code, step by step.

  2. Plan what should change next. Press C and switch the chat to Plan (or press Shift+Tab). Describe a change ("make the retry interval configurable", "add a test for the live-server guard") and Pin the code line it's about if you like. Claude reads the code and drafts the change as a plan deck: a second set of slides with the proposed code as hand-written diffs, the approach, and the tests to add. Nothing in the repository changes while you plan. Open the plan with the Plan button in the bar, keep chatting to revise it, and go back and forth until the slides say what you want.

  3. Implement: in the panel's Plan tab, press Send plan to agent.

    • If your agent (the one that built the deck) is waiting in wait_for_feedback, the panel says Agent is listening and the agent receives the plan: its outline and every slide's authoring JSON.

    • Otherwise Claude Code running in the viewer implements it. It edits the code in the deck's repository on the checked-out branch, never commits, and you follow along in the Chat tab. If it doesn't finish, the plan goes back so you can send it again.

    • The agent replies when it's done (Done or Declined). Reply under it to reopen. Review the result with git diff as usual.

Copy as prompt gives you a prompt for any other agent to implement the plan.

The chat

The chat is a conversation with a Claude Code agent dedicated to the deck. It runs headless (claude -p) in the deck's repository, using your existing Claude Code login.

  • Every message carries what you're looking at: the slide, the step, and anything you Pin (a code line, node, row…).

  • Ask mode answers questions and can edit the deck you're reviewing. Plan mode edits only the plan deck. Neither can touch repository files: only a sent plan does, and each mode can only write to its own deck.

  • Replies stream into the panel along with what the agent is doing ("Reading bind.ts", "Adding slides"), and slides update live.

  • The conversation continues across messages. New chat starts over, and Stop interrupts.

Set FERRY_CHAT_MODEL to pick a model (e.g. sonnet for faster replies), or FERRY_CLAUDE_BIN if claude isn't on your PATH. Chat logs are stored in ~/.ferry/chat/ and sent plans in ~/.ferry/feedback/. The viewer only accepts JSON requests from localhost pages, so other websites can't send instructions to your agent.

Slide types

title · section · points (cards, list, checklist) · files · diff (from git, before/after, hand-written lines, or plain code; with steps, focus, callouts, morph or review mode) · sequence (before/after phases) · flow (architecture with status changes and travelling packets) · metrics (rolling numbers) · compare (code, points, markdown, or a draggable image wipe for UI changes) · markdown.

Viewer keys

→ / Space: next step · ← back · ↑ ↓ slides · C chat & plan · P pin · O overview · N speaker notes · V voice narration (auto-advances) · T theme (midnight, tokyo, evergreen, paper) · S slow motion · R replay · F fullscreen · ? help

CLI

node bin/ferry.js serve [--open]        # standalone viewer
node bin/ferry.js list                  # saved decks
node bin/ferry.js delete <deck-id>…     # delete decks (or use the trash button on the home page)
node bin/ferry.js export <deck-id> [out.html]
npm run demo                            # builds the showcase deck through MCP
npm run record                          # re-records docs/demo.mp4 (needs ffmpeg and Playwright's Chromium)
npm run banner                          # re-renders docs/banner.png
npm test                                # end-to-end check of every tool

Layout

src/           MCP server (Node runs TypeScript directly)
  mcp.ts         tools, prompt, resource
  schema.ts      authoring input (zod) — what agents send
  compile.ts     authoring → render model: ids, git, highlighting, steps, warnings
  diff.ts        line diff with re-indent detection, change blocks, folding
  model.ts       render model shared with the viewer
  server.ts      viewer HTTP server + live updates (SSE) + feedback API
  feedback.ts    change requests, agent presence, change-plan formatting
  chat.ts        viewer chat: headless Claude Code per deck, streamed over SSE
viewer/src/    presentation app (bundled with esbuild on demand)
  motion.ts      closed-form interruptible springs
  feedback.ts    side panel: chat tab, change-plan tab, pinning
  markdown.ts    safe Markdown for chat replies
  slides/        one view per slide type
scripts/       demo, smoke test, screenshot walker, demo-video recorder, banner
docs/          banner, demo video and GIF

Available Tools

18 tools
add_slidesAdd slidesA

Append slides to a deck (or insert after a slide id). Returns the outline and any warnings (unmatched callouts, unknown ids). Changes appear live in an open viewer. See authoring_guide for slide types.

Inputs: slides (required), deck_id (required), after.

authoring_guideFerry authoring guideA
Read-only

Slide types, JSON shapes, and storytelling rules for explaining code changes. Read once before building a deck.

Inputs: no named parameters.

create_deckCreate deckA

Create an empty presentation deck. Returns its id and live viewer URL. Add content with add_slides.

Inputs: title (required), ref, repo, theme, +1 more.

delete_deckDelete deckA
Destructive

Permanently delete a deck, its change plan and its viewer chat. Only do this when the user asks: it cannot be undone.

Inputs: deck_id (required).

draft_deck_from_gitDraft deck from gitA

Create a skeleton deck from a git range: title with stats, a file map, and one stepped diff slide per significant file (one step per hunk). Then refine: add narration, callouts, behavior slides, and a review checklist with update_slide/add_slides.

Inputs: repo (required), base, head, theme, +2 more.

export_deckExport deckB

Write the deck as one self-contained HTML file (viewer, fonts, and code inlined) to share or attach to a PR.

Inputs: deck_id (required), path.

get_deckGet deckB
Read-only

Return the deck outline and the authoring JSON of its slides (or one slide), e.g. to edit with update_slide.

Inputs: deck_id (required), slide_id.

get_feedbackGet feedbackA

Return the pending change plan left in the viewer (without waiting) and mark it as being worked on: code changes to make in the repository the deck explains. Use when the user says they left feedback.

Inputs: deck_id (required).

inspect_changesInspect git changesA
Read-only

List changed files (status, churn) and their numbered changes (contiguous blocks of added/removed/re-indented lines) with previews. Change numbers match diff slides with a git source: assign them to steps with steps[].changes.

Inputs: repo (required), base, head, paths, +1 more.

list_decksList decksA
Read-only

List saved decks, newest first.

Inputs: no named parameters.

open_deckOpen deckB

Open the deck in the user's browser (live: later edits appear immediately). Returns the URL.

Inputs: deck_id (required), slide, launch.

remove_slidesRemove slidesC

Remove slides by id.

Inputs: deck_id (required), slide_ids (required).

reorder_slidesReorder slidesC

Set the slide order. Ids you omit keep their relative order after the listed ones.

Inputs: order (required), deck_id (required).

reply_feedbackReply in feedback chatA

Post a message in the viewer chat without closing anything: ask a clarifying question about a request (by id), or say something about the whole deck (no id). The user answers in the viewer; wait_for_feedback returns their answer.

Inputs: text (required), deck_id (required), id.

resolve_feedbackResolve feedbackB

Close change requests after making the code changes (or declining them). Each reply appears in the viewer next to the request.

Inputs: items (required), deck_id (required).

update_deckUpdate deckC

Change deck metadata or theme.

Inputs: deck_id (required), ref, repo, theme, +2 more.

update_slideUpdate slideA

Replace one slide with a new definition (send the complete slide). Keeps its id and position.

Inputs: slide (required), deck_id (required), slide_id (required).

wait_for_feedbackWait for feedbackA

Wait until the user sends a change plan from the viewer's feedback panel (C key), then return it: code changes they want in the repository the deck explains, each with the slide, step and pinned element (often a code line) it was written on, plus the slide's authoring JSON. Returns at once if requests are already pending. The viewer shows the user that you are listening. Make the changes in the code (not the slides), resolve_feedback, then call this again to keep reviewing together.

Inputs: deck_id (required), timeout_seconds.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 18 tools

    Disambiguation5/5

    Each tool targets a distinct resource or action, from deck and slide CRUD to git inspection and viewer feedback. The only subtle overlap is between get_feedback and wait_for_feedback, but their descriptions clearly distinguish immediate retrieval from blocking wait, and resolve_feedback vs reply_feedback are similarly well separated.

    Naming Consistency4/5

    All operational tools follow a consistent snake_case verb_noun pattern (e.g., create_deck, add_slides, update_slide, wait_for_feedback). The lone deviation is authoring_guide, which is a noun phrase rather than an action, but the overall convention is predictable.

    Tool Count4/5

    18 tools is slightly above the ideal 3-15 range, but the server's domain is genuinely broad: deck lifecycle, slide editing, git diff import, viewer control, and feedback handling. Each tool earns its place, though a few could conceivably be consolidated.

    Completeness5/5

    The surface covers full CRUD for decks and slides, list/open/export operations, git change inspection and skeleton deck generation, plus a complete feedback loop (wait, get, resolve, reply). No obvious dead ends exist for the stated purpose of building and refining code-explanation decks.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      C
      maintenance
      Enables AI agents to present interactive code walkthroughs with voice narration, opening files, highlighting code, and showing inline explanations with synchronized text-to-speech.
      5
      20 npm
      MIT
    • F
      license
      Not graded
      quality
      D
      maintenance
      Turn your AI coding agent into a producer of interactive, narrated walkthroughs — code, whiteboard, and 3D casts, each a single self-contained HTML file that opens in any browser. Runs locally over npx.
      1
      -
    • A
      license
      A
      quality
      C
      maintenance
      Enables LLMs to create animated, narrated tours of GitHub pull requests, with a local browser viewer showing diffs and code highlights while speaking the narration aloud.
      7
      MIT