From 05ac9457b82ae82c83d7c1bc4435ae6cbff35696 Mon Sep 17 00:00:00 2001 From: William Easton Date: Thu, 6 Nov 2025 09:11:16 -0600 Subject: [PATCH] Fix duplicate keyword argument error in configure_logging (#2381) Allow traceback-related kwargs to override defaults by building a dict with defaults first, then updating with user-provided values. Fixes #2356 Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: William Easton --- src/fastmcp/utilities/logging.py | 22 +++++++++++++--------- tests/utilities/test_logging.py | 28 +++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/fastmcp/utilities/logging.py b/src/fastmcp/utilities/logging.py index e2361bb03..476bdff23 100644 --- a/src/fastmcp/utilities/logging.py +++ b/src/fastmcp/utilities/logging.py @@ -74,15 +74,19 @@ def configure_logging( import mcp import pydantic - traceback_handler = RichHandler( - console=Console(stderr=True), - show_path=False, - show_level=False, - rich_tracebacks=enable_rich_tracebacks, - tracebacks_max_frames=3, - tracebacks_suppress=[fastmcp, mcp, pydantic], - **rich_kwargs, - ) + # Build traceback kwargs with defaults that can be overridden + traceback_kwargs = { + "console": Console(stderr=True), + "show_path": False, + "show_level": False, + "rich_tracebacks": enable_rich_tracebacks, + "tracebacks_max_frames": 3, + "tracebacks_suppress": [fastmcp, mcp, pydantic], + } + # Override defaults with user-provided values + traceback_kwargs.update(rich_kwargs) + + traceback_handler = RichHandler(**traceback_kwargs) # type: ignore[arg-type] traceback_handler.setFormatter(formatter) traceback_handler.addFilter(lambda record: record.exc_info is not None) diff --git a/tests/utilities/test_logging.py b/tests/utilities/test_logging.py index e6d8086fc..58e53eb12 100644 --- a/tests/utilities/test_logging.py +++ b/tests/utilities/test_logging.py @@ -1,6 +1,6 @@ import logging -from fastmcp.utilities.logging import get_logger +from fastmcp.utilities.logging import configure_logging, get_logger def test_logging_doesnt_affect_other_loggers(caplog): @@ -28,3 +28,29 @@ def test_logging_doesnt_affect_other_loggers(caplog): finally: logging.getLogger("fastmcp").setLevel(original_level) + + +def test_configure_logging_with_traceback_kwargs(): + """Test that traceback-related kwargs can be passed without causing duplicate argument errors.""" + # This should not raise TypeError about duplicate keyword arguments + configure_logging(enable_rich_tracebacks=True, tracebacks_max_frames=20) + + # Verify the logger was configured + logger = logging.getLogger("fastmcp") + assert logger.handlers + assert len(logger.handlers) == 2 # One for normal logs, one for tracebacks + + +def test_configure_logging_traceback_defaults_can_be_overridden(): + """Test that default traceback settings can be overridden by kwargs.""" + configure_logging( + enable_rich_tracebacks=True, + tracebacks_max_frames=20, + show_path=True, + show_level=True, + ) + + logger = logging.getLogger("fastmcp") + assert logger.handlers + # The traceback handler should have been created with custom values + # We can't directly inspect RichHandler internals easily, but we verified no error was raised