mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-29 02:32:09 +02:00
* Add prefab auto-wiring for MCP Apps (#3119) Tools that return prefab types (UIResponse, Component) automatically get wired to the shared prefab renderer resource. Works via app=True, return type inference, or both. * Prefab compatibility updates * Use published prefab-ui >=0.6.0, remove local source override * Migrate UIResponse to PrefabApp for Prefab UI integration PrefabApp is a pure data object with to_json(), html(), and csp() methods. Tools can return PrefabApp, bare Components, or ToolResult with structured_content for custom LLM fallback text. * Add Prefab UI apps documentation * Add mini apps and full apps documentation pages Mini apps covers the common single-screen patterns: charts (bar, line, area, pie), data tables with sorting/search/pagination, forms (manual and Pydantic-generated), status displays, conditional content, and layout composition with tabs and accordions. Full apps covers multi-page applications using Pages/Page components, shared state across pages, and using ToolCall with result_key for server-driven state updates. * Reframe apps docs around motivation, add generative UIs page The docs now lead with the problem — MCP tools stuff data into the LLM context window, and building HTML/JS/CSS frontends is a non-starter for Python developers — before introducing Prefab as the solution. Mini apps are framed as the primary use case: focused, single-purpose UIs that present data visually and collect structured input. New generative UIs page covers the concept of LLMs producing component JSON directly, enabling adaptive dashboards, tailored forms, and exploratory workflows. * Tag Prefab docs pages as SOON instead of NEW * Rename Low-Level API to Custom HTML Apps The page is about using the MCP Apps extension directly, not a FastMCP or Prefab internal API. Reframed to make clear this is the open MCP protocol with FastMCP providing convenience wrappers. * Tighten apps docs and widen content area Strip editorial motivation from all app doc pages — let code examples do the talking. Add content-area max-width override (44rem) to style.css. * Restructure apps docs, fix code issues Rename Prefab UI → Prefab Apps, mini-apps → patterns, remove generative-uis and full-apps pages. Rewrite prefab page to lead with what users do (declare a UI, return it) before explaining internals. Patterns page now has fully self-contained copy-pasteable examples with explicit imports and links to prefab docs. Forms show the two-tool pattern (form + handler). Add patterns_server.py example. Code fixes: move get_args to module-level import, remove dead AuthCheckCallable type alias, fix ToolCall→CallTool in all docs. * Remove unused ToolResult import from chart_server * Handle composite Prefab types in type inference and schema suppression _has_prefab_return_type and the output schema suppression logic only checked bare classes, missing unions (Column | None) and Annotated wrappers (Annotated[PrefabApp | None, ...]). Recurse through Union, types.UnionType, and Annotated to detect Prefab types in composite annotations.
198 lines
5.7 KiB
TOML
198 lines
5.7 KiB
TOML
[project]
|
|
name = "fastmcp"
|
|
dynamic = ["version"]
|
|
description = "The fast, Pythonic way to build MCP servers and clients."
|
|
authors = [{ name = "Jeremiah Lowin" }]
|
|
dependencies = [
|
|
"python-dotenv>=1.1.0",
|
|
"exceptiongroup>=1.2.2",
|
|
"httpx>=0.28.1,<1.0",
|
|
"mcp>=1.24.0,<2.0",
|
|
"openapi-pydantic>=0.5.1",
|
|
"opentelemetry-api>=1.20.0",
|
|
"packaging>=24.0",
|
|
"platformdirs>=4.0.0",
|
|
"rich>=13.9.4",
|
|
"cyclopts>=4.0.0",
|
|
"authlib>=1.6.5",
|
|
"pydantic[email]>=2.11.7",
|
|
"pyyaml>=6.0,<7.0",
|
|
"pyperclip>=1.9.0",
|
|
"py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0",
|
|
"uvicorn>=0.35",
|
|
"websockets>=15.0.1",
|
|
"jsonschema-path>=0.3.4",
|
|
"jsonref>=1.1.0",
|
|
"watchfiles>=1.0.0",
|
|
]
|
|
|
|
requires-python = ">=3.10"
|
|
readme = "README.md"
|
|
license = "Apache-2.0"
|
|
|
|
keywords = [
|
|
"mcp",
|
|
"mcp server",
|
|
"mcp client",
|
|
"model context protocol",
|
|
"fastmcp",
|
|
"llm",
|
|
"agent",
|
|
]
|
|
classifiers = [
|
|
"Intended Audience :: Developers",
|
|
"License :: OSI Approved :: Apache Software License",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
"Programming Language :: Python :: 3.10",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Typing :: Typed",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
anthropic = ["anthropic>=0.40.0"]
|
|
apps = ["prefab-ui>=0.6.0"]
|
|
azure = ["azure-identity>=1.16.0"]
|
|
code-mode = ["pydantic-monty>=0.0.7"]
|
|
openai = ["openai>=1.102.0"]
|
|
tasks = ["pydocket>=0.17.2"]
|
|
|
|
[dependency-groups]
|
|
dev = [
|
|
"dirty-equals>=0.9.0",
|
|
"fastmcp[anthropic,apps,azure,code-mode,openai,tasks]",
|
|
# add optional dependencies for fastmcp dev
|
|
"fastapi>=0.115.12",
|
|
"opentelemetry-sdk>=1.20.0",
|
|
"inline-snapshot[dirty-equals]>=0.27.2",
|
|
"ipython>=8.12.3",
|
|
"pdbpp>=0.11.7",
|
|
"psutil>=7.0.0",
|
|
"pyinstrument>=5.0.2",
|
|
"pyperclip>=1.9.0",
|
|
"pytest>=8.3.3",
|
|
"pytest-asyncio>=1.2.0",
|
|
"pytest-cov>=6.1.1",
|
|
"pytest-env>=1.1.5",
|
|
"pytest-flakefinder>=1.1.0",
|
|
"pytest-httpx>=0.35.0",
|
|
"pytest-report>=0.2.1",
|
|
"pytest-retry>=1.7.0",
|
|
"pytest-timeout>=2.4.0",
|
|
"pytest-xdist>=3.6.1",
|
|
"ruff>=0.12.8",
|
|
"ty>=0.0.15",
|
|
"prek>=0.2.12",
|
|
"loq>=0.1.0a3",
|
|
"opentelemetry-exporter-otlp-proto-grpc>=1.39.0",
|
|
]
|
|
|
|
[project.scripts]
|
|
fastmcp = "fastmcp.cli:app"
|
|
|
|
[project.urls]
|
|
Homepage = "https://gofastmcp.com"
|
|
Repository = "https://github.com/PrefectHQ/fastmcp"
|
|
Documentation = "https://gofastmcp.com"
|
|
|
|
[build-system]
|
|
requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[tool.hatch.version]
|
|
source = "uv-dynamic-versioning"
|
|
|
|
[tool.hatch.metadata]
|
|
allow-direct-references = true
|
|
|
|
|
|
[tool.uv-dynamic-versioning]
|
|
vcs = "git"
|
|
style = "pep440"
|
|
bump = true
|
|
fallback-version = "0.0.0"
|
|
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
asyncio_default_fixture_loop_scope = "function"
|
|
# filterwarnings = ["error::DeprecationWarning"]
|
|
filterwarnings = [
|
|
# Suppress OAuth in-memory token storage warnings in tests
|
|
# Tests intentionally use ephemeral storage; this warning is for end users
|
|
"ignore:Using in-memory token storage:UserWarning",
|
|
# Treat unawaited coroutine warnings as errors - these are almost always bugs
|
|
"error:coroutine .* was never awaited:RuntimeWarning",
|
|
"error:Exception ignored in.*coroutine:pytest.PytestUnraisableExceptionWarning",
|
|
]
|
|
timeout = 5
|
|
env = [
|
|
"FASTMCP_TEST_MODE=1",
|
|
'D:FASTMCP_LOG_LEVEL=DEBUG',
|
|
'D:FASTMCP_ENABLE_RICH_TRACEBACKS=0',
|
|
|
|
]
|
|
markers = [
|
|
"integration: marks tests as integration tests (deselect with '-m \"not integration\"')",
|
|
"client_process: marks tests that spawn client processes via stdio transport. These can create issues when run in the same CI environment as other subprocess-based tests.",
|
|
]
|
|
# Automatically mark all tests in integration_tests folder
|
|
pythonpath = ["."]
|
|
testpaths = ["tests"]
|
|
python_files = ["test_*.py", "*_test.py"]
|
|
python_classes = ["Test*"]
|
|
python_functions = ["test_*"]
|
|
addopts = ["--inline-snapshot=disable"]
|
|
|
|
[tool.ty.src]
|
|
include = ["src", "tests"]
|
|
exclude = ["**/node_modules", "**/__pycache__", ".venv", ".git", "dist"]
|
|
|
|
[tool.ty.environment]
|
|
python-version = "3.10"
|
|
|
|
[tool.ty.rules]
|
|
# NOTE: ty currently doesn't support type narrowing with isinstance() on unions
|
|
# See: https://github.com/astral-sh/ty/issues/122 and https://github.com/astral-sh/ty/issues/1113
|
|
# Some code uses `# ty: ignore[invalid-argument-type]` for this limitation.
|
|
# TODO: Remove these ignores once ty supports union narrowing
|
|
|
|
[tool.ty.terminal]
|
|
error-on-warning = true
|
|
|
|
[tool.ruff.lint]
|
|
fixable = ["ALL"]
|
|
ignore = [
|
|
"COM812",
|
|
"PLR0913", # Too many arguments, MCP Servers have a lot of arguments, OKAY?!
|
|
"SIM102", # Dont require combining if statements
|
|
]
|
|
extend-select = [
|
|
"B", # flake8-bugbear: Catches actual bugs like mutable default arguments
|
|
"C4", # flake8-comprehensions: More efficient/readable comprehensions
|
|
"I", # flake8-builtins: Catches builtins that are not explicitly imported
|
|
"PIE", # flake8-pie: More idiomatic Python code
|
|
"RUF", # Ruff-specific: Modern best practices unique to Ruff
|
|
"SIM", # flake8-simplify: Simplifies verbose code patterns
|
|
"UP", # flake8-unused-imports: Catches unused imports
|
|
]
|
|
|
|
[tool.ruff.lint.isort]
|
|
known-first-party = ["fastmcp"]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"__init__.py" = ["F401", "I001", "RUF013"]
|
|
# allow imports not at the top of the file
|
|
"src/fastmcp/__init__.py" = ["E402"]
|
|
"!src/**.py" = [ # Only enforce extended ruff rules for code in src/
|
|
"B", # flake8-bugbear
|
|
"C4", # flake8-comprehensions
|
|
"PIE", # flake8-pie
|
|
"RUF", # Ruff-specific
|
|
"SIM", # flake8-simplify
|
|
]
|
|
|
|
|
|
[tool.codespell]
|
|
ignore-words-list = "asend,shttp,te"
|