Skip to content

Simplify .key as computed property#2648

Merged
jlowin merged 4 commits intomainfrom
simplify-key-computed-property
Dec 18, 2025
Merged

Simplify .key as computed property#2648
jlowin merged 4 commits intomainfrom
simplify-key-computed-property

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Dec 18, 2025

The .key property now serves as a universal lookup interface for all components, implemented as a computed property rather than a stored field.

Before: Components had a _key private attribute and custom model_copy(key=...) for setting keys separately from names/URIs. This created complexity and confusion about when to use .key vs .name.

After: .key is computed from the underlying identifier:

  • Tools/Prompts: .key returns .name
  • Resources: .key returns str(.uri)
  • Templates: .key returns .uri_template

When prefixing components via model_copy(update={"name": "prefixed_tool"}), the .key automatically updates. Resource/template names are NOT prefixed—only their URIs are prefixed.

@mcp.tool()
def greet(name: str) -> str:
    return f"Hello, {name}!"

tool = await mcp.get_tool("greet")
assert tool.key == "greet"  # .key returns .name

# After prefixing
prefixed = tool.model_copy(update={"name": "api_greet"})
assert prefixed.key == "api_greet"  # automatically updated

Also moves import_server tests to tests/deprecated/ with warning suppression.

Keep .key as the standard lookup interface for all components but
implement it as a computed property instead of a stored field.

- Remove _key private attribute and custom model_copy(key=...)
- .key returns .name for tools/prompts, str(.uri) for resources,
  .uri_template for templates
- Use .key universally for component lookups in managers
- MountedProvider: prefix URIs only for resources/templates, not names
- Docket registration: tools/prompts use .key, resources use .name
  (matches fn.__name__ for function lookup)
Keep .key as the standard lookup interface for all components but
implement it as a computed property instead of a stored field.

- Remove _key private attribute and custom model_copy(key=...)
- .key returns .name for tools/prompts, str(.uri) for resources,
  .uri_template for templates
- Use .key universally for component lookups and Docket registration
- MountedProvider: prefix URIs only for resources/templates, not names
- Add _backend_* fields to proxy classes to preserve original identifiers
  for backend calls when prefixed via import_server
@marvin-context-protocol marvin-context-protocol Bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. server Related to FastMCP server implementation or server-side functionality. labels Dec 18, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 18, 2025

Walkthrough

Adds backend-aware identifiers to proxy classes (ProxyTool, ProxyResource, ProxyTemplate, ProxyPrompt) with corresponding _backend_* fields and model_copy overrides so backend-prefixed names/URIs are preserved when public properties change. Internal call sites now prefer backend-prefixed identifiers and error messages reflect backend URIs when present. Server code switches docket registrations and import paths from name-based to key-based semantics for resources/templates and uses .values() to import components while applying prefixing via model_copy(update=...). Task handlers now queue by .key instead of .name. Component key logic was simplified to derive keys from name/URI.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description provides comprehensive detail on the changes, including before/after comparison, code examples, and implementation across all component types. However, the contributors checklist items are not marked, which are required per the template. Complete the contributors checklist by checking all applicable items (issues, workflow, testing, documentation, self-review) to meet repository requirements.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Simplify .key as computed property' clearly and concisely describes the main change: converting .key from a stored field to a computed property.
Docstring Coverage ✅ Passed Docstring coverage is 84.38% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch simplify-key-computed-property

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/fastmcp/server/proxy.py (1)

413-419: Consider extracting the error message to a constant or helper.

The static analysis tool flags TRY003 for the inline error message. While this is a minor style issue, you could optionally extract it to improve consistency.

🔎 Optional: Extract error message
+class ProxyResource(Resource, MirroredComponent):
+    """..."""
+    _EMPTY_CONTENT_ERROR = "Remote server returned empty content for {uri}"
+    # ... existing code ...

     async def read(self) -> ResourceContent:
         # ...
         if not result:
-            raise ResourceError(
-                f"Remote server returned empty content for {backend_uri}"
-            )
+            raise ResourceError(self._EMPTY_CONTENT_ERROR.format(uri=backend_uri))
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d758ba and 1c285dc.

⛔ Files ignored due to path filters (1)
  • tests/server/tasks/test_server_tasks_parameter.py is excluded by none and included by none
