From 7533de43fa0d83a8a541a7d580fc32e73d31886b Mon Sep 17 00:00:00 2001 From: nigel brown Date: Fri, 7 Nov 2025 12:36:22 +0000 Subject: [PATCH 1/4] fix: handle non-semver ToolHive versions and use configurable timeout - Update _parse_toolhive_version to gracefully handle development builds that don't follow semver (e.g., 'build-7c3a3077') by returning a default version '0.0.0-dev' instead of raising an error - Replace hardcoded 1.0s timeout with self.timeout in _is_toolhive_available for better configurability --- src/mcp_optimizer/toolhive/toolhive_client.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/mcp_optimizer/toolhive/toolhive_client.py b/src/mcp_optimizer/toolhive/toolhive_client.py index 7d603f3..eef740a 100644 --- a/src/mcp_optimizer/toolhive/toolhive_client.py +++ b/src/mcp_optimizer/toolhive/toolhive_client.py @@ -149,13 +149,22 @@ def _discover_port(self, port: int | None = None) -> None: asyncio.run(self._discover_port_async(port)) def _parse_toolhive_version(self, version_str: str) -> Version: - """Parse ToolHive version string into a Version object.""" + """Parse ToolHive version string into a Version object. + + For development/build versions that don't follow SemVer, returns a default version. + """ try: version = Version.parse(version_str.replace("v", "")) return version except (ValueError, TypeError) as e: - logger.warning("Invalid semver version string", version=version_str, error=str(e)) - raise ToolhiveScanError(f"Invalid ToolHive version string: {version_str}") from e + # For development builds like "build-7c3a3077", use a default version + # This allows the connection to succeed while still logging the issue + logger.info( + "Using default version for non-semver ToolHive build", + version=version_str, + default_version="0.0.0-dev" + ) + return Version.parse("0.0.0-dev") async def _is_toolhive_available(self, host: str, port: int) -> tuple[Version, int]: """ @@ -165,7 +174,7 @@ async def _is_toolhive_available(self, host: str, port: int) -> tuple[Version, i Tuple of (Version object, port) if available, raises ToolhiveScanError otherwise """ try: - async with httpx.AsyncClient(timeout=1.0) as client: + async with httpx.AsyncClient(timeout=self.timeout) as client: response = await client.get(f"http://{host}:{port}/api/v1beta/version") response.raise_for_status() From f0704f773164bc5777c8932be91e0a7bfbdbfc6f Mon Sep 17 00:00:00 2001 From: nigel brown Date: Fri, 7 Nov 2025 16:40:53 +0000 Subject: [PATCH 2/4] lint Signed-off-by: nigel brown --- src/mcp_optimizer/toolhive/toolhive_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mcp_optimizer/toolhive/toolhive_client.py b/src/mcp_optimizer/toolhive/toolhive_client.py index eef740a..12e8cf6 100644 --- a/src/mcp_optimizer/toolhive/toolhive_client.py +++ b/src/mcp_optimizer/toolhive/toolhive_client.py @@ -156,7 +156,7 @@ def _parse_toolhive_version(self, version_str: str) -> Version: try: version = Version.parse(version_str.replace("v", "")) return version - except (ValueError, TypeError) as e: + except (ValueError, TypeError): # For development builds like "build-7c3a3077", use a default version # This allows the connection to succeed while still logging the issue logger.info( From 5c007ddbebfb3c92c55a4f2fbe4f5aea6f8e3ec8 Mon Sep 17 00:00:00 2001 From: nigel brown Date: Fri, 7 Nov 2025 16:44:20 +0000 Subject: [PATCH 3/4] more checks Signed-off-by: nigel brown --- tests/test_toolhive_client.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_toolhive_client.py b/tests/test_toolhive_client.py index 43cf2c4..3e5f1f9 100644 --- a/tests/test_toolhive_client.py +++ b/tests/test_toolhive_client.py @@ -356,6 +356,7 @@ async def test_is_toolhive_available_validates_response_format(monkeypatch): # """ client = ToolhiveClient.__new__(ToolhiveClient) client.thv_host = "localhost" + client.timeout = 5 # Set the timeout attribute that _is_toolhive_available needs # Test case 1: Service returns 200 OK but response has no 'version' field mock_response_wrong_format = Mock() From 81b36c96fa8a4c7e0921840c8f3f78c41e68b2b2 Mon Sep 17 00:00:00 2001 From: nigel brown Date: Fri, 7 Nov 2025 17:09:45 +0000 Subject: [PATCH 4/4] chore: trigger CI after tag cleanup