Skip to main content
Glama
logging_guide.md8.08 kB
# Logging Guide for MCP Servers ## Overview This guide covers best practices for implementing logging in Model Context Protocol (MCP) servers. Proper logging is essential for debugging, monitoring, and ensuring the reliability of MCP servers. ## Logging Configuration MCP servers MUST implement a standardized logging system to help with debugging and monitoring. The following implementation is REQUIRED: ```python import logging def configure_logging(debug=False): """Configure logging based on specified verbosity level. Args: debug: Whether to enable debug-level logging """ # Create a logger with a descriptive name logger = logging.getLogger("my_mcp_server") # Clear any existing handlers if logger.handlers: logger.handlers.clear() # Configure the appropriate log level if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) # Create a console handler with better formatting handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) handler.setFormatter(formatter) logger.addHandler(handler) return logger # Initialize logger logger = configure_logging() ``` This exact pattern MUST be followed to ensure consistent logging across all MCP servers. ## Using Logging Levels Effectively Use appropriate logging levels to categorize messages based on their importance: ```python # Critical errors that prevent operation logger.critical("Failed to start: cannot connect to required service") # Errors that affect functionality but don't prevent operation logger.error("API request failed: {e}", exc_info=True) # Warnings about potential issues logger.warning("Rate limit approaching: {rate_limit_remaining} requests remaining") # General information about normal operation logger.info("Processing request for object: {object_name}") # Detailed information useful for debugging logger.debug("Request parameters: {params}") ``` ### Logging Level Guidelines - **CRITICAL (50)**: Use for fatal errors that prevent the server from functioning at all - **ERROR (40)**: Use for errors that affect some functionality but don't prevent basic operation - **WARNING (30)**: Use for potential issues that don't immediately affect functionality - **INFO (20)**: Use for normal operational information and significant events - **DEBUG (10)**: Use for detailed troubleshooting information ## Debug Mode in CLI For CLI tools, implement a `--debug` flag using argparse to enable more verbose logging: ```python parser = argparse.ArgumentParser(description="My MCP Server") parser.add_argument( "--debug", action="store_true", help="Enable debug logging" ) args = parser.parse_args() logger = configure_logging(debug=args.debug) ``` This allows users to get more detailed log output when troubleshooting issues. ## Required Logging Practices All MCP servers MUST follow these logging practices: ### 1. Use Structured Logging for Machine-Parseable Logs Include key-value pairs in log messages to make them easily parseable: ```python # GOOD logger.info(f"Processing request: method={method}, object_id={object_id}, user={user}") # AVOID logger.info(f"Processing a request for {object_id}") ``` ### 2. Log at Appropriate Levels - **CRITICAL**: For errors that prevent the server from functioning - **ERROR**: For errors that affect functionality but don't prevent operation - **WARNING**: For potential issues that don't affect functionality - **INFO**: For normal operation events (server start/stop, request handling) - **DEBUG**: For detailed troubleshooting information only ### 3. Include Context in All Log Messages Every log message should include sufficient context to understand what it refers to: ```python # GOOD logger.info(f"Successfully retrieved resource: id={resource_id}, size={len(data)} bytes") # AVOID logger.info("Successfully retrieved resource") ``` ### 4. Log Start/End of All Significant Operations For important operations, log both the start and completion: ```python logger.info(f"Starting data processing job: job_id={job_id}") # ... processing ... logger.info(f"Completed data processing job: job_id={job_id}, records_processed={count}") ``` ### 5. Never Log Sensitive Data Never include sensitive information in logs: ```python # BAD - logs API key logger.debug(f"Making API request with key: {api_key}") # GOOD - masks sensitive data logger.debug(f"Making API request with key: {api_key[:4]}...{api_key[-4:]}") ``` Sensitive data includes: - API keys and secrets - Passwords and tokens - Personal identifiable information - Authentication credentials ### 6. Always Log Exceptions with Traceback When catching exceptions, always include the traceback: ```python try: # Code that might raise an exception result = api_client.fetch_data(params) except Exception as e: # Always include exc_info=True to get the traceback logger.error(f"Error fetching data: {str(e)}", exc_info=True) raise ``` ### 7. Use Consistent Log Formatting Use the same log formatting across your entire application: ```python formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) ``` ### 8. Include Timing Information for Performance-Critical Operations For operations where performance matters, include timing information: ```python import time start_time = time.time() # ... operation ... duration = time.time() - start_time logger.info(f"Completed operation in {duration:.2f} seconds") ``` ## Logging in MCP Tools When implementing MCP tools, follow this pattern for logging: ```python @mcp.tool() async def my_tool(param1: str, param2: int, optional_param: bool = True) -> str: """Tool description.""" try: # Log the function call at debug level logger.debug(f"my_tool called with params: {param1}, {param2}, {optional_param}") # Your tool implementation here result = f"Processed {param1} with {param2}" # Log successful completion at info level logger.info(f"Successfully processed request: param1={param1}") return result except Exception as e: # Log the error with traceback logger.error(f"Error in my_tool: {str(e)}", exc_info=True) # Convert exceptions to MCP errors raise McpError(ErrorData( code=INTERNAL_ERROR, message=f"Error in my_tool: {str(e)}" )) ``` ## Logging Configuration for CLI vs MCP Server Mode Configure logging differently based on the mode: ```python if __name__ == "__main__": # If running in CLI mode if len(sys.argv) > 1: args = parse_args() # Configure logging based on CLI arguments logger = configure_logging(debug=args.debug) # If running in MCP server mode else: # Configure default logging for MCP server mode logger = configure_logging(debug=os.environ.get("DEBUG") == "true") ``` ## Troubleshooting with Logs Effective logging is critical for troubleshooting. Ensure your logs provide enough information to: 1. Identify what went wrong 2. Determine the cause of the issue 3. Understand the context of the error 4. Reproduce the problem if needed Example of good troubleshooting logs: ``` 2023-04-15 14:32:10 - my_mcp_server - INFO - Starting API request: url=https://api.example.com/data, method=GET 2023-04-15 14:32:11 - my_mcp_server - WARNING - API rate limit header: remaining=5, limit=100 2023-04-15 14:32:12 - my_mcp_server - ERROR - API request failed: status=429, message=Too Many Requests 2023-04-15 14:32:12 - my_mcp_server - INFO - Initiating retry: attempt=1, backoff=2.0 seconds ``` ## Next Steps After implementing logging, refer to: - [Error Handling](implementation_guide.md#error-handling-strategy) in the Implementation Guide - [Testing Guide](testing_guide.md) for testing with different log levels

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MammothGrowth/dbt-cli-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server