Skip to main content
Glama

CodeTour

Animated, LLM-driven guided tours of code, pitched at a developer new to the codebase.

CodeTour is an MCP server paired with a local browser viewer. Claude (or any MCP-driving LLM) calls CodeTour's tools step by step; the viewer animates through the code — file tree, diffs or source excerpts, pulsing line highlights — while the narration is shown as captions and spoken aloud via the browser's built-in text-to-speech. The subject can be a pull request, an area of existing code, or local git work; where there is a GitHub page behind it, every stop links back to it.

How it works

Claude ──(MCP stdio)──▶ codetour ──(WebSocket)──▶ your browser
                          │                        (or a headless one, recorded to .mp4)
                          └──(REST)──▶ GitHub API
  1. The LLM calls get_pr_info / get_file_diff to read the PR through CodeTour, so its narration matches exactly what is displayed. (For a codebase tour it uses its own Read/Grep tools to decide what to show, and CodeTour reads the files from disk.)

  2. start_tour opens the viewer in your browser and waits for you to click Start (the click also enables audio).

  3. show_overview and a series of show_step calls animate through the changes. Each call blocks until the narration finishes speaking, so the tour paces itself naturally.

  4. end_tour shows a closing summary, with a link back to GitHub where the tour has one.

Related MCP server: Code Review MCP Server

Four ways to start a tour

A tour does not have to be about a change. Whatever the subject, the viewer, narration and controls are the same.

Subject

Tool

Example ask

A GitHub pull request

start_tour(pr_url)

"tour PR 1234"

An area of existing code

start_code_tour(title, root)

"walk me through how auth works"

Local git work

start_diff_tour(root, commit/base/head)

"tour my uncommitted changes"

A repo you have not cloned

start_code_tour(title, repo, ref)

"explain owner/name's parser"

Stops come in two flavours and can be mixed in one tour: show_step for a diff hunk and show_code for an excerpt of existing source (real file line numbers, no diff markers). That means a PR tour started with root= can also show the unchanged caller of new code.

Source files are only ever read from inside the tour's root — paths that resolve outside it are refused.

Video mode

Any tour can be recorded to an .mp4 instead of played live — handy for attaching to a pull request. Pass video="/absolute/path.mp4" to any start_* tool (the skill does this for "record a video of this PR" or /codetour --video). Nothing opens on screen: a headless Chromium renders the viewer, each stop's narration is synthesised with macOS say, and end_tour muxes the two with ffmpeg and returns the file's path and size.

uv sync --extra video               # Playwright
uv run playwright install chromium  # the headless browser (~150 MB, once)
brew install ffmpeg

Try it without an MCP client: uv run codetour --demo code --video ~/Desktop/demo.mp4.

A three-minute tour at the default 1280×720 and CRF 26 comes out at a few megabytes, well under GitHub's 10 MB attachment cap for free plans (100 MB on paid plans). GitHub has no upload API for PR attachments, so the last step is a drag into the PR description or a comment. Recording is macOS-only for now (say); the narration engine is a small interface in tts.py if you want to add another.

Installation

Requires Python 3.11+ and uv.

git clone <this repo> && cd CodeTour
uv sync

Register with Claude Code at user scope, so the tools are available in every repo:

claude mcp add --scope user codetour -- uv --directory /path/to/CodeTour run codetour

Then just ask:

Give me an executive tour of https://github.com/owner/repo/pull/123

The codetour skill

The repo ships a Claude Code skill (skills/codetour/SKILL.md) that teaches Claude the craft of a good tour: choosing the right entry point, auto-detecting the current branch's PR via gh, planning 3–7 stops before opening the viewer, junior-developer-level narration style (references/narration.md), how to route a codebase tour (references/code-tours.md), and how to recover when the viewer is closed. Install it by linking (or copying) it into your personal skills directory:

ln -s /path/to/CodeTour/skills/codetour ~/.claude/skills/codetour

With the skill installed, a plain "tour this PR" in any repo does the right thing. Restart your Claude Code session after installing the MCP server or the skill.

GitHub authentication

Public PRs work unauthenticated (low rate limit). For private repos or a higher limit, CodeTour uses the first of: GITHUB_TOKEN, GH_TOKEN, or the gh CLI's stored token (gh auth login).

Configuration

Env var

Default

Meaning

CODETOUR_PORT

8765

Viewer port (probes upward if busy)

CODETOUR_NO_BROWSER

unset

Set to 1 to never auto-open the browser

CODETOUR_MAX_FILES

300

Max changed files fetched per PR

CODETOUR_MAX_PATCH_BYTES

100000

Per-file diff cap before truncation

CODETOUR_MAX_EXCERPT_LINES

400

Longest source excerpt shown in one stop

CODETOUR_EXCERPT_CONTEXT

6

Default lines shown either side of a highlight

CODETOUR_MAX_SOURCE_BYTES

2000000

Largest source file CodeTour will read

CODETOUR_ROOT

unset

If set, tour roots are restricted to this directory

CODETOUR_VOICE

Daniel

say voice used when recording (say -v '?' lists them)

CODETOUR_VIDEO_SIZE

1280x720

Recording resolution

CODETOUR_VIDEO_CRF

26

H.264 quality for recordings; higher is smaller

Viewer controls

The tour plays itself as the LLM narrates, but the viewer can take over at any point:

Control

Action

