Skip to content

Capabilities

Capability

Capability(route: RouteInfo)

One route, exposed as an MCP tool.

Source code in python/aether/_capabilities.py
def __init__(self, route: RouteInfo) -> None:
    self.route = route
    self.name = getattr(route.fn, "__name__", "handler")
    self.description = self._describe(route)
    self._body_fields: set[str] = set()
    self.input_schema = self._build_schema(route)

route instance-attribute

route = route

name instance-attribute

name = getattr(route.fn, '__name__', 'handler')

description instance-attribute

description = self._describe(route)

input_schema instance-attribute

input_schema = self._build_schema(route)

annotations

annotations() -> dict[str, Any]

MCP hints about what calling this does.

Inferred from the HTTP method, which already carries the intent: a GET reads, a DELETE destroys, a POST is neither safe nor repeatable.

Source code in python/aether/_capabilities.py
def annotations(self) -> dict[str, Any]:
    """MCP hints about what calling this does.

    Inferred from the HTTP method, which already carries the intent: a GET
    reads, a DELETE destroys, a POST is neither safe nor repeatable.
    """
    method = self.route.method.upper()
    return {
        "title": self.route.summary or self.name,
        "readOnlyHint": method in _READ_ONLY,
        "destructiveHint": method in _DESTRUCTIVE,
        "idempotentHint": method in _IDEMPOTENT,
        "openWorldHint": False,
    }

describe

describe() -> dict[str, Any]

The tool definition an MCP client receives.

Source code in python/aether/_capabilities.py
def describe(self) -> dict[str, Any]:
    """The tool definition an MCP client receives."""
    return {
        "name": self.name,
        "description": self.description,
        "inputSchema": self.input_schema,
        "annotations": self.annotations(),
    }

invoke async

invoke(arguments: dict[str, Any]) -> Any

Call the handler directly, without going back out over HTTP.

The synthesized request is what lets the same handler serve both, and means the body still passes through the route's own pydantic validation rather than a second copy of it.

Source code in python/aether/_capabilities.py
async def invoke(self, arguments: dict[str, Any]) -> Any:
    """Call the handler directly, without going back out over HTTP.

    The synthesized request is what lets the same handler serve both, and
    means the body still passes through the route's own pydantic
    validation rather than a second copy of it.
    """
    params, body, unknown = self._split(arguments or {})
    if unknown:
        raise CapabilityError(
            f"{self.name}: unexpected argument(s) "
            f"{', '.join(sorted(repr(k) for k in unknown))}"
        )

    missing = [
        name
        for name in self.input_schema["required"]
        if name not in params and name not in body
    ]
    if missing:
        raise CapabilityError(
            f"{self.name}: missing required argument(s) "
            f"{', '.join(repr(m) for m in missing)}"
        )

    path = self.route.path
    for param in self.route.params:
        if param.source == "path" and param.name in params:
            path = path.replace(f"{{{param.name}}}", str(params[param.name]))
            path = path.replace(f"{{*{param.name}}}", str(params[param.name]))

    request = Request(
        self.route.method,
        path,
        None,
        json.dumps(body).encode() if body else b"",
    )
    return await self.route.target(request, **params)

CapabilityError

Bases: Exception

A capability could not be built or invoked.