Install
$ agentstack add mcp-fu351-doberman-core Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Destructive filesystem operation.
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Doberman
Adaptive Authorization & Runtime Guardrails for AI Coding Agents
[](https://github.com/fu351/Doberman-Core/actions/workflows/ci.yml) [](./LICENSE) [](https://www.python.org/downloads/) [](#roadmap) [](https://discord.gg/Sfy5XGNqty)
Your AI coding agent can rm -rf your repo, leak your API keys, or be prompt-injected into exfiltrating data — autonomously, with no undo. Doberman is the guard dog on the execution path that stops the dangerous call before it runs.
doberman demo against the live dashboard (doberman dash): five attacks blocked as they happen, then a human denies a high-risk approval.
> If it isn't on the execution path, it's advisory, not protective.
Doberman sits between the agent and its tools — a transparent MCP proxy or host hook — and turns every action into an explicit, auditable decision. Every tool call gets exactly one verdict, decided before it executes:
| Verdict | What happens | |---|---| | PASS | Routine work — straight through, zero friction. | | AUTH | Sensitive — paused for your one-tap approval. | | BLOCK | Dangerous — stopped cold. It never runs. |
AI agent ──▶ Doberman ──▶ real tools (files, shell, MCP servers, APIs)
└─ normalize → risk engine → PASS / AUTH / BLOCK
Works with Claude Code, Cursor, Codex, Copilot, and any MCP-compatible agent. Open-source, local-first, and bound by two rules it will never break: it fails closed (uncertainty denies) and is raise-only (it can tighten automatically, but never silently loosens).
[Get protected in two commands](#quick-start) · Join the pack on Discord
Contents
- [Why Doberman?](#why-doberman) — what it does, and the two guarantees
- [Quick Start](#quick-start) — install and protect an agent in two commands
- [Verify it end-to-end](#verify-it-end-to-end) — watch it front a real MCP server
- [Turn gate](#turn-gate) — the optional pre-inference chokepoint
- [Benchmark](#benchmark) — attack-block rate (ASR) vs. false-positive friction (FPR)
- [Write a custom Guardrail](#write-a-custom-guardrail-plugin) — register your own rule as a plugin
- [Tune to your risk tolerance](#tune-to-your-risk-tolerance) — strictness modes + the enforcement dial
- [Who is this for?](#who-is-this-for)
- [Roadmap](#roadmap)
- [Contributing](#contributing) · [License](#license)
Why Doberman?
Prompt injection, tool poisoning, data exfiltration, and runaway agents are the defining security problems of agentic AI. Most "AI guardrails" inspect prompts and offer advice. Doberman is different: it is on the tool-execution path, so a blocked action never runs.
Those three verdicts aren't advice a model can talk its way past — each is enforced at the one place that counts: the instant before the call runs. Evade the model's own guardrails all you want; the action still has to clear Doberman.
Two non-negotiable properties:
- Fail closed — any error, uncertainty, or unhandled case denies the action. There is no path to a tool around the decision engine.
- Raise-only learning — guardrails and adaptive learning can auto-tighten, never silently loosen. Every permanent policy weakening requires explicit, possession-factor-gated, audited human approval (TOTP if enrolled, otherwise the local Doberman password).
Quick Start
Doberman guards any MCP-compatible coding agent: pick your agent, run one command, and every tool call is reviewed before it executes. The full walkthrough - every option, flag, the dashboard, and health checks - lives in the [Setup Guide](docs/SETUP.md).
pip install doberman-core
| Your agent | How Doberman plugs in | Get started | |---|---|---| | Claude Code | Hooks - gate every built-in and MCP tool call (recommended) | doberman setup -> [guide](docs/SETUP.md#claude-code-hooks) | | Claude Desktop / Cursor / Codex | MCP proxy - wrap your tool server | doberman serve -- -> [guide](docs/SETUP.md#mcp-proxy) | | OpenClaw | Native plugin adapter | [guide](docs/SETUP.md#openclaw) - [adapter](adapters/openclaw/README.md) | | Any MCP-compatible agent | MCP proxy | [guide](docs/SETUP.md#mcp-proxy) |
Fastest path - Claude Code:
doberman setup # pick a strictness mode, tune guardrails, wire the hooks
Doberman now reviews every tool call your agent makes. Confirm it with doberman doctor, or watch real verdicts with doberman demo. Everything else - MCP-proxy wiring, the dashboard, TUI, scan, and 2FA - is in the [Setup Guide](docs/SETUP.md).
Verify it end-to-end
Two ways to watch Doberman front a real MCP server — no in-process test doubles anywhere in the chain.
Interactive demo — MCP Inspector + a real filesystem server:
npx -y @modelcontextprotocol/inspector doberman serve -- npx -y @modelcontextprotocol/server-filesystem ~/my-project
Open the Inspector UI and call tools through Doberman: routine reads and writes PASS straight through to the real filesystem server; a destructive call comes back as a policy error and never executes.
End-to-end test — in a dev checkout:
pytest tests/integration/test_serve_end_to_end.py -q
This spawns doberman serve as a real subprocess fronting a real stdio tool server ([tests/fixtures/stdio_tool_server.py](tests/fixtures/stdiotoolserver.py)), connects to it with a real MCP client playing the agent, and asserts the deployable chain over actual stdio:
- the downstream's tools are re-exposed through the proxy,
- a PASS verdict reaches the tool (the downstream's call log records it), and
- a BLOCK verdict (
rm -rf /) never reaches it — the call log stays empty.
That last assertion is the chokepoint property the whole project hangs on.
> Note on the test fixtures: the rest of the integration suite deliberately uses an in-process fake downstream ([tests/fixtures/fake_tool_server.py](tests/fixtures/faketoolserver.py)) that records every call it executes — recording is how the tests prove a blocked action reached nothing. It is a test fixture, not the runtime. doberman serve always spawns and talks to the real server you give it after --.
Turn gate
A second invocation point for the same decision engine — consulted at a host pre-inference hook on the user's turn (prompt + attached/pasted/tool-fetched content), so a flagrant turn is judged before a single inference token is spent. The turn gate is an efficiency / early-warning layer with a deliberately narrow guarantee — no Tier-0-signature turn reaches the model. The action gate above remains the safety guarantee: an attacker who evades the turn gate still meets it.
- One engine, two invocation points.
decide_turnreuses the raise-onlycombine, theDecisionaudit model, and the tiered-auth challenge — zero new verdict authority. It needs no change to the action path;turngate/is a new adapter (sibling to the proxy), and the engine stays pure (the tier guardrails are injected). Turn verdicts append to the same redacteddecisionslog, markedaction_type='turn'. - Tier 0 — deterministic signatures (the only hard-stop, small by design).
instruction_nullification,authority_override(impersonation / mode-switch / "print your system prompt"),secret_export, andencoded_payload. The precision core is the issue-vs-mention discriminator + origin rule: a match in untrusted (pasted / tool-fetched) content blocks unconditionally (indirect injection); a typed + issued match blocks; a typed + mentioned (quoted / meta-discussion) match steps up to AUTH so a researcher discussing an attack is never hard-blocked; ambiguous → issued; code fences never exempt. - Tier 1 — heuristic recall (AUTH-only, structurally BLOCK-incapable). Embedded agent-directed instructions inside pasted text (not mere imperative mood, so tutorials don't trip it), persona override, sub-threshold obfuscation, and urgency+secrecy framing — a false positive costs one tap, not a denied prompt.
- Stylometric co-occurrence gate. A per-entity prompt-style baseline (coarse scalar buckets only — length, word shape, punctuation/case/digit density; never any text) scores each turn's style as an empirical-CDF p-value, the same calibration idea the subjective baseline uses for actions. The gate steps up only when an extreme style outlier co-occurs with a sensitive apparent intent (credential / destructive / external-send) — never on style alone (people type differently tired/mobile/pasting; a device or language switch is drift, not an attack). Style-weird alone is tagged, not gated, and stays inert until the prompt baseline matures (the same maturity rule as the other baselines); Tier 0 is active from turn one. Known limitation: shared accounts blend typists, degrading the style signal toward noise — co-occurrence bounds the cost at one extra tap.
- Tag-and-pass: turn signals feed the action stage (raise-only). Every released turn publishes its stylometric p-value and heuristic flags as a per-entity
TurnContext. The action stage consumes it two ways — the subjective surprise term accepts a bounded, non-negative contribution (a flagged turn makes its follow-on actions score harsher; a clean turn contributes exactly nothing), and actions tracing to flagged pasted segments inheritprovenance: untrusted_data, which makes the lethal-trifecta floor reachable for them. Raise-only by construction; a blocked turn publishes nothing. - Repeat-after-block escape hatch. A near-match resubmission of a just-blocked turn is treated as deliberate human intent and routed to a challenge with proof scaled to the block (a Tier 0 signature →
two_factor; a replay loop cannot produce a TOTP), the original reason restated. Approval is single-use; the third attempt within the TTL locks out. The cache stores only a per-entity HMAC fingerprint, a reason, a count, and an expiry — never the prompt. - AUTH-first & graceful absence.
BLOCKis reserved for the obvious; everything merely suspicious asks the human. Any internal error fails toward the human (AUTH), never a silent pass. With no host pre-inference hook (pure MCP-proxy deployments) orDOBERMAN_TURN_GATE=off, the gate is simply absent and the action gate carries everything.
Benchmark
A suite-agnostic harness scores Doberman as a filter over labeled actions and reports ASR (attack bypass rate) and FPR (benign over-block / friction). It runs the real decision engine over each labeled tool-call — Doberman is the filter, not the agent — so the gated path is deterministic and offline.
python -m tests.benchmarks.run --suite synthetic --profile both # builtins vs plugins
python -m tests.benchmarks.run --suite synthetic --profile before_after # without vs with Doberman
It reports two plugin profiles — builtins_only and with_plugins (built-ins plus any installed entry-point plugins) — and their uplift. The before_after profile adds a no-guardrail baseline (the unmediated tool path, where every attack executes) so you can read the engine's effect directly as {before, after, delta} — how many otherwise-executing attacks it stops vs. how much benign friction it adds. A deterministic synthetic suite gates in CI; map external task suites (AgentDojo, AgentDyn, AgentSentry, …) onto core's types with a small adapter — see [tests/benchmarks/README.md](tests/benchmarks/README.md).
> Reports hold counts, verdicts, and reason codes only — never payload text. ASR is reported alongside a stricter asr_strict (where only a hard BLOCK counts as mitigation): honest measurement, not a single headline number.
Write a custom Guardrail (plugin)
Third-party rules register through the doberman.rules entry-point group. Core never imports your package by name — install it, and discover_rules() / the objective guardrail pick it up automatically.
A five-minute worked example lives at [examples/plugin-guardrail/](examples/plugin-guardrail/) (from a git checkout):
pip install -e ".[dev]"
pip install -e examples/plugin-guardrail
pytest examples/plugin-guardrail/tests -q
pip uninstall -y doberman-example-plugin-guardrail # optional: restore core-only discovery
The tutorial rule steps up a write to SECRETS_TODO.md to AUTH, stays raise-only, and never puts the path or payload into its explanation. Copy the package when you need a real custom rule of your own.
> While the example is installed, core's "no plugins registered" checks will see it — that is expected. Uninstall before re-running the full core suite if you want a clean standalone environment.
Tune to your risk tolerance
Set a mode in .doberman/policies.yaml or via doberman mode . Every mode change made this way — the CLI dial or the setup wizard — is recorded in the append-only policy-change ledger (view it with doberman policy-history). Lowering strictness (paranoid → strict → balanced → light) is a weaken and requires confirmation plus a possession factor: TOTP if enrolled, otherwise the local Doberman password. If neither exists, the lowering fails closed; confirmation alone never suffices. Raising stays frictionless and auto-applies:
| Mode | Best for | Bulk-delete threshold | Step-up for unknown destinations | Step-up for behavioral anomalies | Lethal-trifecta exfil | |---|---|---|---|---|---| | Light | Exploratory / trusted environments | 100 files | No | No | AUTH | | Balanced (default) | Everyday coding agents | 25 files | No | Yes | AUTH | | Strict | Production repos, shared codebases | 10 files | Yes | Yes | BLOCK | | Paranoid | Highly autonomous or security-critical agents | 3 files | Yes | Yes | BLOCK |
> Hard blocks (secret exfiltration, destructive commands, role-boundary violations, smuggled-token-channel exfiltration) are identical in every mode. The mode dial only affects where step-up authentication is required for ambiguous or high-risk actions. > > Unknown network destinations step up to authentication only in Strict/Paranoid. Light and Balanced treat a plain unknown host (e.g. fetching a docs site or an API) as allowed — that AUTH fired on almost every web fetch and was the top source of benign prompts. This relaxes the destination-alone signal only: a secret leaving to any host is still a hard block (secrets rule + raise-only combine, every mode), and the sharper destination smells (credentials embedded in the URL, raw IP addresses, unresolvable hosts) still step up in every mode. An out-of-scope role target likewise steps up in Balanced/Strict/Paranoid but is relaxed in Light; a role-blocked target is a hard block in every mode. > > One escalation is mode-gated: the lethal trifecta — sensitive data and untrusted-content provenance and an external destination — steps up to authentication in Light/Balanced, and is a hard BLOCK in Strict/Paranoid. Those high-security modes refuse this serious-exfil pattern outright rather than leaving it to a confirmation prompt that alert fatigue could rubber-stamp. > > Strict/Paranoid now hard-BLOCK a LOCAL hard smuggled-token channel (previously AUTH); this is raise-only, and Light/Balanced remain unchanged at AUTH.
Enforce / monitor / off — the enforcement dial
Orthogonal to the strictness mode is an enforcement dial (enforce (default) / monitor / off) that decides whether Doberman acts on a verdict or just observes:
enforce— the normal behavior: AUTH prompts, BLOCK denies.monitor— a deliberate observe mode. The discretionary layer (behavioral anomalies, soft step-ups) is evaluated and recorded —doberman log/doberman tuishow what would have happened — but it
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: fu351
- Source: fu351/Doberman-Core
- License: Apache-2.0
- Homepage: https://pypi.org/project/doberman-core/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.