Skip to content

Commit d97f15b

Browse files
fix: Update context logging type hints to match MCP spec
1 parent c2ca8e0 commit d97f15b

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

Diff for: src/mcp/server/fastmcp/server.py

+29-9
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ async def read_resource(self, uri: str | AnyUrl) -> Iterable[ReadResourceContent
660660
async def log(
661661
self,
662662
level: Literal["debug", "info", "warning", "error"],
663-
message: str,
663+
message: Any,
664664
*,
665665
logger_name: str | None = None,
666666
) -> None:
@@ -696,18 +696,38 @@ def session(self):
696696
return self.request_context.session
697697

698698
# Convenience methods for common log levels
699-
async def debug(self, message: str, **extra: Any) -> None:
700-
"""Send a debug log message."""
699+
async def debug(self, message: Any, **extra: Any) -> None:
700+
"""Send a debug log message.
701+
702+
Args:
703+
message: The message to log. Can be any JSON-serializable type.
704+
**extra: Additional structured data to include
705+
"""
701706
await self.log("debug", message, **extra)
702707

703-
async def info(self, message: str, **extra: Any) -> None:
704-
"""Send an info log message."""
708+
async def info(self, message: Any, **extra: Any) -> None:
709+
"""Send an info log message.
710+
711+
Args:
712+
message: The message to log. Can be any JSON-serializable type.
713+
**extra: Additional structured data to include
714+
"""
705715
await self.log("info", message, **extra)
706716

707-
async def warning(self, message: str, **extra: Any) -> None:
708-
"""Send a warning log message."""
717+
async def warning(self, message: Any, **extra: Any) -> None:
718+
"""Send a warning log message.
719+
720+
Args:
721+
message: The message to log. Can be any JSON-serializable type.
722+
**extra: Additional structured data to include
723+
"""
709724
await self.log("warning", message, **extra)
710725

711-
async def error(self, message: str, **extra: Any) -> None:
712-
"""Send an error log message."""
726+
async def error(self, message: Any, **extra: Any) -> None:
727+
"""Send an error log message.
728+
729+
Args:
730+
message: The message to log. Can be any JSON-serializable type.
731+
**extra: Additional structured data to include
732+
"""
713733
await self.log("error", message, **extra)

Diff for: tests/server/fastmcp/test_server.py

+37
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,43 @@ async def logging_tool(msg: str, ctx: Context) -> str:
554554
level="error", data="Error message", logger=None
555555
)
556556

557+
@pytest.mark.anyio
558+
async def test_context_logging_any_type(self):
559+
"""Test that context logging methods can handle different types of messages."""
560+
from unittest.mock import patch
561+
562+
import mcp.server.session
563+
564+
mcp = FastMCP()
565+
566+
async def logging_tool(ctx: Context) -> str:
567+
# Test with different data types
568+
await ctx.debug(42) # integer
569+
await ctx.info(["list", "of", "items"]) # list
570+
await ctx.warning({"key": "value"}) # dictionary
571+
await ctx.error(3.14) # float
572+
return "Logged messages of different types"
573+
574+
mcp.add_tool(logging_tool)
575+
576+
with patch("mcp.server.session.ServerSession.send_log_message") as mock_log:
577+
async with client_session(mcp._mcp_server) as client:
578+
result = await client.call_tool("logging_tool", {})
579+
assert len(result.content) == 1
580+
content = result.content[0]
581+
assert isinstance(content, TextContent)
582+
assert "Logged messages of different types" in content.text
583+
584+
assert mock_log.call_count == 4
585+
mock_log.assert_any_call(level="debug", data=42, logger=None)
586+
mock_log.assert_any_call(
587+
level="info", data=["list", "of", "items"], logger=None
588+
)
589+
mock_log.assert_any_call(
590+
level="warning", data={"key": "value"}, logger=None
591+
)
592+
mock_log.assert_any_call(level="error", data=3.14, logger=None)
593+
557594
@pytest.mark.anyio
558595
async def test_optional_context(self):
559596
"""Test that context is optional."""

0 commit comments

Comments
 (0)