diff --git a/src/ghydramcp/mixins/instances.py b/src/ghydramcp/mixins/instances.py index 51a3df2..4b93269 100644 --- a/src/ghydramcp/mixins/instances.py +++ b/src/ghydramcp/mixins/instances.py @@ -166,13 +166,20 @@ class InstancesMixin(GhydraMixinBase): Returns: Confirmation message with instance details """ + # Register lazily without blocking HTTP calls. + # If the instance is unknown, create a stub entry — the first + # actual tool call (functions_list, etc.) will validate the + # connection and fail fast with a clear error if unreachable. with self._instances_lock: - needs_register = port not in self._instances - - if needs_register: - result = self.register_instance(port) - if "Failed" in result or "Error" in result: - return result + if port not in self._instances: + config = get_config() + self._instances[port] = { + "url": f"http://{config.ghidra_host}:{port}", + "project": "", + "file": "", + "registered_at": time.time(), + "lazy": True, + } self.set_current_port(port) diff --git a/src/ghydramcp/server.py b/src/ghydramcp/server.py index 767572d..959e4b1 100644 --- a/src/ghydramcp/server.py +++ b/src/ghydramcp/server.py @@ -105,10 +105,14 @@ def create_server( def _periodic_discovery(interval: int = 30): """Background thread for periodic instance discovery. + Uses a short timeout per port so a full scan completes quickly + even when most ports are unreachable. + Args: interval: Seconds between discovery attempts """ - from .core.http_client import safe_get + import requests as _requests + from .mixins.base import GhydraMixinBase config = get_config() @@ -116,19 +120,26 @@ def _periodic_discovery(interval: int = 30): while True: time.sleep(interval) try: - # Quick scan of common ports + # Quick scan — use discovery_timeout (0.5s), NOT request_timeout (30s) for port in config.quick_discovery_range: try: - response = safe_get(port, "") - if response.get("success", False): - with GhydraMixinBase._instances_lock: - if port not in GhydraMixinBase._instances: - GhydraMixinBase._instances[port] = { - "url": f"http://{config.ghidra_host}:{port}", - "project": response.get("project", ""), - "file": response.get("file", ""), - "discovered_at": time.time(), - } + url = f"http://{config.ghidra_host}:{port}/" + resp = _requests.get( + url, + timeout=config.discovery_timeout, + headers={"Accept": "application/json"}, + ) + if resp.ok: + response = resp.json() + if response.get("success", False): + with GhydraMixinBase._instances_lock: + if port not in GhydraMixinBase._instances: + GhydraMixinBase._instances[port] = { + "url": url.rstrip("/"), + "project": response.get("project", ""), + "file": response.get("file", ""), + "discovered_at": time.time(), + } except Exception: pass except Exception: