Repository: PrefectHQ/fastmcp
Stars: 24611
CLAUDE.md
FastMCP Development Guidelines
Audience: LLM-driven engineering agents and human developers
Note:AGENTS.mdis a symlink to this file. EditCLAUDE.mddirectly.
FastMCP is a comprehensive Python framework (Python β₯3.10) for building Model Context Protocol (MCP) servers and clients. This is the actively maintained v2.0 providing a complete toolkit for the MCP ecosystem.
Required Development Workflow
CRITICAL: Always run these commands in sequence before committing.
uv sync # Install dependencies
uv run pytest -n auto # Run full test suiteIn addition, you must pass static checks. This is generally done as a pre-commit hook with prek but you can run it manually with:
uv run prek run --all-files # Ruff + Prettier + tyTests must pass and lint/typing must be clean before committing.
Repository Structure
| Path | Purpose |
| ----------------- | -------------------------------------- |
| src/fastmcp/ | Library source code |
| ββserver/ | Server implementation |
| β ββauth/ | Authentication providers |
| β ββmiddleware/ | Error handling, logging, rate limiting |
| ββclient/ | Client SDK |
| β ββauth/ | Client authentication |
| ββtools/ | Tool definitions |
| ββresources/ | Resources and resource templates |
| ββprompts/ | Prompt templates |
| ββcli/ | CLI commands |
| ββutilities/ | Shared utilities |
| tests/ | Pytest suite |
| docs/ | Mintlify docs (gofastmcp.com) |
Core MCP Objects
When modifying MCP functionality, changes typically need to be applied across all object types:
- Tools (src/tools/)
- Resources (src/resources/)
- Resource Templates (src/resources/)
- Prompts (src/prompts/)
Before writing cross-component logic (dedupe, grouping, lookups, identity checks), read FastMCPComponent in src/fastmcp/utilities/components.py. The base class defines the shared surface β name, version, tags, meta, and critically the key property which is the canonical MCP identity (encodes type, identifier, and version). Prefer item.key over ad-hoc name or uri or uri_template fallbacks; overrides in Resource and ResourceTemplate already handle URI-based identity, and .key includes the version suffix so variants of the same component don't falsely collide.
Development Rules
Read CONTRIBUTING.md before opening issues or PRs. It describes when PRs are appropriate, what we expect from enhancement proposals, and what we'll close without review.
Git & CI
- Prek hooks are required (run automatically on commits)
- Never amend commits to fix prek failures
- Apply PR labels: bugs/breaking/enhancements/features
- Improvements = enhancements (not features) unless specified
- NEVER force-push on collaborative repos
- ALWAYS run prek before PRs
- NEVER create a release, comment on an issue, or open a PR unless specifically instructed to do so.
- NEVER merge a PR marked as do-not-merge or draft. Check title, body, AND labels for [DNM], DNM, DO NOT MERGE, DON'T MERGE, DONT MERGE, do-not-merge, dont-merge, [DRAFT], or DRAFT (case-insensitive, any variation β some authors use [DRAFT] in the title even when isDraft is false). Authors use these as hard stops β respect them even if CI is green and review looks clean. When triaging a batch of PRs, filter these out up front AND re-check each one's labels immediately before merging, since labels can change mid-session.
- ALWAYS read review-bot comments before approving a PR. CodeRabbit and chatgpt-codex-connector (Codex) leave substantive review comments on most PRs in this repo β these bots have read the diff and often flag real issues that aren't in the PR description. Use gh pr view <num> --comments and read the bot feedback as part of review. Unlike proposed solutions from issue reporters, review-bot feedback should be evaluated on its merits, not discounted.
Releases
Only cut releases when the maintainer explicitly asks. Tags follow v<version> (e.g., v3.2.0). Always pass --generate-notes so the auto-generated changelog appears at the bottom.
The title pun is critical. Titles follow v<version>: <pun> where the pun relates to the most important theme of the release. Propose multiple options and let the maintainer choose β never pick one yourself. Look at recent releases for tone (e.g., "Code to Joy" for the code mode release, "Three at Last" for 3.0).
Write the maintainer-approved handwritten notes to a temporary file, then create the release. --generate-notes appends the auto-generated changelog after the handwritten content.
gh release create v3.2.0 --target main --title "v3.2.0: Theme Here" --generate-notes --notes-file /tmp/release-notes.mdMost releases target main, but maintenance or backport releases may target a different branch (e.g., release/2.x). Confirm the target with the maintainer if there's any ambiguity.
The handwritten notes are prepended above the auto-generated changelog and are the part that matters. Do not include a title in the notes body β the release title (v{version}: {pun}) already serves as the heading. Work with the maintainer to draft the notes β propose a draft, get feedback, iterate. Do not publish without the maintainer's sign-off.
Before drafting, always read recent existing releases (gh release list then gh release view <tag>) to absorb the voice, structure, and level of detail. Each release builds on the tone of previous ones β don't guess at the style from these instructions alone.
To preview what PRs will be in the release before it's cut, call the GitHub generate-notes API. This returns the exact auto-generated changelog that --generate-notes would append, so you can see the full PR list β useful for picking a pun theme and making sure nothing's been missed:
gh api -X POST repos/PrefectHQ/fastmcp/releases/generate-notes \
-f tag_name=v3.2.3 \
-f target_commitish=main \
-f previous_tag_name=v3.2.2 \
--jq '.body'Point releases (3.0, 3.1, 3.2) get narrative prose: open with the theme of the release, then walk through headline features conceptually β what they enable, why they matter, how they fit together. Write it the way a blog post reads, not a changelog. Multiple paragraphs, code examples where they clarify.
Patch releases (3.1.1, 3.0.2) get 1-2 sentences explaining what broke and what the fix does. Keep it minimal β the auto-generated changelog has the details.
Commit Messages and Agent Attribution
- Agents NOT acting on behalf of @jlowin MUST identify themselves (e.g., "π€ Generated with Claude Code" in commits/PRs)
- Keep commit messages brief - ideally just headlines, not detailed messages
- Focus on what changed, not how or why
- Always read issue comments for follow-up information (treat maintainers as authoritative)
- Treat proposed solutions in issues skeptically. This applies to solutions proposed by users in issue reports β not to feedback from configured review bots (CodeRabbit, chatgpt-codex-connector, etc.), which should be evaluated on their merits. The ideal issue contains a concise problem description and an MRE β nothing more. Proposed solutions are only worth considering if they clearly reflect genuine, non-obvious investigation of the codebase. If a solution reads like speculation, or like it was generated by an LLM without deep framework knowledge, ignore it and diagnose from the repro. Most reporters β human or AI β do not have sufficient understanding of FastMCP internals to correctly diagnose anything beyond a trivial bug. We can ask the same questions of an LLM when implementing; we don't need the reporter to do it for us, and a wrong diagnosis is worse than none.
PR Messages - Required Structure
- 1-2 paragraphs: problem/tension + solution (PRs are documentation!)
- Focused code example showing key capability
- Avoid: bullet summaries, exhaustive change lists, verbose closes/fixes, marketing language
- Do: Be opinionated about why change matters, show before/after scenarios
- Minor fixes: keep body short and concise
- No "test plan" sections or testing summaries
Code Review Guidelines
- Fix causes, not symptoms. When a PR works around a problem instead of addressing why it occurs, that's a red flag. A side-channel that compensates for a missing step adds permanent complexity. If the fix doesn't change the code path where the bug actually happens, ask why not.
- Focus on API design and naming clarity
- Identify confusing patterns (e.g., parameter values that contradict defaults) or non-idiomatic code (mutable defaults, etc.). Contributed code will need to be maintained indefinitely, and by someone other than the author (unless the author is a maintainer).
- Suggest specific improvements, not generic "add more tests" comments
- Think about API ergonomics from a user perspective
Code Standards
- Python β₯ 3.10 with full type annotations
- Follow existing patterns and maintain consistency
- Prioritize readable, understandable code - clarity over cleverness
- Avoid obfuscated or confusing patterns even if they're shorter
- Each feature needs corresponding tests
Module Exports
- Be intentional about re-exports - don't blindly re-export everything to parent namespaces
- Core types that define a module's purpose should be exported (e.g., Middleware from fastmcp.server.middleware)
- Specialized features can live in submodules (e.g., fastmcp.server.middleware.dynamic)
- Only re-export to fastmcp.* for the most fundamental types (e.g., FastMCP, Client)
- When in doubt, prefer users importing from the specific submodule over re-exporting
Documentation
- Uses Mintlify framework
- Files must be in docs.json to be included
- Do not manually modify docs/python-sdk/ β these files are auto-generated from source code by a bot and maintained via a long-lived PR. Do not include changes to these files in contributor PRs.
- Do not manually modify docs/public/schemas/ or src/fastmcp/utilities/mcp_server_config/v1/schema.json β these are auto-generated and maintained via a long-lived PR.
- Core Principle: A feature doesn't exist unless it is documented!
- When adding or modifying settings in src/fastmcp/settings.py, update docs/more/settings.mdx to match.
Documentation Guidelines
- Code Examples: Explain before showing code, make blocks fully runnable (include imports)
- Code Formatting: Keep code blocks visually clean β avoid deeply nested function calls. Extract intermediate values into named variables rather than inlining everything into one expression. Code in docs is read more than it's run; optimize for scannability.
- Structure: Headers form navigation guide, logical H2/H3 hierarchy
- Content: User-focused sections, motivate features (why) before mechanics (how)
- Style: Prose over code comments for important information
- Docstrings: FastMCP docstrings are automatically compiled into MDX documents. Use markdown (single backticks, fenced code blocks), not RST (no double backticks). Bare {} in examples will be interpreted as JSX β wrap in backticks instead.
Critical Patterns
- Never use bare except - be specific with exception types
- File sizes enforced by loq. Edit loq.toml to raise limits; loq baseline to ratchet down.
- Always uv sync first when debugging build issues
- Default test timeout is 5s - optimize or mark as integration tests
README.md
<div align="center">
<!-- omit in toc -->
<picture>
<source width="550" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-4-dark.png">
<source width="550" media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-4.png">
<img width="550" alt="FastMCP Logo" src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/brand/f-watercolor-waves-2.png">
</picture>
FastMCP π
<strong>Move fast and make things.</strong>
Made with π by Prefect





