Skip to content

Conversation

@akshaykumarbedre
Copy link

Fix Issue #397: Context Logging Type Compliance

Problem

According to the MCP specification, the data field in logging notifications can be any JSON-serializable type. However, the FastMCP Context logging methods (info(), debug(), warning(), error()) were incorrectly typed to only accept str for the message parameter.

The issue was that while the underlying ServerSession.send_log_message() correctly accepts data: Any, the FastMCP convenience methods exposed message: str, preventing users from logging structured data like dictionaries, lists, numbers, etc.

Solution

This fix makes the FastMCP context logging functions spec-compliant by:

  1. Changed Context.log() method signature:

    • From: async def log(..., message: str, ..., extra: dict[str, Any] | None = None)
    • To: async def log(..., data: Any, ...)
    • Removed the confusing extra parameter since data now accepts any JSON-serializable type directly
  2. Updated convenience methods (debug(), info(), warning(), error()):

    • Changed parameter from message: str to data: Any
    • Removed extra parameter for cleaner API
    • Updated docstrings with examples
  3. Added comprehensive tests:

    • Added test_context_logging_with_structured_data() to verify logging works with:
      • Dictionary data: await ctx.info({"status": "success", "message": msg})
      • List data: await ctx.debug([1, 2, 3])
      • Number data: await ctx.warning(42)
      • Boolean data: await ctx.error(True)

Example Usage

# Now this works (was previously a type error):
await ctx.info({"status": "success", "items": 42})

# This also works:
await ctx.debug([1, 2, 3])
await ctx.warning(42)

# Original string usage still works:
await ctx.info("Operation completed")

Testing

  • ✅ All existing logging tests pass (12/12)
  • ✅ New structured data logging test passes
  • ✅ Type checking (pyright) passes with 0 errors
  • ✅ Code style (ruff) passes

Breaking Changes

The extra parameter has been removed from all logging methods. Users who were using this pattern:

# Old pattern
await ctx.info("message", extra={"key": "value"})

Should now use:

# New pattern
await ctx.info({"message": "message", "key": "value"})

This is actually more intuitive and aligns with the MCP specification.

Files Changed

  • src/mcp/server/fastmcp/server.py: Updated Context.log() method and convenience methods
  • tests/server/fastmcp/test_server.py: Added test for structured data logging

@akshaykumarbedre
Copy link
Author

Closing this PR because it was opened by mistake. Will create a proper one later

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant