fastmcp/fastmcp_slim/pyproject.toml
nate nowack 5a876c4cbe
transforms: add experimental JevSearchTransform (#5170)
* transforms: add experimental JevSearchTransform

A third tool-search transform that ranks tools with TypeSafe's Jev, a
System One model that returns calibrated probabilities over options the
caller defines. The query is the state and the tool names are the
options: a wide pass ranks the whole catalog on one-line summaries
(chunked and concurrent above chunk_size), then a close read of the
shortlist sees each tool's rendered description and parameters. A
Choice orders the results and one Noul per candidate decides whether it
fits at all, so a request no tool serves returns nothing instead of the
least-wrong match.

Lives in fastmcp.experimental.transforms beside CodeMode, behind a new
`jev` extra (typesafe-sdk>=0.5.7, the newest release inside the repo's
one-week exclude-newer window). Tests drive it through a fake client.
On the 187-tool Prefect OpenAPI catalog, five natural-language queries
returned the right tool first in four cases and an empty result for the
off-topic one, each in under a second.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jev search: snapshot text per search, bound the close read, fail early on a missing key

Review findings on the first cut. Summaries and details were instance
dicts replaced wholesale per catalog hash and read after awaits, so two
sessions with different visible tools searching at once raised KeyError
mid-search; text is now rendered into locals per search from a cache
that is only ever added to, keyed by a fingerprint that includes
parameters so a signature change re-renders. The close read had no size
bound, so a catalog of a few thousand tools produced a Choice over more
than 255 options or past the 32k-token question budget on every search;
wide passes now repeat until at most 3 * shortlist candidates remain,
and chunk_size is capped at 255. A missing API key is a ValueError at
construction instead of an error string on every search. Tool summaries
move out of the noul instructions into state, referenced by path, and
the wide instruction no longer says "if any" on a forced choice. The
docs lose the unmeasured latency claim, the fabricated example output,
and the statement that every default came from the cookbook.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* jev search: add close_read=False, a single-request mode

Asks the fit noul of every tool in the wide pass, on summaries, and skips
the close read. Measured on the 187-tool Prefect catalog: 0.06s faster
and six points worse at returning the right tool first, because one
188-question request is nearly the size of the two it replaces. The
two-stage default stands; the option is there for catalogs where a
single round trip matters more than sibling disambiguation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 17:55:55 -05:00

111 lines
3 KiB
TOML

[project]
name = "fastmcp-slim"
dynamic = ["version", "optional-dependencies"]
description = "The dependency-slim FastMCP package."
authors = [{ name = "Jeremiah Lowin" }, { name = "Nate Nowack" }]
dependencies = [
"mcp-types>=2.0.0,<3.0.0",
"platformdirs>=4.0.0",
"pydantic[email]>=2.12.0",
"pydantic-settings>=2.0.0",
"python-dotenv>=1.1.0",
"rich>=13.9.4",
"typing-extensions>=4.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.urls]
Homepage = "https://gofastmcp.com"
Repository = "https://github.com/PrefectHQ/fastmcp"
Documentation = "https://gofastmcp.com"
[project.scripts]
fastmcp = "fastmcp.cli:app"
[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.hatch.build.targets.wheel]
packages = ["fastmcp"]
[tool.uv-dynamic-versioning]
vcs = "git"
style = "pep440"
bump = true
fallback-version = "0.0.0"
[tool.hatch.metadata.hooks.uv-dynamic-versioning.optional-dependencies]
anthropic = ["anthropic>=0.48.0,<2"]
apps = ["prefab-ui>=0.18.0"]
# PyJWT floor: transitive via msal; CVE-2026-32597 affects <= 2.11.0
azure = ["azure-identity>=1.16.0", "PyJWT>=2.12.0"]
client = [
"fastmcp-slim[mcp]=={{ version }}",
"authlib>=1.6.11",
"py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0",
]
code-mode = ["pydantic-monty==0.0.21"]
jev = ["typesafe-sdk>=0.5.7"]
gemini = ["google-genai>=1.18.0", "jsonref>=1.1.0"]
mcp = [
"exceptiongroup>=1.2.2",
# FastMCP uses httpx2 exclusively: the MCP SDK boundary (client transports,
# client auth) requires it, and all FastMCP-owned HTTP (server auth provider
# upstream calls, OpenAPI provider, version check, etc.) uses it too.
"httpx2>=2.5.0",
"mcp>=2.0.0,<3.0.0",
"opentelemetry-api>=1.28.0",
# starlette floor: transitive via mcp (which only requires >=0.27).
# Pin past CVE-2026-48710, which was patched in 1.0.1.
"starlette>=1.0.1",
]
openai = ["openai>=1.102.0"]
server = [
"fastmcp-slim[mcp]=={{ version }}",
"authlib>=1.6.11",
"cyclopts>=4.0.0",
"griffelib>=2.0.0",
"jsonref>=1.1.0",
"jsonschema-path>=0.3.4",
"joserfc>=1.5.0",
"openapi-pydantic>=0.5.1",
"packaging>=24.0",
"py-key-value-aio[filetree,keyring,memory]>=0.4.4,<0.5.0",
"pyperclip>=1.9.0",
"python-multipart>=0.0.26",
"pyyaml>=6.0,<7.0",
"uncalled-for>=0.4.0",
"uvicorn>=0.35",
"watchfiles>=1.0.0",
"websockets>=15.0.1",
]