Local-first MCP runtime for multi-agent consensus guard workflows — AI code review, weighted voting, HITL approval gates, and full observability on SQLite. MCP stdio mode (Claude Desktop, OpenClaw, etc.): Prerequisites: Node.js 20+, npm 10+. Optional: gh CLI (for GitHub PR triggers), OpenAI API key (falls back to deterministic heuristics without one). Any model accessible via the OpenAI or Anthrop
Add this skill
npx mdskills install kaicianflone/consensus-local-mcp-boardSophisticated multi-agent consensus workflow engine with weighted voting, HITL gates, and observability
1[](https://www.typescriptlang.org/)2[](https://modelcontextprotocol.io/)3[](https://www.sqlite.org/)4[](https://vitejs.dev/)5[](./LICENSE)67# consensus-local-mcp-board89Local-first MCP runtime for multi-agent consensus guard workflows — AI code review, weighted voting, HITL approval gates, and full observability on SQLite.1011---1213## Quick Start1415```bash16git clone https://github.com/kaicianflone/consensus-local-mcp-board.git17cd consensus-local-mcp-board18npm install19npm run start20```2122| Service | URL |23|---|---|24| API | `http://127.0.0.1:4010` |25| UI | `http://127.0.0.1:5000` |2627MCP stdio mode (Claude Desktop, OpenClaw, etc.):2829```bash30npm run mcp:dev31```3233**Prerequisites:** Node.js 20+, npm 10+. Optional: `gh` CLI (for GitHub PR triggers), OpenAI API key (falls back to deterministic heuristics without one).3435---3637## Supported Models3839Any model accessible via the OpenAI or Anthropic SDKs works. The UI dropdown includes:4041| Provider | Model | ID | Notes |42|---|---|---|---|43| OpenAI | GPT-5.4 | `gpt-5.4` | **Default.** Most capable for professional work |44| OpenAI | GPT-5.4 Pro | `gpt-5.4-pro` | Smarter, more precise responses |45| OpenAI | GPT-5.2 | `gpt-5.2` | Previous frontier model |46| OpenAI | GPT-5.1 | `gpt-5.1` | Best for coding and agentic tasks |47| OpenAI | GPT-5 | `gpt-5` | Reasoning model |48| OpenAI | GPT-5 Mini | `gpt-5-mini` | Faster, cost-efficient |49| OpenAI | GPT-5 Nano | `gpt-5-nano` | Fastest, most cost-efficient |50| OpenAI | GPT-5.3 Codex | `gpt-5.3-codex` | Most capable agentic coding model |51| Anthropic | Claude Opus 4.6 | `claude-opus-4-6` | Most intelligent for agents and coding |52| Anthropic | Claude Sonnet 4.6 | `claude-sonnet-4-6` | Best speed/intelligence balance |53| Anthropic | Claude Haiku 4.5 | `claude-haiku-4-5` | Fastest, near-frontier intelligence |5455Configure per-agent in the workflow definition or via the UI. Set `AI_MODEL` env var or store via `POST /api/settings/credentials` to change the default.5657---5859## Template 1: GitHub PR Merge Guard6061The flagship workflow. Fetches a GitHub PR, runs 3 parallel AI reviews, resolves consensus through weighted voting, gates on human approval when risk is high, and merges only when everything passes.6263```text64┌─────────────────────┐65│ 1. Trigger │ Fetches PR diff, files, metadata via gh CLI66│ GitHub PR Opened │67└──────────┬──────────┘68 │69 ▼70┌─────────────────────┐71│ 2. Parallel Review │ 3 agents run concurrently:72│ (Group Node) │ • security-reviewer73│ │ • performance-analyst74│ │ • code-quality-reviewer75│ │ Each returns: vote, risk score, rationale76└──────────┬──────────┘77 │78 ▼79┌─────────────────────┐80│ 3. Code Merge Guard │ Weighted voting resolution:81│ (Guard Node) │ • reputation-modulated weights82│ │ • combined risk scoring83│ │ • quorum threshold check84└──────────┬──────────┘85 │86 ▼87┌─────────────────────┐88│ 4. HITL Gate │ Slack / Teams / Discord DM89│ (Human Approval) │ when risk > threshold90│ │ Reply: YES / NO / REWRITE91└──────────┬──────────┘92 │93 ▼94┌─────────────────────┐95│ 5. Action │ Merge PR. Executes only if96│ (Merge PR) │ guard passed + human approved97└─────────────────────┘98```99100### Decision Model101102Every guard evaluation produces one of four decisions:103104| Decision | When | Result |105|---|---|---|106| `ALLOW` | Risk acceptable, quorum met | Action proceeds |107| `BLOCK` | Any NO votes with high risk, or risk > `blockAboveRisk` | Rejected |108| `REWRITE` | High risk, majority REWRITE votes, zero NOs | Paused with rewrite guidance |109| `REQUIRE_HUMAN` | Weighted YES ratio below quorum | Paused, HITL approval prompt sent |110111The logic:1121131. **Risk > threshold?**114 - Any NO → `BLOCK`115 - Majority REWRITE (no NOs) → `REWRITE`116 - Otherwise → `BLOCK`1172. **REWRITE + risk > `blockAboveRisk`?** → escalated to `BLOCK`1183. **YES ratio < quorum?** → `REQUIRE_HUMAN`1194. **Otherwise** → `ALLOW`120121`blockAboveRisk` is configurable per guard node (default `1.0` / disabled). Template 1 sets `0.92`.122123### Weighting Modes124125| Mode | Formula | Use case |126|---|---|---|127| `static` | raw weight | Equal voices |128| `reputation` | reputation / 100 | Ledger-driven trust |129| `hybrid` | weight × (reputation / 100) | **Default.** Manual weight modulated by earned reputation |130131---132133## Architecture134135```text136web (Vite/React)137 │ polls API (1-2s)138 ▼139server/api (Express + zod)140 │141 ├──▶ workflows/runner.ts Durable workflow engine142 │ ├──▶ adapters/ai-sdk.ts OpenAI agent evaluation143 │ ├──▶ adapters/chat-sdk.ts Slack/Teams/Discord/Telegram HITL144 │ └──▶ adapters/consensus-tools Board resolution + ledger145 │146 ├──▶ tools/registry.ts MCP tool registry147 ├──▶ db/store.ts SQLite (boards, runs, events, participants)148 │ └──▶ db/credentials.ts AES-256-GCM encrypted credentials149 └──▶ engine/hitl-tracker.ts Approval timeout management150```151152```text153consensus-local-mcp-board/154 shared/src/index.ts Zod schemas, voting logic, decision model155 server/src/156 index.ts API routes, Template 1 definition157 workflows/runner.ts Workflow execution engine158 adapters/ ai-sdk, chat-sdk, consensus-tools159 db/ SQLite store, encrypted credentials160 tools/registry.ts MCP tool registry161 mcp/server.ts MCP stdio server162 web/src/163 pages/ WorkflowsDashboard164 components/workflow/ NodeCanvas, NodeSettings, EventTimeline165 components/agents/ AgentsPanel166```167168---169170<details>171<summary><strong>Integrating External Agents</strong></summary>172173### Register an agent174175```bash176curl -X POST http://127.0.0.1:4010/api/agents/connect \177 -H 'content-type: application/json' \178 -d '{179 "name": "ci-bot",180 "scopes": ["workflow.run", "tool.*"],181 "boards": ["workflow-system"]182 }'183```184185Response includes an `apiKey`. Store it securely.186187### Register agent participants188189```bash190curl -X POST http://127.0.0.1:4010/api/participants \191 -H 'content-type: application/json' \192 -d '{193 "boardId": "workflow-system",194 "subjectType": "agent",195 "subjectId": "security-reviewer",196 "role": "reviewer",197 "weight": 1,198 "reputation": 100,199 "metadata": {200 "model": "gpt-5.4",201 "systemPrompt": "You are a security-focused code reviewer."202 }203 }'204```205206### Trigger via agent API207208```bash209curl -X POST http://127.0.0.1:4010/api/agent/trigger \210 -H 'x-agent-key: <your-api-key>' \211 -H 'content-type: application/json' \212 -d '{ "workflowId": "<workflow-id>" }'213```214215Reputation updates automatically after each resolution: aligned verdicts earn payouts, opposed verdicts get slashed. The `hybrid` weighting mode makes earned reputation meaningful.216217</details>218219<details>220<summary><strong>Integrating Humans (HITL)</strong></summary>221222### Store bot tokens223224```bash225# Slack226curl -X POST http://127.0.0.1:4010/api/settings/credentials \227 -H 'content-type: application/json' \228 -d '{ "provider": "slack", "keyName": "bot_token", "value": "xoxb-..." }'229230# Discord231curl -X POST http://127.0.0.1:4010/api/settings/credentials \232 -H 'content-type: application/json' \233 -d '{ "provider": "discord", "keyName": "bot_token", "value": "..." }'234235# Telegram236curl -X POST http://127.0.0.1:4010/api/settings/credentials \237 -H 'content-type: application/json' \238 -d '{ "provider": "telegram", "keyName": "bot_token", "value": "..." }'239240# Teams241curl -X POST http://127.0.0.1:4010/api/settings/credentials \242 -H 'content-type: application/json' \243 -d '{ "provider": "teams", "keyName": "webhook_url", "value": "https://..." }'244```245246### Register human participants with chat metadata247248```bash249curl -X POST http://127.0.0.1:4010/api/participants \250 -H 'content-type: application/json' \251 -d '{252 "boardId": "workflow-system",253 "subjectType": "human",254 "subjectId": "kai",255 "role": "approver",256 "weight": 1,257 "metadata": { "chatAdapter": "slack", "chatHandle": "U0123456789" }258 }'259```260261### Approval flow2622631. Guard resolves → risk > threshold → workflow pauses2642. DM sent to registered humans via their chat adapter2653. Human replies: YES / NO / REWRITE2664. Workflow resumes accordingly267268### Manual approval (no chat adapter)269270```bash271curl -X POST http://127.0.0.1:4010/api/workflow-runs/<runId>/approve \272 -H 'content-type: application/json' \273 -d '{ "decision": "YES", "approver": "kai" }'274```275276### Prompt modes277278| Mode | Behavior |279|---|---|280| `yes-no` | YES or NO (default) |281| `approve-reject-revise` | APPROVE, REJECT, or REVISE |282| `vote` | Multiple votes required (configurable) |283| `acknowledge` | ACK to acknowledge |284285HITL nodes support `timeoutSec` (default 900). On expiry, auto-resolves with `autoDecisionOnExpiry` (default: `BLOCK`).286287</details>288289<details>290<summary><strong>UI Dashboard</strong></summary>291292The web UI at `http://127.0.0.1:5000` provides real-time observability.293294**What it shows:**295- **Workflow builder** — drag-and-drop nodes (trigger, agent, guard, HITL, group, action), visual canvas, per-node config296- **Node settings** — model selection, persona assignment, guard thresholds, HITL channel/timeout297- **Workflow runs** — status badges, one-click approve/block for pending runs298- **Event timeline** — chronological append-only stream (WORKFLOW_STARTED, AGENT_VERDICT, RISK_SCORE, CONSENSUS_QUORUM, etc.)299- **Agents panel** — participants, reputation scores, weight assignments300- **Board inspector** — board listing, run history, event drill-down301302### Forking / embedding303304The UI is a standalone Vite/React app in `web/`. It polls the API via `web/src/lib/api.ts`. To embed: copy `web/`, point the API base URL at your server.305306Key files: `WorkflowsDashboard.tsx`, `NodeCanvas.tsx`, `NodeSettings.tsx`, `EventTimeline.tsx`, `AgentsPanel.tsx`.307308</details>309310<details>311<summary><strong>API Reference</strong></summary>312313### Workflows314315| Method | Endpoint | Description |316|---|---|---|317| `GET` | `/api/workflows` | List workflows (auto-creates Template 1 if empty) |318| `POST` | `/api/workflows` | Create workflow `{ name, definition }` |319| `GET` | `/api/workflows/:id` | Get workflow + run history |320| `PUT` | `/api/workflows/:id` | Update workflow |321| `POST` | `/api/workflows/:id/run` | Execute workflow |322| `POST` | `/api/workflow-runs/:runId/approve` | Resume paused workflow `{ decision, approver }` |323324### Guards325326| Method | Endpoint | Description |327|---|---|---|328| `POST` | `/api/mcp/evaluate` | Generic guard evaluation `{ boardId, action }` |329| `POST` | `/api/guard.evaluate` | Typed guard evaluation `{ runId, boardId, guardType, payload, policy }` |330| `POST` | `/api/human.approve` | Human approval `{ runId, replyText, approver }` |331332### Participants333334| Method | Endpoint | Description |335|---|---|---|336| `GET` | `/api/participants?boardId=...` | List participants |337| `POST` | `/api/participants` | Create participant |338| `PATCH` | `/api/participants/:id` | Update participant |339| `DELETE` | `/api/participants/:id` | Delete participant |340341### Agents342343| Method | Endpoint | Description |344|---|---|---|345| `POST` | `/api/agents/connect` | Register agent → returns `apiKey` |346| `GET` | `/api/agents` | List agents |347| `POST` | `/api/agent/trigger` | Agent-triggered execution (requires `x-agent-key`) |348349### Votes + Policies350351| Method | Endpoint | Description |352|---|---|---|353| `POST` | `/api/votes` | Submit vote |354| `GET` | `/api/votes/:runId` | Get votes + aggregate |355| `POST` | `/api/policies/assign` | Assign policy to board |356| `GET` | `/api/policies/:boardId/:policyId` | Get policy assignment |357358### Credentials359360| Method | Endpoint | Description |361|---|---|---|362| `GET` | `/api/settings/credentials` | List credentials (no values) |363| `POST` | `/api/settings/credentials` | Store credential `{ provider, keyName, value }` |364| `DELETE` | `/api/settings/credentials/:provider/:keyName` | Delete credential |365| `GET` | `/api/settings/credentials/:provider/status` | Check provider status |366367### Boards + Events368369| Method | Endpoint | Description |370|---|---|---|371| `GET` | `/api/mcp/boards` | List boards |372| `GET` | `/api/mcp/events` | List events `?boardId=&runId=&type=&limit=` |373| `DELETE` | `/api/mcp/events` | Delete events `?boardId=&runId=` |374| `GET` | `/api/mcp/runs/:id` | Get run + events |375| `GET` | `/api/mcp/audit/search` | Search events `?query=` |376377### Webhooks (Inbound)378379| Method | Endpoint | Description |380|---|---|---|381| `POST` | `/api/webhooks/github` | GitHub webhook (triggers matching workflows) |382| `POST` | `/api/webhooks/slack/events` | Slack Events API |383| `POST` | `/api/webhooks/teams/activity` | Teams Bot Framework |384| `POST` | `/api/webhooks/discord/interactions` | Discord interactions |385| `POST` | `/api/webhooks/telegram` | Telegram updates |386| `POST` | `/api/webhooks/chat/:adapter` | Generic chat adapter |387388### MCP Tools389390| Method | Endpoint | Description |391|---|---|---|392| `GET` | `/api/mcp/tools` | List tool names |393| `POST` | `/api/mcp/tool/:name` | Invoke tool |394395</details>396397<details>398<summary><strong>Configuration</strong></summary>399400### Environment variables401402| Variable | Description | Default |403|---|---|---|404| `OPENAI_API_KEY` | OpenAI API key | (deterministic fallback) |405| `AI_MODEL` | Default agent model | `gpt-5.4` |406| `CHAT_PROVIDER` | Chat dispatch: `webhook` or `stdout` | `webhook` |407| `SLACK_BOT_TOKEN` | Slack bot token | — |408| `DISCORD_BOT_TOKEN` | Discord bot token | — |409| `TELEGRAM_BOT_TOKEN` | Telegram bot token | — |410| `TEAMS_WEBHOOK_URL` | Teams webhook URL | — |411| `GCHAT_WEBHOOK_URL` | Google Chat webhook URL | — |412| `CREDENTIALS_SECRET` | Master encryption key | (auto-generated) |413| `VERBOSE` | Verbose logging (`1`) | — |414415All secrets can also be stored via `POST /api/settings/credentials` (encrypted at rest, takes precedence over env vars).416417### .consensus/config.json418419```json420{421 "board_mode": "local",422 "api_url": "http://127.0.0.1:4010"423}424```425426</details>427428---429430## Tool Matrix431432| Tool | Status | Description |433|---|---|---|434| `guard.evaluate` | ✅ | Generic guard entrypoint |435| `guard.code_merge` | ✅ | Sensitive files, protected branches, CI checks |436| `guard.send_email` | ✅ | Allowlist/blocklist, attachment policy, secrets scanning |437| `guard.publish` | ✅ | Profanity filter, PII detection, blocked words |438| `guard.support_reply` | ✅ | Escalation keywords, auto-escalate |439| `guard.agent_action` | ✅ | Tool allowlist/blocklist, irreversibility check |440| `guard.deployment` | ✅ | Environment-aware approval gates |441| `guard.permission_escalation` | ✅ | Break-glass, MFA support |442| `guard.policy.describe` | ✅ | Describe policy schema for any guard type |443| `persona.generate` | ✅ | Generate persona set for a board |444| `board.list` / `board.get` | ✅ | Ledger-backed board queries |445| `run.get` | ✅ | Ledger-backed run queries |446| `audit.search` | ✅ | Search events by payload/type |447| `human.approve` | ✅ | Submit human approval decision |448449---450451## Safety452453- **Append-only events** — no mutation after write. Full audit trail.454- **Secret redaction** — sensitive fields (`apiKey`, `token`, `password`, `secret`, `authorization`, `cookie`) redacted before persistence.455- **Encrypted credentials** — AES-256-GCM. Key derived from `CREDENTIALS_SECRET` via scrypt or auto-generated on first run.456- **Localhost-only** — binds to `127.0.0.1:4010`. No external exposure unless explicitly proxied.457- **Typed contracts** — all API I/O validated with zod. Invalid payloads return structured errors.458- **Idempotency keys** — guard evaluations, votes, and approvals prevent duplicate processing.459- **GitHub webhook verification** — HMAC-SHA256 signature verification via `crypto.timingSafeEqual`.460461---462463## License464465MIT466
Full transparency — inspect the skill content before installing.