fastmcp/AGENTS.md
Jeremiah Lowin 07d89c4038
Add transform system for modifying components in provider chains (#2836)
* Consolidate tool transformation logic into TransformingProvider

Tool transformations were previously scattered across LocalProvider,
ProxyProvider, and MCPConfig. This consolidates all transformation
logic into TransformingProvider via with_transforms(tool_transforms={...}).

- Add tool_transforms parameter to TransformingProvider
- Add tool_transforms to Provider.with_transforms()
- Remove transformation storage from LocalProvider and ProxyProvider
- Remove add_tool_transformation() and remove_tool_transformation() from FastMCP
- Add tool_transforms parameter to factory methods (from_openapi, from_fastapi, create_proxy)
- Update tests to use new patterns

* Fix: reject tool lookups by pre-transform name

* Add collision validation for tool_transforms and fix docstring examples

- Validate duplicate target names in tool_transforms raise ValueError
- Fix docstring examples to use arguments/ArgTransformConfig (not args/ArgTransform)
- Add test for collision validation

* Add server-level tool transform APIs and fix task registration

- Add AggregateProvider to present multiple providers as one
- Add _get_root_provider() to apply server-level transforms uniformly
- Fix _docket_lifespan to use root provider (ensures renamed tools
  register with correct keys for background execution)
- Add tool_transforms kwarg to __init__ (non-deprecated)
- Add add_tool_transform(), remove_tool_transform(), tool_transforms property
- Deprecate old API names (tool_transformations, add_tool_transformation, etc.)
- Update tests to use new API

* Add graceful degradation for provider errors in AggregateProvider

* Match original behavior: parallel queries with DEBUG logging

* Refactor transforms to middleware-style call_next pattern

Replaces the ad-hoc transformation system with a unified Transform
abstraction using the same call_next pattern as server middleware.

Key changes:
- New src/fastmcp/server/transforms/ module with Transform base class
- Namespace, ToolTransform, Visibility all implement the same interface
- Transforms compose via functools.partial chain building
- Visibility is now just the first transform in provider._transforms
- Server-level transforms apply after provider aggregation
- Task registration now applies full transform chain

Removes TransformingProvider, _BoundTransform, ComponentSource protocol.
User-facing API unchanged: mount(), add_transform(), enable/disable all
work as before.

* Add comprehensive transforms and visibility documentation

New docs/servers/providers/transforms.mdx covering:
- Mental model for middleware-style transform pattern
- Built-in transforms (Namespace, ToolTransform)
- Server vs provider-level transforms and ordering
- Tool modification (immediate vs deferred)
- Custom transform creation

New docs/servers/visibility.mdx covering:
- Enable/disable API for runtime visibility control
- Keys and tags for targeting components
- Allowlist mode with only=True
- Server vs provider visibility layering

Updates existing docs to reference new pages and simplifies
redundant content. Visibility is documented as a user feature,
not as an implementation detail.

* Restructure transforms docs and delete tool-transformation pattern

* Cleanup: simplify get_tasks and remove unused Provider.get_component

* Update loq

* Update loq limits and add loq note to AGENTS.md

* Deprecate add_tool_transformation and tool_transformations param

* Address PR review feedback: remove redundant imports, fix path reference

* Add missing imports to code examples in v3-features.mdx
2026-01-12 22:11:16 -05:00

5.1 KiB

FastMCP Development Guidelines

Audience: LLM-driven engineering agents and human developers

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 prek run --all-files          # Ruff + Prettier + ty
uv run pytest -n auto                # Run full test suite

All three must pass - this is enforced by CI. Alternative: just build && just typecheck && just test

Tests must pass and lint/typing must be clean before committing.

Before creating a PR, evaluate whether documentation needs updating:

  • New features or APIs require corresponding docs
  • Changed behavior should be reflected in existing docs
  • Check docs/ for affected pages

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

Development Rules

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.

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)

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 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
  • Never modify docs/python-sdk/** (auto-generated)
  • Core Principle: A feature doesn't exist unless it is documented!

Documentation Guidelines

  • Code Examples: Explain before showing code, make blocks fully runnable (include imports)
  • 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

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