📒 Files selected for processing (3)
  • src/fastmcp/server/proxy.py (9 hunks)
  • src/fastmcp/server/server.py (2 hunks)
  • src/fastmcp/server/tasks/handlers.py (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/server.py
  • src/fastmcp/server/tasks/handlers.py
  • src/fastmcp/server/proxy.py
🧬 Code graph analysis (2)
src/fastmcp/server/server.py (3)
src/fastmcp/resources/template.py (1)
  • key (221-228)
src/fastmcp/utilities/components.py (1)
  • key (66-73)
src/fastmcp/resources/resource.py (1)
  • key (276-283)
src/fastmcp/server/proxy.py (3)
src/fastmcp/utilities/components.py (1)
  • model_copy (99-120)
src/fastmcp/exceptions.py (1)
  • ResourceError (14-15)
src/fastmcp/prompts/prompt_manager.py (1)
  • get_prompt (53-58)
🪛 Ruff (0.14.8)
src/fastmcp/server/proxy.py

417-419: Avoid specifying long messages outside the exception class

(TRY003)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.10 on windows-latest
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
🔇 Additional comments (12)
src/fastmcp/server/proxy.py (7)

283-283: LGTM! Backend-aware dispatch for ProxyTool.

The _backend_name field and model_copy override correctly preserve the original tool name for backend calls when the local name is prefixed. This ensures proper routing to the remote server.

Also applies to: 289-296


343-344: Correct usage of backend identifier for tool calls.

Using self._backend_name or self.name ensures the tool call is routed with the original backend identifier when available, falling back to the local name otherwise.


364-364: LGTM! Backend-aware dispatch for ProxyResource.

The pattern mirrors ProxyTool correctly. The _backend_uri is captured on first URI change and used for backend read operations.

Also applies to: 377-384


442-442: LGTM! Backend-aware dispatch for ProxyTemplate.

Consistent implementation preserving _backend_uri_template on first change. The pattern aligns with the other proxy types.

Also applies to: 448-455


487-488: Correct template parameterization using backend template.

The backend_template is correctly used for formatting the parameterized URI, ensuring the remote server receives the expected URI pattern.


534-534: LGTM! Backend-aware dispatch for ProxyPrompt.

Completes the consistent pattern across all proxy types. The _backend_name field and model_copy override follow the same approach as ProxyTool.

Also applies to: 540-547


578-580: Correct usage of backend identifier for prompt rendering.

The fallback pattern self._backend_name or self.name ensures proper routing to the remote server.

src/fastmcp/server/server.py (2)

445-445: LGTM! Consistent key-based docket registration for local components.

For resources, .key returns str(self.uri), and for templates, .key returns self.uri_template. This aligns docket registrations with the canonical identifiers used for lookups, ensuring tasks are correctly dispatched.

Also applies to: 452-452


461-463: LGTM! Consistent key-based docket registration for provider components.

Provider resources and templates now use .key for docket registration, matching the local component approach and ensuring uniform task dispatch behavior.

src/fastmcp/server/tasks/handlers.py (3)

102-107: LGTM! Tool task queuing uses canonical key.

Using tool.key ensures the docket lookup matches the registered name, correctly handling prefixed tools from mounted servers.


208-213: LGTM! Prompt task queuing uses canonical key.

Consistent with the tool handler, using prompt.key ensures proper dispatch for both local and mounted prompts.


312-326: LGTM! Resource task queuing uses canonical key.

Both template-based and direct resource paths now use resource.key for docket dispatch, aligning with the key-based registration in _docket_lifespan.

@jlowin jlowin marked this pull request as draft December 18, 2025 19:18
Copy link
Copy Markdown
Collaborator

@chrisguidry chrisguidry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it!

- .key is now a read-only computed property:
  - Tools/Prompts: returns .name
  - Resources: returns str(.uri)
  - Templates: returns .uri_template
- Prefixing uses model_copy(update={...}) to change underlying field
- Resource/template names are NOT prefixed, only URIs
- Move import_server tests to tests/deprecated/
@jlowin jlowin marked this pull request as ready for review December 18, 2025 19:44
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/fastmcp/server/providers/mounted.py (1)

199-205: LGTM! URI template prefixing correctly implemented.

The method properly prefixes only the uri_template field using model_copy(update={"uri_template": new_template}). The docstring correctly clarifies that the name field is not prefixed.

Optional: Minor redundancy in condition

Line 201 checks if self.prefix and template.uri_template:, but uri_template is a required field in ResourceTemplate, so the second condition is always true. You could simplify to:

-        if self.prefix and template.uri_template:
+        if self.prefix:

This doesn't affect correctness, just a minor simplification.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c285dc and 711d1fc.

⛔ Files ignored due to path filters (8)
  • tests/deprecated/__init__.py is excluded by none and included by none
  • tests/deprecated/conftest.py is excluded by none and included by none
  • tests/deprecated/test_import_server.py is excluded by none and included by none
  • tests/resources/test_resource_manager.py is excluded by none and included by none
  • tests/server/test_mount.py is excluded by none and included by none
  • tests/server/test_server.py is excluded by none and included by none
  • tests/tools/test_tool_manager.py is excluded by none and included by none
  • tests/utilities/test_components.py is excluded by none and included by none
📒 Files selected for processing (6)
  • src/fastmcp/resources/resource.py (1 hunks)
  • src/fastmcp/resources/resource_manager.py (2 hunks)
  • src/fastmcp/resources/template.py (1 hunks)
  • src/fastmcp/server/providers/mounted.py (1 hunks)
  • src/fastmcp/server/server.py (3 hunks)
  • src/fastmcp/utilities/components.py (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/fastmcp/resources/resource_manager.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/fastmcp/server/server.py
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/resources/resource.py
  • src/fastmcp/resources/template.py
  • src/fastmcp/server/providers/mounted.py
  • src/fastmcp/utilities/components.py
🧠 Learnings (2)
📚 Learning: 2025-12-17T03:06:14.522Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T03:06:14.522Z
Learning: Applies to src/fastmcp/**/__init__.py : Be intentional about re-exports; core types that define a module's purpose should be exported; specialized features can live in submodules; only re-export to fastmcp.* for fundamental types

Applied to files:

  • src/fastmcp/utilities/components.py
📚 Learning: 2025-12-17T03:06:14.522Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T03:06:14.522Z
Learning: Applies to src/fastmcp/**/*.py : Write Python code with ≥3.10 type annotations required throughout

Applied to files:

  • src/fastmcp/utilities/components.py
🧬 Code graph analysis (2)
src/fastmcp/server/providers/mounted.py (4)
src/fastmcp/server/proxy.py (4)
  • model_copy (289-296)
  • model_copy (377-384)
  • model_copy (448-455)
  • model_copy (540-547)
src/fastmcp/resources/resource.py (1)
  • Resource (133-278)
src/fastmcp/resources/template.py (1)
  • ResourceTemplate (92-223)
src/fastmcp/prompts/prompt.py (1)
  • Prompt (113-230)
src/fastmcp/utilities/components.py (1)
src/fastmcp/server/server.py (1)
  • name (362-363)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (6)
src/fastmcp/utilities/components.py (1)

59-68: LGTM! Clean simplification of the key property.

The shift to a computed .key property that returns self.name by default is much cleaner than maintaining a stored _key attribute. The docstring clearly documents the override pattern for subclasses.

src/fastmcp/resources/resource.py (1)

276-278: LGTM! URI-based key is the right identifier for resources.

The key property correctly returns str(self.uri) as the lookup identifier for resources, which aligns with the resource identification model.

src/fastmcp/resources/template.py (1)

221-223: LGTM! URI template-based key is consistent with resource identification.

The key property correctly returns self.uri_template as the lookup identifier for templates, maintaining consistency with the Resource pattern of URI-based identification.

src/fastmcp/server/providers/mounted.py (3)

181-189: LGTM! Prefixing logic correctly uses model_copy with update.

The method properly handles both tool_names overrides and default prefixing, using model_copy(update={"name": new_name}) to update the name field. The optimization to return the original tool when unchanged is good. The updated docstring correctly notes that name changes affect .key.


191-197: LGTM! URI prefixing correctly updates the uri field.

The method properly prefixes only the URI (not the name), using model_copy(update={"uri": new_uri}). Pydantic will validate and coerce the string to AnyUrl. The docstring correctly clarifies that the name field is not prefixed.


207-212: LGTM! Prompt prefixing follows the same pattern as tool prefixing.

The method correctly updates the prompt name using model_copy(update={"name": new_name}), with proper optimization to return the original when unchanged. The docstring accurately notes that name changes affect .key.

@jlowin jlowin merged commit caeaa86 into main Dec 18, 2025
12 of 13 checks passed
@jlowin jlowin deleted the simplify-key-computed-property branch December 18, 2025 19:48
@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: Integration test timeout caused by GitHub API rate limiting (429 error), not a code issue.

Root Cause: The test test_call_tool_list_commits is failing with a 30-second timeout. The error logs reveal that during teardown, the client received an HTTP 429 (Too Many Requests) error from https://api.githubcopilot.com/mcp/:

httpx.HTTPStatusError: Client error '429 Too Many Requests' for url 'https://api.githubcopilot.com/mcp/'

The test appears to hang waiting for a response from GitHub's MCP API, which is rate limiting requests. This is an external API issue, not a bug in the PR's changes.

Suggested Solution:

The PR changes themselves are sound - they simplify the .key property to be a computed property based on the relevant identifier (uri, name, etc.). The integration test failure is unrelated to these changes and is caused by external rate limiting.

Options to address this:

  1. Retry the workflow - The rate limit is likely temporary
  2. Add retry logic to the GitHub MCP integration tests with exponential backoff
  3. Mock the GitHub MCP API for these tests to avoid rate limits
  4. Mark as flaky - Add @pytest.mark.flaky to this test since it depends on an external API

Since this PR is already merged and the failure is environmental (not caused by the code changes), no immediate action is required unless this becomes a recurring issue.

Detailed Analysis

Error Location: tests/integration_tests/test_github_mcp_remote.py:99

Stack Trace: The timeout occurs in the asyncio event loop while waiting for the GitHub API response. The 429 error appears during session teardown (__aexit__), suggesting the initial request may have succeeded but subsequent cleanup operations were rate limited.

PR Changes Review: The changes in this PR modify how .key is computed for Resources, ResourceTemplates, Tools, and Prompts. The integration test that failed tests calling tools on a remote GitHub MCP server - none of the changes in this PR would affect how that external API call is made or handled.

Related Files
  • tests/integration_tests/test_github_mcp_remote.py:99-122 - Test that timed out
  • src/fastmcp/client/client.py:503,630,648 - Client teardown where 429 error occurred

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The Windows test suite is timing out (5s timeout) during initialization of in the test due to SQLite database locking issues.

Root Cause: The test creates an which initializes a at line 821 of . On Windows, the initialization is hitting SQLite database locking contention, likely due to:

  1. Multiple tests running in parallel (pytest is not using on Windows but still collected 3185 tests)
  2. Windows file locking being more restrictive than Unix systems
  3. The default 5-second pytest timeout being too short for Windows SQLite operations

Suggested Solution: This issue is not directly related to the PR changes (which focused on simplifying the .key property). The timeout occurs during test setup when creating the disk-based client storage. To fix:

  1. Isolate test directories: Ensure each test uses a unique directory for to avoid lock contention:

    # In the test
    with tempfile.TemporaryDirectory() as tmpdir:
        client_storage = FernetEncryptionWrapper(
            key_value=DiskStore(directory=Path(tmpdir) / "oauth-proxy"),
            fernet=Fernet(key=storage_encryption_key),
        )
        proxy = OIDCProxy(..., client_storage=client_storage)
  2. Use in-memory storage for tests: Since this is a test, consider using an in-memory key-value store instead of disk-based storage to avoid file system issues entirely.

  3. Increase timeout for Windows: Mark this test (and similar ones) with a longer timeout on Windows:

    @pytest.mark.timeout(30 if sys.platform == "win32" else 5)
    def test_custom_token_verifier_with_audience_allowed(...):

Recommendation: Option 2 (in-memory storage for tests) is cleanest and will make tests faster and more reliable across all platforms.

Detailed Analysis

Test that timed out: tests/server/auth/test_oidc_proxy.py::test_custom_token_verifier_with_audience_allowed (line 773)

Stack trace location:

File "src/fastmcp/server/auth/oauth_proxy.py", line 821, in __init__
  key_value=DiskStore(directory=settings.home / "oauth-proxy"),
File "diskcache/core.py", line 480, in __init__
  sql(
File "diskcache/core.py", line 666, in _execute_with_retry
  return sql(statement, *args, **kwargs)
+++++++++++++++++++++++++++++++++++ Timeout +++++++++++++++++++++++++++++++++++

The timeout occurs when diskcache.Cache tries to initialize its SQLite database. This is a known issue with diskcache on Windows in parallel test environments where multiple processes/threads can contend for the same SQLite database file.

Why this happens on Windows: Windows uses mandatory file locking (the OS enforces locks), while Unix systems use advisory locking (applications cooperate). This makes Windows more susceptible to SQLite locking issues in parallel test scenarios.

References:

Related Files
  • tests/server/auth/test_oidc_proxy.py:773 - Test that timed out during OIDCProxy initialization
  • src/fastmcp/server/auth/oauth_proxy.py:821 - Where DiskStore is created with shared directory
  • src/fastmcp/server/auth/oidc_proxy.py:378 - OIDCProxy.__init__ calls parent OAuthProxy.__init__

@marvin-context-protocol
Copy link
Copy Markdown
Contributor

Test Failure Analysis

Summary: The Windows test suite is timing out (5s timeout) during initialization of DiskStore in the test_custom_token_verifier_with_audience_allowed test due to SQLite database locking issues.

Root Cause: The test creates an OIDCProxy which initializes a DiskStore at line 821 of oauth_proxy.py. On Windows, the diskcache.Cache initialization is hitting SQLite database locking contention, likely due to:

  1. Multiple tests running in parallel (pytest collected 3185 tests)
  2. Windows file locking being more restrictive than Unix systems
  3. The default 5-second pytest timeout being too short for Windows SQLite operations under contention

Suggested Solution: This issue is not directly related to the PR changes (which focused on simplifying the .key property). The timeout occurs during test setup when creating the disk-based client storage. To fix:

  1. Isolate test directories: Ensure each test uses a unique directory for DiskStore to avoid lock contention by providing client_storage parameter in tests
  2. Use in-memory storage for tests: Since this is a test, consider using an in-memory key-value store instead of disk-based storage to avoid file system issues entirely (recommended)
  3. Increase timeout for Windows: Mark this test (and similar ones) with a longer timeout on Windows

Recommendation: Option 2 (in-memory storage for tests) is cleanest and will make tests faster and more reliable across all platforms.

Detailed Analysis

Test that timed out: tests/server/auth/test_oidc_proxy.py::test_custom_token_verifier_with_audience_allowed (line 773)

Stack trace location:

File "src/fastmcp/server/auth/oauth_proxy.py", line 821, in __init__
  key_value=DiskStore(directory=settings.home / "oauth-proxy"),
File "diskcache/core.py", line 480, in __init__
  sql(
File "diskcache/core.py", line 666, in _execute_with_retry
  return sql(statement, *args, **kwargs)
+++++++++++++++++++++++++++++++++++ Timeout +++++++++++++++++++++++++++++++++++

The timeout occurs when diskcache.Cache tries to initialize its SQLite database. This is a known issue with diskcache on Windows in parallel test environments where multiple processes/threads can contend for the same SQLite database file.

Why this happens on Windows: Windows uses mandatory file locking (the OS enforces locks), while Unix systems use advisory locking (applications cooperate). This makes Windows more susceptible to SQLite locking issues in parallel test scenarios. All tests are using the same settings.home / "oauth-proxy" directory, causing lock contention.

References:

Related Files
  • tests/server/auth/test_oidc_proxy.py:773 - Test that timed out during OIDCProxy initialization
  • src/fastmcp/server/auth/oauth_proxy.py:821 - Where DiskStore is created with shared directory
  • src/fastmcp/server/auth/oidc_proxy.py:378 - OIDCProxy.__init__ calls parent OAuthProxy.__init__

@jlowin jlowin removed the breaking change Breaks backward compatibility. Requires minor version bump. Critical for maintainer attention. label Dec 18, 2025
@jlowin jlowin added this to the 2.15 milestone Dec 18, 2025
@jlowin jlowin added the provider Related to the FastMCP Provider class label Dec 19, 2025
@ajram23
Copy link
Copy Markdown

ajram23 commented Jan 29, 2026

@jlowin I see this merged into 3.X branch. Any recommendations for folks running on 2.14.X where prefix is broken?

@jlowin
Copy link
Copy Markdown
Member Author

jlowin commented Jan 29, 2026

This wasn't a bug fix. What issue are you referring to?

@ajram23
Copy link
Copy Markdown

ajram23 commented Jan 29, 2026

@jlowin thanks for the prompt response - I came here through #2300

@jlowin
Copy link
Copy Markdown
Member Author

jlowin commented Jan 29, 2026

Oh I see - that was an inadvertent outcome of this change. We're not planning to back port this, it would be complicated. I recommend using the 3.0 b1 if you need that middleware to work!

@ajram23
Copy link
Copy Markdown

ajram23 commented Jan 29, 2026

:( just upgraded to .14.X from .10.X

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to existing functionality. For issues and smaller PR improvements. provider Related to the FastMCP Provider class server Related to FastMCP server implementation or server-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants