Module fastmcp_extensions.utils.test_tool
MCP tool testing utilities.
This module provides utilities for testing MCP tools directly with JSON arguments, supporting both stdio and HTTP transports.
Usage (stdio transport):
python -m fastmcp_extensions.utils.test_tool –app
Example:
python -m fastmcp_extensions.utils.test_tool --app my_mcp_server.server:app list_tools '{}'
Poe task configuration:
[tool.poe.tasks.mcp-tool-test]
cmd = "python -m fastmcp_extensions.utils.test_tool --app my_mcp_server.server:app"
help = "Test MCP tools with JSON arguments"
Usage (HTTP transport):
python -m fastmcp_extensions.utils.test_tool –http –app
Example:
python -m fastmcp_extensions.utils.test_tool --http --app my_mcp_server.server:app
python -m fastmcp_extensions.utils.test_tool --http --app my_mcp_server.server:app get_version '{}'
Poe task configuration:
[tool.poe.tasks.mcp-tool-test-http]
cmd = "python -m fastmcp_extensions.utils.test_tool --http --app my_mcp_server.server:app"
help = "Test MCP tools over HTTP transport"
Functions
async def call_mcp_tool(app: FastMCP, tool_name: str, args: dict[str, Any]) ‑> object-
Expand source code
async def call_mcp_tool(app: FastMCP, tool_name: str, args: dict[str, Any]) -> object: """Call an MCP tool using the FastMCP client.""" async with Client(app) as client: return await client.call_tool(tool_name, args)Call an MCP tool using the FastMCP client.
def find_free_port() ‑> int-
Expand source code
def find_free_port() -> int: """Find an available port on localhost.""" with socket.socket() as s: s.bind(("127.0.0.1", 0)) return s.getsockname()[1]Find an available port on localhost.
async def list_mcp_tools(app: FastMCP) ‑> list[Any]-
Expand source code
async def list_mcp_tools(app: FastMCP) -> list[Any]: """List all available MCP tools.""" async with Client(app) as client: return await client.list_tools()List all available MCP tools.
async def run_http_tool_test(app: FastMCP,
port: int | None = None,
tool_name: str | None = None,
args: dict[str, Any] | None = None) ‑> int-
Expand source code
async def run_http_tool_test( app: FastMCP, port: int | None = None, tool_name: str | None = None, args: dict[str, Any] | None = None, ) -> int: """Run a tool test over HTTP transport using the app directly.""" import uvicorn if port is None: port = find_free_port() url = f"http://127.0.0.1:{port}/mcp" os.environ["MCP_HTTP_PORT"] = str(port) print(f"Starting HTTP server on port {port}...", file=sys.stderr) server_error: Exception | None = None def run_server() -> None: nonlocal server_error try: uvicorn.run( app.http_app(), host="127.0.0.1", port=port, log_level="error", ) except Exception as e: server_error = e server_thread = threading.Thread(target=run_server, daemon=True) server_thread.start() try: if not await wait_for_server(url): if server_error: print(f"Server error: {server_error}", file=sys.stderr) print(f"Server failed to start on port {port}", file=sys.stderr) return 1 async with Client(url) as client: tools = await client.list_tools() print(f"HTTP transport OK - {len(tools)} tools available") if tool_name: print(f"Calling tool: {tool_name}", file=sys.stderr) result = await client.call_tool(tool_name, args or {}) if hasattr(result, "text"): print(result.text) else: print(str(result)) return 0 finally: passRun a tool test over HTTP transport using the app directly.
def run_tool_test(app: FastMCP, tool_name: str, json_args: str) ‑> None-
Expand source code
def run_tool_test( app: FastMCP, tool_name: str, json_args: str, ) -> None: """Run a tool test with JSON arguments and print the result.""" args: dict[str, Any] = json.loads(json_args) result = asyncio.run(call_mcp_tool(app, tool_name, args)) if hasattr(result, "text"): print(result.text) else: print(str(result))Run a tool test with JSON arguments and print the result.
async def wait_for_server(url: str, timeout: float = 10.0) ‑> bool-
Expand source code
async def wait_for_server(url: str, timeout: float = SERVER_STARTUP_TIMEOUT) -> bool: """Wait for the MCP server to be ready by attempting to list tools.""" deadline = asyncio.get_event_loop().time() + timeout while asyncio.get_event_loop().time() < deadline: try: async with Client(url) as client: await client.list_tools() return True except Exception: await asyncio.sleep(POLL_INTERVAL) return FalseWait for the MCP server to be ready by attempting to list tools.