aeat.entrypoints.mcp._input_schema module

Derive a per-verb JSON input schema from the CLI’s own click parameters.

Each operator-callable registry command key resolves to exactly one leaf in the aeat Typer/click command tree. This module walks that tree once, reads each command’s declared parameters (positional Argument`s and `–option`` Option`s), and projects them into a strict, typed :class:`VerbInputSchema: the ordered parameter list, each parameter’s JSON type, requiredness, enum choices, multiplicity, and flag shape, plus the resolved CLI path tokens.

The resolved path is load-bearing. A registry command key carries segment tokens with underscores (app.live.iva_wallet.pull) while the live CLI command is hyphenated (aeat app live iva-wallet pull); walking the real tree records the command names as click knows them, so cli_argv_for() builds an argv that actually dispatches. The prior {args: [string]} bag forced the operator to run --help per verb and split the argv itself; a per-verb schema replaces it so a client renders a typed form and the console maps named arguments back to CLI tokens deterministically.

This module owns no MCP protocol detail. It reads the CLI command tree and emits SDK-independent pydantic records, so it is unit-tested directly.

class VerbParamKind(*values)[source]

Bases: StrEnum

Whether a parameter is a positional argument or a -- option.

ARGUMENT
OPTION
class JsonType(*values)[source]

Bases: StrEnum

The JSON Schema scalar type a CLI parameter projects onto.

STRING
INTEGER
NUMBER
BOOLEAN
class VerbParameter(**data)[source]

Bases: BaseModel

One CLI parameter projected into a JSON-schema property.

name is the click parameter name (the JSON property key). For an OPTION the cli_flag is the long option token (--file); for an ARGUMENT it is empty and the value is a bare positional. multiple renders the property as a JSON array and repeats the token per element; is_flag is a bare boolean switch that emits its cli_flag when truthy and, for a --flag/--no-flag pair, its off_flag (the secondary --no- token) when explicitly false. default carries the parameter’s click default rendered JSON-safely, so a client can see the real default (including a default-on flag it may disable).

Parameters:
name: str
kind: VerbParamKind
cli_flag: str
off_flag: str
json_type: JsonType
required: bool
is_flag: bool
multiple: bool
choices: tuple[str, ...]
default: bool | int | float | str | list[Any] | None
help: str
property_schema()[source]

Return the JSON-schema fragment for this parameter’s property.

Return type:

dict[str, Any]

class VerbInputSchema(**data)[source]

Bases: BaseModel

The strict per-verb input contract for one exposed MCP tool.

cli_path is the resolved command path as click names it (hyphenated leaf tokens), so dispatch never re-derives it from the underscored command key. parameters preserves the CLI declaration order, which cli_argv_for() relies on to place positional arguments before options.

Parameters:
command_key: str
cli_path: tuple[str, ...]
parameters: tuple[VerbParameter, ...]
help: str

The command’s own one-line help (its click short_help / first help line), so the MCP tool description can be verb-specific rather than the shared family intent (ADR mcp-progressive-discovery P2/S05).

json_schema()[source]

Project the parameters into a JSON Schema object for the tool.

Return type:

dict[str, Any]

Returns:

A JSON Schema object with one property per parameter, the required names, and additionalProperties closed.

exception SchemaResolutionError[source]

Bases: RuntimeError

A command key’s CLI subtree failed to materialise during schema build.

Raised by assert_schema_coverage() when the tree walk RAISED while materialising a lazily-loaded subcommand. Such a failure would otherwise degrade silently to an argument-free schema (research finding F2), shipping a verb whose parameters vanished because of a Typer declaration bug; this error turns that silent degradation into a loud, verb-named build-time failure.

assert_schema_coverage(resolution_errors)[source]

Fail the build when any command key’s subtree failed to materialise.

resolution_errors maps a command key to the reason its lazily-loaded subtree raised during the tree walk. An empty mapping is the healthy state (a genuine no-arg command or a stale not-found key never appears here — only a resolution FAILURE does). Any entry names a verb that would silently ship an argument-free schema and raises SchemaResolutionError.

Return type:

None

Parameters:

resolution_errors (Mapping[str, str])

build_verb_input_schema(root, command_key)[source]

Build the VerbInputSchema for one command key.

Resolves the leaf command in the tree rooted at root and reads its click parameters. A key that does not resolve to a live command - a stale registry key, or one whose subtree cannot be introspected because a command in it declares a Typer-unconvertible parameter type - falls back to an empty parameter set over the naive path, yielding a valid (argument-free) descriptor rather than crashing this single-key build. The batch entry point build_verb_input_schemas() runs the coverage gate that turns a resolution FAILURE into a loud build error.

Return type:

VerbInputSchema

Returns:

The strict VerbInputSchema for the command.

Parameters:
  • root (Command)

  • command_key (str)

build_verb_input_schemas(command_keys)[source]

Build the per-verb input schemas for every command key.

Materialises the aeat click command once and walks it per key. The walk imports each lazily-loaded command subtree exactly as real dispatch does, so the schemas reflect the live CLI surface. Any subtree whose materialisation RAISES fails the coverage gate (assert_schema_coverage()) with the offending verb named, rather than silently degrading to an argument-free schema.

Return type:

dict[str, VerbInputSchema]

Returns:

A mapping of command key to its VerbInputSchema.

Parameters:

command_keys (tuple[str, ...])

cli_argv_for(schema, arguments)[source]

Build the aeat argv tail for a tool call from named arguments.

Positional arguments are emitted in their CLI declaration order and precede every option; a multiple argument or option repeats per element; a boolean flag emits its on-token when truthy and, for a --flag/--no-flag pair, its off_flag (--no-flag) when explicitly false — so a default-on flag can be turned off through the surface. A bare switch (no off-token) emits nothing when false. --format json leads the tail so the machine envelope is always requested, followed by the resolved command path.

Return type:

list[str]

Returns:

The argv tokens that follow the aeat executable.

Parameters: