AggregateProvider (used by mount()) has three issues that affect server composition reliability:
1. Duplicate tool names across providers go undetected
When two providers contribute tools with the same name (e.g., mounting two sub-servers with the same namespace), _collect_list_results silently returns both. list_tools() shows duplicates and get_tool() returns whichever provider responds first. The parent server's on_duplicate setting is never checked across provider boundaries.
from fastmcp import FastMCP
import asyncio
async def main():
main = FastMCP("Main", on_duplicate="error")
sub1, sub2 = FastMCP("Sub1"), FastMCP("Sub2")
@sub1.tool
def greet(name: str) -> str: return f"Sub1: {name}"
@sub2.tool
def greet(name: str) -> str: return f"Sub2: {name}"
main.mount(sub1, "ns")
main.mount(sub2, "ns") # No error!
tools = await main.list_tools()
print([t.name for t in tools]) # ['ns_greet', 'ns_greet']
asyncio.run(main())
2. Provider errors silently swallowed at DEBUG level
When a provider raises during list_tools() / list_resources() etc., _collect_list_results logs at DEBUG level (line 113) and skips the provider. All components from that provider silently disappear with no user-visible indication. This should be WARNING.
3. mask_error_details not propagated to mounted sub-servers
Setting mask_error_details=True on the parent server doesn't apply to errors from mounted sub-servers. Sensitive details (database passwords, internal paths, etc.) leak through child server error messages.
parent = FastMCP("parent", mask_error_details=True)
child = FastMCP("child") # No masking
@child.tool
def secret_tool() -> str:
raise ValueError("DATABASE_PASSWORD=hunter2")
parent.mount(child, "ns")
# Error response includes "DATABASE_PASSWORD=hunter2"
🤖 Generated with Claude Code
AggregateProvider(used bymount()) has three issues that affect server composition reliability:1. Duplicate tool names across providers go undetected
When two providers contribute tools with the same name (e.g., mounting two sub-servers with the same namespace),
_collect_list_resultssilently returns both.list_tools()shows duplicates andget_tool()returns whichever provider responds first. The parent server'son_duplicatesetting is never checked across provider boundaries.2. Provider errors silently swallowed at DEBUG level
When a provider raises during
list_tools()/list_resources()etc.,_collect_list_resultslogs atDEBUGlevel (line 113) and skips the provider. All components from that provider silently disappear with no user-visible indication. This should beWARNING.3.
mask_error_detailsnot propagated to mounted sub-serversSetting
mask_error_details=Trueon the parent server doesn't apply to errors from mounted sub-servers. Sensitive details (database passwords, internal paths, etc.) leak through child server error messages.🤖 Generated with Claude Code