io.github.koten-ai/zeus-dev-helper
Official# Zeus Dev Helper MCP
<!-- mcp-name: io.github.koten-ai/zeus-dev-helper -->
Stdio MCP server that coaches a coding agent and a human to a first successful Zeus Client app turn.
This is not a data-plane MCP. It does not run Explore/Verify verbs on your behalf, invent contract hashes, or perform Hub admin mutations. After the first-green smokes pass, data-plane and multi-agent work are **handoffs only**.
| | |
| --- | --- |
| **Package** | `zeus-dev-helper-mcp` |
| **Registry name** | `io.github.koten-ai/zeus-dev-helper` |
| **Transport** | stdio |
| **Python** | 3.11+ |
| **MCP SDK** | `mcp` (`FastMCP` on 1.x / `MCPServer` on 2.x) |
## What it does
The server walks a first-app checklist: prereqs, live readiness on the public Zeus API, catalog templates, contract bind (copy a stamped hash only), surface/verb coaching, config lint, and smoke tests. Prefer a live Zeus stamp for catalogs. `fetch_chat_request` is always **template only**.
Hard constraints the tools enforce:
- Public Zeus API on port **8080** only (never Hub **9091** from the app path)
- Never invent `contract_hash`
- No secrets in tool results, checklist evidence, or support packs
- Semantic cache stays off
## Install
```bash
pip install zeus-dev-helper-mcp
# or
uvx zeus-dev-helper-mcp
```
Optional extra for `smoke_test_agent` (pulls the Zeus Client package):
```bash
pip install "zeus-dev-helper-mcp[agent]"
```
## Run
```bash
zeus-dev-helper-mcp
# or
python -m zeus_dev_helper_mcp
```
Prefer the published console script (`uvx` / `pip install`) so hosts do not need a source checkout.
## Host install
Set `ZEUS_URL` to your Zeus **public API** on port **8080** (never Hub `:9091`). Prefer the remote host you actually use. Use `http://localhost:8080` only when Zeus runs on the **same machine** as the MCP host.
```bash
# Remote Zeus (typical lab / shared engine) — put your host here
export ZEUS_URL=http://192.168.0.219:8080
# or: http://<zeus-host>:8080
#
# Same-machine Zeus only:
# export ZEUS_URL=http://localhost:8080
```
If the user names a URL or sample in chat, call **`set_prereq`** with that `zeus_url` / bucket / scope (do not keep a stale localhost default). `doctor` reports **stored vs effective** URL routing (see [ZDM-3](https://kotenai.atlassian.net/browse/ZDM-3)).
### Grok Build
`grok mcp add` treats flags like `-m` as its own unless they come **after `--`**. The `uvx` argument is the **PyPI package** `zeus-dev-helper-mcp`, not the MCP server id `zeus-dev-helper`.
```bash
grok mcp add zeus-dev-helper \
-e ZEUS_URL=http://192.168.0.219:8080 \
-- uvx zeus-dev-helper-mcp
```
From a local checkout after `pip install -e ".[dev]"`, point `command` at this tree’s venv so the host can start the server even when it was launched without the venv activated:
```bash
grok mcp add zeus-dev-helper \
-e ZEUS_URL=http://192.168.0.219:8080 \
-- "$(pwd)/.venv/bin/python" -m zeus_dev_helper_mcp
```
Equivalent config:
```toml
[mcp_servers.zeus-dev-helper]
command = "uvx"
args = ["zeus-dev-helper-mcp"]
env = { ZEUS_URL = "http://192.168.0.219:8080" }
enabled = true
```
Then refresh MCP servers, or `grok mcp doctor zeus-dev-helper`.
Common failures:
- `unexpected argument '-m'` — missing `--` before the python command
- `uvx zeus-dev-helper` / `No solution found` — wrong package name; use **`zeus-dev-helper-mcp`**
- `No module named 'zeus_dev_helper_mcp'` / `python: No such file or directory` — the host did not inherit the venv; use the `.venv/bin/python` path above
- `No module named 'mcp.server.fastmcp'` — mcp 2.x renamed FastMCP; use Helper **0.6.0+** (`mcp>=1.8.0,<3`)
### Claude Code / Claude Desktop
```json
{
"mcpServers": {
"zeus-dev-helper": {
"command": "uvx",
"args": ["zeus-dev-helper-mcp"],
"env": {
"ZEUS_URL": "http://192.168.0.219:8080"
}
}
}
}
```
### Cursor
Add (or merge) `.cursor/mcp.json` in the project (or use Cursor’s global MCP settings):
```json
{
"mcpServers": {
"zeus-dev-helper": {
"command": "uvx",
"args": ["zeus-dev-helper-mcp"],
"env": {
"ZEUS_URL": "http://192.168.0.219:8080"
}
}
}
}
```
### Other stdio hosts
Point the host’s MCP stdio entry at `uvx zeus-dev-helper-mcp` (or `python -m zeus_dev_helper_mcp` from a venv) with the same env vars. Replace the sample IP with your Zeus host.
## Day-one coach path
```text
doctor → (if user named URL/sample) set_prereq → start_project → next_step
→ readiness_check
→ use_sample | scaffold_app → bind_contract → recommend_surface
→ smoke_test_zeus → smoke_test_agent → diagnose_error
```
Prefer `next_step` over dumping the full checklist. Two first-green paths (TravelPlan is **not** the only path):
- **Travel + LLM (UI default):** `start_project(sample=travel)` → **`use_sample`**, which **clones** public [`demo_travel_sample`](https://github.com/koten-ai/demo_travel_sample) when missing (optional `project_name` for the directory) and sets `DEMO_TRAVEL_SAMPLE_DIR`. Checklist **1.2** stays open until this process has `LLM_API_KEY`, `XAI_API_KEY`, or `OPENAI_API_KEY`. `smoke_test_agent` reads that variable. Standalone clones pin `kotenai-zeus-client>=2.4.0,<2.5` so `run_turn` can recover a fenced pipeline inside the SDK.
- **Beer catalog UI:** `start_project(sample=beer)` → `use_sample(sample=beer)` **writes** `demo_beer_sample` (FastAPI BFF + static page). Search matches travel: `rt.agent.run_turn` with `chat_request` omitted so `catalog.load_for_turn` merges the live SCOPE BRIEF and MINI-SCHEMA. The key is required even when `has_llm_key=false`. Put it in the app `.env`. Leave `config.json` `llm.api_key_env` as that variable name. `verify_local_setup` keeps checklist **3.2** open until that file check passes. The BFF does not build a pipeline body. Do not clone `demo_travel_sample`.
- **Yelp demo UI:** `start_project(sample=demo_yelp)` → `use_sample(sample=demo_yelp)` **clones** the LocalAI template [`demo_yelp`](https://github.com/koten-ai/demo_yelp) when missing (utterances `yelp-demo` / `demo_yelp`) and sets `DEMO_YELP_SAMPLE_DIR`. When `parent_dir` is set, the clone is created in that directory. That checkout is the app: run it, and do not write a replacement or copy the beer sample. `use_sample` also downloads the public business photo set into `frontend/public/business-images/<id>/{1,2,3}.png` (no `biz:` prefix, no API key). Search POSTs `/api/search` and sends the live chat request for `yelp-demo` / `_default` as the session body. Search cards unwrap a hybrid `{node, score}` hit and a nested pipeline row. The business page GETs `/api/business/{id}` when the id is not in the bundled catalog. Review text is the source document, not a `rev:` doc key. `set_prereq` bucket is `yelp-demo`, scope `_default`. Do not clone `demo_travel_sample`. Bare `sample=yelp` stays the multi-agent handoff.
- **API-only:** user asks for an API/REST app → `start_project(sample=api)` → `scaffold_app(app_kind=api, coding_language=python)` (FastAPI `POST /turn` on `kotenai-zeus-client`). Other languages not scaffolded yet.
- Credentials from chat → process env / gitignored `.env`; `set_prereq` presence flags only. `has_llm_key=true` does not count as the key. Pass the user’s Zeus URL into `set_prereq(zeus_url=…)`. Do not paste the secret into `llm.api_key_env`.
- Integrating into an arbitrary existing repo is **out of scope**.
Read `zeus-helper://` resources for glossary, verbs, policies, and catalog modes. Hosts can pick prompts `first_green`, `smoke_question`, and `support_pack`.
## Default tools (`core`)
Live `tools/list` is the call contract. Default surface is the **core** toolset (`ZEUS_DEV_HELPER_TOOLSETS=core`).
| Tool | Job |
| --- | --- |
| `doctor` | Health. `detail=health\|env\|compat\|cache\|all` (env/compat/cache fold lint-toolset checks) |
| `start_project` | Init checklist; `sample=travel` (UI default), `sample=beer` (catalog UI, `run_turn`), `sample=demo_yelp` (clone `demo_yelp`), or `sample=api` |
| `next_step` | Current item plus recommended tools and resource links |
| `set_prereq` | Store non-secret prereqs (presence flags only; `has_llm_key` is not the key) |
| `readiness_check` | Live gates: healthz / readyz / version, auth, bootstrap. Marks **1.2** done only when the URL is set and, on a `run_turn` path, the process has an LLM key |
| `explain_scope` | Live public `:8080` `chat_request.json` summary: entity types, display fields, text-search fields, FK fields, and list/detail/search verbs. A failed stamp leaves entity types empty. `fetch_chat_request` stays template only |
| `scaffold_app` | CLI or FastAPI (`app_kind=cli\|api`) ZeusRuntime app; python only |
| `use_sample` | Travel UI clone, beer catalog UI (`run_turn`, `chat_request` omitted), `sample=catalog` from `explain_scope`, or yelp demo clone (`sample=demo_yelp`, sets `DEMO_YELP_SAMPLE_DIR`; downloads public photos into `frontend/public/business-images/<id>/`, no API key; live search and business page, review text from the source document) |
| `bind_contract` | Copy a stamped `contract.hash` only; refuses empty / local compute |
| `recommend_surface` | Intent → Client surface + do-not list |
| `smoke_test_zeus` | No LLM: readiness plus a read-only describe |
| `website_green` | Install, start, and check the catalog page (named list card, page ids, search when Pour is on). A title-cased `doc_key` is not a search card. A describe 200 is not this check |
| `smoke_test_agent` | One Client `run_turn`. Needs `[agent]` extra and `LLM_API_KEY`, `XAI_API_KEY`, or `OPENAI_API_KEY` in this process |
| `diagnose_error` | Map a symptom, hop name, and result keys to a failure class and one generated-file change |
| `sample_support_pack` | Read-only paste for a beer, travel, or yelp-demo gate failure. Writes nothing and calls no Zeus API. Session ids stay in `support_pack_from_turn` |
Opt-in toolsets (static, comma-separated): `catalog`, `lint`, `travel`, `support`, `handoff`. `all` enables every set. Full when/args/side-effects map: [`docs/TOOLS.md`](docs/TOOLS.md).
Resources (always on): `zeus-helper://checklist`, `zeus-helper://glossary/{topic}`, `zeus-helper://verbs/{name}`, `zeus-helper://policy/hash-boundary`, `zeus-helper://policy/req-id`, `zeus-helper://catalog/modes`.
## Environment
Secrets stay in the process environment. `set_prereq` stores presence flags only. Tool results redact secret values.
| Variable | Purpose |
| --- | --- |
| `ZEUS_URL` | Public Zeus API base URL (port 8080). Remote host first; `localhost` only when Zeus is local |
| `ZEUS_BUCKET` / `ZEUS_SCOPE` / `ZEUS_COLLECTION` | Scope for bootstrap and auth probes |
| `ZEUS_MODE` | Default catalog mode (`analytics`) |
| `ZEUS_AUTH_MODE` | Auth mode (`none`, basic, bearer) |
| `ZEUS_USERNAME` / `ZEUS_PASSWORD` | Basic auth (never logged) |
| `ZEUS_BEARER_TOKEN` | Bearer auth (never logged) |
| `LLM_API_KEY` / `XAI_API_KEY` / `OPENAI_API_KEY` | Process key for checklist **1.2**, `validate_env`, and `smoke_test_agent`. The app `.env` needs the same name for Pour / `uvicorn`. `config.json` `llm.api_key_env` stays the name. A stored `has_llm_key` flag does not count |
| `ZEUS_CHAT_REQUEST_DIR` | Local directory of min catalog templates; auto-set when `list_catalog_modes` / `fetch_chat_request` locate or clone public `zeus_chat_request` |
| `DEMO_TRAVEL_SAMPLE_DIR` | Local sample directory for `use_sample` / `travel_golden_path` |
| `DEMO_YELP_SAMPLE_DIR` | Local `demo_yelp` directory for `use_sample(sample=demo_yelp)` |
| `BUSINESS_IMAGES_BASE_URL` | Optional CDN prefix for the yelp photo download (no trailing slash). Default is the public `koten-yelp-demo-photos` Space. No API key |
| `ZEUS_DEV_HELPER_SKIP_YELP_IMAGES` | Set to `1` to skip the yelp photo download during `use_sample(sample=demo_yelp)` |
| `YELP_IMAGE_FETCH_WORKERS` | Parallel downloads for that photo set. Default `8` |
| `ZEUS_DEV_HELPER_STATE_DIR` | Checklist, prereqs, local metrics, the write-once sample creation logs (`beer-sample-build.md`, `travel-sample-build.md`, `yelp-demo-build.md`), and the support journals (`beer-sample-support.md`, `travel-sample-support.md`, `yelp-demo-support.md`). Default `~/.config/zeus_dev_helper` |
| `ZEUS_DEV_HELPER_TOOLSETS` | Static toolsets: `core` (default), plus `catalog,lint,travel,support,handoff` or `all` |
## Boundaries
| This MCP | Not this MCP |
| --- | --- |
| Onboarding coach to first green | Data-plane Explore/Verify tools |
| Catalog **templates** plus readiness and smoke | Inventing or locally computing `contract_hash` |
| Verb explain / lint / draft (`posted=false`) | POSTing `find` / `search` / `get` / `pipeline` |
| Detective **URL templates** | Hub scrape or Hub admin mutations |
| Multi / data-plane **handoffs** | Multi-agent job runtime |
| Local checklist and metrics | Shipping secrets in evidence or support packs |
## Dev install
From a local checkout:
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
# optional agent smoke:
pip install -e ".[agent]"
export ZEUS_URL=http://localhost:8080
```
```bash
pytest -q
```
## MCP Registry
Official registry name: `io.github.koten-ai/zeus-dev-helper`. The registry hosts metadata only; the install artifact is the PyPI package `zeus-dev-helper-mcp`.
## License
BSD-3-Clause — see [LICENSE](LICENSE).
TDQS
Scored across 16 tools
Several tools overlap in verification/prereq/diagnostic space (readiness_check, smoke_test_zeus, smoke_test_agent, website_green, doctor, diagnose_error), and setup tools (set_prereq, load_process_login) can be confused. Descriptions explicitly clarify separations and non-goals, but the agent still needs careful reading to avoid misselection.
Most names are snake_case, but the set mixes verb_noun patterns (start_project, use_sample, bind_contract) with noun phrases (readiness_check, sample_support_pack) and a single bare noun (doctor). It remains readable but not predictably patterned.
With 16 tools, the set sits at the heavy end for a dev-helper server. Many tools earn their place across the lifecycle, but the count feels borderline and contributes to overlap among readiness, smoke, website, and diagnostic operations.
The surface covers prereq setup, login loading, sample creation, scaffolding, readiness, smoke tests, website checks, diagnostics, support, next-step coaching, surface recommendation, and contract binding. Minor gaps exist around cleanup/reset beyond start_project and explicit secret management, but core workflows are covered.