WERKHub - the local, governed MCP control plane (browse, connect, supervise agent extensions)
Project description
WERKHub
One local MCP front door for all your agent tools — with policy gates, approvals, and a tamper-evident evidence ledger.
WERKHub is the control layer I wanted before letting agents touch real tools. No invisible routing. No blind trust. No random tool calls flying around without a trace.
Your agent host connects to one MCP server: WERKHub.
WERKHub then routes calls to Claude Code, Codex, Cursor, local MCPs, model workers, vault tools, trace tools, and whatever else you wire in — but every call goes through the same local gate.
The short version
| Layer | What WERKHub does |
|---|---|
| Front door | Exposes 8 always-on bridge tools through one MCP server. |
| Policy gate | Deny-by-default. Unknown tools do not run. Risky tools need approval. |
| Evidence | Every decision and tool call is written to a hash-chained JSONL ledger. |
| Secrets | Env-var key names are detected, values are not stored. |
| Dashboard | Local supervisor console for fleet health, connectors, approvals, and ledger tail. |
| Tests | 1069 tests, offline-first, Linux + Windows CI. |
Why this exists
Agent tooling is getting powerful, but the wiring is still messy.
Each host — Claude Code, Codex, Cursor, Windsurf, Gemini, Kimi, Antigravity — tends to manage MCP servers on its own. That means every tool stack gets its own config, its own trust story, and usually no shared audit trail.
WERKHub makes that boring in the best way:
Agent host
↓
WERKHub MCP gateway
↓
Policy / approval gate
↓
Downstream MCP tools
↓
Hash-chained evidence ledger
The idea is simple: agents can do work, but the operator should still see what happened, what was allowed, what was denied, and what needs human approval.
What it ships
werktools is the Python package. WERKHub is the product layer inside it.
It currently includes:
werktools hub serve— stdio MCP gateway with 8 bridge tools.werktools hub onboard— scans existing host MCP configs and adopts them as connectors.werktools hub doctor— runtime detection + machine-checked invariants.werktools hub dashboard— local HTTP dashboard, loopback-first, CSP-safe.- Approval queue — one-use, argument-bound, expiring tokens.
- Hash-chained ledger — verified reads via
chain_verified. - Downstream relay — discovery, forwarding, per-downstream
cwd, stderr diagnostics, failure classifier. - Trust taxonomy —
Official,Security-Scanned,Community-Unverified. - Local tool slices — truth, mine, trace, vault, data-gate, swarm, cost, eval, audit, skills, integration-gate.
- Desktop supervisor —
desktop/, built with Deno Desktop + Vite + React + Tailwind.
Current status
Version: 0.1.0
Core: Python ≥ 3.10, stdlib-only core
License: AGPL-3.0-or-later
Package name: werktools
Product name: WERKHub
Working now
- MCP front door with 8 bridge tools:
tool_searchtool_describetool_callprofile_infoledger_recentapproval_statushub_statusregistry_search
- Deny-by-default policy gate via
enforce(). - File-based approvals with one-use, argument-bound tokens.
- Tamper-evident JSONL ledger with verified-chain reads.
- Downstream MCP discovery + policy-gated forwarding.
- Runtime/onboarding Doctor for Claude, Cursor, Windsurf, Gemini, Kimi, Antigravity, Codex.
- Local dashboard and desktop supervisor console.
- 1069 passing tests.
Experimental / honest limits
- The dashboard
killaction is gated and wired defensively, but still preview-level under stub process wiring. - Tier-1 allowlist entries currently carry
digest=unpinnedtrust notes. OCI digest backfill is planned. - Single-instance downstream MCPs are detected, but not solved yet. The relay currently spawns a fresh subprocess per call; attach/reuse is on the roadmap.
- The package is not published to PyPI yet. Install from a clone for now.
Architecture
WERKHub separates the agent-facing interface, the policy layer, the relay, and the truth layer.
┌──────────────────────────────────────────────────────────┐
│ Interface │
│ Agent host over stdio MCP │
│ Desktop console over loopback HTTP │
│ werktools CLI │
├──────────────────────────────────────────────────────────┤
│ Front door │
│ werk-hub MCP server │
│ 8 always-on bridge tools │
├──────────────────────────────────────────────────────────┤
│ Control │
│ deny-by-default policy gate │
│ one-use approvals │
│ argument-bound tokens │
│ trust tiers + allowlist │
├──────────────────────────────────────────────────────────┤
│ Relay │
│ downstream MCP discovery │
│ policy-gated forwarding │
│ stderr diagnostics │
│ failure classification │
├──────────────────────────────────────────────────────────┤
│ Truth │
│ hash-chained JSONL ledger │
│ SQLite registry.db │
│ hub.json config │
└──────────────────────────────────────────────────────────┘
Repository layout
WERKHub/
├── src/werktools/
│ ├── hub/ # MCP gateway: server, relay, policy, approvals, ledger, registry
│ ├── tools/ # local slices: truth, trace, vault, cost, swarm, audit, skills, ...
│ └── *.py # shared primitives: envelope, profile, redaction, classify, ledger
├── desktop/ # Deno Desktop supervisor console, Vite/React/Tailwind
├── docs/ # MkDocs site, ADRs, concepts, setup docs
├── examples/ # small MCP demos
├── tests/ # 59 test files, 1069 tests
├── CHANGELOG.md
├── SETUP.md
├── SECURITY.md
├── CONTRIBUTING.md
├── LICENSE
└── pyproject.toml # Python package: werktools
Installation
Requires Python ≥ 3.10.
Until werktools is published to PyPI, install from a clone:
git clone https://github.com/Shuwajaja/WERKHub.git
cd WERKHub
pip install -e ".[server]"
Run the MCP gateway:
werktools hub serve --config .werktools/hub.json
Run the local dashboard:
werktools hub dashboard --port 7879 --open
When the package is published to PyPI, the clean one-liner will be:
uvx --from "werktools[server]" werktools hub serve
Extras
| Extra | Purpose |
|---|---|
server |
Installs the FastMCP runtime needed for werktools hub serve. |
yaml |
Adds YAML parsing helpers. |
swarm |
Keeps the swarm helper install path stable without pulling extra runtime deps. |
lifecycle |
Reserved marker for process-supervision extensions while the current implementation stays stdlib-only. |
worker |
Adds the HTTP client used for model-worker dispatch. |
onboard |
Adds TOML support for reading Codex configs on Python 3.10. |
all |
Installs every optional extra in one step. |
30-second onboard
The Doctor can adopt the MCP servers already configured in your agent hosts.
# 1. Create or inspect local hub config
werktools --config .werktools/hub.json hub init
werktools --config .werktools/hub.json hub status
# 2. Dry-run existing MCP discovery
werktools hub onboard
# 3. Adopt discovered MCPs into hub.json
WERK_ALLOW_HUB_ONBOARD=1 werktools hub onboard --apply
# 4. Start the hub profile
werktools hub serve --profile claude-reviewer --config .werktools/hub.json
Then point your agent host at WERKHub as its MCP server.
{
"mcpServers": {
"werkhub": {
"command": "werktools",
"args": ["hub", "serve", "--profile", "claude-reviewer", "--config", ".werktools/hub.json"]
}
}
}
Bridge tools
Agents do not call every downstream tool directly. They go through WERKHub's bridge tools.
| Tool | Purpose |
|---|---|
tool_search |
Find available downstream tools. |
tool_describe |
Inspect one tool before calling it. |
tool_call |
Execute a policy-gated downstream call. |
profile_info |
Show the active pinned profile. |
ledger_recent |
Read recent verified ledger events. |
approval_status |
Check pending/approved/denied approval records. |
hub_status |
Inspect hub health and connector state. |
registry_search |
Search the capability registry when profile policy allows it. |
This keeps the surface small. The agent gets power, but the operator gets one control point.
Development
pip install -e ".[all]"
pytest -q
python -m mypy src/werktools
python -m ruff check src tests examples
python -c "from werktools.hub.invariants import run_all; print(run_all())"
Desktop app:
cd desktop
pnpm install
pnpm dev
Run the dashboard sidecar separately:
werktools hub dashboard --port 7879
Configuration
WERKHub is configured through hub.json.
| Config piece | Meaning |
|---|---|
hub.json |
Connectors, profiles, tools, ledger path, allowlist path. |
--config <path> |
Selects the hub config. Default: .werktools/hub.json. |
--profile <id> |
Pins the active profile at launch. |
WERKTOOLS_HUB_PROFILE |
Env alternative to --profile. |
Connector env |
Stores env-var key names only, not secret values. |
Mutation flags are fail-closed and opt-in:
WERK_ALLOW_HUB_APPROVALS
WERK_ALLOW_HUB_ONBOARD
WERK_ALLOW_HUB_KILL
WERK_ALLOW_HUB_CONFIG_WRITE
WERK_ALLOW_HUB_REGISTRY
Dashboard mutations also require a per-session X-Werk-Token.
See SETUP.md for the full self-test.
Security model
WERKHub is local-first, but it does not pretend local equals safe.
Project rules:
- Deny-by-default, fail-closed. A tool runs only when
enforce()returnsallow. - Unknown means no. Unknown profile, unknown tool, unknown risk: denied.
- Secrets stay presence-only. Config stores env-var key names, not values.
- Approvals are one-use. Tokens are argument-bound, expiring, and consumed once.
- Ledger is evidence, not decoration. Every important decision is append-only and hash-chained.
- No telemetry. Local HTTP binds loopback by default; network surfaces are explicit.
Read SECURITY.md for the threat model and known limits.
Agent usage
This repo is designed to be changed by humans and AI coding agents.
Agents working on this repo should:
- inspect existing structure before editing;
- keep changes small and reviewable;
- run
pytest -q,mypy,ruff, and the invariant gate before claiming success; - keep the core dependency-free;
- never add daemon loops to core modules;
- treat JSONL events, SQLite, and the ledger as truth;
- preserve evidence and avoid deleting files unless explicitly instructed.
Agents using WERKHub reach downstream tools only through the bridge surface. Risky calls return a request_id and must be retried with a human-approved, argument-bound token.
Roadmap
- Publish
werktoolsto PyPI. - Add connection reuse / attach-to-running for single-instance downstream MCPs.
- Backfill OCI digests for the Tier-1 install allowlist.
- Finish live process supervision behind the dashboard
killaction. - Windows code-signing for the desktop
.msi. - Public docs polish + launch examples.
Docs
| Topic | File |
|---|---|
| Setup & self-test | SETUP.md |
| Security model | SECURITY.md |
| Contributing | CONTRIBUTING.md |
| Changelog | CHANGELOG.md |
| MkDocs site | docs/ |
License
AGPL-3.0-or-later. See LICENSE.
Security issue? Use the private reporting path in SECURITY.md. Do not open a public issue for vulnerabilities.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file werktools-0.1.0.tar.gz.
File metadata
- Download URL: werktools-0.1.0.tar.gz
- Upload date:
- Size: 562.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
49204b698bddbe4ff1ada307ae6851db30a1ae6e0b99474d3868ec860b27593f
|
|
| MD5 |
6e8362f5fb08bb72579faa794423a0cb
|
|
| BLAKE2b-256 |
e67c6bc0c59b87c3d3df4da759bb7faf89fecff75e06cb0d4880258c627ed5ae
|
File details
Details for the file werktools-0.1.0-py3-none-any.whl.
File metadata
- Download URL: werktools-0.1.0-py3-none-any.whl
- Upload date:
- Size: 265.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1f4bf18f5f61cbb5f8f2e05d749a6cb800a4c298a92a2cf9c1a6e2c4084290f
|
|
| MD5 |
c309325a947c0e3d720a050d4afe5ae7
|
|
| BLAKE2b-256 |
3ca9478d1b583d4da84d371ff82bbb18ec539dc18d8776dc35e2d3de01af7e4c
|