hermes-backup/daily/2026-04-28_203212/skills/arifos/arifos-fastmcp-tool-registration-fix/SKILL.md
Fix KeyError 'mode' in arifOS FastMCP tool registration caused by _wrap_handler() overwriting __annotations__
npx skillsauth add ariffazil/openclaw-workspace arifos-fastmcp-tool-registration-fixInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
After fixing circular imports, arifOS MCP starts but fails tool registration with:
KeyError: 'mode'
on the first tool call (e.g. arif_session_init).
_wrap_handler() in arifosmcp/runtime/tools.py wraps canonical handlers with a generic signature:
def _wrap_handler(handler, name):
async def wrapper(args: Any = None, kwargs: Any = None) -> Any:
...
wrapper.__wrapped__ = handler
wrapper.__annotations__ = {"args": "Any", "kwargs": "Any", "return": "Any"}
return wrapper
FastMCP's ParsedFunction.from_function reads __annotations__ directly from the function object — NOT from __wrapped__. So when it looks up mode (the first parameter of arif_session_init), it's searching the wrapper's {"args", "kwargs", "return"} annotation dict and raises KeyError.
The _wrap_handler() function should NOT overwrite __annotations__ with generic types. Instead, preserve the original function's annotations:
def _wrap_handler(handler, name):
async def wrapper(args: Any = None, kwargs: Any = None) -> Any:
...
wrapper.__wrapped__ = handler
# Do NOT override __annotations__ — FastMCP reads them from the wrapper directly
# If you must set annotations, preserve the original's:
# wrapper.__annotations__ = {**handler.__annotations__}
return wrapper
The __wrapped__ attribute is used elsewhere (e.g. by inspect.signature) but NOT by FastMCP's ParsedFunction when it resolves parameter names.
docker run --rm arifos:local python3 -c "
import sys; sys.path.insert(0, '/app/arifosmcp')
from arifosmcp.runtime.tools import _CANONICAL_HANDLERS, _wrap_handler
import inspect
h = _CANONICAL_HANDLERS['arif_session_init']
w = _wrap_handler(h, 'arif_session_init')
print('Wrapped annotations:', w.__annotations__) # Must include mode, actor_id, etc.
print('Wrapped signature:', inspect.signature(w)) # Must show (mode, actor_id, ...)
"
core.judgment: sys.path prepend + explicit sys.modules["core"].floors = floors attachmentarifosmcp/core/__init__.py had sys.path.insert(0, '/app') which duplicated the path since /app/arifosmcp was already at position 0testing
OpenClaw edge agent bridge — operational triage, doctor, restart, and A2A bridge routing for the federation edge (Telegram surface). USE WHEN: "openclaw unhealthy", "gateway down", "edge bot not responding", "a2a bridge disconnected", "watchdog tripped", "openclaw doctor", "openclaw restart". NOT for token/security audit — use FORGE-telegram-audit.
tools
Generate images, videos, TTS, voice clone, and music via MiniMax MCP server. Use when user asks to "draw", "generate image", "create picture", "make a photo", "text to image", "image generation".
testing
Single load-bearing constitutional-judgment skill. Routes all F1–F13, verdict, hold, seal, scope, authority and floor-check calls through the live arif_judge surface. Replaces 7 overlapping predecessors (arifos-constitutional-judge, arifos-constitutional-judge, arifos-constitutional-judge, arifos-constitutional-judge, arifos-constitutional-judge, arifos-constitutional-judge, arifos-constitutional-judge).
development
MANDATORY LSP grounding gate BEFORE any code mutation on .ts, .py, .js, .tsx, .jsx files. Forces the agent to read real-time compiler diagnostics and structural project context before editing — eliminating blind guesses and anchoring every mutation in F2 (TRUTH). Routes through arifOS kernel (:8088) for centralized gate logic.