chore(mcp): fix stdio-safe CLI import order; quiet logging; bump hanzo-mcp to 0.8.4 and hanzo to 0.3.24

This commit is contained in:
2025-09-06 06:06:10 -05:00
parent 8e0b3c1149
commit a8a1ebc5e5
5 changed files with 57 additions and 29 deletions
+1 -1
View File
@@ -28,4 +28,4 @@ if os.environ.get("HANZO_MCP_TRANSPORT") == "stdio":
except ImportError:
pass
__version__ = "0.7.7"
__version__ = "0.8.4"
+45 -21
View File
@@ -1,4 +1,10 @@
"""Command-line interface for the Hanzo AI server."""
"""Command-line interface for the Hanzo AI server.
This module intentionally defers heavy imports (like the server and its
dependencies) until after we determine the transport and configure logging.
This prevents any stdout/stderr noise from imports that would corrupt the
MCP stdio transport used by Claude Desktop and other MCP clients.
"""
import os
import sys
@@ -9,52 +15,62 @@ import argparse
from typing import Any, cast
from pathlib import Path
from hanzo_mcp.server import HanzoMCPServer
def main() -> None:
"""Run the CLI for the Hanzo AI server."""
# Pre-parse arguments to check transport type early
import sys
# Pre-parse arguments to check transport type early, BEFORE importing server
early_parser = argparse.ArgumentParser(add_help=False)
early_parser.add_argument("--transport", choices=["stdio", "sse"], default="stdio")
early_args, _ = early_parser.parse_known_args()
# Configure logging VERY early based on transport
suppress_stdout = False
original_stdout = sys.stdout
if early_args.transport == "stdio":
# Set environment variable for server to detect stdio mode
import os
# Set environment variable for server to detect stdio mode as early as possible
os.environ["HANZO_MCP_TRANSPORT"] = "stdio"
# Aggressively quiet common dependency loggers/warnings in stdio mode
os.environ.setdefault("PYTHONWARNINGS", "ignore")
os.environ.setdefault("LITELLM_LOG", "ERROR")
os.environ.setdefault("LITELLM_LOGGING_LEVEL", "ERROR")
os.environ.setdefault("FASTMCP_LOG_LEVEL", "ERROR")
# For stdio transport, disable ALL logging immediately
from fastmcp.utilities.logging import configure_logging
# Suppress FastMCP logging (if available) and all standard logging
try:
from fastmcp.utilities.logging import configure_logging # type: ignore
# Set to ERROR to suppress INFO/WARNING messages from FastMCP
configure_logging(level="ERROR")
configure_logging(level="ERROR")
except Exception:
pass
# Also configure standard logging to ERROR level
logging.basicConfig(
level=logging.ERROR, # Only show errors
handlers=[], # No handlers for stdio to prevent protocol corruption
)
# Redirect stderr to devnull for stdio transport to prevent any output
import sys
sys.stderr = open(os.devnull, "w")
from hanzo_mcp import __version__
# Suppress stdout during potentially noisy imports unless user requested help/version
if not any(flag in sys.argv for flag in ("--version", "-h", "--help")):
sys.stdout = open(os.devnull, "w")
suppress_stdout = True
# Import the server only AFTER transport/logging have been configured to avoid import-time noise
from hanzo_mcp.server import HanzoMCPServer
# Avoid importing hanzo_mcp package just to get version (it can have side-effects).
try:
from importlib.metadata import version as _pkg_version # py3.8+
_version = _pkg_version("hanzo-mcp")
except Exception:
_version = "unknown"
parser = argparse.ArgumentParser(
description="MCP server implementing Hanzo AI capabilities"
)
parser.add_argument(
"--version", action="version", version=f"hanzo-mcp {__version__}"
)
parser.add_argument("--version", action="version", version=f"hanzo-mcp {_version}")
_ = parser.add_argument(
"--transport",
@@ -199,6 +215,14 @@ def main() -> None:
args = parser.parse_args()
# Restore stdout after parsing, before any explicit output or server start
if suppress_stdout:
try:
sys.stdout.close() # Close devnull handle
except Exception:
pass
sys.stdout = original_stdout
# Cast args attributes to appropriate types to avoid 'Any' warnings
name: str = cast(str, args.name)
install: bool = cast(bool, args.install)
+1 -2
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "hanzo-mcp"
version = "0.8.3"
version = "0.8.4"
description = "The Zen of Hanzo MCP: One server to rule them all. The ultimate MCP that orchestrates all others."
readme = "README.md"
requires-python = ">=3.12"
@@ -166,4 +166,3 @@ exclude_lines = [
[tool.coverage.html]
directory = "htmlcov"
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "hanzo"
version = "0.3.23"
version = "0.3.24"
description = "Hanzo AI - Complete AI Infrastructure Platform with CLI, Router, MCP, and Agent Runtime"
authors = [
{name = "Hanzo AI", email = "[email protected]"},
+9 -4
View File
@@ -6,11 +6,16 @@ import click
def main():
"""Start the Hanzo MCP server."""
try:
from hanzo_mcp.server import main as mcp_main
"""Start the Hanzo MCP server.
mcp_main()
This wrapper defers to hanzo_mcp.cli:main so that the CLI can parse
transport flags and configure logging BEFORE importing any heavy modules,
preventing stdio protocol corruption.
"""
try:
from hanzo_mcp.cli import main as cli_main
cli_main()
except ImportError:
click.echo(
"Error: hanzo-mcp is not installed. Please run: pip install hanzo[mcp] or pip install hanzo[all]",