io.github.koten-ai/zeus-dev-helper
OfficialServer Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ZEUS_URL | Yes | Public Zeus API base URL (port 8080). Remote host first; localhost only when Zeus is local. | |
| ZEUS_MODE | No | Default catalog mode | analytics |
| ZEUS_SCOPE | No | Scope for bootstrap and auth probes | |
| LLM_API_KEY | No | Presence checked by validate_env; required for smoke_test_agent | |
| ZEUS_BUCKET | No | Scope for bootstrap and auth probes | |
| ZEUS_PASSWORD | No | Basic auth (never logged) | |
| ZEUS_USERNAME | No | Basic auth (never logged) | |
| OPENAI_API_KEY | No | Presence checked by validate_env; required for smoke_test_agent | |
| ZEUS_AUTH_MODE | No | Auth mode (none, basic, bearer) | |
| ZEUS_COLLECTION | No | Scope for bootstrap and auth probes | |
| ZEUS_BEARER_TOKEN | No | Bearer auth (never logged) | |
| ZEUS_CHAT_REQUEST_DIR | No | 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 | No | Local sample directory for use_sample / travel_golden_path | |
| ZEUS_DEV_HELPER_TOOLSETS | No | Static toolsets: core (default), plus catalog,lint,travel,support,handoff or all | core |
| ZEUS_DEV_HELPER_STATE_DIR | No | Checklist, prereqs, and local metrics | ~/.config/zeus_dev_helper |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Developer Helper MCP coaches a first Zeus Client app to green (session_id / req_id on public :8080). Human docs for first green: https://docs.koten.ai/zeus-client (live published Zeus Client hub — For AI agents, Start, Using Zeus Client, Errors, Dev Helper MCP). Prefer that hub + Helper tools + live :8080; do not clone koten_docs or grep the Zeus engine for first green. Order: doctor → (if user gave URL/sample) set_prereq with those values → start_project → next_step, then only the recommended tool. If the user named a Zeus URL or sample (e.g. beer-sample), call set_prereq with that zeus_url/bucket/scope — do not keep localhost defaults and do not grep the Zeus source tree or hand-roll curl for first green; use readiness_check / smoke_test_zeus / zeus-helper://. If the user did not name a Zeus URL, leave zeus_url empty and wait for the form. Do not copy the host ZEUS_URL into set_prereq. Call recommend_surface before choosing Travel LLM vs the beer catalog pair vs FastAPI. A website returns inputs: Direct list, chips, typeahead, paging, and detail, plus One chat for the question box. It does not return one mode for the whole app. If has_llm_key=false, do not offer smoke_test_agent / travel as the only path. Hard constraints: public API is :8080 not Hub :9091; never invent contract_hash; fetch_chat_request / catalog resources are TEMPLATE ONLY (prefer a live Zeus stamp); no secrets in results or checklist evidence; semantic cache stays off. scaffold_app / smoke_test_agent emit ZeusRuntime + run_turn, not V1 ZeusClient / run_agent. TravelPlan / demo_travel_sample is the agent-plane (LLM chat UI) example; demo_beer_sample is the beer-sample catalog UI: Direct lists plus One chat Pour. Lists, chips, and detail are find and get and need no LLM key. Pour is rt.agent.run_turn with chat_request omitted so catalog.load_for_turn merges SCOPE BRIEF + MINI-SCHEMA. max_rounds is 4. Pour stays off until LLM_API_KEY, XAI_API_KEY, or OPENAI_API_KEY is in the app .env. Checklist 1.2 does not block the lists. config.json llm.api_key_env stays the name LLM_API_KEY. has_llm_key=true is not the key. verify_local_setup before Pour or smoke_test_agent. verify_local_setup imports zeus_client in this Helper process. The app .venv does not satisfy that check. Install the agent extra (uvx --from '[agent]' zeus-dev-helper-mcp) and restart this MCP server. Do not pip install kotenai-zeus-client into the app as the fix for that check. The BFF does not build a pipeline body — https://docs.koten.ai/zeus-client/using-zeus-client. Bootstrap default is UI: use_sample follows the beer creation procedure for https://github.com/koten-ai/demo_travel_sample.git. The destination is sample_dir, or parent_dir plus project_name. A blank parent is the directory next to this Helper checkout. A foreign default directory moves to the next open sibling. An explicit foreign sample_dir returns foreign_sample_dir and writes nothing. A recorded checkout that answers GET /api/health returns already_serving. Basic auth with no process login returns login_not_in_process before git clone. The create path does not rewrite Docker files. python -m travel_planner listens on port 5000 unless PORT is set. use_sample writes a mode 600 .env from the non-secret Zeus and LLM names, keeps populated values, and fills empties. ZEUS_USERNAME defaults to demo_1. A rewrite of an existing .env sets env_change. settings_written names which of ZEUS_AUTH_MODE, ZEUS_USERNAME, LLM_BASE_URL, and LLM_MODEL changed. settings_kept gives the populated values that stayed. ZEUS_PASSWORD, ZEUS_BEARER_TOKEN, and LLM_API_KEY stay presence-only in secret_presence. Restart the app before run_turn when env_change is true. Checklist 1.2 stays open until this process has an LLM key, because this page is search and has no Direct list. Checklist 3.2 stays open until the app .env has LLM_API_KEY, XAI_API_KEY, or OPENAI_API_KEY. set_prereq(has_llm_key=true) does not count. After the app is on disk, checklist 5.1, 5.2, and 6.1 recommend website_green. Travel is one scope: do not add handoff_to_multi after smoke-green and do not write jobs.host_url. Beer / website: start_project(sample=beer) → use_sample(sample=beer) shallow-clones https://github.com/koten-ai/demo_beer_sample when missing and sets DEMO_BEER_SAMPLE_DIR. That checkout is the app. Create the virtualenv with Python 3.11 or newer. The use_sample run string uses python3 -m venv only when python3 is 3.11 or newer. kotenai-zeus-client does not install on Python 3.9. Then pip install -r requirements.txt and python main.py. use_sample writes mode 600 .env from .env.example, keeps populated values, and adds missing template keys. Resolve LLM_API_KEY, LLM_BASE_URL, and LLM_MODEL together. Copy OPENAI_API_KEY or XAI_API_KEY only when the base URL and model match that provider. The clone keeps LLM_MODEL=grok-4.5-latest. Do not copy .env.example over a .env that already has values. A rewrite of an existing .env sets env_change. settings_written names which of ZEUS_AUTH_MODE, ZEUS_USERNAME, LLM_BASE_URL, and LLM_MODEL changed. settings_kept gives the populated values that stayed. ZEUS_PASSWORD, ZEUS_BEARER_TOKEN, and LLM_API_KEY stay presence-only in secret_presence. Restart the app before run_turn when env_change is true. python main.py binds 127.0.0.1:8090. Lists are Direct. Pour is the same run_turn shape as travel, with max_rounds 4, and it stays off until an LLM key is in .env. Do not clone demo_travel_sample. Do not write jobs.host_url for this one-scope page. A Pour result shows the fields the question asked for, including fields from a joined entity, while the current tab stays selected. The Beers and Breweries controls stay the Direct lists. Search sends the question text and does not add an entity type. When use_sample or website_green returns serve_choice_required, the checkout has both a Dockerfile and a compose file. Follow host_question and next_action on that result. Do not start either command before that answer. The helper does not run Docker. Yelp demo: utterances yelp-demo / demo_yelp use start_project(sample=demo_yelp) → use_sample(sample=demo_yelp), which clones the LocalAI template https://github.com/koten-ai/demo_yelp when missing and sets DEMO_YELP_SAMPLE_DIR. set_prereq bucket yelp-demo scope _default. When parent_dir is set, the clone is created in that directory. That git checkout is the app: pip install -e . && python -m local_guide (API http://127.0.0.1:5000) and cd frontend && npm install && npm run dev (SPA http://localhost:5173, proxies /api to port 5000). Search POSTs /api/search and sends the live chat_request.json for yelp-demo/_default mode analytics as the session body. Search cards get latitude and longitude from biz:yelp: when the project step omits them, including a cached business page. use_sample also downloads the public business photo set into frontend/public/business-images//{1,2,3}.png (no biz: prefix, no API key). Do not scaffold a replacement and do not copy demo_beer_sample. Do not clone demo_travel_sample on that path. Bare sample=yelp stays the multi-agent handoff. API-only: start_project(sample=api) → scaffold_app(app_kind=api, coding_language=python) (FastAPI POST /turn). Other coding languages are not scaffolded yet. Never pass username/password/token into MCP tools — env + set_prereq presence flags only. On the first create, before that sample's creation log exists, use_sample and scaffold_app(app_kind=api) show an elicitation card for ZEUS_URL and ZEUS_USERNAME. The card names the app .env. Put ZEUS_PASSWORD there. Do not type the password into the card. When the checklist needs an LLM, a second card asks LLM_PROVIDER and LLM_MODEL. Put LLM_API_KEY in the same .env. Do not type the key into the card. Existing values are prefilled and can be changed. Decline or cancel does not create the app. A sealed creation log does not open these cards. When the client cannot show a card, keep the ask_user text. When auth is basic and a name is missing, write ZEUS_USERNAME and ZEUS_PASSWORD to a mode-600 env file and call load_process_login with that path. The password is not a tool argument. When a result includes ask_user, follow that result's next_action. A choice row has question and options. Pass that row. A text or password row has no options. Use the host tool's text field. Skip a row whose when does not match. llm_options lists Grok, OpenAI, Anthropic, Gemini, and Other. Set LLM_BASE_URL from the chosen base_url. For Other, ask for the provider name and the base URL. Then ask LLM_MODEL and offer that option's model as the default. Then ask LLM_API_KEY. Write LLM_BASE_URL, LLM_MODEL, and LLM_API_KEY to the same mode-600 file. Do not pass the password or the API key as a tool argument. use_sample for beer, travel, and demo_yelp, and scaffold_app for the API sample, include that full ask_user set when the first-create cards were not shown, including a second build after the creation log is sealed. ZEUS_AUTH_MODE is none, basic, or bearer. basic asks ZEUS_USERNAME as text (beer default tester_beer, travel default demo_1) and ZEUS_PASSWORD as a password. bearer asks ZEUS_BEARER_TOKEN as a password. none skips those. Prefill text fields from the current value. Password, bearer token, and API key have no value in the result. Also write the same names in the app .env. config.json llm.api_key_env stays LLM_API_KEY. set_prereq stores auth_mode and presence flags only. Those secrets stay out of checklist evidence, creation logs, and support journals. validate_env, next_step, readiness_check, smoke_test_agent, verify_local_setup, and a load_process_login that is still missing a name keep the shorter missing-name questions. Knowledge is resources under zeus-helper:// (checklist, glossary, verbs, policies, catalog modes). Walkthroughs are prompts: first_green, smoke_question, support_pack. sample_support_pack(sample=beer|travel|demo_yelp) pastes the support journal for a red beer, travel, or yelp-demo gate. It writes nothing and calls no Zeus API. Session ids stay in support_pack_from_turn. When the user asks to add or inject a business rule and does not name an app, call inject_business_rules. When the result has ask_user, ask and wait, then call again with app_dir or sample. wire_required means the app builds ClientSettings itself. Pass settings.rules into that constructor. The tool writes config.json only. After 5.1+5.2 green: data-plane and multi-agent are handoffs only. A one-scope catalog page does not take handoff_to_multi as the next build step. A job hint is two or more Zeus URLs, two or more scopes, or a report wait of 20 seconds to 5 minutes, and only after the operator confirms. Smoke-green does not write jobs.host_url.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| doctorA | Health / doctor. detail: health | env | compat | cache | all. health checks that env/compat/cache fold validate_env, compat_check, and semantic_cache_status (those names stay on the lint toolset). If the user already gave a Zeus URL or sample name, next call set_prereq with those values (not Helper localhost defaults), then start_project / next_step. Do not grep the Zeus engine tree for first green. |
| start_projectB | Start or reset first-app coaching checklist (single-agent default). sample:
Multi-agent goals (goal=multi or sample=yelp) are gated until single-agent smokes are green, unless force_multi=true (ZDH-11). When no Zeus URL is stored, the MCP call asks for the public :8080 URL before the checklist starts. Leave zeus_url empty when the user did not name one. Do not copy the host ZEUS_URL. Do not pass a password. |
| next_stepA | Return the single current checklist blocker + recommended Helper tools (coach). Call only the recommended tool next. If the user named a URL/bucket and prereqs are unset, recommend set_prereq first. Prefer zeus-helper:// + readiness_check / smoke_test_zeus over hand-rolled curl. |
| set_prereqA | Store non-secret prereqs for readiness (does not store password/token values). Put real secrets in environment variables (ZEUS_PASSWORD, ZEUS_BEARER_TOKEN, LLM_API_KEY). When the user named a Zeus URL or sample in chat, pass that zeus_url / bucket / scope here (not Helper localhost defaults). If the user did not name a URL, leave zeus_url empty and wait for the form. Do not copy the host ZEUS_URL. Persisted values override MCP host ZEUS_* env defaults so readiness/doctor hit the user's cluster (ZDM-3). Presence flags only for credentials and LLM key. |
| load_process_loginA | Load Zeus login from a mode-600 env file into this process. Write ZEUS_USERNAME and ZEUS_PASSWORD to a file outside the repo or gitignored, chmod 600, then pass that path. The password is not an argument. The same file may set ZEUS_AUTH_MODE (none, basic, or bearer), LLM_BASE_URL, LLM_MODEL, and LLM_API_KEY. set_prereq stores presence flags only. The result lists loaded names and never values. Then readiness_check. |
| readiness_checkB | Live Zeus platform gates: healthz/readyz/version, auth, bootstrap, chat_request. Never returns secret values. Emits failure_class + next_action on red paths. |
| explain_scopeA | Summarize the live chat_request stamp on public :8080. Entity types, display fields, text-search fields, foreign-key fields, and the verb for list (find), detail (get), and search. No prompt text, document bodies, or secrets. fetch_chat_request stays template only. When GET /v1/ai/chat_request.json has no ## MINI-SCHEMA heading, the summary is parsed from bootstrap.chat_request. missing_mini_schema remains when that message also has no heading. A failed stamp sets failure_class and does not invent entity types. |
| scaffold_appA | Write a ZeusRuntime middle-man. app_kind=cli (default) or api (FastAPI POST /turn). coding_language=python only today. UI demos use use_sample / demo_travel_sample, not this tool. When no Zeus URL is stored, the MCP call asks before writing files. Do not pass a password. |
| use_sampleA | UI sample: travel clone, beer catalog UI, live-stamp page, or yelp demo clone. sample=travel — shallow-clone https://github.com/koten-ai/demo_travel_sample.git when the destination is missing. The destination is sample_dir, or parent_dir plus project_name. A blank parent is the directory next to this Helper checkout. Start with python -m travel_planner on port 5000 unless PORT is set. The create path does not rewrite Docker files. Set DEMO_TRAVEL_SAMPLE_DIR. A mode 600 .env keeps populated values and fills empty Zeus and LLM names. ZEUS_USERNAME defaults to demo_1. A rewrite of an existing .env sets env_change. settings_written names which of ZEUS_AUTH_MODE, ZEUS_USERNAME, LLM_BASE_URL, and LLM_MODEL changed. settings_kept gives the populated values that stayed. ZEUS_PASSWORD, ZEUS_BEARER_TOKEN, and LLM_API_KEY stay presence-only in secret_presence. Restart the app before run_turn when env_change is true. sample=beer — shallow-clone https://github.com/koten-ai/demo_beer_sample when missing; set DEMO_BEER_SAMPLE_DIR. Start with python main.py after a Python 3.11+ virtualenv (python3 -m venv only when python3 is 3.11 or newer) and pip install -r requirements.txt. use_sample writes mode 600 .env from .env.example, keeps populated values, and adds missing template keys. LLM_API_KEY, LLM_BASE_URL, and LLM_MODEL are resolved together. The clone keeps LLM_MODEL=grok-4.5-latest. Do not copy .env.example over a .env that already has values. A rewrite of an existing .env sets env_change. settings_written names which of ZEUS_AUTH_MODE, ZEUS_USERNAME, LLM_BASE_URL, and LLM_MODEL changed. settings_kept gives the populated values that stayed. ZEUS_PASSWORD, ZEUS_BEARER_TOKEN, and LLM_API_KEY stay presence-only in secret_presence. Restart the app before run_turn when env_change is true. Lists are Direct and need no LLM key. Pour is rt.agent.run_turn with chat_request omitted (catalog.load_for_turn merges MINI-SCHEMA) and max_rounds 4. Pour stays off until an LLM key is in the app .env. No pipeline body. Do not write a job for this one-scope page. Clone success is not website_green. When the checkout has both a Dockerfile and a compose file, serve_choice_required is true, serve_options lists Python and Docker, host_question is the selection, and run is empty until serve_with is python or docker. Follow host_question and next_action on that result. The helper does not run Docker. Pass serve_with on a later use_sample or website_green call. An already-serving checkout does not ask. sample=catalog — write demo_catalog_sample from explain_scope. A beer-sample bucket, or entity types that are exactly Beer and Brewery, still writes the beer UI. sample=demo_yelp — locate or clone the LocalAI template https://github.com/koten-ai/demo_yelp (aliases yelp-demo, demo-yelp); set DEMO_YELP_SAMPLE_DIR. When parent_dir is set, clone into that directory. The checkout is the app: pip install -e . && python -m local_guide on http://127.0.0.1:5000, and cd frontend && npm install && npm run dev on http://localhost:5173 (the SPA proxies /api to port 5000). Writes gitignored mode-600 config.json from this process. llm.api_key_env stays the name LLM_API_KEY. Search POSTs /api/search and sends the live chat_request.json for yelp-demo/_default mode analytics as the session body. A 401 stays red. Search cards get latitude and longitude from biz:yelp: when the project step omits them, including a cached business page. The business page GETs /api/business/{id} when the id is not in the bundled catalog. Review text is the source document, not the rev: doc key. Also downloads the public business photo set into frontend/public/business-images//{1,2,3}.png (no biz: prefix, no API key). Do not write a replacement or copy demo_beer_sample. Bare sample=yelp stays the multi-agent handoff. project_name = directory name (defaults: demo_travel_sample / demo_beer_sample / demo_catalog_sample / demo_yelp). Extra travel-only phases stay on travel_golden_path (travel toolset). When no Zeus URL is stored, the MCP call asks before writing or cloning. Do not pass a password. |
| inject_business_rulesB | Write named business rules into the current Zeus app. Omit app_dir and sample to use the current directory when it is a Zeus app, otherwise the checklist sample (the beer app just created). ask_user means ask and wait, then call again. An explicit path that is not a Zeus app returns not_a_zeus_app and does not write. wire_required means the app builds ClientSettings itself. Pass settings.rules into that constructor. This tool writes config.json only. |
| smoke_test_zeusB | Smoke Zeus without LLM: readiness + POST /v2/{bucket}/{scope}/describe. |
| website_greenA | Install, start, and check the catalog page. Separate from smoke_test_zeus. Mints the scope session when auth is basic, then checks list cards and, when Pour is on, one search. A title-cased doc_key or src_keys entry is not a search card. A describe 200 is not this check. Does not call smoke_test_agent. No secrets in the result. serve_with is python or docker. When the checkout has both a Dockerfile and a compose file and serve_with is empty, this returns serve_choice_required and host_question and does not start Python. Follow host_question and next_action. Docker is not run. |
| smoke_test_agentC | One ZeusRuntime run_turn (requires kotenai-zeus-client>=2.3.0 + LLM key). If the client is missing and demo_travel_sample documents Docker install, returns guide-only docker compose next_action instead of only pip install. |
| diagnose_errorB | Map a symptom to failure_class + one generated-file change. Accepts symptom text, optional req_id, hop name, HTTP status, and the top-level keys of the hop result. Does not accept document bodies. Does not echo a password, session id, or document body. Includes Detective URL templates when req_id/chat_id are present. Does not scrape Hub. |
| sample_support_packA | Read-only paste for a beer, travel, or yelp-demo support request. Writes nothing and calls no Zeus API. Returns one Markdown paste: sample kind, bound directory, creation log, prereqs, open checklist rows in phases 1–5, the last website_green class, local setup, recent tool names, and the support-journal tail. Session ids stay in support_pack_from_turn. sample=api and bare sample=yelp are refused. |
| recommend_surfaceC | Name each website input. One box still returns one surface. Does not call Zeus. A website (intent=nl_question) returns inputs: Direct list, chips, typeahead, paging, and detail, plus a One chat question box. url_count, scope_count, or report_wait_s of 20 seconds or more is a Job hint. The tool does not write jobs.host_url. Zero counts mean one URL and one scope. |
| bind_contractC | Extract stamped contract.hash only. Refuse placeholders / compute_local (ZDH-22). With no path, copy the hash from the live bootstrap chat_request. A helper chat_request.json directory pointer is not an unstamped catalog. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| first_green | Day-one path to a first green ZeusRuntime turn. |
| smoke_question | Advice-shaped question for smoke_test_agent. |
| support_pack | Redacted support pack from a failed turn. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| checklist | First-app coaching checklist JSON |
| glossary | Glossary topic index (read zeus-helper://glossary/{topic} for a page) |
| verbs | V2 verb index (read zeus-helper://verbs/{name} for a page) |
| hash_boundary | What is excluded from contract_hash (MINI-SCHEMA / brief) |
| req_id_policy | One UUID per hop; never composite hop ids; never Rewind /turn |
| catalog_modes | V2 min chat_request modes from zeus_chat_request (TEMPLATE ONLY) |
TDQS
Scored across 17 tools
The set contains five overlapping health/smoke tools (doctor, readiness_check, smoke_test_zeus, smoke_test_agent, website_green) whose boundaries only become clear after reading long descriptions that explicitly negate each other ('Separate from smoke_test_zeus', 'A describe 200 is not this check'). Similarly use_sample, start_project, and scaffold_app all initiate project setup and rely on prose to differentiate. Descriptions do enough work that a careful agent can pick correctly, but the surface invites misselection.
Almost everything is snake_case with a verb_noun shape (diagnose_error, explain_scope, scaffold_app, bind_contract, set_prereq, start_project, next_step, inject_business_rules). A few outliers break the verb pattern: doctor, website_green, readiness_check, and sample_support_pack read as nouns/adjectives. Minor deviations only, still predictable overall.
17 tools is at the upper edge for a dev helper; the coaching/checklist workflow (start_project, next_step, set_prereq) plus three distinct sample workflows inflate the count. Each tool has a rationale, but several (doctor vs readiness_check, smoke_test_zeus vs smoke_test_agent) could plausibly be folded into parameterized tools. Borderline heavy rather than clearly over-scoped.
The surface covers the full lifecycle for its stated purpose: prereq storage, login loading, readiness/smoke checks, scaffolding, sample cloning, surface recommendation, contract binding, business-rule injection, and error diagnosis with a support pack. Gaps exist around teardown/stop, log or artifact inspection, and editing files other than config.json, but these are minor workarounds rather than dead ends.