chore(deps): fastmcp 4 (mcp 2.2)

No code change needed: the server side (`FastMCP`, `@mcp.tool`,
`get_http_headers`, `http_app`) and the client side (`Client`, `BearerAuth`,
the three transports, and the `mcp.client.auth` / `mcp.shared.auth` OAuth
types imported directly) all kept their signatures.

Verified beyond the suite by driving the real `/mcp` mount over a live
uvicorn socket with the fastmcp client: tool discovery, a `search_docs` call
and bearer-token extraction all round-trip, with the token reaching
`search()` intact.

fastmcp 4 and mcp 2.2 also moved to httpx2, so the retry tuple's comment now
places them on that side of the split.
This commit is contained in:
Alex committed 2026-09-12 17:54:18 +01:00
1 parent f7baa1952f
commit 108b8fd56b
7 files changed
+74 -56

No files matched your search

+4 -4
View File
@@ -22,10 +22,10 @@ logger = logging.getLogger(__name__)
# retries — RateLimitError needs backoff, BadRequestError won't get any
# better on retry, and the existing fallback handles both.
# Both HTTP stacks are listed because the providers are split across them and
# the two libraries' exception classes are unrelated types: openai and
# anthropic run on httpx2, while google-genai, elevenlabs, qdrant-client and
# the MCP client are still on httpx. Naming only one silently stops matching
# for half the providers — the retry just never fires.
# the two libraries' exception classes are unrelated types: openai, anthropic
# and the MCP client run on httpx2, while google-genai, elevenlabs,
# qdrant-client and daytona are still on httpx. Naming only one silently stops
# matching for half the providers — the retry just never fires.
_TRANSPORT_ERROR_NAMES = (
"RemoteProtocolError",
"ReadError",
+12 -8
View File
@@ -231,9 +231,9 @@ fast-ebook==0.2.0
# via docsgpt
fastembed==0.8.0
# via docsgpt
fastmcp==3.4.7
fastmcp==4.0.3
# via docsgpt
fastmcp-slim==3.4.7
fastmcp-slim==4.0.3
# via fastmcp
filelock==3.32.6
# via
@@ -327,20 +327,18 @@ httpx==0.28.1
# daytona
# docling-slim
# elevenlabs
# fastmcp-slim
# google-genai
# httpx-ws
# huggingface-hub
# mcp
# qdrant-client
httpx-sse==0.4.3
# via mcp
httpx-ws==0.9.0
# via daytona
httpx2==2.12.0
# via
# anthropic
# docsgpt
# fastmcp-slim
# mcp
# openai
httpx2-jsfetch==1.0 ; sys_platform == 'emscripten'
# via httpx2
@@ -444,8 +442,12 @@ markupsafe==3.0.3
# werkzeug
marshmallow==3.26.2
# via dataclasses-json
mcp==1.30.0
mcp==2.2.0
# via fastmcp-slim
mcp-types==2.2.0
# via
# fastmcp-slim
# mcp
mdurl==0.1.2
# via markdown-it-py
mmh3==5.3.0
@@ -519,6 +521,7 @@ opentelemetry-api==1.44.0
# daytona
# fastmcp-slim
# google-api-core
# mcp
# opentelemetry-distro
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
@@ -734,6 +737,7 @@ pydantic==2.13.5
# fastmcp-slim
# google-genai
# mcp
# mcp-types
# openai
# openapi-pydantic
# openapi3-parser
@@ -749,7 +753,6 @@ pydantic-settings==2.15.0
# docling-slim
# docsgpt
# fastmcp-slim
# mcp
pygments==2.21.0
# via
# mpire
@@ -1049,6 +1052,7 @@ typing-extensions==4.16.0
# httpx2
# huggingface-hub
# mcp
# mcp-types
# obstore
# openai
# opentelemetry-api
+12 -8
View File
@@ -193,9 +193,9 @@ fast-ebook==0.2.0
# via docsgpt
fastembed==0.8.0
# via docsgpt
fastmcp==3.4.7
fastmcp==4.0.3
# via docsgpt
fastmcp-slim==3.4.7
fastmcp-slim==4.0.3
# via fastmcp
filelock==3.32.6
# via
@@ -285,20 +285,18 @@ httpx==0.28.1
# via
# daytona
# elevenlabs
# fastmcp-slim
# google-genai
# httpx-ws
# huggingface-hub
# mcp
# qdrant-client
httpx-sse==0.4.3
# via mcp
httpx-ws==0.9.0
# via daytona
httpx2==2.12.0
# via
# anthropic
# docsgpt
# fastmcp-slim
# mcp
# openai
httpx2-jsfetch==1.0 ; sys_platform == 'emscripten'
# via httpx2
@@ -386,8 +384,12 @@ markupsafe==3.0.3
# werkzeug
marshmallow==3.26.2
# via dataclasses-json
mcp==1.30.0
mcp==2.2.0
# via fastmcp-slim
mcp-types==2.2.0
# via
# fastmcp-slim
# mcp
mdurl==0.1.2
# via markdown-it-py
milvus-lite==3.2.1 ; sys_platform != 'win32'
@@ -438,6 +440,7 @@ opentelemetry-api==1.44.0
# daytona
# fastmcp-slim
# google-api-core
# mcp
# opentelemetry-distro
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
@@ -639,6 +642,7 @@ pydantic==2.13.5
# fastmcp-slim
# google-genai
# mcp
# mcp-types
# openai
# openapi-pydantic
# openapi3-parser
@@ -652,7 +656,6 @@ pydantic-settings==2.15.0
# via
# docsgpt
# fastmcp-slim
# mcp
pygments==2.21.0
# via
# rich
@@ -855,6 +858,7 @@ typing-extensions==4.16.0
# httpx2
# huggingface-hub
# mcp
# mcp-types
# obstore
# openai
# opentelemetry-api
+12 -8
View File
@@ -189,9 +189,9 @@ fast-ebook==0.2.0
# via docsgpt
fastembed==0.8.0
# via docsgpt
fastmcp==3.4.7
fastmcp==4.0.3
# via docsgpt
fastmcp-slim==3.4.7
fastmcp-slim==4.0.3
# via fastmcp
filelock==3.32.6
# via
@@ -279,20 +279,18 @@ httpx==0.28.1
# via
# daytona
# elevenlabs
# fastmcp-slim
# google-genai
# httpx-ws
# huggingface-hub
# mcp
# qdrant-client
httpx-sse==0.4.3
# via mcp
httpx-ws==0.9.0
# via daytona
httpx2==2.12.0
# via
# anthropic
# docsgpt
# fastmcp-slim
# mcp
# openai
httpx2-jsfetch==1.0 ; sys_platform == 'emscripten'
# via httpx2
@@ -380,8 +378,12 @@ markupsafe==3.0.3
# werkzeug
marshmallow==3.26.2
# via dataclasses-json
mcp==1.30.0
mcp==2.2.0
# via fastmcp-slim
mcp-types==2.2.0
# via
# fastmcp-slim
# mcp
mdurl==0.1.2
# via markdown-it-py
mmh3==5.3.0
@@ -429,6 +431,7 @@ opentelemetry-api==1.44.0
# daytona
# fastmcp-slim
# google-api-core
# mcp
# opentelemetry-distro
# opentelemetry-exporter-otlp-proto-grpc
# opentelemetry-exporter-otlp-proto-http
@@ -623,6 +626,7 @@ pydantic==2.13.5
# fastmcp-slim
# google-genai
# mcp
# mcp-types
# openai
# openapi-pydantic
# openapi3-parser
@@ -636,7 +640,6 @@ pydantic-settings==2.15.0
# via
# docsgpt
# fastmcp-slim
# mcp
pygments==2.21.0
# via
# rich
@@ -835,6 +838,7 @@ typing-extensions==4.16.0
# httpx2
# huggingface-hub
# mcp
# mcp-types
# obstore
# openai
# opentelemetry-api
+1 -1
View File
@@ -55,7 +55,7 @@ dependencies = [
# with no model downloads. The docling engine is the `docling` extra.
"firecrawl-anydoc>=0.2.4,<0.3",
"fastembed>=0.8.0,<0.9",
"fastmcp>=3.4.6,<4",
"fastmcp>=4.0.3,<5",
"Flask>=3.1.3,<4",
"flask-restx>=1.3.2,<2",
"google-api-python-client>=2.198.0,<3",
+4 -3
View File
@@ -372,9 +372,10 @@ class TestStreamingFallback:
self, patch_model_utils, error
):
"""The providers are split across two HTTP stacks whose exception
classes are unrelated types: openai and anthropic raise from httpx2,
google-genai and elevenlabs still from httpx. Naming one stack makes
the retry silently stop firing for the other half.
classes are unrelated types: openai, anthropic and the MCP client
raise from httpx2, google-genai and elevenlabs still from httpx.
Naming one stack makes the retry silently stop firing for the other
half.
"""
backup = FakeLLM(stream_chunks=["fallback"])
patch_model_utils(
Generated
+29 -24
View File
@@ -1467,7 +1467,7 @@ requires-dist = [
{ name = "faiss-cpu", specifier = ">=1.15.0,<2" },
{ name = "fast-ebook", specifier = ">=0.2.0,<0.3" },
{ name = "fastembed", specifier = ">=0.8.0,<0.9" },
{ name = "fastmcp", specifier = ">=3.4.6,<4" },
{ name = "fastmcp", specifier = ">=4.0.3,<5" },
{ name = "firecrawl-anydoc", specifier = ">=0.2.4,<0.3" },
{ name = "flask", specifier = ">=3.1.3,<4" },
{ name = "flask-restx", specifier = ">=1.3.2,<2" },
@@ -1719,21 +1719,22 @@ wheels = [
[[package]]
name = "fastmcp"
version = "3.4.7"
version = "4.0.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "fastmcp-slim", extra = ["client", "server"] },
]
sdist = { url = "https://files.pythonhosted.org/packages/62/dd/fd444d94ae7afdaf5b6dd168799d34023f576b405872d6a27d5686a9d1f4/fastmcp-3.4.7.tar.gz", hash = "sha256:43117aca886f5ee2f6a569bba91cef02b59c339aad04ba29950ff18d251c822a", size = 28808982, upload-time = "2026-08-10T21:17:55.045Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5d/1a/bee10aff530338f3b8982a3dd1c377c3ba5d0bc724615bf358422c4e9ecf/fastmcp-4.0.3.tar.gz", hash = "sha256:0dd50baf070105ee4436c245f087ac3c047e655c32d9e783de16d0bf15783a98", size = 42311418, upload-time = "2026-09-05T00:31:36.932Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ac/14/6d950459cc831fa17fe2d1797926b6eb2d2f2af50f830e62d0c098cc1ec8/fastmcp-3.4.7-py3-none-any.whl", hash = "sha256:e4e7698cb4af5bc667b1901685261fa2f3526dc73d243a461fca42500c8dbe56", size = 8016, upload-time = "2026-08-10T21:17:51.391Z" },
{ url = "https://files.pythonhosted.org/packages/e4/cb/66600db497b3be21cf141f01296308169859d48ed9b1bc8ba7c9d83279b7/fastmcp-4.0.3-py3-none-any.whl", hash = "sha256:f743f43193e1daf606e6497a9dddba5bbaad7df7957a98fd093716ecf4458b99", size = 8076, upload-time = "2026-09-05T00:31:33.957Z" },
]
[[package]]
name = "fastmcp-slim"
version = "3.4.7"
version = "4.0.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mcp-types" },
{ name = "platformdirs" },
{ name = "pydantic", extra = ["email"] },
{ name = "pydantic-settings" },
@@ -1741,16 +1742,16 @@ dependencies = [
{ name = "rich" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/12/ac/7924e803368d0758ee4d6b1259066550df78f58f0f9f8bfebd5a123e957d/fastmcp_slim-3.4.7.tar.gz", hash = "sha256:06b32a358320a7dc2b2ee040ba89ea55ddc20763dff2949f384f7974b13b5d8f", size = 594357, upload-time = "2026-08-10T21:17:28.723Z" }
sdist = { url = "https://files.pythonhosted.org/packages/b0/a9/b7b796b0d4a5e095dadef233833c82ac1136f5c110dd9947b2e9a4988518/fastmcp_slim-4.0.3.tar.gz", hash = "sha256:3ce04a82b82cc41ccb12bb3bb366cfd65b52bc797b8fee332a75da9d480f9b74", size = 685704, upload-time = "2026-09-05T00:31:12.346Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/b4/97/e0e53642cd029a9a7635ae9c548f9f2cc995af5914e487b3df795664e4be/fastmcp_slim-3.4.7-py3-none-any.whl", hash = "sha256:6c931a0089705f3f2935428ef9b2bc74ad94140adc64aab84d116d103e694b3a", size = 769370, upload-time = "2026-08-10T21:17:27.227Z" },
{ url = "https://files.pythonhosted.org/packages/43/4b/6b31820d87f56d5773538860878c8634b618cd1e9044b3bfbd8a78380a0f/fastmcp_slim-4.0.3-py3-none-any.whl", hash = "sha256:3756ed4bd9f82f40adaf51974b7cdd1463ab6b9f479cf69b69b2692969312b87", size = 859717, upload-time = "2026-09-05T00:31:10.93Z" },
]
[package.optional-dependencies]
client = [
{ name = "authlib" },
{ name = "exceptiongroup" },
{ name = "httpx" },
{ name = "httpx2" },
{ name = "mcp" },
{ name = "opentelemetry-api" },
{ name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] },
@@ -1761,7 +1762,7 @@ server = [
{ name = "cyclopts" },
{ name = "exceptiongroup" },
{ name = "griffelib" },
{ name = "httpx" },
{ name = "httpx2" },
{ name = "joserfc" },
{ name = "jsonref" },
{ name = "jsonschema-path" },
@@ -2380,15 +2381,6 @@ http2 = [
{ name = "h2" },
]
[[package]]
name = "httpx-sse"
version = "0.4.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0f/4c/751061ffa58615a32c31b2d82e8482be8dd4a89154f003147acee90f2be9/httpx_sse-0.4.3.tar.gz", hash = "sha256:9b1ed0127459a66014aec3c56bebd93da3c1bc8bb6618c8082039a44889a755d", size = 15943, upload-time = "2025-10-10T21:48:22.271Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d2/fd/6668e5aec43ab844de6fc74927e155a3b37bf40d7c3790e49fc0406b6578/httpx_sse-0.4.3-py3-none-any.whl", hash = "sha256:0ac1c9fe3c0afad2e0ebb25a934a59f4c7823b60792691f779fad2c5568830fc", size = 8960, upload-time = "2025-10-10T21:48:21.158Z" },
]
[[package]]
name = "httpx-ws"
version = "0.9.0"
@@ -3051,15 +3043,15 @@ wheels = [
[[package]]
name = "mcp"
version = "1.30.0"
version = "2.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "anyio" },
{ name = "httpx" },
{ name = "httpx-sse" },
{ name = "httpx2" },
{ name = "jsonschema" },
{ name = "mcp-types" },
{ name = "opentelemetry-api" },
{ name = "pydantic" },
{ name = "pydantic-settings" },
{ name = "pyjwt", extra = ["crypto"] },
{ name = "python-multipart" },
{ name = "pywin32", marker = "sys_platform == 'win32'" },
@@ -3069,9 +3061,22 @@ dependencies = [
{ name = "typing-inspection" },
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ba/93/0142dc84a666daf8ad51a34268f34c12fd6fda4f3810c4be2504eecc8212/mcp-1.30.0.tar.gz", hash = "sha256:445414625fce5c295faa505bb11bacece661ab6f4028d57c935db57820b7a3e4", size = 680511, upload-time = "2026-09-07T14:34:15.845Z" }
sdist = { url = "https://files.pythonhosted.org/packages/76/31/ac54fb0fdd5b37de704486e288bba4fbbb463f24cfcfedbede407b854513/mcp-2.2.0.tar.gz", hash = "sha256:2dc37ecb1974becdcebdbf7561e7c15a07dbbf20ba21ba16c3593b3038b3afbd", size = 4084129, upload-time = "2026-09-07T16:06:23.439Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f5/f4/e58bc33317c92a0203664daaf00bf6f41166cc0149e5d6870a03f7cd004a/mcp-1.30.0-py3-none-any.whl", hash = "sha256:666edb5009503e1047c9d60346a756f94b261f05cc2625f23d41c728ffc484d0", size = 234581, upload-time = "2026-09-07T14:34:14.266Z" },
{ url = "https://files.pythonhosted.org/packages/1b/ff/8e7eade68b8a28f7da0ed1085544341b51f9c935dbf6b95c76b7edfea6a0/mcp-2.2.0-py3-none-any.whl", hash = "sha256:bde982589473a060ae145e3406e9a5333fe538c97229ba841f5a7f92be004f81", size = 365656, upload-time = "2026-09-07T16:06:19.711Z" },
]
[[package]]
name = "mcp-types"
version = "2.2.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "pydantic" },
{ name = "typing-extensions" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ae/91/762d7755d971aff8a28d75f7961656148edf27875c8026e6385aaab08ae7/mcp_types-2.2.0.tar.gz", hash = "sha256:d3ed53703ddd10d9c6399f29d322bb66f3f67ab41348ac8556ba23e07fedefad", size = 65892, upload-time = "2026-09-07T16:06:25.187Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8f/d7/6ffba5d8cd5dd9b8a19478875c50e04945314ba5074e84d749283f27f62d/mcp_types-2.2.0-py3-none-any.whl", hash = "sha256:ea476b73ee86709ab5abc9452385ed36cc05907e582355622e294595c9a04f13", size = 69106, upload-time = "2026-09-07T16:06:21.461Z" },
]
[[package]]