---
schema: rendered-html/v1
title: "Server Logging - FastMCP"
source_url: https://gofastmcp.com/clients/logging
generated_at: 2026-06-11T19:37:36.780536+00:00
---




[FastMCP home page![light logo](images/gofastmcp__com__clients__logging__wordmark.avif)![dark logo](images/gofastmcp__com__clients__logging__wordmark-white.avif)](gofastmcp__com.md)







Operations

Server Logging

















  - [Tools](gofastmcp__com__clients__tools.md)
  - [Resources](gofastmcp__com__clients__resources.md)
  - [Prompts](gofastmcp__com__clients__prompts.md)
  - [Sampling](gofastmcp__com__clients__sampling.md)
  - [Elicitation](gofastmcp__com__clients__elicitation.md)
  - [Tasks

    NEW](gofastmcp__com__clients__tasks.md)
  - [Progress](gofastmcp__com__clients__progress.md)
  - [Logging](/clients/logging)
  - [Roots](gofastmcp__com__clients__roots.md)
  - [Notifications](gofastmcp__com__clients__notifications.md)






- [Log Handler](#log-handler)
- [Structured Logs](#structured-logs)
- [Default Behavior](#default-behavior)

Operations

# Server Logging


Receive and handle log messages from MCP servers.


New in version `2.0.0`
Use this when you need to capture or process log messages sent by the server.
MCP servers can emit log messages to clients. The client handles these through a log handler callback.

## [​](#log-handler) Log Handler

Provide a `log_handler` function when creating the client:

import logging
from fastmcp.client.logging import LogMessage

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'

logger = logging.getLogger(__name__)
LOGGING_LEVEL_MAP = logging.getLevelNamesMapping()

async def log_handler(message: LogMessage):
    """Forward MCP server logs to Python's logging system."""
    msg = message.data.get('msg')
    extra = message.data.get('extra')

    level = LOGGING_LEVEL_MAP.get(message.level.upper(), logging.INFO)
    logger.log(level, msg, extra=extra)

client = Client(
    "my_mcp_server.py",
    log_handler=log_handler,

The handler receives a `LogMessage` object:

## LogMessage

[​](#param-level)

level

Literal["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]

The log level

[​](#param-logger)

logger

str | None

The logger name (may be None)

[​](#param-data)

data

dict

The log payload, containing `msg` and `extra` keys

## [​](#structured-logs) Structured Logs

The `message.data` attribute is a dictionary containing the log payload. This enables structured logging with rich contextual information.

async def detailed_log_handler(message: LogMessage):
    msg = message.data.get('msg')
    extra = message.data.get('extra')

    if message.level == "error":
        print(f"ERROR: {msg} | Details: {extra}")
    elif message.level == "warning":
        print(f"WARNING: {msg} | Details: {extra}")
    else:
        print(f"{message.level.upper()}: {msg}")

This structure is preserved even when logs are forwarded through a FastMCP proxy, making it useful for debugging multi-server applications.

## [​](#default-behavior) Default Behavior

If you do not provide a custom `log_handler`, FastMCP’s default handler routes server logs to Python’s logging system at the appropriate severity level. The MCP levels map as follows: `notice` becomes INFO; `alert` and `emergency` become CRITICAL.

client = Client("my_mcp_server.py")

async with client:
    # Server logs are forwarded at proper severity automatically
    await client.call_tool("some_tool")

[Progress Monitoring

Previous](gofastmcp__com__clients__progress.md)[Client Roots

Next](gofastmcp__com__clients__roots.md)






