Wrapping
wrapping
Tool-call wrapping, tracing, and per-key locking runtime.
Builds the synchronous and async wrapper closures handed to MCPServer 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, *, shared_mode=False, write_contract_resolver=None)
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 callers pass the same
shared-mode flag and per-request write-contract resolver, so write-scope
enforcement cannot diverge between exposure routes. In dedicated mode,
omitting the resolver preserves the environment-backed fallback. The same
wrappers also keep kwarg unwrapping, tracing, flattening and locking aligned.
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.