Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 38 additions & 27 deletions hexstrike_mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,34 +160,36 @@ def __init__(self, server_url: str, timeout: int = DEFAULT_REQUEST_TIMEOUT):
self.session = requests.Session()

# Try to connect to server with retries
connected = False
for i in range(MAX_RETRIES):
try:
logger.info(f"🔗 Attempting to connect to HexStrike AI API at {server_url} (attempt {i+1}/{MAX_RETRIES})")
# First try a direct connection test before using the health endpoint
# If running under an MCP host (stdio not attached to a TTY), skip HTTP health checks to avoid bootstrap delays.
if sys.stdin.isatty() or sys.stdout.isatty():
connected = False
for i in range(MAX_RETRIES):
try:
test_response = self.session.get(f"{self.server_url}/health", timeout=5)
test_response.raise_for_status()
health_check = test_response.json()
connected = True
logger.info(f"🎯 Successfully connected to HexStrike AI API Server at {server_url}")
logger.info(f"🏥 Server health status: {health_check.get('status', 'unknown')}")
logger.info(f"📊 Server version: {health_check.get('version', 'unknown')}")
break
except requests.exceptions.ConnectionError:
logger.warning(f"🔌 Connection refused to {server_url}. Make sure the HexStrike AI server is running.")
time.sleep(2) # Wait before retrying
logger.info(f"🔗 Attempting to connect to HexStrike AI API at {server_url} (attempt {i+1}/{MAX_RETRIES})")
try:
test_response = self.session.get(f"{self.server_url}/health", timeout=5)
test_response.raise_for_status()
health_check = test_response.json()
connected = True
logger.info(f"🎯 Successfully connected to HexStrike AI API Server at {server_url}")
logger.info(f"🏥 Server health status: {health_check.get('status', 'unknown')}")
logger.info(f"📊 Server version: {health_check.get('version', 'unknown')}")
break
except requests.exceptions.ConnectionError:
logger.warning(f"🔌 Connection refused to {server_url}. Make sure the HexStrike AI server is running.")
time.sleep(2)
except Exception as e:
logger.warning(f"⚠️ Connection test failed: {str(e)}")
time.sleep(2)
except Exception as e:
logger.warning(f"⚠️ Connection test failed: {str(e)}")
time.sleep(2) # Wait before retrying
except Exception as e:
logger.warning(f"❌ Connection attempt {i+1} failed: {str(e)}")
time.sleep(2) # Wait before retrying

if not connected:
error_msg = f"Failed to establish connection to HexStrike AI API Server at {server_url} after {MAX_RETRIES} attempts"
logger.error(error_msg)
# We'll continue anyway to allow the MCP server to start, but tools will likely fail
logger.warning(f"❌ Connection attempt {i+1} failed: {str(e)}")
time.sleep(2)
if not connected:
error_msg = f"Failed to establish connection to HexStrike AI API Server at {server_url} after {MAX_RETRIES} attempts"
logger.error(error_msg)
# continue anyway; MCP stdio server will still start
else:
logger.info("🧪 Stdio host detected (non-TTY). Skipping HTTP health checks and starting MCP stdio immediately.")

def safe_get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
"""
Expand Down Expand Up @@ -5459,7 +5461,16 @@ def main():
mcp = setup_mcp_server(hexstrike_client)
logger.info("🚀 Starting HexStrike AI MCP server")
logger.info("🤖 Ready to serve AI agents with enhanced cybersecurity capabilities")
mcp.run()
# Minimal stdio fallback for MCP clients that require stdio transport.
try:
mcp.run()
except AttributeError:
# Older/newer FastMCP variants expose an async stdio runner.
import asyncio
if hasattr(mcp, "run_stdio"):
asyncio.run(mcp.run_stdio())
else:
raise
except Exception as e:
logger.error(f"💥 Error starting MCP server: {str(e)}")
import traceback
Expand Down