mcp-logger-utils


Namemcp-logger-utils JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryShared utilities for MCP servers, including robust logging and JSON repair.
upload_time2025-07-18 12:25:37
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords debugging json-repair logging mcp model-context-protocol
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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"
}
        
Elapsed time: 0.73225s