ᗣᗣ Milo

August 4, 2026 · View on GitHub

PyPI version Build Status Python 3.14+ License: MIT

Milo, a Russian blue cat, routing one typed command into terminal, MCP, and agent-discovery surfaces

One typed Python function becomes a human CLI command, an MCP tool, and an agent-readable discovery entry. (evidence: one-definition-three-surfaces)

Milo keeps the interfaces for people, Python, and AI agents tied to one command contract. Define the types, defaults, constraints, and docstring once; Milo derives argparse, JSON Schema, MCP dispatch, and llms.txt without a second adapter layer.

Get started · Read the docs · Compare with Typer + FastMCP

Prove It in 60 Seconds

With uv installed, paste this into a clean directory. uv downloads Python 3.14 and Milo when needed:

uvx --python 3.14 --from milo-cli milo new hello_milo
uv run --python 3.14 --with milo-cli python hello_milo/app.py greet --name World
uv run --python 3.14 --with milo-cli milo verify hello_milo/app.py

The command prints Hello, World!. The ten-check verifier (evidence: verify-ten-check-conformance) exercises import, schema generation, MCP discovery, MCP Apps conformance, gateway projection, and a real subprocess JSON-RPC handshake. Do not register a new tool until it reports zero failures.

Give Claude Code the same file as a local stdio MCP server:

claude mcp add --transport stdio hello_milo -- \
  uv run --python 3.14 --with milo-cli python "$PWD/hello_milo/app.py" --mcp

Now the terminal and the agent call the same function.

What is Milo?

Milo is a pure-Python framework for capabilities that must stay aligned across human and agent interfaces. One command definition owns CLI + MCP + llms.txt, including parsing, generated schema, validation, discovery, dispatch, and structured results.

from milo import CLI

cli = CLI(name="greet", description="Say hello", version="1.0")


@cli.command("greet", description="Return a greeting")
def greet(name: str, loud: bool = False) -> str:
    """Greet someone by name.

    Args:
        name: The person to greet.
        loud: If true, SHOUT.
    """
    message = f"Hello, {name}!"
    return message.upper() if loud else message


if __name__ == "__main__":
    cli.run()

That definition becomes:

SurfaceMilo derives
Human CLIargparse command, help, flags, exit behavior, and terminal rendering
Pythondirect typed dispatch through invoke(), call(), and call_raw()
MCPtruthful inputSchema, validation, tool metadata, and JSON-RPC dispatch
Discoveryllms.txt and MCP tools/list from the same registered command

Why Milo

  • One contract, not synchronized wrappers. A renamed option or tighter constraint cannot quietly update the CLI while leaving the MCP tool behind.
  • Verification is part of the product. milo verify app.py checks the assembled application, not just an isolated schema.
  • Humans and agents get appropriate presentation. A person can receive a confirmation flow or terminal UI while an agent receives structured input, progress, errors, and results.
  • Types stay auditable. Standard annotations, Annotated[...] constraints, defaults, and docstrings are the schema source—without another model layer.
  • Terminal applications are first-class. Immutable state, pure reducers, Kida views, forms, flows, commands, and sagas support interactive tools when a single command needs a richer human experience.
  • Free-threading ready. Milo is tested with PYTHON_GIL=0 on Python 3.14t. (evidence: free-threaded-runtime)
  • One runtime dependency. Milo depends only on kida-templates; there is no Click, Rich, Pydantic, curses, or compiled runtime layer. (evidence: one-runtime-dependency)

Use Milo For

  • Internal or developer CLIs that agents should discover and call safely.
  • Dual-mode commands: interactive for people, structured over MCP for agents.
  • Tool gateways that collect several local CLIs behind one agent connection.
  • Wizards, installers, forms, and multi-screen terminal workflows.
  • Commands that stream progress or expose resources and MCP Apps UI metadata.
  • Refactorable command suites that need schema, direct-dispatch, and protocol parity tests.

If MCP itself is the product—including hosted transports, clients, auth, and deployment—start with FastMCP. If only the polished human CLI matters, Typer may be the stronger fit. Choose Milo when drift between the human and agent surfaces is the problem you want the framework to own.

Migrating an established framework or developer CLI? The mature-CLI adoption guide covers compatibility inventory, phased cutover, and exact-version downstream proof.

Interactive Terminal Apps

Milo also supplies an Elm-style runtime for commands that need more than line output:

from milo import Action, App


def reducer(state, action: Action):
    if state is None:
        return {"count": 0}
    if action.type == "INCREMENT":
        return {"count": state["count"] + 1}
    return state


app = App(template="counter.kida", reducer=reducer, initial_state=None)

State remains explicit, reducers remain pure, effects move through Cmd or sagas, and Kida templates own presentation. See Build Apps for forms, flows, input, live rendering, cleanup, and testing.

Examples

Start with examples/greet, then use the examples/README.md map for run commands and copy paths.

ExampleWhat it demonstrates
greetSmallest CLI + MCP + llms.txt definition
deployFlagship dual-mode command with progress and confirmation
mcp_appMCP Apps UI resource with structured fallback
ctxdemoContext injection, output, progress, and confirmation
groupsNested command groups
lazyappDeferred imports for fast startup
devtoolProduction CLI with before_command/after_command, completions, and doctor
taskman@cli.command, @cli.resource, llms.txt, and MCP
outputgalleryTerminal reports and diagnostics
configappTOML configuration and profiles
pluggableHooks, listeners, and plugins
buildpipeDependency-aware pipelines and retries
counterSmallest reducer-driven terminal app
todoModal input and derived filtering
stopwatchTick-driven animation
filepickerViewports and saga I/O
wizardForms and multi-screen flows
fetcherGenerator-based side effects
downloaderParallel work, delays, and timeouts
spinnerBubbletea-style Cmd thunks
liverenderLive rendering outside an App

For a recording-ready demonstration of hooks, CLI, MCP, TUI, and MCP Apps in one scenario, run the Waypoint showcase.

Explore

  • Agent quickstart: from typed function to verified Claude MCP tool.
  • Testing guide: schema, direct dispatch, MCP dispatch, verifier, rendering, and free-threading proof.
  • Build CLIs: commands, groups, context, output, MCP, gateway, help, and llms.txt.
  • Build Apps: state, reducers, templates, forms, flows, effects, input, and live rendering.
  • Quality: verification, testing, debugging, and pipelines.
  • Reference: schema, dispatch, error codes, actions, and public types.

Status

Milo is pre-1.0. The core commitment is stable: one typed definition owns its human CLI, Python dispatch, MCP tool, and agent discovery contract. Public claims are classified in public-claims.json; pending claims stay out of product copy until their evidence lands.

See the release notes for current changes and migration guidance.

Development

git clone https://github.com/lbliii/milo-cli.git
cd milo-cli
uv sync --group dev --python 3.14t
make ci
make docs-test

See CONTRIBUTING.md for repository setup, proof, changelog, and pull-request expectations. Report vulnerabilities through SECURITY.md, not a public issue.

Python Components Ecosystem

Milo is the terminal and agent-tooling layer in a personal, pure-Python stack built for Python 3.14t.

ProjectRole
⌁⌁ChirpWeb framework
=^..^=PounceASGI server
)彡KidaServer-side component system
∿∿PurrContent runtime
ᓚᘏᗢBengalStatic-site integration
ฅᨐฅPatitasMarkdown parser
⌾⌾⌾RosettesSyntax highlighter
ᗣᗣMiloCLI and agent-tooling framework ← You are here

License

MIT License — see LICENSE.