Catalog PyPI
Back to packageRELEASE DETAILS

0.2.3

PyPI

agent-surface

Project typed Python operations as agent-friendly CLIs, MCP tools, and schemas

Published4 Sept 2026
Direct dependencies4
Transitive dependenciesNot calculated

README

Version 0.2.3 documentation

agent-surface

CI PyPI License: MIT

Typed Python operations that become HATEOAS CLI and MCP surfaces. A response tells a person or agent the next valid thing to do, so callers follow concrete actions instead of guessing commands, routes, or object encodings.

Define an operation once with Pydantic. agent-surface projects it as a YAML-first Click CLI and native MCP tools with bounded, concrete next_actions.

See a HATEOAS trajectory

From a checkout of this repository, run the bookstore example:

uv sync --frozen --all-extras --dev
./examples/bookstore books search --query dune --limit 2

The relevant fields from its YAML envelope show the first page and its concrete next actions:

result:
  query: dune
  items:
  - ref: {value: book_dune}
    title: Dune
    author: Frank Herbert
  - ref: {value: book_dune_messiah}
    title: Dune Messiah
    author: Frank Herbert
  total: 3
  returned: 2
  truncated: true
  next_cursor: book_dune_messiah
next_actions:
  items:
  - rel: inspect
    description: Inspect the first returned book
    command: [./examples/bookstore, books, inspect, --book, book_dune]
    operation: books.inspect
    bound: {book: book_dune}
    slots: {}
  - rel: next-page
    description: Continue this search
    command: [./examples/bookstore, books, search, --query, dune, --cursor, book_dune_messiah, --limit, '2']
    operation: books.search
    bound: {query: dune, cursor: book_dune_messiah, limit: 2}
    slots: {}
  total: 2
  returned: 2
  truncated: false

Follow the advertised CLI command verbatim:

./examples/bookstore books inspect --book book_dune

For MCP, call operation: books.inspect with bound: {book: book_dune} instead. The complete search → inspect → reserve → cancel → delete trajectory is executable in the bookstore tutorial.

Use the library now

Save this as hello.py:

import asyncio
import sys

from pydantic import BaseModel

from agent_surface import App
from agent_surface.adapters.click import build_click_group
from agent_surface.adapters.mcp import MCPAdapter


class GreetRequest(BaseModel):
    name: str


class Greeting(BaseModel):
    message: str


app = App("hello")


@app.operation("people.greet", summary="Greet one person", read_only=True)
def greet(request: GreetRequest) -> Greeting:
    return Greeting(message=f"Hello, {request.name}!")


cli = build_click_group(app)
mcp = MCPAdapter(app)

if __name__ == "__main__":
    if sys.argv[1:] == ["--mcp"]:
        asyncio.run(mcp.run_stdio())
    else:
        cli()

Install the package into your existing Python environment and run the CLI:

pip install 'agent-surface[mcp]'
python hello.py people greet --name Ada

The same typed operation is callable from Python, exposed through Click, and available as the exact MCP tool people.greet.

Connect it to MCP

For a local client, use stdio: the client starts hello.py --mcp and exchanges MCP messages over standard input and output. Add this to ~/.codex/config.toml, replacing both absolute paths. python must be the interpreter where you installed agent-surface:

[mcp_servers.hello]
command = "/absolute/path/to/.venv/bin/python"
args = ["/absolute/path/to/hello.py", "--mcp"]

Restart Codex, then use /mcp to inspect hello. For Claude Code, save the equivalent project-local .mcp.json next to hello.py:

{
  "mcpServers": {
    "hello": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["/absolute/path/to/hello.py", "--mcp"]
    }
  }
}

Streamable HTTP is only for serving MCP remotely from a web application. See the MCP contract when you need that deployment.

Author a new surface

Install the optional authoring skills for an agent that will build a HATEOAS CLI or MCP tool:

curl -fsSL https://raw.githubusercontent.com/allenday/agent-surface/main/src/agent_surface/skills/install.sh | sh

The agent-surface-authoring skill first checks how the current project manages Python before it uses the library; it does not choose a virtual environment or install packages globally. You can also read the skills directly:

Go deeper when needed

Start with the documentation map if you are unsure which path fits.

Principles

  • one typed operation registry; sibling Python, Click, and MCP adapters
  • YAML-first structured output with compact flow style for small values
  • bounded HATEOAS next_actions, stable references, and explicit confirmation for writes
  • predictable discovery and repair-oriented errors

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 4

Native requirements
4 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
click
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.12",
  "evaluation": "NOT_EVALUATED"
}
click<9,>=8.1runtime
pydantic
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.12",
  "evaluation": "NOT_EVALUATED"
}
pydantic<3,>=2.11runtime
ruamel-yaml
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.12",
  "evaluation": "NOT_EVALUATED"
}
ruamel-yaml<0.20,>=0.19.1runtime
mcp
Environment
{
  "extras": "",
  "marker": "extra == \"mcp\"",
  "requires_python": ">=3.12",
  "evaluation": "NOT_EVALUATED"
}
mcp<3,>=2.0.0; extra == "mcp"runtime

Distribution files

2 collected
agent_surface-0.2.3-py3-none-any.whl

bdist_wheel · 57.68 KB · Python py3

Source file
agent_surface-0.2.3.tar.gz

sdist · 200.42 KB · Python source

Source file

Repository

PENDING
allenday/agent-surface

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 23:30 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:a94d2a4cd7356f6bf99357dd59c69cd9fbca5e31670b81c9d4f86eef0b7a450a

Other collected versions

View all collected versions →