"""
``register_animedex_tools`` - lazy MCP registration entry point.
The function walks a Click group (defaulting to the registered
top-level :data:`animedex.entry.animedex_cli`), extracts each leaf
command's :func:`animedex.policy.lint.extract_agent_guidance` block,
and calls the duck-typed server object's ``add_tool`` method with
the command name, the guidance block as the tool description, and
the underlying callable as the handler.
Tool name convention: ``animedex.<dotted-command-path>``. A top-level
command ``status`` registers as ``"animedex.status"``; a nested
``backends jikan search`` registers as ``"animedex.backends.jikan.search"``.
This matches the example in :func:`animedex.mcp.tool_decorator.mcp_tool`'s
docstring so the two MCP-side surfaces use the same ID space.
The registration is explicit (the caller passes the server in)
because ``import animedex`` should never spin up an MCP server as a
side effect. The signature is duck-typed so unit tests can pass a
small fake server, and so the eventual wiring to the upstream
``mcp`` package can use whatever object that package exposes.
"""
from __future__ import annotations
from typing import Any, Optional
import click
[docs]
def selftest() -> bool:
"""Smoke-test the registration entry point.
Builds a synthetic Click group with one well-formed command,
registers it against a tiny fake server, and asserts the
metadata round-trips. Stays import-only against the real
``mcp`` package; the actual MCP runtime ships in future authenticated work.
:return: ``True`` on success.
:rtype: bool
"""
class _FakeServer:
def __init__(self):
self.tools: list = []
def add_tool(self, *, name, description, handler):
self.tools.append((name, description, handler))
@click.group()
def root():
pass # pragma: no cover - click never invokes the group body
@root.command()
def hello() -> None:
"""Smoke command.
Backend: _selftest.
Rate limit: 1 req/s.
--- LLM Agent Guidance ---
smoke guidance.
--- End ---
"""
server = _FakeServer()
count = register_animedex_tools(server, group=root)
assert count == 1
assert server.tools[0][0] == "animedex.hello"
assert "smoke guidance" in server.tools[0][1]
return True