An Enterprise AI Workforce OS. A Planner launches a mission into a live ecosystem of specialist tools, discovers them over the Model Context Protocol, plans an execution order, runs each tool, verifies the results, holds a council vote, and synthesizes an executive report — streaming every step to a Mission Control UI in real time.
What makes this real: the seven specialist capabilities are served by a NitroStack MCP server and consumed by the orchestrator through the official MCP client SDK. Discovery is a real
listTools()call and execution is a realcallTool()over Streamable HTTP — not an in-memory registry pretending to be MCP. Swap in any other MCP server and the Planner keeps working unchanged.
Built for the Enterprise AI & Workplace Automation track: the missions, tools, and prompts are modelled on the cross-domain decisions operations teams actually automate (approval routing, vendor evaluation, risk/compliance sign-off).
Most "AI agent" demos are one LLM call behind a system prompt. Real operational decisions aren't like that: a request touches finance, risk, and compliance at once, needs more than one specialist, and shouldn't be trusted until it's been checked. MADMAX models that explicitly and makes the orchestration visible — discovery, planning, execution, verification, and a recorded vote — instead of hiding it inside one prompt.
Crucially, the specialists are MCP tools behind a protocol boundary. They have no handle to each other and cannot call one another. The Planner is the only thing that sequences work. That's not a stylistic choice — it's enforced by the architecture.
┌────────────────────────────┐ Streamable HTTP (MCP) ┌──────────────────────────────┐
│ Orchestrator (MCP client) │ ─── listTools() / callTool() ───► │ NitroStack MCP server │
│ • Planner (Gemini) │ │ 7 tools: │
│ • retry + recovery │ ◄─── structured tool results ───── │ research, finance, risk, │
│ • council vote │ │ compliance, strategy, │
│ • report synthesis │ │ verification, report │
│ • WebSocket gateway │ └──────────────────────────────┘
└──────────────┬─────────────┘
│ WebSocket (typed events)
▼
Mission Control UI (real-time execution graph, confidence chart, transcript, vote, replay)
Two processes, one repo. See ARCHITECTURE.md for the full breakdown.
Requirements: Node.js ≥ 20.18.
# 1. install
npm install
# 2. (optional) configure
cp .env.example .env
# Set GEMINI_API_KEY=... (a Google AI Studio key, starts with "AIza") for live
# Gemini output. If you skip this entirely,
# MADMAX still boots — it auto-runs in labelled MOCK mode (the UI shows a
# "MOCK LLM" banner), so a fresh clone works with zero configuration.
# 3. run both services (tools MCP server + orchestrator/UI)
npm run dev
# 4. open the Mission Control UI
open http://localhost:4000Type a goal (or pick a preset) and click Launch Mission. The tools server
(:4001/mcp) and the orchestrator + UI (:4000) start together.
- "Cannot reach the orchestrator" in the UI. The backend isn't running (or
isn't up yet). Start it with
npm run devand reloadhttp://localhost:4000. The UI auto-retries the connection on launch, so a slow first boot resolves on its own — you only see this banner if the orchestrator is genuinely down. - Opened the page from disk (
file://). The UI must be served by the orchestrator so it can reach the WebSocket. Usehttp://localhost:4000, not the file path. - No API key. Not required for a demo — MADMAX auto-falls back to labelled
MOCK mode. Set
GEMINI_API_KEYfor live model output. Runnpm run gemini:checkto verify your key and connectivity in isolation.
npm run smokeThis boots the real NitroStack MCP server, connects the real MCP client,
discovers the tools over the protocol, and runs a complete mission in offline
mode — asserting every pipeline stage fired. If this prints PASS, the whole
system is wired correctly on your machine.
| Tool | Input | Output |
|---|---|---|
research |
businessGoal |
summary, insights[], sources[], confidence |
finance |
proposal |
roi, costAnalysis, financialRisk, confidence |
risk |
proposal |
riskScore (0–100), risks[], confidence |
compliance |
proposal |
complianceScore (0–100), issues[], confidence |
strategy |
proposal, context |
recommendation, tradeoffs[], priority, confidence |
verification |
allOutputs |
confidenceScore, verificationSummary, contradictions[] |
report |
verifiedResults, goal |
executiveReport, confidence |
Each is a pure capability: it reasons over its own input via the LLM and
returns validated structured output. Full schemas in API.md.
- Discovery — the orchestrator calls
listTools()on the MCP server. - Plan — the Planner (one LLM call) chooses which tools to run, in what order, with what inputs — constrained to the discovered tool set.
- Execute — each planned tool runs via
callTool(), with real retry and failure recovery (a failed call is retried, then skipped, never faked). - Verify — the
verificationtool cross-checks the aggregated outputs. - Vote — a council vote is derived from the actual tool outputs (verification confidence ≥ 0.6; risk score ≤ 60), not scripted.
- Report — the
reporttool synthesizes the executive brief.
Every step emits a typed event over WebSocket; the UI is a pure projection of
that event stream. See API.md for the event contract and
DEMO.md for the judge-facing walkthrough.
MOCK_LLM=true runs the entire pipeline with deterministic, clearly-labelled
stub outputs and no API key — for CI, offline development, and as a live-demo
safety net if conference wifi or the API misbehaves. It is off by default,
the UI shows a MOCK LLM banner whenever it's on, and every stub value is tagged
[MOCK]. Nothing fabricated is ever presented as a real model response. The real
default path calls Google Gemini.
src/
shared/events.ts # the typed event contract (backend ⇄ UI)
shared/errors.ts # maps low-level failures to actionable messages
shared/log.ts # startup log hygiene
llm/provider.ts # Gemini provider + labelled offline mock
servers/tools-mcp/
tools.ts # 7 MCP tools via one DRY factory
server.ts # NitroStack server bootstrap (HTTP transport)
orchestrator/
mcpClient.ts # real MCP client (listTools / callTool)
planner.ts # the sole orchestrator: plan→execute→verify→vote→report
eventBus.ts # per-mission typed event bus
server.ts # Express static UI + health + WebSocket gateway
frontend/index.html # Mission Control UI (projection of the event stream)
scripts/
smoke.ts # offline end-to-end test
patch_frontend.py # how the UI was wired to the backend (reproducible)
| Script | What it does |
|---|---|
npm run dev |
Run tools server + orchestrator/UI together (hot reload). |
npm run dev:tools |
Run only the NitroStack MCP tools server. |
npm run dev:orch |
Run only the orchestrator + UI. |
npm run smoke |
Offline end-to-end pipeline test (no key required). |
npm run typecheck |
TypeScript type checking. |
npm run gemini:check |
Diagnose Gemini key/connectivity in isolation. |
The MCP tools server is designed to deploy to NitroCloud (git push, auto-SSL,
serverless). Point the orchestrator's MCP_SERVER_URL at the deployed URL. See
DEPLOY_NITROCLOUD.md.
- Council vote uses fixed thresholds on real tool outputs; a production version would size the council to the mission and let voters reason in natural language.
- No persistence of mission history server-side — the UI keeps ecosystem
metrics in
localStorage; the backend is currently stateless between missions. - NitroStack framework logs are suppressed by default for a clean startup.
Set
NITRO_DEBUG=trueto see the rawNITRO_LOG::lines and the benign unconfigured-OAuth warning; MADMAX doesn't enable OAuth, so that warning is framework noise, not an error. - Single MCP server — the Planner is built to discover across multiple MCP servers, but only one (the MADMAX tools server) is wired today.
- Multiple MCP servers (e.g. a real ticketing/ERP server) discovered together.
- Server-side mission history + audit-trail export.
- Dynamic-size consensus council with natural-language reasoning.
- Scheduled/triggered missions, not just user-initiated ones.
MIT.