Shared utilities for MCP servers, including robust logging, JSON repair, and debug tools with automatic cache clearing.
Project description
MCP Logger Utils
A robust, shared logging and utility package for MCP (Model Context Protocol) servers, especially tailored for Claude Code environments.
Features
- Isolated Logging: Prevents conflicts with other libraries using
loguru. - Automatic Truncation: Automatically shortens large strings, base64 data, and long lists (like embeddings) in logs to keep them clean and readable.
- Universal Decorator: The
@debug_tooldecorator works seamlessly with bothasyncandsyncfunctions. - Safe Serialization: Handles non-serializable types (
datetime,Path, etc.), preventing the logger from crashing. - Rich Context: Logs function arguments, return values, execution time, and detailed error tracebacks.
- Configurable: Customize log directory, level, and truncation limits via constructor arguments or environment variables.
- Robust JSON Repair: Includes a powerful utility to parse malformed JSON commonly produced by LLMs.
- Structured Error Response: Returns a standardized JSON object on tool failure, including a unique error ID.
- Standardized Response Format: Provides utilities for consistent MCP response formatting across all tools.
Installation
pip install mcp-logger-utils
Or using uv:
uv pip install mcp-logger-utils
Usage
1. Robust Logging with @debug_tool
Decorate your MCP tool functions to get automatic logging of inputs, outputs, performance, and errors.
a. Initialize the Logger
In your MCP server file, create an instance of MCPLogger. You can optionally configure truncation limits.
from mcp_logger_utils import MCPLogger
# Default initialization
mcp_logger = MCPLogger("my-awesome-server")
# Customizing truncation limits
mcp_logger_custom = MCPLogger(
"my-data-server",
max_log_str_len=512, # Allow longer strings in logs
max_log_list_len=5 # Show fewer list items
)
b. Apply the Decorator
The same decorator works for both async and sync functions.
from mcp_logger_utils import debug_tool
@mcp.tool()
@debug_tool(mcp_logger)
async def process_data(embedding: list, image_data: str) -> dict:
# `embedding` (if long) and `image_data` (if long) will be
# automatically truncated in the debug logs.
return {"status": "processed"}
c. Configuration via Environment Variables
MCP_LOG_DIR: Overrides the default log directory (~/.claude/mcp_logs).MCP_LOG_LEVEL: Sets the console log level (e.g.,DEBUG,INFO).MCP_DEBUG: Set totrueor1for verboseDEBUGlevel logging.
2. JSON Repair Utility
When working with LLMs, you often get responses that are almost JSON but contain small errors or are wrapped in text. This utility provides a robust way to handle such cases.
repair_and_parse_json(content, logger_instance=None)
This function takes a string and does its best to return a valid Python dict or list.
- It automatically extracts JSON from markdown code blocks (e.g.,
```json ... ```). - It uses the
json-repairlibrary to fix common syntax errors. - If parsing fails, it safely returns the original string.
Example: Creating a Robust Tool
Here is how you can combine @debug_tool and repair_and_parse_json to build a tool that reliably processes LLM output.
from mcp_logger_utils import MCPLogger, debug_tool, repair_and_parse_json
# from some_llm_library import get_llm_response
# Initialize logger
mcp_logger = MCPLogger("llm-processor-tool")
@mcp.tool()
@debug_tool(mcp_logger)
async def get_structured_data_from_llm(prompt: str) -> dict:
"""
Calls an LLM to get structured data and robustly parses the response.
"""
# 1. Get a response from an LLM. It might be messy.
messy_response = "Here is the JSON you requested: ```json\n{\n \"name\": \"Claude\",\n \"version\": 3.0,\n \"is_helpful\": true, // He is very helpful!\n}\n```"
# messy_response = await get_llm_response(prompt)
# 2. Use the utility to clean and parse it.
# The logger passed to it will log the repair steps for easy debugging.
parsed_data = repair_and_parse_json(messy_response, logger_instance=mcp_logger.logger)
# 3. Check if parsing was successful before proceeding.
if not isinstance(parsed_data, dict):
raise ValueError(f"Failed to parse a valid dictionary from the LLM response. Got: {parsed_data}")
# 4. Now you can safely work with the clean data.
parsed_data["processed_at"] = "2024-07-19"
return parsed_data
Why this is a good pattern:
- Observability: The
@debug_toollogs the raw, messy input from the LLM, so you can always see exactly what your tool received. - Robustness: Your tool doesn't crash on slightly malformed JSON.
- Clarity: The code explicitly shows the step where data is being cleaned, making the logic easy to follow.
3. Standardized Response Format
All MCP tools should return consistent JSON responses. This package provides utilities to ensure consistency:
from mcp_logger_utils import create_success_response, create_error_response
import time
@mcp.tool()
@debug_tool(mcp_logger)
async def my_tool(param: str) -> str:
start_time = time.time()
try:
# Your tool logic here
result = {"processed": param, "status": "complete"}
# Return standardized success response
return create_success_response(result, "my_tool", start_time)
except Exception as e:
# Return standardized error response
return create_error_response(str(e), "my_tool", start_time)
The response format is:
{
"success": true,
"data": {...},
"error": null,
"metadata": {
"duration_ms": 123,
"tool": "my_tool",
"version": "2025-07-21",
"timestamp": "2025-07-21T12:34:56.789Z"
}
}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcp_logger_utils-0.2.8.tar.gz.
File metadata
- Download URL: mcp_logger_utils-0.2.8.tar.gz
- Upload date:
- Size: 5.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e9068074bf93a6969e02e261a48f1138656b5cd2986b5311ca11f329ea7b563
|
|
| MD5 |
3463d08987d15468e78a8afc7e44c188
|
|
| BLAKE2b-256 |
bda6ecb1577a150d661e4aa2a124a9224fe845334de32ad905748b4aec5986d6
|
File details
Details for the file mcp_logger_utils-0.2.8-py3-none-any.whl.
File metadata
- Download URL: mcp_logger_utils-0.2.8-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.10.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f0d0f275dbd18c849d0d81af708154fd3dde617ca229987e67aa5f19f7bad32
|
|
| MD5 |
b4767a15617ea9274bceb0de452e403e
|
|
| BLAKE2b-256 |
bb39057cdf6e452333864af6e6e5f1cdb820eba75f1bb5b527837bbd59cc9bc9
|