Skip to content
Open
Show file tree
Hide file tree
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
10 changes: 7 additions & 3 deletions src/mcp/server/mcpserver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
)
from mcp.server.mcpserver.tools import Tool, ToolManager
from mcp.server.mcpserver.utilities.context_injection import find_context_parameter
from mcp.server.mcpserver.utilities.logging import configure_logging, get_logger
from mcp.server.mcpserver.utilities.logging import configure_logging as _configure_logging
from mcp.server.mcpserver.utilities.logging import get_logger
from mcp.server.request_state import RequestStateBoundary, RequestStateSecurity
from mcp.server.sse import SseServerTransport
from mcp.server.stdio import stdio_server
Expand Down Expand Up @@ -174,6 +175,7 @@ def __init__(
extensions: Sequence[Extension] | None = None,
debug: bool = False,
log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] = "INFO",
configure_logging: bool = True,
warn_on_duplicate_resources: bool = True,
warn_on_duplicate_tools: bool = True,
warn_on_duplicate_prompts: bool = True,
Expand Down Expand Up @@ -256,8 +258,10 @@ def __init__(
self._token_verifier = ProviderTokenVerifier(auth_server_provider)
self._custom_starlette_routes: list[Route] = []

# Configure logging
configure_logging(self.settings.log_level)
# Configure logging (opt-out via configure_logging=False for applications
# that embed MCPServer and manage their own logging setup; see #1656)
if configure_logging:
_configure_logging(self.settings.log_level)

self._extensions: list[Extension] = []
for extension in extensions or ():
Expand Down
35 changes: 35 additions & 0 deletions tests/server/mcpserver/test_configure_logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from unittest.mock import patch

from mcp.server.mcpserver import MCPServer


class TestConfigureLogging:
def test_default_calls_configure_logging(self):
"""By default, `MCPServer` configures logging on construction (the
pre-existing behavior, preserved for backwards compatibility)."""
with patch("mcp.server.mcpserver.server._configure_logging") as spy:
MCPServer("test-server")

spy.assert_called_once_with("INFO")

def test_configure_logging_false_skips_configuration(self):
"""`configure_logging=False` opts a server out of calling
`_configure_logging` (and therefore `logging.basicConfig()`)
entirely, so an application can safely manage its own logging
setup without the server racing to configure the root logger
first.

See: https://github.com/modelcontextprotocol/python-sdk/issues/1656
"""
with patch("mcp.server.mcpserver.server._configure_logging") as spy:
MCPServer("test-server", configure_logging=False)

spy.assert_not_called()

def test_configure_logging_true_still_calls_configure_logging(self):
"""Explicitly passing `configure_logging=True` behaves the same as
the default (sanity check for the new parameter's positive case)."""
with patch("mcp.server.mcpserver.server._configure_logging") as spy:
MCPServer("test-server", configure_logging=True, log_level="DEBUG")

spy.assert_called_once_with("DEBUG")
Loading