Additional MCP and test clean-up

This commit is contained in:
William Easton 2025-08-13 12:52:05 -05:00
commit 22d3e1452c
No known key found for this signature in database
3 changed files with 29 additions and 29 deletions

View file

@ -7,29 +7,6 @@ from fastmcp.mcp_config import (
)
from fastmcp.server.server import FastMCP
# def composite_server_from_mcp_config(
# config: MCPConfig, name_as_prefix: bool = True
# ) -> tuple[FastMCP[None], list[ClientTransport]]:
# """A utility function to create a composite server from an MCPConfig, returns the underlying
# transports for each server.
# """
# composite_server = FastMCP[None]()
# transports = mount_mcp_config_into_server(config, composite_server, name_as_prefix)
# return composite_server, transports
# def mount_mcp_config_into_server(
# config: MCPConfig,
# server: FastMCP[Any],
# name_as_prefix: bool = True,
# ) -> None:
# """A utility function to mount the servers from an MCPConfig into a FastMCP server, returns the underlying
# transports for each server.
# """
# for name, server_to_mount, transport in mcp_config_to_servers_and_transports(config):
# server.mount(server=server_to_mount, prefix=name if name_as_prefix else None)
def mcp_config_to_servers_and_transports(
config: MCPConfig,
@ -40,6 +17,7 @@ def mcp_config_to_servers_and_transports(
for name, mcp_server in config.mcpServers.items()
]
def mcp_server_type_to_servers_and_transports(
name: str,
mcp_server: MCPServerTypes,
@ -48,13 +26,12 @@ def mcp_server_type_to_servers_and_transports(
from fastmcp.mcp_config import (
TransformingRemoteMCPServer,
TransformingStdioMCPServer,
)
)
server: FastMCP[Any]
transport: ClientTransport
if isinstance(
mcp_server, TransformingRemoteMCPServer | TransformingStdioMCPServer
):
if isinstance(mcp_server, TransformingRemoteMCPServer | TransformingStdioMCPServer):
server, transport = mcp_server._to_server_and_transport()
else:
transport = mcp_server.to_transport()

View file

@ -1,6 +1,7 @@
import asyncio
import gc
import inspect
import os
import weakref
import psutil
@ -10,6 +11,10 @@ from fastmcp import Client
from fastmcp.client.transports import PythonStdioTransport, StdioTransport
def running_under_debugger():
return os.environ.get("DEBUGPY_RUNNING") == "true"
def gc_collect_harder():
gc.collect()
gc.collect()
@ -69,6 +74,9 @@ class TestKeepAlive:
assert pid1 == pid2
@pytest.mark.skipif(
running_under_debugger(), reason="Debugger holds a reference to the transport"
)
async def test_keep_alive_true_exit_scope_kills_transport(self, stdio_script):
transport_weak_ref: weakref.ref[PythonStdioTransport] | None = None
@ -83,12 +91,14 @@ class TestKeepAlive:
gc_collect_harder()
# When debugging, the debugger holds extra references so this test
# will pass when running and fail under the debugger.
# This test will fail while debugging because the debugger holds a reference to the underlying transport
assert transport_weak_ref
transport = transport_weak_ref()
assert transport is None
@pytest.mark.skipif(
running_under_debugger(), reason="Debugger holds a reference to the transport"
)
async def test_keep_alive_true_exit_scope_kills_client(self, stdio_script):
pid: int | None = None
@ -107,6 +117,8 @@ class TestKeepAlive:
gc_collect_harder()
# This test may fail/hang while debugging because the debugger holds a reference to the underlying transport
with pytest.raises(psutil.NoSuchProcess):
while True:
psutil.Process(pid)

View file

@ -2,6 +2,7 @@ import asyncio
import gc
import inspect
import logging
import os
import tempfile
from collections.abc import AsyncGenerator
from pathlib import Path
@ -32,6 +33,10 @@ from fastmcp.mcp_config import (
from fastmcp.tools.tool import Tool as FastMCPTool
def running_under_debugger():
return os.environ.get("DEBUGPY_RUNNING") == "true"
def gc_collect_harder():
gc.collect()
gc.collect()
@ -237,6 +242,9 @@ async def test_multi_client(tmp_path: Path):
assert result_2.data == 3
@pytest.mark.skipif(
running_under_debugger(), reason="Debugger holds a reference to the transport"
)
async def test_multi_client_lifespan(tmp_path: Path):
pid_1: int | None = None
pid_2: int | None = None
@ -285,6 +293,8 @@ async def test_multi_client_lifespan(tmp_path: Path):
gc_collect_harder()
# This test will fail while debugging because the debugger holds a reference to the underlying transport
with pytest.raises(psutil.NoSuchProcess):
while True:
psutil.Process(pid_1)
@ -295,6 +305,7 @@ async def test_multi_client_lifespan(tmp_path: Path):
psutil.Process(pid_2)
await asyncio.sleep(0.1)
async def test_multi_client_force_close(tmp_path: Path):
server_script = inspect.cleandoc("""
from fastmcp import FastMCP