⏸ / ▶, or space

Pause or resume, mid-sentence

‹ / ›, or ← / →

Previous / next stop, at your own pace

Progress dots

Jump straight to a stop

↻

Replay the whole tour from the beginning

Voice menu

Choose the narration voice (remembered next time)

🔊

Mute or unmute the narration

Navigating is local to the browser: it re-narrates the stop you land on and never disturbs the LLM. If you browse backwards or pause while the LLM is still adding stops, the view stays where you are and new stops simply extend the dots — the viewer keeps acknowledging them so the LLM is never left waiting. Step forward to the newest stop and the viewer follows along live again.

Development

uv run pytest                 # unit tests, including the frontend harness
uv run ruff check .           # lint
uv run codetour --demo       # web viewer only, plays a canned pull request tour once
uv run codetour --demo code  # a tour of CodeTour's own source, via the real read path
uv run codetour --demo code --video /tmp/demo.mp4  # record it instead (video extras needed)

tests/frontend/dom_harness.mjs runs app.js under Node against a stub DOM to test the viewer's navigation state machine without a browser (needs node; no npm packages). Run it directly for a readable pass/fail list:

node tests/frontend/dom_harness.mjs

Demo mode is the quickest way to iterate on the frontend: it needs no MCP client and no GitHub access — open the printed URL, click Start, and watch the canned tour.

MCP tools

Tool

Purpose

get_pr_info(pr_url)

PR metadata + per-file hunk line ranges (call first)

get_file_diff(pr_url, path)

Full parsed diff for one file

start_tour(pr_url, tour_title?, root?, video?)

Tour a pull request

start_code_tour(title, root/repo, ref?, files?, video?)

Tour existing source, local or on GitHub

start_diff_tour(root, commit/base/head?, video?)

Tour a local commit, branch range or working tree

show_overview(narration, key_points?)

Overview card, spoken

show_step(file, narration, line_start?, line_end?, side?, style?)

Animated stop on a diff hunk

show_code(file, narration, line_start?, line_end?, context?, style?)

Animated stop on a source excerpt

end_tour(summary)

Closing card, with a GitHub link where there is one; in video mode, renders and returns the .mp4

tour_status()

Diagnostics

Available Tools

7 tools
end_tourA

Finish the tour: shows a closing summary card with a 'View on GitHub' button and speaks the summary. Blocks until spoken.

Inputs: summary (required).

get_file_diffA

Return the full parsed diff for one changed file in the PR: every hunk with every line (kind add/del/ctx, old/new line numbers, text). Use this to read the actual code changes so your show_step narration is accurate.

Inputs: path (required), pr_url (required).

get_pr_infoA

Fetch a GitHub pull request's metadata and a compact summary of every changed file. Call this FIRST, before start_tour, so your narration matches what will be displayed.

Each file includes its diff hunk ranges: {old_start, old_end, new_start, new_end}. Those are the line numbers you pass to show_step (side="new" uses new_start/new_end). Use get_file_diff to read the actual changed lines of a specific file.

Inputs: pr_url (required).

show_overviewA

Show the PR overview card (title, author, +/- stats, file count) with your narration as a spoken caption, plus optional short bullet key_points. Blocks until the narration finishes speaking. Keep narration to 1-3 short, plain-language sentences.

Inputs: narration (required), key_points.

show_stepA

Show one tour step: selects file in the file tree, animates its diff into view, scrolls to line_start..line_end (line numbers on the side version, as returned by get_pr_info/get_file_diff), and pulses a highlight ("highlight") or dims everything else ("spotlight"). The narration appears as a caption and is spoken aloud; the call BLOCKS until speech completes, so call show_step sequentially to pace the tour. Omit line_start/line_end to frame the whole file. Out-of-range lines are snapped to the nearest hunk and reported in warnings.

Inputs: file (required), narration (required), side, style, +2 more.

start_tourA

Start an animated tour of the pull request. Fetches the PR, opens the viewer in the user's browser, and shows a title/start screen. Blocks up to ~30s waiting for the viewer to connect and the user to click Start (which also enables audio). Replaces any previous tour. Call get_pr_info first so you can plan your steps.

Inputs: pr_url (required), tour_title.

tour_statusA

Diagnostics: whether a tour is active, whether a browser viewer is connected, audio state, steps shown, and the viewer URL. Use this if a call timed out or you suspect the viewer window was closed.

Inputs: no named parameters.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A4.2/5.0

    Scored across 7 tools

    Disambiguation5/5

    Each tool has a distinctly different role: fetching PR metadata, fetching file diffs, starting the tour, showing overview/step/end screens, and checking diagnostics. No two tools overlap in purpose, making selection unambiguous.

    Naming Consistency4/5

    Most tools follow a clear verb_noun pattern (get_pr_info, get_file_diff, start_tour, show_overview, show_step, end_tour). 'tour_status' is the one outlier, reading as a noun phrase rather than a verb-driven action.

    Tool Count5/5

    Seven tools is well-scoped for a PR tour workflow: two for data retrieval, four for tour progression, and one for diagnostics. Each tool serves a necessary function without redundancy.

    Completeness5/5

    The tool surface covers the full tour lifecycle: retrieving PR context, reading diffs, starting the tour, showing overview and steps, ending cleanly, and diagnosing state. No obvious dead ends or missing operations for the stated purpose.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers