diff --git a/docs/changelog.mdx b/docs/changelog.mdx
index 0e84bd4da8..eec90a81d5 100644
--- a/docs/changelog.mdx
+++ b/docs/changelog.mdx
@@ -1234,7 +1234,7 @@ This release introduces completely new tools for generating and customizing MCP
## [v2.4.0: Config and Conquer](https://github.com/jlowin/fastmcp/releases/tag/v2.4.0)
-**Note**: this release includes a backwards-incompatible change to how resources are prefixed when mounted in composed servers. However, it is only backwards-incompatible if users were running tests or manually loading resources by prefixed key; LLMs should not have any issue discovering the new route. See [Resource Prefix Formats](https://gofastmcp.com/servers/composition#resource-prefix-formats) for more.
+**Note**: this release includes a backwards-incompatible change to how resources are prefixed when mounted in composed servers. However, it is only backwards-incompatible if users were running tests or manually loading resources by prefixed key; LLMs should not have any issue discovering the new route.
### New Features 🎉
diff --git a/docs/servers/composition.mdx b/docs/servers/composition.mdx
index d90bb47c76..6c614000c6 100644
--- a/docs/servers/composition.mdx
+++ b/docs/servers/composition.mdx
@@ -41,7 +41,7 @@ FastMCP supports [MCP proxying](/servers/proxy), which allows you to mirror a lo
You can also create proxies from configuration dictionaries that follow the MCPConfig schema, which is useful for quickly connecting to one or more remote servers. See the [Proxy Servers documentation](/servers/proxy#configuration-based-proxies) for details on configuration-based proxying. Note that MCPConfig follows an emerging standard and its format may evolve over time.
-Prefixing rules for tools, prompts, resources, and templates are identical across importing, mounting, and proxies.
+Prefixing rules for tools, prompts, resources, and templates are identical across importing, mounting, and proxies. When prefixes are used, resource URIs are prefixed using path format (since 2.4.0): `resource://prefix/path/to/resource`.
## Importing (Static Composition)
@@ -207,6 +207,10 @@ The same prefixing rules apply as with `import_server` for naming tools, resourc
The `prefix` parameter is optional. If omitted, components are mounted without modification.
+
+When mounting servers, custom HTTP routes defined with `@server.custom_route()` are also forwarded to the parent server, making them accessible through the parent's HTTP application.
+
+
#### Performance Considerations
Due to the "live link", operations like `list_tools()` on the parent server will be impacted by the speed of the slowest mounted server. In particular, HTTP-based mounted servers can introduce significant latency (300-400ms vs 1-2ms for local tools), and this slowdown affects the whole server, not just interactions with the HTTP-proxied tools. If performance is important, importing tools via [`import_server()`](#importing-static-composition) may be a more appropriate solution as it copies components once at startup rather than delegating requests at runtime.
@@ -320,62 +324,3 @@ This ensures that parent server tag policies act as a global policy for everythi
This filtering applies to both **listing** (e.g., `list_tools()`) and **execution** (e.g., `call_tool()`). Filtered components are neither visible nor executable through the parent server.
-
-## Resource Prefix Formats
-
-
-
-When mounting or importing servers, resource URIs are usually prefixed to avoid naming conflicts. FastMCP supports two different formats for resource prefixes:
-
-### Path Format (Default)
-
-In path format, prefixes are added to the path component of the URI:
-
-```
-resource://prefix/path/to/resource
-```
-
-This is the default format since FastMCP 2.4. This format is recommended because it avoids issues with URI protocol restrictions (like underscores not being allowed in protocol names).
-
-### Protocol Format (Legacy)
-
-In protocol format, prefixes are added as part of the protocol:
-
-```
-prefix+resource://path/to/resource
-```
-
-This was the default format in FastMCP before 2.4. While still supported, it's not recommended for new code as it can cause problems with prefix names that aren't valid in URI protocols.
-
-### Configuring the Prefix Format
-
-You can configure the prefix format globally in code:
-
-```python
-import fastmcp
-fastmcp.settings.resource_prefix_format = "protocol"
-```
-
-Or via environment variable:
-
-```bash
-FASTMCP_RESOURCE_PREFIX_FORMAT=protocol
-```
-
-Or per-server:
-
-```python
-from fastmcp import FastMCP
-
-# Create a server that uses legacy protocol format
-server = FastMCP("LegacyServer", resource_prefix_format="protocol")
-
-# Create a server that uses new path format
-server = FastMCP("NewServer", resource_prefix_format="path")
-```
-
-When mounting or importing servers, the prefix format of the parent server is used.
-
-
-When mounting servers, custom HTTP routes defined with `@server.custom_route()` are also forwarded to the parent server, making them accessible through the parent's HTTP application.
-
diff --git a/docs/servers/proxy.mdx b/docs/servers/proxy.mdx
index 354db48835..401005dea1 100644
--- a/docs/servers/proxy.mdx
+++ b/docs/servers/proxy.mdx
@@ -266,8 +266,6 @@ These rules apply uniformly whether you:
- Create a multi-server proxy from an `MCPConfig`
- Use `FastMCP.as_proxy()` directly
-For resource URI prefix formats (path vs legacy protocol style) and configuration options, see Server Composition → Resource Prefix Formats.
-
## Mirrored Components
diff --git a/docs/servers/server.mdx b/docs/servers/server.mdx
index 8c46654a03..7f013f2dc3 100644
--- a/docs/servers/server.mdx
+++ b/docs/servers/server.mdx
@@ -357,7 +357,6 @@ import fastmcp
# Access global settings
print(fastmcp.settings.log_level) # Default: "INFO"
print(fastmcp.settings.mask_error_details) # Default: False
-print(fastmcp.settings.resource_prefix_format) # Default: "path"
print(fastmcp.settings.strict_input_validation) # Default: False
print(fastmcp.settings.include_fastmcp_meta) # Default: True
```
@@ -365,7 +364,6 @@ print(fastmcp.settings.include_fastmcp_meta) # Default: True
Common global settings include:
- **`log_level`**: Logging level ("DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"), set with `FASTMCP_LOG_LEVEL`
- **`mask_error_details`**: Whether to hide detailed error information from clients, set with `FASTMCP_MASK_ERROR_DETAILS`
-- **`resource_prefix_format`**: How to format resource prefixes ("path" or "protocol"), set with `FASTMCP_RESOURCE_PREFIX_FORMAT`
- **`strict_input_validation`**: Controls tool input validation mode (default: False for flexible coercion), set with `FASTMCP_STRICT_INPUT_VALIDATION`. See [Input Validation Modes](/servers/tools#input-validation-modes)
- **`include_fastmcp_meta`**: Whether to include FastMCP metadata in component responses (default: True), set with `FASTMCP_INCLUDE_FASTMCP_META`
- **`env_file`**: Path to the environment file to load settings from (default: ".env"), set with `FASTMCP_ENV_FILE`. Useful when your project uses a `.env` file with syntax incompatible with python-dotenv
@@ -399,7 +397,6 @@ Global FastMCP settings can be configured via environment variables (prefixed wi
# Configure global FastMCP behavior
export FASTMCP_LOG_LEVEL=DEBUG
export FASTMCP_MASK_ERROR_DETAILS=True
-export FASTMCP_RESOURCE_PREFIX_FORMAT=protocol
export FASTMCP_STRICT_INPUT_VALIDATION=False
export FASTMCP_INCLUDE_FASTMCP_META=False
```
diff --git a/src/fastmcp/contrib/component_manager/component_service.py b/src/fastmcp/contrib/component_manager/component_service.py
index b23f96420c..9fb2e4fbae 100644
--- a/src/fastmcp/contrib/component_manager/component_service.py
+++ b/src/fastmcp/contrib/component_manager/component_service.py
@@ -105,16 +105,8 @@ async def _enable_resource(self, key: str) -> Resource | ResourceTemplate:
# 2. Check mounted servers using the filtered protocol path.
for mounted in reversed(self._server._mounted_servers):
if mounted.prefix:
- if has_resource_prefix(
- key,
- mounted.prefix,
- mounted.resource_prefix_format,
- ):
- key = remove_resource_prefix(
- key,
- mounted.prefix,
- mounted.resource_prefix_format,
- )
+ if has_resource_prefix(key, mounted.prefix):
+ key = remove_resource_prefix(key, mounted.prefix)
mounted_service = ComponentService(mounted.server)
mounted_resource: (
Resource | ResourceTemplate
@@ -148,16 +140,8 @@ async def _disable_resource(self, key: str) -> Resource | ResourceTemplate:
# 2. Check mounted servers using the filtered protocol path.
for mounted in reversed(self._server._mounted_servers):
if mounted.prefix:
- if has_resource_prefix(
- key,
- mounted.prefix,
- mounted.resource_prefix_format,
- ):
- key = remove_resource_prefix(
- key,
- mounted.prefix,
- mounted.resource_prefix_format,
- )
+ if has_resource_prefix(key, mounted.prefix):
+ key = remove_resource_prefix(key, mounted.prefix)
mounted_service = ComponentService(mounted.server)
mounted_resource: (
Resource | ResourceTemplate
diff --git a/src/fastmcp/server/server.py b/src/fastmcp/server/server.py
index 17da944c9c..dafe2a806b 100644
--- a/src/fastmcp/server/server.py
+++ b/src/fastmcp/server/server.py
@@ -156,7 +156,6 @@ def __init__(
auth: AuthProvider | NotSetT | None = NotSet,
middleware: Sequence[Middleware] | None = None,
lifespan: LifespanCallable | None = None,
- resource_prefix_format: Literal["protocol", "path"] | None = None,
mask_error_details: bool | None = None,
tools: Sequence[Tool | Callable[..., Any]] | None = None,
tool_transformations: Mapping[str, ToolTransformConfig] | None = None,
@@ -185,10 +184,6 @@ def __init__(
sampling_handler: ServerSamplingHandler[LifespanResultT] | None = None,
sampling_handler_behavior: Literal["always", "fallback"] | None = None,
):
- self.resource_prefix_format: Literal["protocol", "path"] = (
- resource_prefix_format or fastmcp.settings.resource_prefix_format
- )
-
self._additional_http_routes: list[BaseRoute] = []
self._mounted_servers: list[MountedServer] = []
self._tool_manager: ToolManager = ToolManager(
@@ -495,9 +490,7 @@ async def get_resources(self) -> dict[str, Resource]:
child_resources = await mounted.server.get_resources()
for key, resource in child_resources.items():
new_key = (
- add_resource_prefix(
- key, mounted.prefix, mounted.resource_prefix_format
- )
+ add_resource_prefix(key, mounted.prefix)
if mounted.prefix
else key
)
@@ -534,9 +527,7 @@ async def get_resource_templates(self) -> dict[str, ResourceTemplate]:
child_templates = await mounted.server.get_resource_templates()
for key, template in child_templates.items():
new_key = (
- add_resource_prefix(
- key, mounted.prefix, mounted.resource_prefix_format
- )
+ add_resource_prefix(key, mounted.prefix)
if mounted.prefix
else key
)
@@ -814,11 +805,7 @@ async def _list_resources(
key = resource.key
if mounted.prefix:
- key = add_resource_prefix(
- resource.key,
- mounted.prefix,
- mounted.resource_prefix_format,
- )
+ key = add_resource_prefix(resource.key, mounted.prefix)
resource = resource.model_copy(
key=key,
update={"name": f"{mounted.prefix}_{resource.name}"},
@@ -910,11 +897,7 @@ async def _list_resource_templates(
key = template.key
if mounted.prefix:
- key = add_resource_prefix(
- template.key,
- mounted.prefix,
- mounted.resource_prefix_format,
- )
+ key = add_resource_prefix(template.key, mounted.prefix)
template = template.model_copy(
key=key,
update={"name": f"{mounted.prefix}_{template.name}"},
@@ -1170,13 +1153,9 @@ async def _read_resource(
for mounted in reversed(self._mounted_servers):
key = uri_str
if mounted.prefix:
- if not has_resource_prefix(
- key, mounted.prefix, mounted.resource_prefix_format
- ):
+ if not has_resource_prefix(key, mounted.prefix):
continue
- key = remove_resource_prefix(
- key, mounted.prefix, mounted.resource_prefix_format
- )
+ key = remove_resource_prefix(key, mounted.prefix)
try:
# First, get the resource to check if parent's filter allows it
@@ -2197,7 +2176,6 @@ def mount(
mounted_server = MountedServer(
prefix=prefix,
server=server,
- resource_prefix_format=self.resource_prefix_format,
)
self._mounted_servers.append(mounted_server)
@@ -2298,9 +2276,7 @@ async def import_server(
# Import resources and templates from the server
for key, resource in (await server.get_resources()).items():
if prefix:
- resource_key = add_resource_prefix(
- key, prefix, self.resource_prefix_format
- )
+ resource_key = add_resource_prefix(key, prefix)
resource = resource.model_copy(
update={"name": f"{prefix}_{resource.name}"}, key=resource_key
)
@@ -2308,9 +2284,7 @@ async def import_server(
for key, template in (await server.get_resource_templates()).items():
if prefix:
- template_key = add_resource_prefix(
- key, prefix, self.resource_prefix_format
- )
+ template_key = add_resource_prefix(key, prefix)
template = template.model_copy(
update={"name": f"{prefix}_{template.name}"}, key=template_key
)
@@ -2572,13 +2546,10 @@ def generate_name(cls, name: str | None = None) -> str:
class MountedServer:
prefix: str | None
server: FastMCP[Any]
- resource_prefix_format: Literal["protocol", "path"] | None = None
-def add_resource_prefix(
- uri: str, prefix: str, prefix_format: Literal["protocol", "path"] | None = None
-) -> str:
- """Add a prefix to a resource URI.
+def add_resource_prefix(uri: str, prefix: str) -> str:
+ """Add a prefix to a resource URI using path formatting (resource://prefix/path).
Args:
uri: The original resource URI
@@ -2588,16 +2559,10 @@ def add_resource_prefix(
The resource URI with the prefix added
Examples:
- With new style:
```python
add_resource_prefix("resource://path/to/resource", "prefix")
"resource://prefix/path/to/resource"
```
- With legacy style:
- ```python
- add_resource_prefix("resource://path/to/resource", "prefix")
- "prefix+resource://path/to/resource"
- ```
With absolute path:
```python
add_resource_prefix("resource:///absolute/path", "prefix")
@@ -2610,54 +2575,32 @@ def add_resource_prefix(
if not prefix:
return uri
- # Get the server settings to check for legacy format preference
-
- if prefix_format is None:
- prefix_format = fastmcp.settings.resource_prefix_format
-
- if prefix_format == "protocol":
- # Legacy style: prefix+protocol://path
- return f"{prefix}+{uri}"
- elif prefix_format == "path":
- # New style: protocol://prefix/path
- # Split the URI into protocol and path
- match = URI_PATTERN.match(uri)
- if not match:
- raise ValueError(
- f"Invalid URI format: {uri}. Expected protocol://path format."
- )
+ # Split the URI into protocol and path
+ match = URI_PATTERN.match(uri)
+ if not match:
+ raise ValueError(f"Invalid URI format: {uri}. Expected protocol://path format.")
- protocol, path = match.groups()
+ protocol, path = match.groups()
- # Add the prefix to the path
- return f"{protocol}{prefix}/{path}"
- else:
- raise ValueError(f"Invalid prefix format: {prefix_format}")
+ # Add the prefix to the path
+ return f"{protocol}{prefix}/{path}"
-def remove_resource_prefix(
- uri: str, prefix: str, prefix_format: Literal["protocol", "path"] | None = None
-) -> str:
+def remove_resource_prefix(uri: str, prefix: str) -> str:
"""Remove a prefix from a resource URI.
Args:
uri: The resource URI with a prefix
prefix: The prefix to remove
- prefix_format: The format of the prefix to remove
+
Returns:
The resource URI with the prefix removed
Examples:
- With new style:
```python
remove_resource_prefix("resource://prefix/path/to/resource", "prefix")
"resource://path/to/resource"
```
- With legacy style:
- ```python
- remove_resource_prefix("prefix+resource://path/to/resource", "prefix")
- "resource://path/to/resource"
- ```
With absolute path:
```python
remove_resource_prefix("resource://prefix//absolute/path", "prefix")
@@ -2670,41 +2613,24 @@ def remove_resource_prefix(
if not prefix:
return uri
- if prefix_format is None:
- prefix_format = fastmcp.settings.resource_prefix_format
-
- if prefix_format == "protocol":
- # Legacy style: prefix+protocol://path
- legacy_prefix = f"{prefix}+"
- if uri.startswith(legacy_prefix):
- return uri[len(legacy_prefix) :]
- return uri
- elif prefix_format == "path":
- # New style: protocol://prefix/path
- # Split the URI into protocol and path
- match = URI_PATTERN.match(uri)
- if not match:
- raise ValueError(
- f"Invalid URI format: {uri}. Expected protocol://path format."
- )
+ # Split the URI into protocol and path
+ match = URI_PATTERN.match(uri)
+ if not match:
+ raise ValueError(f"Invalid URI format: {uri}. Expected protocol://path format.")
- protocol, path = match.groups()
+ protocol, path = match.groups()
- # Check if the path starts with the prefix followed by a /
- prefix_pattern = f"^{re.escape(prefix)}/(.*?)$"
- path_match = re.match(prefix_pattern, path)
- if not path_match:
- return uri
+ # Check if the path starts with the prefix followed by a /
+ prefix_pattern = f"^{re.escape(prefix)}/(.*?)$"
+ path_match = re.match(prefix_pattern, path)
+ if not path_match:
+ return uri
- # Return the URI without the prefix
- return f"{protocol}{path_match.group(1)}"
- else:
- raise ValueError(f"Invalid prefix format: {prefix_format}")
+ # Return the URI without the prefix
+ return f"{protocol}{path_match.group(1)}"
-def has_resource_prefix(
- uri: str, prefix: str, prefix_format: Literal["protocol", "path"] | None = None
-) -> bool:
+def has_resource_prefix(uri: str, prefix: str) -> bool:
"""Check if a resource URI has a specific prefix.
Args:
@@ -2715,16 +2641,10 @@ def has_resource_prefix(
True if the URI has the specified prefix, False otherwise
Examples:
- With new style:
```python
has_resource_prefix("resource://prefix/path/to/resource", "prefix")
True
```
- With legacy style:
- ```python
- has_resource_prefix("prefix+resource://path/to/resource", "prefix")
- True
- ```
With other path:
```python
has_resource_prefix("resource://other/path/to/resource", "prefix")
@@ -2737,28 +2657,13 @@ def has_resource_prefix(
if not prefix:
return False
- # Get the server settings to check for legacy format preference
-
- if prefix_format is None:
- prefix_format = fastmcp.settings.resource_prefix_format
-
- if prefix_format == "protocol":
- # Legacy style: prefix+protocol://path
- legacy_prefix = f"{prefix}+"
- return uri.startswith(legacy_prefix)
- elif prefix_format == "path":
- # New style: protocol://prefix/path
- # Split the URI into protocol and path
- match = URI_PATTERN.match(uri)
- if not match:
- raise ValueError(
- f"Invalid URI format: {uri}. Expected protocol://path format."
- )
+ # Split the URI into protocol and path
+ match = URI_PATTERN.match(uri)
+ if not match:
+ raise ValueError(f"Invalid URI format: {uri}. Expected protocol://path format.")
- _, path = match.groups()
+ _, path = match.groups()
- # Check if the path starts with the prefix followed by a /
- prefix_pattern = f"^{re.escape(prefix)}/"
- return bool(re.match(prefix_pattern, path))
- else:
- raise ValueError(f"Invalid prefix format: {prefix_format}")
+ # Check if the path starts with the prefix followed by a /
+ prefix_pattern = f"^{re.escape(prefix)}/"
+ return bool(re.match(prefix_pattern, path))
diff --git a/src/fastmcp/settings.py b/src/fastmcp/settings.py
index b8b579ab1c..3babc40448 100644
--- a/src/fastmcp/settings.py
+++ b/src/fastmcp/settings.py
@@ -155,19 +155,6 @@ def normalize_log_level(cls, v):
),
] = True
- resource_prefix_format: Annotated[
- Literal["protocol", "path"],
- Field(
- description=inspect.cleandoc(
- """
- When perfixing a resource URI, either use path formatting (resource://prefix/path)
- or protocol formatting (prefix+resource://path). Protocol formatting was the default in FastMCP < 2.4;
- path formatting is current default.
- """
- ),
- ),
- ] = "path"
-
client_init_timeout: Annotated[
float | None,
Field(
diff --git a/tests/deprecated/test_resource_prefixes.py b/tests/deprecated/test_resource_prefixes.py
deleted file mode 100644
index 44390f80f3..0000000000
--- a/tests/deprecated/test_resource_prefixes.py
+++ /dev/null
@@ -1,105 +0,0 @@
-"""Tests for legacy resource prefix behavior."""
-
-import pytest
-
-from fastmcp import Client, FastMCP
-from fastmcp.server.server import (
- add_resource_prefix,
- has_resource_prefix,
- remove_resource_prefix,
-)
-from fastmcp.utilities.tests import temporary_settings
-
-# reset deprecation warnings for this module
-pytestmark = pytest.mark.filterwarnings("default::DeprecationWarning")
-
-
-class TestLegacyResourcePrefixes:
- """Test the legacy resource prefix behavior."""
-
- def test_add_resource_prefix_legacy(self):
- """Test that add_resource_prefix uses the legacy format when resource_prefix_format is 'protocol'."""
- with temporary_settings(resource_prefix_format="protocol"):
- result = add_resource_prefix("resource://path/to/resource", "prefix")
- assert result == "prefix+resource://path/to/resource"
-
- # Empty prefix should return the original URI
- result = add_resource_prefix("resource://path/to/resource", "")
- assert result == "resource://path/to/resource"
-
- def test_remove_resource_prefix_legacy(self):
- """Test that remove_resource_prefix uses the legacy format when resource_prefix_format is 'protocol'."""
- with temporary_settings(resource_prefix_format="protocol"):
- result = remove_resource_prefix(
- "prefix+resource://path/to/resource", "prefix"
- )
- assert result == "resource://path/to/resource"
-
- # URI without the prefix should be returned as is
- result = remove_resource_prefix("resource://path/to/resource", "prefix")
- assert result == "resource://path/to/resource"
-
- # Empty prefix should return the original URI
- result = remove_resource_prefix("resource://path/to/resource", "")
- assert result == "resource://path/to/resource"
-
- def test_has_resource_prefix_legacy(self):
- """Test that has_resource_prefix uses the legacy format when resource_prefix_format is 'protocol'."""
- with temporary_settings(resource_prefix_format="protocol"):
- result = has_resource_prefix("prefix+resource://path/to/resource", "prefix")
- assert result is True
-
- result = has_resource_prefix("resource://path/to/resource", "prefix")
- assert result is False
-
- # Empty prefix should always return False
- result = has_resource_prefix("resource://path/to/resource", "")
- assert result is False
-
-
-async def test_mount_with_legacy_prefixes():
- """Test mounting a server with legacy resource prefixes."""
- with temporary_settings(resource_prefix_format="protocol"):
- main_server = FastMCP("MainServer")
- sub_server = FastMCP("SubServer")
-
- @sub_server.resource("resource://test")
- def get_test():
- return "test content"
-
- # Mount the server with a prefix (using old argument order for this legacy test)
- with pytest.warns(DeprecationWarning, match="Mount prefixes are now optional"):
- main_server.mount("sub", sub_server) # type: ignore[arg-type]
-
- # Check that the resource is prefixed using the legacy format
- resources = await main_server.get_resources()
-
- # In legacy format, the key would be "sub+resource://test"
- assert "sub+resource://test" in resources
-
- # Test accessing the resource through client
- async with Client(main_server) as client:
- result = await client.read_resource("sub+resource://test")
- # Different content types might be returned, but we just want to verify we got something
- assert len(result) > 0
-
-
-async def test_import_server_with_legacy_prefixes():
- """Test importing a server with legacy resource prefixes."""
- with temporary_settings(resource_prefix_format="protocol"):
- main_server = FastMCP("MainServer")
- sub_server = FastMCP("SubServer")
-
- @sub_server.resource("resource://test")
- def get_test():
- return "test content"
-
- # Import the server with a prefix (using old argument order for this legacy test)
- with pytest.warns(DeprecationWarning, match="Import prefixes are now optional"):
- await main_server.import_server("sub", sub_server) # type: ignore[arg-type]
-
- # Check that the resource is prefixed using the legacy format
- resources = await main_server.get_resources()
-
- # In legacy format, the key would be "sub+resource://test"
- assert "sub+resource://test" in resources
diff --git a/tests/deprecated/test_settings.py b/tests/deprecated/test_settings.py
index 84e2c250e5..c0692a14eb 100644
--- a/tests/deprecated/test_settings.py
+++ b/tests/deprecated/test_settings.py
@@ -178,7 +178,6 @@ def test_non_deprecated_kwargs_no_warnings(self):
on_duplicate_tools="warn",
on_duplicate_resources="error",
on_duplicate_prompts="replace",
- resource_prefix_format="path",
mask_error_details=True,
)
diff --git a/tests/server/test_import_server.py b/tests/server/test_import_server.py
index 0d5661e17c..446dbfcc94 100644
--- a/tests/server/test_import_server.py
+++ b/tests/server/test_import_server.py
@@ -391,25 +391,6 @@ def create_user(name: str, email: str):
assert content["email"] == "john@example.com"
-async def test_import_invalid_resource_prefix():
- main_app = FastMCP("MainApp")
- api_app = FastMCP("APIApp")
-
- # This test doesn't apply anymore with the new prefix format since we're not validating
- # the protocol://prefix/path format
- # Just import the server to maintain test coverage without deprecated parameters
- await main_app.import_server(api_app, "api")
-
-
-async def test_import_invalid_resource_separator():
- main_app = FastMCP("MainApp")
- api_app = FastMCP("APIApp")
-
- # This test is for maintaining coverage for importing with prefixes
- # We no longer pass the deprecated resource_separator parameter
- await main_app.import_server(api_app, "api")
-
-
async def test_import_with_no_prefix():
"""Test importing a server without providing a prefix."""
main_app = FastMCP("MainApp")
diff --git a/tests/server/test_mount.py b/tests/server/test_mount.py
index d02e86b6cb..844fd24649 100644
--- a/tests/server/test_mount.py
+++ b/tests/server/test_mount.py
@@ -66,22 +66,6 @@ def greet(name: str) -> str:
result = await client.call_tool("sub_greet", {"name": "World"})
assert result.data == "Hello, World!"
- async def test_mount_invalid_resource_prefix(self):
- main_app = FastMCP("MainApp")
- api_app = FastMCP("APIApp")
-
- # This test doesn't apply anymore with the new prefix format
- # just mount the server to maintain test coverage
- main_app.mount(api_app, "api:sub")
-
- async def test_mount_invalid_resource_separator(self):
- main_app = FastMCP("MainApp")
- api_app = FastMCP("APIApp")
-
- # This test doesn't apply anymore with the new prefix format
- # Mount without deprecated parameters
- main_app.mount(api_app, "api")
-
@pytest.mark.parametrize("prefix", ["", None])
async def test_mount_with_no_prefix(self, prefix):
main_app = FastMCP("MainApp")
diff --git a/tests/server/test_resource_prefix_formats.py b/tests/server/test_resource_prefix_formats.py
deleted file mode 100644
index c45731ccde..0000000000
--- a/tests/server/test_resource_prefix_formats.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""Tests for different resource prefix formats in server mounting and importing."""
-
-from fastmcp import FastMCP
-
-
-async def test_resource_prefix_format_in_constructor():
- """Test that the resource_prefix_format parameter is respected in the constructor."""
- server_path = FastMCP("PathFormat", resource_prefix_format="path")
- server_protocol = FastMCP("ProtocolFormat", resource_prefix_format="protocol")
-
- # Check that the format is stored correctly
- assert server_path.resource_prefix_format == "path"
- assert server_protocol.resource_prefix_format == "protocol"
-
- # Register resources
- @server_path.resource("resource://test")
- def get_test_path():
- return "test content"
-
- @server_protocol.resource("resource://test")
- def get_test_protocol():
- return "test content"
-
- # Create mount servers
- main_server_path = FastMCP("MainPath", resource_prefix_format="path")
- main_server_protocol = FastMCP("MainProtocol", resource_prefix_format="protocol")
-
- # Mount the servers
- main_server_path.mount(server_path, "sub")
- main_server_protocol.mount(server_protocol, "sub")
-
- # Check that the resources are prefixed correctly
- path_resources = await main_server_path.get_resources()
- protocol_resources = await main_server_protocol.get_resources()
-
- # Path format should be resource://sub/test
- assert "resource://sub/test" in path_resources
- # Protocol format should be sub+resource://test
- assert "sub+resource://test" in protocol_resources
-
-
-async def test_resource_prefix_format_in_import_server():
- """Test that the resource_prefix_format parameter is respected in import_server."""
- server = FastMCP("TestServer")
-
- @server.resource("resource://test")
- def get_test():
- return "test content"
-
- # Import with path format
- main_server_path = FastMCP("MainPath", resource_prefix_format="path")
- await main_server_path.import_server(server, "sub")
-
- # Import with protocol format
- main_server_protocol = FastMCP("MainProtocol", resource_prefix_format="protocol")
- await main_server_protocol.import_server(server, "sub")
-
- # Check that the resources are prefixed correctly
- path_resources = await main_server_path._resource_manager.get_resources()
- protocol_resources = await main_server_protocol._resource_manager.get_resources()
-
- # Path format should be resource://sub/test
- assert "resource://sub/test" in path_resources
- # Protocol format should be sub+resource://test
- assert "sub+resource://test" in protocol_resources
diff --git a/tests/server/test_server.py b/tests/server/test_server.py
index f319ad4386..7a21d78b23 100644
--- a/tests/server/test_server.py
+++ b/tests/server/test_server.py
@@ -1287,20 +1287,11 @@ async def test_mounted_server_matching_and_stripping(
"""Test that resource prefix utility functions correctly match and strip resource prefixes."""
from fastmcp.server.server import has_resource_prefix, remove_resource_prefix
- # Create a basic server to get the default resource prefix format
- server = FastMCP()
-
# Test matching
- assert (
- has_resource_prefix(uri, prefix, server.resource_prefix_format)
- == expected_match
- )
+ assert has_resource_prefix(uri, prefix) == expected_match
# Test stripping
- assert (
- remove_resource_prefix(uri, prefix, server.resource_prefix_format)
- == expected_strip
- )
+ assert remove_resource_prefix(uri, prefix) == expected_strip
async def test_import_server_with_new_prefix_format(self):
"""Test that import_server correctly uses the new prefix format."""