"""Logging to stderr (stdout is the protocol channel in stdio mode).""" from __future__ import annotations import json import logging import sys from datetime import UTC, datetime class JsonFormatter(logging.Formatter): """One JSON object per line, for log aggregation.""" def format(self, record: logging.LogRecord) -> str: entry = { "time": datetime.fromtimestamp(record.created, tz=UTC).isoformat(timespec="milliseconds"), "level": record.levelname, "logger": record.name, "message": record.getMessage(), } if record.exc_info: entry["exception"] = self.formatException(record.exc_info) return json.dumps(entry, ensure_ascii=False) def setup_logging(level: str = "INFO", fmt: str = "text") -> None: handler = logging.StreamHandler(sys.stderr) if fmt == "json": handler.setFormatter(JsonFormatter()) else: handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)-7s %(name)s: %(message)s")) logging.basicConfig(level=level.upper(), handlers=[handler], force=True) # The SDK logs every request at INFO; keep it quieter unless debugging. if level.upper() != "DEBUG": for noisy in ("mcp.server.lowlevel.server", "mcp.server.streamable_http", "mcp.server.streamable_http_manager"): logging.getLogger(noisy).setLevel(logging.WARNING)