Skip to content

Tools

tools

Register the four facade meta-tools on a FastMCP server.

register_facade(mcp, catalog) wires axm_search / axm_describe / axm_call / axm_capabilities to a :class:~axm_mcp.facade.catalog.ToolCatalog. Each returns a plain dict (or, for axm_call, a str) so FastMCP renders it without extra schema work.

axm_call translates an :class:UnknownToolError into a structured error payload and, on a TypeError from bad kwargs, appends the accepted-params hint — the mitigation the spec mandates for the loss of client-side schema validation.

register_facade(mcp, catalog)

Register the four facade meta-tools against catalog.

Parameters:

Name Type Description Default
mcp FastMCP

FastMCP server instance.

required
catalog ToolCatalog

The tool catalog the meta-tools delegate to.

required
Source code in packages/axm-mcp/src/axm_mcp/facade/tools.py
Python
def register_facade(  # type: ignore[explicit-any]  # FastMCP tool-schema boundary
    mcp: FastMCP, catalog: ToolCatalog
) -> None:
    """Register the four facade meta-tools against *catalog*.

    Args:
        mcp: FastMCP server instance.
        catalog: The tool catalog the meta-tools delegate to.
    """

    @mcp.tool(name="axm_search")
    def axm_search(
        query: str = "",
        domain: str | None = None,
        limit: int = 20,
    ) -> dict[str, object]:
        """Search the AXM tool catalog.

        Args:
            query: Case-insensitive substring matched against name, summary,
                tags and domain. Empty lists everything (browsable).
            domain: Optional exact-match domain filter (e.g. "git").
            limit: Maximum number of results (default 20).

        Returns:
            ``{results: [{name, summary, domain, tags}], count}``.
        """
        hits = catalog.search(query, domain=domain, limit=limit)
        return {"results": hits, "count": len(hits)}

    @mcp.tool(name="axm_describe")
    def axm_describe(name: str) -> dict[str, object]:
        """Return the full invocation contract for one tool.

        Args:
            name: The tool's name (as listed by ``axm_search``).

        Returns:
            ``{name, summary, domain, tags, docstring, params}`` — or
            ``{error}`` if the tool is unknown.
        """
        try:
            return catalog.describe(name)
        except UnknownToolError as exc:
            return {"error": str(exc)}

    @mcp.tool(name="axm_call")
    def axm_call(name: str, arguments: dict[str, object] | None = None) -> str:
        """Execute an AXM tool by name and return its text output.

        Args:
            name: The tool's name.
            arguments: Keyword arguments for the tool.

        Returns:
            The tool's pre-rendered text (or a rendering of its data). On
            error, a message — including the accepted parameters when the
            arguments did not match the tool's signature.
        """
        try:
            return catalog.call(name, arguments)
        except UnknownToolError as exc:
            return f"error: {exc}"
        except TypeError as exc:
            hint = catalog.param_hint(name)
            suffix = f" — accepted params: {hint}" if hint else ""
            return f"error: bad arguments for {name!r}: {exc}{suffix}"

    @mcp.tool(name="axm_capabilities")
    def axm_capabilities(domain: str | None = None) -> dict[str, object]:
        """List AXM tools grouped by domain.

        Args:
            domain: Optional single domain to return.

        Returns:
            ``{domains: {domain: [names]}, count}``.
        """
        groups = catalog.capabilities(domain=domain)
        total = sum(len(v) for v in groups.values())
        return {"domains": groups, "count": total}