Fastmcp
Tommy-yw/RunbookHermes
Build, test, inspect, install, and deploy MCP servers with FastMCP in Python.
Build MCP servers in Python with FastMCP. An agent skill from jezweb/claude-skills.
$ npx skills add jezweb/claude-skills --skill mcp-builder -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install jezweb/claude-skills mcp-builder --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .claude/skills/mcp-builder && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .claude/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builderType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add jezweb/claude-skills --skill mcp-builder -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install jezweb/claude-skills mcp-builder --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .agents/skills/mcp-builder && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .agents/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jezweb/claude-skills --skill mcp-builder -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install jezweb/claude-skills mcp-builder --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .cursor/skills/mcp-builder && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .cursor/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/jezweb/claude-skills.git --path plugins/integrations/skills/mcp-builder--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add jezweb/claude-skills --skill mcp-builder -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install jezweb/claude-skills mcp-builder --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .gemini/skills/mcp-builder && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .gemini/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install jezweb/claude-skills mcp-builderInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add jezweb/claude-skills --skill mcp-builder -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .github/skills/mcp-builder && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .github/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jezweb/claude-skills --skill mcp-builder -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install jezweb/claude-skills mcp-builder --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jezweb/claude-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/integrations/skills/mcp-builder .opencode/skills/mcp-builder && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "mcp-builder" agent skill from https://github.com/jezweb/claude-skills/tree/main/plugins/integrations/skills/mcp-builder into .opencode/skills/mcp-builder/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "mcp-builder", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
mcp-builderBuild MCP servers in Python with FastMCP. An agent skill from jezweb/claude-skills.
MCP Builder is an agent skill from jezweb/claude-skills. Build MCP servers in Python with FastMCP. Define tools / resources / prompts, build the server, test locally, deploy to FastMCP Cloud or Docker. Use whenever the user mentions building an MCP server, exposing tools to LLMs, FastMCP, building a Claude integration, or troubleshooting FastMCP module-level server, storage, lifespan, middleware, OAuth, or deployment errors.
Its SKILL.md is about 3.1k tokens, which your agent loads only when the skill is triggered. The skill folder holds 16 other files, including reference files and assets (for example `assets/SCRIPTS-TEMPLATE.md`, `assets/api-client-pattern.py` and `assets/basic-server.py`). Compatibility notes: claude-code-only
It sits in Agent Workflows, covering MCP servers and Deployment. It works with Model Context Protocol, Python and Docker. The repository describes itself as: Skills for Claude Code CLI such as full stack dev Cloudflare, React, Tailwind v4, and AI integrations. The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 64965d9. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships script files (Python and TypeScript), which the agent can run.
Shell commands in SKILL.md call:
gitpippythonpython3From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git and pip, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
API_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
claude-code-only
From compatibility in the SKILL.md frontmatter.
MCP Builder loads about 3.1k tokens when it runs, and up to ~5.9k if it reads all its reference files. Until then it costs about 96 tokens; SKILL.md has 659 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
7. `.gitignore` includes `.env`Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from jezweb/claude-skills at commit 64965d9, republished under its MIT licence (© jezweb). 659 words, ~3,088 tokens.
.claude/skills/mcp-builder/SKILL.md (or your agent's skills folder). This skill also uses 14 other files; get the full folder from GitHub.Build a working MCP server from a description of the tools you need. Produces a deployable Python server using FastMCP.
Ask what the server needs to provide:
A brief like "MCP server for querying our customer database" is enough.
pip install fastmcpCreate the server file. The server instance MUST be at module level:
from fastmcp import FastMCP
# MUST be at module level for FastMCP Cloud
mcp = FastMCP("My Server")
@mcp.tool()
async def search_customers(query: str) -> str:
"""Search customers by name or email."""
# Implementation here
return f"Found customers matching: {query}"
@mcp.resource("customers://{customer_id}")
async def get_customer(customer_id: str) -> str:
"""Get customer details by ID."""
return f"Customer {customer_id} details"
if __name__ == "__main__":
mcp.run()For Claude Code terminal use, add scripts alongside the MCP server:
my-mcp-server/
├── src/index.ts # MCP server (for Claude.ai)
├── scripts/
│ ├── search.ts # CLI version of search tool
│ └── _shared.ts # Shared auth/config
├── SCRIPTS.md # Documents available scripts
└── package.jsonCLI scripts provide file I/O, batch processing, and richer output that MCP can't.
See assets/SCRIPTS-TEMPLATE.md and assets/script-template.ts for TypeScript templates.
Quick test -- run directly:
python server.pyDev mode with inspector UI (recommended):
fastmcp dev server.py
# Opens inspector at http://localhost:5173
# Hot reload, detailed logging, tool/resource inspectionHTTP mode for remote clients:
python server.py --transport http --port 8000Automated test script using FastMCP Client:
import asyncio
from fastmcp import Client
async def test_server(server_path):
async with Client(server_path) as client:
# List everything
tools = await client.list_tools()
resources = await client.list_resources()
prompts = await client.list_prompts()
print(f"Tools: {[t.name for t in tools]}")
print(f"Resources: {[r.uri for r in resources]}")
print(f"Prompts: {[p.name for p in prompts]}")
# Call first tool
if tools:
result = await client.call_tool(tools[0].name, {})
print(f"Tool result: {result}")
# Read first resource
if resources:
data = await client.read_resource(resources[0].uri)
print(f"Resource data: {data}")
asyncio.run(test_server("server.py"))Run these checks before deploying. All required checks must pass.
Required (will cause deploy failure):
python3 -m py_compile server.pygrep -q "^mcp = FastMCP\|^server = FastMCP\|^app = FastMCP" server.pyrequirements.txt exists with PyPI packages only (no git+, -e, .whl, .tar.gz)api_key = "..." patterns excluding os.getenv/os.environ)Advisory (warnings):
fastmcp listed in requirements.txt.gitignore includes .envtimeout 5 fastmcp inspect server.pyFastMCP Cloud (simplest):
git add . && git commit -m "Ready for deployment"
git push -u origin main
# Visit https://fastmcp.cloud, connect repo, add env vars, deploy
# URL: https://your-project.fastmcp.app/mcpCloud requirements:
mcp, server, or apprequirements.txtDocker (self-hosted):
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "server.py", "--transport", "http", "--port", "8000"]Cloudflare Workers (edge):
Build it in TypeScript with Cloudflare's agents SDK (McpAgent); Cloudflare's remote MCP server docs carry the current template.
FastMCP Cloud requires the server instance at module level:
# CORRECT
mcp = FastMCP("My Server")
@mcp.tool()
def my_tool(): ...
# WRONG -- Cloud can't find the server
def create_server():
mcp = FastMCP("My Server")
return mcp
# FIX for factory pattern -- export at module level
def create_server() -> FastMCP:
mcp = FastMCP("server")
return mcp
mcp = create_server()FastMCP uses type annotations to generate tool schemas:
@mcp.tool()
async def search(
query: str, # Required parameter
limit: int = 10, # Optional with default
tags: list[str] = [] # Complex types supported
) -> str:
"""Docstring becomes the tool description."""
...Return errors as strings, don't raise exceptions:
@mcp.tool()
async def get_data(id: str) -> str:
try:
result = await fetch_data(id)
return json.dumps(result)
except NotFoundError:
return f"Error: No data found for ID {id}"import os
from fastmcp import FastMCP
mcp = FastMCP("production-server")
API_KEY = os.getenv("API_KEY")
@mcp.tool()
async def production_tool(data: str) -> dict:
if not API_KEY:
return {"error": "API_KEY not configured"}
return {"status": "success", "data": data}
if __name__ == "__main__":
mcp.run()These are the errors you will hit. Fix them before deploying.
| Error | Cause | Fix |
|---|---|---|
RuntimeError: No server object found at module level | Server inside a function | Export mcp = FastMCP(...) at module level |
RuntimeError: no running event loop | Missing async/await | Use async def for async operations |
TypeError: missing required argument 'context' | Context not type-hinted | Add context: Context with type hint |
ValueError: Invalid resource URI | Missing URI scheme | Use data://, file://, info://, api:// |
| Resource template parameter mismatch | Name mismatch | user://{user_id} needs def get_user(user_id: str) |
| Pydantic validation error | Wrong type hints | Ensure hints match actual data types |
| Transport mismatch | Client/server protocol differ | Match both to stdio or both to http |
| Import errors with editable package | Package not installed | pip install -e . or add to PYTHONPATH |
DeprecationWarning: mcp.settings | Old API | Use os.getenv() instead |
| Port already in use | Stale process | lsof -ti:8000 | xargs kill -9 |
| Schema generation failure | Non-JSON types | Use JSON-compatible types (no NumPy arrays) |
| JSON serialization error | datetime/bytes in response | Convert to .isoformat() or string |
| Circular import | Factory in __init__.py | Use direct imports, avoid factory pattern |
| Python 3.12+ datetime warning | datetime.utcnow() deprecated | Use datetime.now(timezone.utc) |
| Import-time execution | Async resource at module level | Use lazy init pattern |
Keep all utilities in one file to avoid circular imports:
from fastmcp import FastMCP
import os
mcp = FastMCP("my-server")
# Config
class Config:
API_KEY = os.getenv("API_KEY", "")
BASE_URL = os.getenv("BASE_URL", "https://api.example.com")
# Helpers
def format_success(data): return {"status": "success", "data": data}
def format_error(msg): return {"status": "error", "message": msg}
@mcp.tool()
async def my_tool(query: str) -> dict:
if not Config.API_KEY:
return format_error("API_KEY not configured")
return format_success({"query": query})Don't create async resources at module level. Initialise on first use:
_db = None
async def get_db():
global _db
if _db is None:
_db = await create_connection(Config.DB_URL)
return _db@mcp.resource("health://status")
async def health_check() -> dict:
return {
"status": "healthy",
"version": "1.0.0",
"checks": {
"api": "connected",
"database": "connected"
}
}import httpx
_client = None
def get_client() -> httpx.AsyncClient:
global _client
if _client is None:
_client = httpx.AsyncClient(
base_url=Config.BASE_URL,
headers={"Authorization": f"Bearer {Config.API_KEY}"},
limits=httpx.Limits(max_connections=20, max_keepalive_connections=5),
timeout=30.0
)
return _clientasync def retry_with_backoff(func, max_retries=3, initial_delay=1.0):
for attempt in range(max_retries):
try:
return await func()
except Exception as e:
if attempt == max_retries - 1:
raise
delay = initial_delay * (2 ** attempt)
await asyncio.sleep(delay)from fastmcp import Context
@mcp.tool()
async def tool_with_context(param: str, context: Context) -> dict:
# Context parameter MUST have type hint
pass@mcp.tool()
async def long_task(items: list[str], context: Context) -> str:
for i, item in enumerate(items):
await context.report_progress(i + 1, len(items), f"Processing {item}")
await process(item)
return "Done"@mcp.tool()
async def summarise(text: str, context: Context) -> str:
result = await context.request_sampling(
messages=[{"role": "user", "content": f"Summarise: {text}"}],
max_tokens=200
)
return resultfastmcp dev server.py # Dev mode with inspector UI
fastmcp run server.py # Run (stdio)
fastmcp run server.py --transport http --port 8000 # Run (HTTP)
fastmcp inspect server.py # Inspect without running
fastmcp install server.py # Install to Claude Desktop
fastmcp deploy server.py --name my-server # Deploy to CloudEnvironment variables: FASTMCP_LOG_LEVEL (DEBUG/INFO/WARNING/ERROR), FASTMCP_ENV (development/staging/production).
For specific integration approaches, see references/integration-patterns.md:
httpx.AsyncClient with reusable clientFastMCP.from_openapi(spec, client, route_maps=[...])FastMCP.from_fastapi(app)assets/basic-server.py -- Minimal FastMCP server templateassets/self-contained-server.py -- Server with storage and middlewareassets/tools-examples.py -- Tool patterns and type annotationsassets/resources-examples.py -- Resource URI patternsassets/prompts-examples.py -- Prompt template patternsassets/client-example.py -- MCP client usageassets/SCRIPTS-TEMPLATE.md -- CLI companion docs templateassets/script-template.ts -- TypeScript CLI script template© jezweb, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 14 other files (references, assets) in plugins/integrations/skills/mcp-builder of jezweb/claude-skills.
Open the folder on GitHubat commit 64965d9
MCP Builder next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| MCP Builder this skilljezweb/claude-skills | 1.1k | — | ~3.1k | Automated safety check: Notes | MIT | |
| FastmcpTommy-yw/RunbookHermes | 546 | 4 repos | ~2.1k | Automated safety check: Pass | MIT | |
| Building MCP Serversaiskillstore/marketplace | 430 | — | ~1.4k | Automated safety check: Pass | None | |
| Unraiddinglebear-ai/unraid | 135 | — | ~5.4k | Automated safety check: Notes | MIT | |
| Task Orchestrator Server Setupjpicklyk/task-orchestrator | 207 | — | ~3.1k | Automated safety check: Pass | MIT | |
| AWS Cdk Developmentzxkane/aws-skills | 367 | 2 repos | ~2.5k | Automated safety check: Pass | MIT |
Tommy-yw/RunbookHermes
Build, test, inspect, install, and deploy MCP servers with FastMCP in Python.
aiskillstore/marketplace
Guides creation of high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools.
dinglebear-ai/unraid
This skill should be used when the user mentions Unraid, asks to check server health, monitor array or disk status, list or restart Docker containers, start or stop VMs, read system logs, check…
jpicklyk/task-orchestrator
Walks through how to launch and reach the MCP Task Orchestrator server container: transport, REST API, port publishing, config mounts and config-sync.
zxkane/aws-skills
AWS Cloud Development Kit (CDK) expert for building cloud infrastructure with TypeScript/Python.
aliyun/alibabacloud-observability-mcp-server
Deploy, start, and update the Alibaba Cloud Observability MCP Server (阿里云可观测 MCP Server).
jezweb/claude-skills
Build conversational AI voice agents on the ElevenLabs platform.
jezweb/claude-skills
Generate custom favicons from logos, text, or brand colours.
jezweb/claude-skills
Set up Tailwind v4 + shadcn/ui themed UI with dark mode. An agent skill from jezweb/claude-skills.
jezweb/claude-skills
All-in-one project configuration and health management. An agent skill from jezweb/claude-skills.
jezweb/claude-skills
Test website responsiveness across viewport widths using browser automation.
jezweb/claude-skills
Compare UX patterns across multiple reference apps using pattern libraries produced by ux-extract.
Works with
Categories
Build MCP servers in Python with FastMCP. An agent skill from jezweb/claude-skills. MCP Builder is an agent skill from jezweb/claude-skills. Build MCP servers in Python with FastMCP.
MCP Builder fits situations like: the user mentions building an MCP server; exposing tools to LLMs; building a Claude integration; troubleshooting FastMCP module-level server.
Run `npx skills add jezweb/claude-skills --skill mcp-builder -a claude-code`. Or copy the skill folder (plugins/integrations/skills/mcp-builder in jezweb/claude-skills) into .claude/skills/mcp-builder in your project. Claude Code loads it when a task matches its description.
Run `npx skills add jezweb/claude-skills --skill mcp-builder -a codex`. Or copy the skill folder (plugins/integrations/skills/mcp-builder in jezweb/claude-skills) into .agents/skills/mcp-builder in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jezweb/claude-skills --skill mcp-builder -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/mcp-builder, .gemini/skills/mcp-builder, .github/skills/mcp-builder and .opencode/skills/mcp-builder in your project.
Going by SKILL.md and its folder, MCP Builder needs Python and TypeScript for the scripts in its folder, the command-line tools its instructions call (git, pip, python and python3) and credentials named API_KEY. Our summary lists: Python 3; Node.js; Docker; A credential in API_KEY. Compatibility (from SKILL.md): claude-code-only.
SKILL.md contains no URLs. Its commands use git and pip, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
MCP Builder is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 3.1k tokens (SKILL.md is roughly 12k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.8k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with MCP Builder: Fastmcp (Tommy-yw/RunbookHermes, 546 stars), Building MCP Servers (aiskillstore/marketplace, 430 stars), Unraid (dinglebear-ai/unraid, 135 stars) and Task Orchestrator Server Setup (jpicklyk/task-orchestrator, 207 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
jezweb (a GitHub user) maintains it in jezweb/claude-skills, which has 1,051 GitHub stars. The repository holds 52 skills in this directory. The repository was last updated on October 5, 2026.
Source: jezweb/claude-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.