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
Local-first MCP runtime for multi-agent consensus guard workflows — AI code review, weighted voting, HITL approval gates, and full observability on SQLite.
git clone https://github.com/kaicianflone/consensus-local-mcp-board.git
cd consensus-local-mcp-board
npm install
npm run start
| Service | URL |
|---|---|
| API | http://127.0.0.1:4010 |
| UI | http://127.0.0.1:5000 |
MCP stdio mode (Claude Desktop, OpenClaw, etc.):
npm run mcp:dev
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 Anthropic SDKs works. The UI dropdown includes:
| Provider | Model | ID | Notes |
|---|---|---|---|
| OpenAI | GPT-5.4 | gpt-5.4 | Default. Most capable for professional work |
| OpenAI | GPT-5.4 Pro | gpt-5.4-pro | Smarter, more precise responses |
| OpenAI | GPT-5.2 | gpt-5.2 | Previous frontier model |
| OpenAI | GPT-5.1 | gpt-5.1 | Best for coding and agentic tasks |
| OpenAI | GPT-5 | gpt-5 | Reasoning model |
| OpenAI | GPT-5 Mini | gpt-5-mini | Faster, cost-efficient |
| OpenAI | GPT-5 Nano | gpt-5-nano | Fastest, most cost-efficient |
| OpenAI | GPT-5.3 Codex | gpt-5.3-codex | Most capable agentic coding model |
| Anthropic | Claude Opus 4.6 | claude-opus-4-6 | Most intelligent for agents and coding |
| Anthropic | Claude Sonnet 4.6 | claude-sonnet-4-6 | Best speed/intelligence balance |
| Anthropic | Claude Haiku 4.5 | claude-haiku-4-5 | Fastest, near-frontier intelligence |
Configure 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.
The 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.
┌─────────────────────┐
│ 1. Trigger │ Fetches PR diff, files, metadata via gh CLI
│ GitHub PR Opened │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ 2. Parallel Review │ 3 agents run concurrently:
│ (Group Node) │ • security-reviewer
│ │ • performance-analyst
│ │ • code-quality-reviewer
│ │ Each returns: vote, risk score, rationale
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ 3. Code Merge Guard │ Weighted voting resolution:
│ (Guard Node) │ • reputation-modulated weights
│ │ • combined risk scoring
│ │ • quorum threshold check
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ 4. HITL Gate │ Slack / Teams / Discord DM
│ (Human Approval) │ when risk > threshold
│ │ Reply: YES / NO / REWRITE
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ 5. Action │ Merge PR. Executes only if
│ (Merge PR) │ guard passed + human approved
└─────────────────────┘
Every guard evaluation produces one of four decisions:
| Decision | When | Result |
|---|---|---|
ALLOW | Risk acceptable, quorum met | Action proceeds |
BLOCK | Any NO votes with high risk, or risk > blockAboveRisk | Rejected |
REWRITE | High risk, majority REWRITE votes, zero NOs | Paused with rewrite guidance |
REQUIRE_HUMAN | Weighted YES ratio below quorum | Paused, HITL approval prompt sent |
The logic:
BLOCKREWRITEBLOCKblockAboveRisk? → escalated to BLOCKcurl -X POST http://127.0.0.1:4010/api/agents/connect \
-H 'content-type: application/json' \
-d '{
"name": "ci-bot",
"scopes": ["workflow.run", "tool.*"],
"boards": ["workflow-system"]
}'
Response includes an apiKey. Store it securely.
curl -X POST http://127.0.0.1:4010/api/participants \
-H 'content-type: application/json' \
-d '{
"boardId": "workflow-system",
"subjectType": "agent",
"subjectId": "security-reviewer",
"role": "reviewer",
"weight": 1,
"reputation": 100,
"metadata": {
"model": "gpt-5.4",
"systemPrompt": "You are a security-focused code reviewer."
}
}'
curl -X POST http://127.0.0.1:4010/api/agent/trigger \
-H 'x-agent-key: ' \
-H 'content-type: application/json' \
-d '{ "workflowId": "" }'
Reputation updates automatically after each resolution: aligned verdicts earn payouts, opposed verdicts get slashed. The hybrid weighting mode makes earned reputation meaningful.
Integrating Humans (HITL)
# Slack
curl -X POST http://127.0.0.1:4010/api/settings/credentials \
-H 'content-type: application/json' \
-d '{ "provider": "slack", "keyName": "bot_token", "value": "xoxb-..." }'
# Discord
curl -X POST http://127.0.0.1:4010/api/settings/credentials \
-H 'content-type: application/json' \
-d '{ "provider": "discord", "keyName": "bot_token", "value": "..." }'
# Telegram
curl -X POST http://127.0.0.1:4010/api/settings/credentials \
-H 'content-type: application/json' \
-d '{ "provider": "telegram", "keyName": "bot_token", "value": "..." }'
# Teams
curl -X POST http://127.0.0.1:4010/api/settings/credentials \
-H 'content-type: application/json' \
-d '{ "provider": "teams", "keyName": "webhook_url", "value": "https://..." }'
curl -X POST http://127.0.0.1:4010/api/participants \
-H 'content-type: application/json' \
-d '{
"boardId": "workflow-system",
"subjectType": "human",
"subjectId": "kai",
"role": "approver",
"weight": 1,
"metadata": { "chatAdapter": "slack", "chatHandle": "U0123456789" }
}'
curl -X POST http://127.0.0.1:4010/api/workflow-runs//approve \
-H 'content-type: application/json' \
-d '{ "decision": "YES", "approver": "kai" }'
| Mode | Behavior |
|---|---|
yes-no | YES or NO (default) |
approve-reject-revise | APPROVE, REJECT, or REVISE |
vote | Multiple votes required (configurable) |
acknowledge | ACK to acknowledge |
HITL nodes support timeoutSec (default 900). On expiry, auto-resolves with autoDecisionOnExpiry (default: BLOCK).
UI Dashboard
The web UI at http://127.0.0.1:5000 provides real-time observability.
What it shows:
The 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.
Key files: WorkflowsDashboard.tsx, NodeCanvas.tsx, NodeSettings.tsx, EventTimeline.tsx, AgentsPanel.tsx.
API Reference
| Method | Endpoint | Description |
|---|---|---|
GET | /api/workflows | List workflows (auto-creates Template 1 if empty) |
POST | /api/workflows | Create workflow { name, definition } |
GET | /api/workflows/:id | Get workflow + run history |
PUT | /api/workflows/:id | Update workflow |
POST | /api/workflows/:id/run | Execute workflow |
POST | /api/workflow-runs/:runId/approve | Resume paused workflow { decision, approver } |
| Method | Endpoint | Description |
|---|---|---|
POST | /api/mcp/evaluate | Generic guard evaluation { boardId, action } |
POST | /api/guard.evaluate | Typed guard evaluation { runId, boardId, guardType, payload, policy } |
POST | /api/human.approve | Human approval { runId, replyText, approver } |
| Method | Endpoint | Description |
|---|---|---|
GET | /api/participants?boardId=... | List participants |
POST | /api/participants | Create participant |
PATCH | /api/participants/:id | Update participant |
DELETE | /api/participants/:id | Delete participant |
| Method | Endpoint | Description |
|---|---|---|
POST | /api/agents/connect | Register agent → returns apiKey |
GET | /api/agents | List agents |
POST | /api/agent/trigger | Agent-triggered execution (requires x-agent-key) |
| Method | Endpoint | Description |
|---|---|---|
POST | /api/votes | Submit vote |
GET | /api/votes/:runId | Get votes + aggregate |
POST | /api/policies/assign | Assign policy to board |
GET | /api/policies/:boardId/:policyId | Get policy assignment |
| Method | Endpoint | Description |
|---|---|---|
GET | /api/settings/credentials | List credentials (no values) |
POST | /api/settings/credentials | Store credential { provider, keyName, value } |
DELETE | /api/settings/credentials/:provider/:keyName | Delete credential |
GET | /api/settings/credentials/:provider/status | Check provider status |
| Method | Endpoint | Description |
|---|---|---|
GET | /api/mcp/boards | List boards |
GET | /api/mcp/events | List events ?boardId=&runId=&type=&limit= |
DELETE | /api/mcp/events | Delete events ?boardId=&runId= |
GET | /api/mcp/runs/:id | Get run + events |
GET | /api/mcp/audit/search | Search events ?query= |
| Method | Endpoint | Description |
|---|---|---|
POST | /api/webhooks/github | GitHub webhook (triggers matching workflows) |
POST | /api/webhooks/slack/events | Slack Events API |
POST | /api/webhooks/teams/activity | Teams Bot Framework |
POST | /api/webhooks/discord/interactions | Discord interactions |
POST | /api/webhooks/telegram | Telegram updates |
POST | /api/webhooks/chat/:adapter | Generic chat adapter |
| Method | Endpoint | Description |
|---|---|---|
GET | /api/mcp/tools | List tool names |
POST | /api/mcp/tool/:name | Invoke tool |
Configuration
| Variable | Description | Default |
|---|---|---|
OPENAI_API_KEY | OpenAI API key | (deterministic fallback) |
AI_MODEL | Default agent model | gpt-5.4 |
CHAT_PROVIDER | Chat dispatch: webhook or stdout | webhook |
SLACK_BOT_TOKEN | Slack bot token | — |
DISCORD_BOT_TOKEN | Discord bot token | — |
TELEGRAM_BOT_TOKEN | Telegram bot token | — |
TEAMS_WEBHOOK_URL | Teams webhook URL | — |
GCHAT_WEBHOOK_URL | Google Chat webhook URL | — |
CREDENTIALS_SECRET | Master encryption key | (auto-generated) |
VERBOSE | Verbose logging (1) | — |
All secrets can also be stored via POST /api/settings/credentials (encrypted at rest, takes precedence over env vars).
{
"board_mode": "local",
"api_url": "http://127.0.0.1:4010"
}
| Tool | Status | Description |
|---|---|---|
guard.evaluate | ✅ | Generic guard entrypoint |
guard.code_merge | ✅ | Sensitive files, protected branches, CI checks |
guard.send_email | ✅ | Allowlist/blocklist, attachment policy, secrets scanning |
guard.publish | ✅ | Profanity filter, PII detection, blocked words |
guard.support_reply | ✅ | Escalation keywords, auto-escalate |
guard.agent_action | ✅ | Tool allowlist/blocklist, irreversibility check |
guard.deployment | ✅ | Environment-aware approval gates |
guard.permission_escalation | ✅ | Break-glass, MFA support |
guard.policy.describe | ✅ | Describe policy schema for any guard type |
persona.generate | ✅ | Generate persona set for a board |
board.list / board.get | ✅ | Ledger-backed board queries |
run.get | ✅ | Ledger-backed run queries |
audit.search | ✅ | Search events by payload/type |
human.approve | ✅ | Submit human approval decision |
apiKey, token, password, secret, authorization, cookie) redacted before persistence.CREDENTIALS_SECRET via scrypt or auto-generated on first run.127.0.0.1:4010. No external exposure unless explicitly proxied.crypto.timingSafeEqual.MIT
Install via CLI
npx mdskills install kaicianflone/consensus-local-mcp-boardConsensus Local MCP Board is a free, open-source AI agent skill. 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
Install Consensus Local MCP Board with a single command:
npx mdskills install kaicianflone/consensus-local-mcp-boardThis downloads the skill files into your project and your AI agent picks them up automatically.
Consensus Local MCP Board works with Claude Code, Claude Desktop, Cursor, Vscode Copilot, Windsurf, Continue Dev, Gemini Cli, Amp, Roo Code, Goose. Skills use the open SKILL.md format which is compatible with any AI coding agent that reads markdown instructions.