https://github.com/msradam/coffee-agent
A toy MCP agent built with Theodosia: a coffee-order state machine an LLM drives one enforced step at a time.
https://github.com/msradam/coffee-agent
apache-burr example llm-agents mcp model-context-protocol state-machine theodosia
Last synced: about 14 hours ago
JSON representation
A toy MCP agent built with Theodosia: a coffee-order state machine an LLM drives one enforced step at a time.
- Host: GitHub
- URL: https://github.com/msradam/coffee-agent
- Owner: msradam
- Created: 2026-05-25T02:20:11.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-25T05:16:09.000Z (about 1 month ago)
- Last Synced: 2026-05-25T07:14:46.177Z (about 1 month ago)
- Topics: apache-burr, example, llm-agents, mcp, model-context-protocol, state-machine, theodosia
- Language: Python
- Size: 1.86 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# coffee-agent
A toy agent built with [Theodosia](https://github.com/msradam/theodosia): a coffee
ordering workflow defined as a [Burr](https://burr.dagworks.io/) state machine
and served as an [MCP](https://modelcontextprotocol.io/) server. An LLM drives
it one transition at a time, and the server enforces the order of operations.
```mermaid
stateDiagram-v2
[*] --> take_order
take_order --> add_modifier
take_order --> pay
take_order --> cancel
add_modifier --> add_modifier
add_modifier --> pay
add_modifier --> cancel
pay --> fulfill
fulfill --> [*]
cancel --> [*]
```
This diagram is the contract. The agent can only move along these edges; the
server refuses any step that is not a reachable transition. The workflow lives
in the state machine, not in a prompt the model has to remember. Pay before
ordering, or fulfill before paying, and the response is a structured refusal
listing the actions that are actually reachable.
An LLM drives it over MCP. Here fast-agent connects a Llama-3.3-70B model
(on Together) and the model calls the `step` tool to walk the order:

The same workflow is observable from the terminal. `coffee-agent render` prints
the graph; `coffee-agent sessions show` replays a recorded run, refusals in red:

## Build it yourself
This whole repo is about 90 lines. The shape:
1. `src/coffee_agent/app.py` defines the Burr graph (five `@action`s and the
transitions between them).
2. `src/coffee_agent/cli.py` wraps it in Theodosia's `build_cli` so the package
ships a `coffee-agent` command with the graph baked in.
3. `pyproject.toml` depends on `theodosia` and registers the console script.
## Install
```bash
git clone https://github.com/msradam/coffee-agent.git
cd coffee-agent
uv venv --python 3.13
uv pip install -e .
```
`coffee-agent serve` now runs the MCP server over stdio. You usually do not run
it directly; an MCP client launches it for you (below).
## Run it as an agent
The repo ships an `.mcp.json` pointing a client at `coffee-agent serve`. Pick a
client:
### Claude Code (zero extra install if you have it)
```bash
claude mcp add --transport stdio coffee-agent -- uv run coffee-agent serve
claude
```
Then ask: "Order a latte with an extra shot and pay for it." Claude calls the
`step` tool to walk the graph.
### fast-agent (a terminal REPL, Python)
The repo ships a `fastagent.config.yaml` defining this server, so:
```bash
uvx fast-agent-mcp go --servers coffee-agent -m "Order a latte and pay for it, then fulfill the order."
```
It uses Gemini by default (set `GOOGLE_API_KEY`). To drive it with a Together
model instead, set `GENERIC_API_KEY` and add
`--model generic.meta-llama/Llama-3.3-70B-Instruct-Turbo`. For a fully local
run, point the config's `generic.base_url` at Ollama.
### MCPJam (one npx command, free hosted models, browser playground)
```bash
npx @mcpjam/inspector
```
Add the server with command `uv` and args `run coffee-agent serve`, then chat in
the playground.
## Watch what it did
Every step is recorded to Burr's tracker. From the repo:
```bash
uv run coffee-agent sessions ls
uv run coffee-agent sessions show # per-step timeline, refusals in red
uv run coffee-agent watch # live-tail a running session
uv run coffee-agent verify # check the session's hash-chained ledger
```
`coffee-agent` inherits these observability commands from Theodosia. Every step
and refusal is also hash-chained into a tamper-evident `ledger.jsonl`; `verify`
recomputes the chain and names any line that was edited or reordered after the
fact.
## License
Apache 2.0. Built on [Theodosia](https://github.com/msradam/theodosia),
[Apache Burr](https://github.com/apache/burr), and
[FastMCP](https://github.com/jlowin/fastmcp).