Understanding the log_tool Decorator in MCP Ambari API: Implementation and Usage Guide
The log_tool decorator is a Python wrapper defined in src/mcp_ambari_api/functions.py that automatically instruments FastMCP tools with structured logging, execution timing, and intelligent error classification.
The call518/mcp-ambari-api repository implements a Model Context Protocol (MCP) server for Apache Ambari cluster management. To maintain operational visibility without cluttering business logic, the codebase centers its observability strategy on the log_tool decorator—a reusable mechanism that ensures every tool function emits consistent telemetry.
What Is the log_tool Decorator?
The log_tool decorator is implemented in src/mcp_ambari_api/functions.py (spanning lines 25–60) and designed specifically for async functions exposed to the FastMCP server. It is applied alongside @mcp.tool() on every public tool function declared in src/mcp_ambari_api/mcp_main.py, including utilities like dump_configurations, list_hosts, and restart_service.
By centralizing logging in a single decorator, the codebase eliminates repetitive instrumentation and guarantees uniform measurement across all tool invocations.
How the log_tool Decorator Works
The decorator intercepts tool calls to provide five core observability features:
Execution Timing with Monotonic Clocks
Before the wrapped coroutine executes, log_tool records the start time using time.monotonic(). After completion, it calculates the elapsed duration in milliseconds. This approach ensures that system clock adjustments do not skew performance measurements.
Safe Argument Preview
The decorator inspects keyword arguments and constructs a text preview for logging. To prevent log flooding, it truncates values longer than 120 characters, ensuring large configuration payloads or cluster dumps do not overwhelm log files while still providing context for debugging.
Automatic Result Classification
After the wrapped function returns, log_tool categorizes the outcome based on the return value:
- Success: If the result is a standard string, it logs
TOOL SUCCESSat the INFO level - Error Return: If the result begins with
"Error:"or"[ERROR]", it logsTOOL ERROR_RETURNat the WARNING level
This distinction allows operators to filter logs for functional errors versus successful executions without parsing stack traces.
Exception Handling with Tracebacks
If the wrapped coroutine raises an exception, the decorator logs TOOL EXCEPTION with the full traceback at the ERROR level, then re-raises the exception to allow the MCP framework to handle the failure appropriately. This ensures no error occurs silently while preserving the original exception context.
Consistent Log Format
All log entries use standardized prefixes followed by the tool name:
TOOL START– marks invocation with argument previewTOOL SUCCESS– indicates clean completion with duration and result lengthTOOL ERROR_RETURN– flags error-string returns with timing dataTOOL EXCEPTION– captures unhandled exceptions with full tracebacks
Real-World Usage Examples
Decorating an MCP Tool
In src/mcp_ambari_api/mcp_main.py (line 39), the dump_configurations tool demonstrates standard usage:
@mcp.tool(title="Dump Configurations")
@log_tool
async def dump_configurations(
config_type: Optional[str] = None,
service_filter: Optional[str] = None,
filter: Optional[str] = None,
summarize: bool = False,
include_values: bool = True,
limit: int = 0,
max_chars: int = 30000,
) -> str:
"""Dumps Ambari configuration data with optional filtering."""
# Implementation details...
Log Output Scenarios
When a client invokes the echo tool with valid input:
@mcp.tool(title="Echo")
@log_tool
async def echo(message: str) -> str:
return message
The decorator produces:
INFO TOOL START echo message=Hello world
INFO TOOL SUCCESS echo took=2.3ms len=11
If the function returns an error string:
return "Error: something went wrong"
The log changes to:
INFO TOOL START echo message=Bad input
WARN TOOL ERROR_RETURN echo took=1.7ms len=27
When an exception occurs (e.g., network failure during restart_service):
INFO TOOL START restart_service service_name=HDFS
ERROR TOOL EXCEPTION restart_service failed after 45.2ms
Traceback (most recent call last):
...
aiohttp.ClientError: Connection refused
Summary
- The
log_tooldecorator lives insrc/mcp_ambari_api/functions.pyand wraps all MCP tools inmcp_main.py - It uses
time.monotonic()for accurate execution timing in milliseconds - Arguments are logged with 120-character truncation to balance visibility and log size
- Return values are classified automatically: strings starting with
"Error:"trigger WARN logs, otherwise INFO - Exceptions are logged with full tracebacks at ERROR level and re-raised for framework handling
- The decorator ensures consistent log prefixes (
TOOL START,TOOL SUCCESS,TOOL ERROR_RETURN,TOOL EXCEPTION) for easy parsing by monitoring systems
Frequently Asked Questions
Where is the log_tool decorator defined?
The log_tool decorator is defined in src/mcp_ambari_api/functions.py between lines 25 and 60, according to the source code repository. This file contains shared utilities for the MCP server, with log_tool serving as the primary observability mechanism for tool functions.
How does log_tool handle large function arguments?
The decorator automatically truncates argument values to 120 characters when constructing log previews. This safety measure prevents massive configuration payloads or cluster state dumps from flooding log files while still providing enough context to identify the nature of the request.
What is the difference between TOOL ERROR_RETURN and TOOL EXCEPTION?
TOOL ERROR_RETURN indicates the tool function completed execution but returned a string beginning with "Error:" or "[ERROR]", representing a functional error handled by the application logic. TOOL EXCEPTION indicates an unhandled exception was raised during execution (such as network timeouts or parsing errors), triggering a full traceback log.
Can log_tool be used with synchronous functions?
The implementation is designed specifically for async coroutines used with FastMCP. While Python decorators can technically wrap sync functions, the log_tool implementation uses async/await patterns to measure timing accurately around suspended operations, making it unsuitable for standard synchronous methods in this codebase.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →