Skip to content

v0.2.0 - effectgate

Latest

Choose a tag to compare

@pterbsgame-netizen pterbsgame-netizen released this 31 Jul 02:05
· 2 commits to main since this release

Renamed from mcp-guard, and installing it is now one command.

A security proxy for MCP stdio servers: the client launches effectgate,
effectgate launches the real server, and everything between them is relayed,
recorded, and — depending on the level — refused.

The rename

There were already four projects called mcp-guard in this exact niche, one of
them described as "middleware that blocks dangerous AI agent actions using a
simple YAML config"
, plus mcp-guardian at 198 stars and an npm package of the
same name. Anyone searching for this found one of them instead.

effectgate states the rule the whole design follows — control effects, not
content
— rather than repeating a word four other projects already use.

Nothing about the behaviour changed. What moved: the binary name, the module
path, ~/.effectgate/sessions, effectgate.lock, the EFFECTGATE_ environment
prefix — including the emergency switch, now EFFECTGATE_OFF=1.

New: install and uninstall

Until now the only way to wire this in was to hand-edit the client's JSON
config without breaking it and without mis-escaping a Windows path. That was the
widest part of the funnel and the least defensible.

effectgate install --dry-run    # print what would change, write nothing
effectgate install              # apply, after copying each config aside
effectgate uninstall            # put the original commands back

It finds the client configs on this machine, reports every declaration and what
it decided about each — including the ones it skipped and why — and applies it.
Servers declared under projects.<dir> are covered too; Claude Code launches
those exactly like the global ones.

The file is not re-serialised. Only the declarations that actually change
are re-emitted and spliced back into the original bytes, so key order,
formatting and every field this code has no opinion about survive untouched.
Client configs hold caches, feature flags and window positions beside the
server declarations, and a tool that reformats all of it to change two fields
gets undone by hand and never run again.

Wrapping defaults to the observing level. Enforcement is a decision to make
after a week of numbers; --enforce=enforce bakes a level in if you already
know.

Three defects were found while building it, two of them only because it was run
against real configs rather than fixtures — including encoding/json escaping
angle brackets and ampersands into their unicode form, for the benefit of HTML
nobody here was writing. A real --with mcp<2 argument came back as something
its owner would not recognise in their own config.

Also new

  • macOS builds, which v0.1.0 did not have.
  • A SECURITY.md that lists what is already known and not worth reporting, so
    the documented limits below do not arrive as bug reports.

Everything from v0.1.0 still holds

  • Pins what a server advertises. effectgate approve records each tool's
    name, description and canonicalised (RFC 8785) schema into effectgate.lock.
  • Decides on effects, not wording. Paths are resolved before they are
    matched: ~, environment variables, .. segments, symlinks, letter case,
    Windows 8.3 short names, \\?\ prefixes and NTFS alternate data streams all
    reduce to one form first.
  • Taint by source, not by phrasing.
  • Content signatures that never block — by construction they only raise the
    taint level.
  • Guards the client config from outside the traffic path.
  • Filters the child's environment, so a filesystem server does not start
    life holding a cloud credential.
  • Three levels: observe (default), enforce (deny only), strict.

Measured

On the development machine at enforce: 28 tool calls of ordinary work over
75 hours, zero blocks.
Deliberate probes are excluded and listed in
corpus/excluded-sessions.txt; including them gives 11.1 blocks per week, which
is five correct refusals of attacks. strict produces 24.5 refusals a week in
the same workload, every one of them execute_blender_code hitting the exec
class — which is why strict is marked as not usable yet rather than
recommended.

Every figure comes out of effectgate eval --benign ~/.effectgate/sessions, so
it can be checked rather than believed. If it ever disagrees with these notes,
it is the command that is right.

One machine, one workload, 28 calls. Treat it as a starting point for your own
measurement.

What it still does not do

tools/list is never blocked, so a poisoned description reaches the model.
confirm cannot ask — no client declares elicitation/create. Only stdio; a
server added over HTTP is unguarded and nothing says so. Taint does not cross
servers. A stdio proxy cannot see the server's own network traffic.

Verify what you downloaded

sha256sum -c SHA256SUMS.txt

If it goes wrong

EFFECTGATE_OFF=1 in the client's environment relays with no checks at all. It
is read before any configuration file is opened, so a broken policy cannot cost
you your tools. effectgate uninstall puts the original commands back.