# 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_tool` decorator works seamlessly with both `async` and `sync` functions.
- **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.
## Installation
```bash
pip install mcp-logger-utils
```
Or using `uv`:
```bash
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.
```python
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.
```python
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 to `true` or `1` for verbose `DEBUG` level 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-repair` library 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.
```python
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:**
1. **Observability:** The `@debug_tool` logs the *raw, messy input* from the LLM, so you can always see exactly what your tool received.
2. **Robustness:** Your tool doesn't crash on slightly malformed JSON.
3. **Clarity:** The code explicitly shows the step where data is being cleaned, making the logic easy to follow.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Raw data
{
"_id": null,
"home_page": null,
"name": "mcp-logger-utils",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "debugging, json-repair, logging, mcp, model-context-protocol",
"author": null,
"author_email": "Graham Anderson <graham@grahama.co>",
"download_url": "https://files.pythonhosted.org/packages/40/29/b776f4a8ff57504b11c747730914e9697a47fb55e690f2e03d5b955922aa/mcp_logger_utils-0.2.0.tar.gz",
"platform": null,
"description": "# MCP Logger Utils\n\nA robust, shared logging and utility package for MCP (Model Context Protocol) servers, especially tailored for Claude Code environments.\n\n## Features\n\n- **Isolated Logging:** Prevents conflicts with other libraries using `loguru`.\n- **Automatic Truncation:** Automatically shortens large strings, base64 data, and long lists (like embeddings) in logs to keep them clean and readable.\n- **Universal Decorator:** The `@debug_tool` decorator works seamlessly with both `async` and `sync` functions.\n- **Safe Serialization:** Handles non-serializable types (`datetime`, `Path`, etc.), preventing the logger from crashing.\n- **Rich Context:** Logs function arguments, return values, execution time, and detailed error tracebacks.\n- **Configurable:** Customize log directory, level, and truncation limits via constructor arguments or environment variables.\n- **Robust JSON Repair:** Includes a powerful utility to parse malformed JSON commonly produced by LLMs.\n- **Structured Error Response:** Returns a standardized JSON object on tool failure, including a unique error ID.\n\n## Installation\n\n```bash\npip install mcp-logger-utils\n```\n\nOr using `uv`:\n\n```bash\nuv pip install mcp-logger-utils\n```\n\n## Usage\n\n### 1. Robust Logging with `@debug_tool`\n\nDecorate your MCP tool functions to get automatic logging of inputs, outputs, performance, and errors.\n\n#### a. Initialize the Logger\n\nIn your MCP server file, create an instance of `MCPLogger`. You can optionally configure truncation limits.\n\n```python\nfrom mcp_logger_utils import MCPLogger\n\n# Default initialization\nmcp_logger = MCPLogger(\"my-awesome-server\")\n\n# Customizing truncation limits\nmcp_logger_custom = MCPLogger(\n \"my-data-server\",\n max_log_str_len=512, # Allow longer strings in logs\n max_log_list_len=5 # Show fewer list items\n)\n```\n\n#### b. Apply the Decorator\n\nThe same decorator works for both `async` and `sync` functions.\n\n```python\nfrom mcp_logger_utils import debug_tool\n\n@mcp.tool()\n@debug_tool(mcp_logger)\nasync def process_data(embedding: list, image_data: str) -> dict:\n # `embedding` (if long) and `image_data` (if long) will be\n # automatically truncated in the debug logs.\n return {\"status\": \"processed\"}\n```\n\n#### c. Configuration via Environment Variables\n\n- `MCP_LOG_DIR`: Overrides the default log directory (`~/.claude/mcp_logs`).\n- `MCP_LOG_LEVEL`: Sets the console log level (e.g., `DEBUG`, `INFO`).\n- `MCP_DEBUG`: Set to `true` or `1` for verbose `DEBUG` level logging.\n\n### 2. JSON Repair Utility\n\nWhen 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.\n\n#### `repair_and_parse_json(content, logger_instance=None)`\n\nThis function takes a string and does its best to return a valid Python `dict` or `list`.\n\n- It automatically extracts JSON from markdown code blocks (e.g., ` ```json ... ``` `).\n- It uses the `json-repair` library to fix common syntax errors.\n- If parsing fails, it safely returns the original string.\n\n#### Example: Creating a Robust Tool\n\nHere is how you can combine `@debug_tool` and `repair_and_parse_json` to build a tool that reliably processes LLM output.\n\n```python\nfrom mcp_logger_utils import MCPLogger, debug_tool, repair_and_parse_json\n# from some_llm_library import get_llm_response\n\n# Initialize logger\nmcp_logger = MCPLogger(\"llm-processor-tool\")\n\n@mcp.tool()\n@debug_tool(mcp_logger)\nasync def get_structured_data_from_llm(prompt: str) -> dict:\n \"\"\"\n Calls an LLM to get structured data and robustly parses the response.\n \"\"\"\n # 1. Get a response from an LLM. It might be messy.\n 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```\"\n # messy_response = await get_llm_response(prompt)\n\n # 2. Use the utility to clean and parse it.\n # The logger passed to it will log the repair steps for easy debugging.\n parsed_data = repair_and_parse_json(messy_response, logger_instance=mcp_logger.logger)\n\n # 3. Check if parsing was successful before proceeding.\n if not isinstance(parsed_data, dict):\n raise ValueError(f\"Failed to parse a valid dictionary from the LLM response. Got: {parsed_data}\")\n\n # 4. Now you can safely work with the clean data.\n parsed_data[\"processed_at\"] = \"2024-07-19\"\n return parsed_data\n```\n\n**Why this is a good pattern:**\n\n1. **Observability:** The `@debug_tool` logs the *raw, messy input* from the LLM, so you can always see exactly what your tool received.\n2. **Robustness:** Your tool doesn't crash on slightly malformed JSON.\n3. **Clarity:** The code explicitly shows the step where data is being cleaned, making the logic easy to follow.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.",
"bugtrack_url": null,
"license": "MIT",
"summary": "Shared utilities for MCP servers, including robust logging and JSON repair.",
"version": "0.2.0",
"project_urls": {
"Bug Tracker": "https://github.com/yourusername/mcp-logger-utils/issues",
"Documentation": "https://github.com/yourusername/mcp-logger-utils#readme",
"Homepage": "https://github.com/yourusername/mcp-logger-utils",
"Repository": "https://github.com/yourusername/mcp-logger-utils"
},
"split_keywords": [
"debugging",
" json-repair",
" logging",
" mcp",
" model-context-protocol"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "cd7050d525699bac6521bf55d758353d5f62489bf891042d4ed882d358c55255",
"md5": "81e3ff223168e8bd6fdee493069e3918",
"sha256": "46a00a93953d0ec9178f60fb5df76b1b03e40444a864e641912695f24d16a1e9"
},
"downloads": -1,
"filename": "mcp_logger_utils-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "81e3ff223168e8bd6fdee493069e3918",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 8649,
"upload_time": "2025-07-18T12:25:36",
"upload_time_iso_8601": "2025-07-18T12:25:36.901608Z",
"url": "https://files.pythonhosted.org/packages/cd/70/50d525699bac6521bf55d758353d5f62489bf891042d4ed882d358c55255/mcp_logger_utils-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4029b776f4a8ff57504b11c747730914e9697a47fb55e690f2e03d5b955922aa",
"md5": "cb42141ed0f785faa453e11decb94da6",
"sha256": "5b224738008242fadfb3430d9005bc92d2cee494d04ad0314050f71b4db89c21"
},
"downloads": -1,
"filename": "mcp_logger_utils-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "cb42141ed0f785faa453e11decb94da6",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 14910,
"upload_time": "2025-07-18T12:25:37",
"upload_time_iso_8601": "2025-07-18T12:25:37.835627Z",
"url": "https://files.pythonhosted.org/packages/40/29/b776f4a8ff57504b11c747730914e9697a47fb55e690f2e03d5b955922aa/mcp_logger_utils-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-18 12:25:37",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "mcp-logger-utils",
"github_not_found": true,
"lcname": "mcp-logger-utils"
}