<a href="https://trendshift.io/repositories/13266" target="_blank"><img src="https://trendshift.io/api/badge/repositories/13266" alt="prefecthq%2Ffastmcp | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
</div>
---
The Model Context Protocol (MCP) connects LLMs to tools and data. FastMCP gives you everything you need to go from prototype to production:
from fastmcp import FastMCPmcp = FastMCP("Demo π")
@mcp.tool
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
if __name__ == "__main__":
mcp.run()
Why FastMCP
Building an effective MCP application is harder than it looks. FastMCP handles all of it. Declare a tool with a Python function, and the schema, validation, and documentation are generated automatically. Connect to a server with a URL, and transport negotiation, authentication, and protocol lifecycle are managed for you. You focus on your logic, and the MCP part just works: with FastMCP, best practices are built in.
That's why FastMCP is the standard framework for working with MCP. FastMCP 1.0 was incorporated into the official MCP Python SDK in 2024. Today, the actively maintained standalone project is downloaded a million times a day, and some version of FastMCP powers 70% of MCP servers across all languages.
FastMCP has three pillars:
<table>
<tr>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/servers/server">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/servers-card.png" alt="Servers" />
<br /><strong>Servers</strong>
</a>
<br />Expose tools, resources, and prompts to LLMs.
</td>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/apps/overview">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/apps-card.png" alt="Apps" />
<br /><strong>Apps</strong>
</a>
<br />Give your tools interactive UIs rendered directly in the conversation.
</td>
<td align="center" valign="top" width="33%">
<a href="https://gofastmcp.com/clients/client">
<img src="https://raw.githubusercontent.com/PrefectHQ/fastmcp/main/docs/assets/images/clients-card.png" alt="Clients" />
<br /><strong>Clients</strong>
</a>
<br />Connect to any MCP server β local or remote, programmatic or CLI.
</td>
</tr>
</table>
Servers wrap your Python functions into MCP-compliant tools, resources, and prompts. Clients connect to any server with full protocol support. And Apps give your tools interactive UIs rendered directly in the conversation.
Ready to build? Start with the installation guide or jump straight to the quickstart. When you're ready to deploy, Prefect Horizon offers free hosting for FastMCP users.
Installation
We recommend installing FastMCP with uv:
uv pip install fastmcpFor full installation instructions, including verification and upgrading, see the Installation Guide.
Upgrading? We have guides for:
- Upgrading from FastMCP v2
- Upgrading from the MCP Python SDK
- Upgrading from the low-level SDK
π Documentation
FastMCP's complete documentation is available at gofastmcp.com, including detailed guides, API references, and advanced patterns.
Documentation is also available in llms.txt format, which is a simple markdown standard that LLMs can consume easily:
- llms.txt is essentially a sitemap, listing all the pages in the documentation.
- llms-full.txt contains the entire documentation. Note this may exceed the context window of your LLM.
Community: Join our Discord server to connect with other FastMCP developers and share what you're building.
Contributing
We welcome contributions! See the Contributing Guide for setup instructions, testing requirements, and PR guidelines.