Wrapping
wrapping
Tool-call wrapping, tracing, and per-key locking runtime.
Builds the synchronous and async wrapper closures handed to FastMCP for each discovered tool: kwarg unwrapping, implicit-path warnings, external session tracing, ToolResult flattening, and per-key concurrency locking (active only in HTTP mode).
This module is a leaf — it imports only axm_mcp.concurrency at runtime.
Shared structural protocols (ToolEntry, ToolLike, PlainTool,
ToolResultLike) live in axm_mcp.discovery and are referenced here
under TYPE_CHECKING (annotations are strings via
from __future__ import annotations) plus string-literal cast targets,
keeping the runtime import edge one-directional (discovery -> wrapping).
build_wrappers(name, tool)
Build the (sync, async) wrapper pair for one tool.
The single construction seam shared by the direct MCP registration path
(:func:axm_mcp.discovery.register_one) and the facade path
(:class:axm_mcp.facade.catalog.ToolCatalog). Both invoke the same
wrappers, so kwarg-unwrapping, implicit-path warnings, tracing, exception
flattening and per-key locking are invariant regardless of whether a tool
is reached directly or via axm_call — there is one execution path.
Returns:
| Type | Description |
|---|---|
_SyncWrapper
|
|
_AnyWrapper
|
trace/flatten/exception contract and the async wrapper adds the HTTP |
tuple[_SyncWrapper, _AnyWrapper]
|
|
Source code in packages/axm-mcp/src/axm_mcp/wrapping.py
flatten_result(result)
Flatten a ToolResult into a JSON-friendly dict.
Spreads result.data first, then sets the envelope keys
(success/error/hint) deterministically. Any reserved key
already present in result.data is relocated to data_{key} (with a
warning) so the envelope is never clobbered and the data value is never
silently lost.
Source code in packages/axm-mcp/src/axm_mcp/wrapping.py
log_external_step(tool_name, tool_args, success, result_str, duration_ms)
Instrumentation seam for non-protocol tool calls.
Currently a no-op. This is the hook point where an execution engine
can observe each MCP tool call (name, args, outcome, duration). The
legacy axm-engine tracing wiring was removed when engine was
deprecated; a future axm-loom-based tracer should re-attach here.
Any implementation MUST swallow its own errors — tracing must never
break tool execution.