compliance · mcp
bouncer
Your controls against versioned rule packs for the UK Online Safety Act and the ICO Children's Code. Rules are plain files you can diff. For when "is this lawful?" should not be a chatbot answer. Official MCP server on the registry.
- Node.js
- JavaScript (ESM)
- JSON rule packs
- MCP over stdio
- GitHub Actions
Problem
Regulators now expect controls you can demonstrate: age assurance, high-privacy defaults for children, a way to report and block on user content. Those either exist in a codebase or they do not. Vulnerability scanners look for code that should not be there. Nothing was checking for the code that must be.
Constraints
- No model. Whether a control exists should not be a chatbot answer.
- The engine knows nothing about the law. Everything legal lives in the rule packs.
- A surface it cannot find is unknown, never a pass.
- Every pass points at a file and a line.
- It is an engineering aid, not legal advice, and it says so.
Architecture
A small engine, a set of JSON rule packs, and an adapter that knows where things live in your stack. Read it top to bottom.
Inputs
- Rule packsJSON files. Each rule ties a legal standard to an assertion over a surface.
- ConfigWhich packs to run, which rules to ignore, and which verdicts fail the build.
- Your repositoryRead as files. Nothing is executed.
Adapter
- Surface mapResolves a surface such as sign-up, profile, chat, or livestream to the files that implement it. Next.js and React Native today.
Engine
- AssertionsFind a pattern in a surface and expect it present or absent, combined with all-of, any-of, and not.
- VerdictsPass with a file and line, fail when the surface exists without the control, unknown when the surface cannot be found.
Out
- ReportTerminal output, or a self-contained HTML audit report.
- CI gateExits non-zero when a required control is missing.
- MCP serverFour tools: run a check, list the rules, explain a rule, list the packs.
Key decisions
Checking that required code exists
Instead of scanning for code that should not
Scanners hunt for what should not be there. A repository can be free of vulnerabilities and still fail every obligation in a regulation. bouncer asks the opposite question, and the two are meant to run together.
Rules as JSON packs
Instead of rules written into the engine
The engine knows nothing about the law; the packs do. A pack is a file you can read, diff, and review, and you can point bouncer at a directory of your own.
An honest unknown
Instead of passing what it cannot see
If the sign-up surface cannot be located, bouncer cannot say whether age assurance is there. It reports unknown and never shows green for a surface it did not find.
Gating application source
Instead of policy-as-code over configuration
Policy engines gate configuration and infrastructure. These obligations live in application code: a report button, a default setting, an age gate.
Naming what a scan cannot prove
Instead of pretending everything is checkable
Some obligations are process, not code: a registration with the regulator, a signed agreement, a tax remittance. Those rules surface as gaps to track, not as things a static scan claims to have verified.
What broke, and the fix
The MCP Registry rejected the server manifest.
- Cause
- The description was over the registry's 100-character limit.
- Fix
- Shortened it. The manifest is now published to the registry as part of every release.
Outcome
- Published on npm and the MCP Registry.
- Five packs and 33 rules: the UK Online Safety Act, the ICO Children's Code, and three Nigerian packs for data protection, consumer protection, and tax.
- 19 tests on Node's built-in runner, run in CI on Node 18, 20, and 22.
- It runs as its own check in both BashBop repositories.
- A green report means the coded controls a rule looks for were found. It is not a substitute for a compliance review.