Inspiration

AI agents are being given real tools — refunds, deletions, messages — with no enforcement layer in between. We built ToolGate to fix that: a gateway that sits at the MCP protocol level and enforces policy on every tool call, regardless of which agent framework or SDK is in use.

## What it does

ToolGate is an MCP policy gateway. It intercepts every tool call an AI agent makes and enforces a YAML policy before anything reaches the upstream:

  • Allow — forward and log
  • Deny — block before it hits the upstream
  • Approval required — hold the call, send a human an interactive Lark card, resume or expire on their decision
  • Redact — strip PII or secrets from arguments before forwarding

Every decision lands in a Postgres audit log. Nothing gets through without a record.

ToolGate also ships an eval-gated deployment gate — a test runner that exercises the full gateway stack and blocks promotion if any policy outcome regresses.

## How we built it

ToolGate is a Go service that speaks MCP (JSON-RPC over SSE). It chains a policy engine, approval bridge, and audit writer before proxying to the upstream MCP server. The approval hold uses Go channels + Redis pub/sub with a hard TTL so it never blocks indefinitely. A Python demo agent and fake Stripe MCP server are included purely to make the policy scenarios runnable end-to-end.

Everything runs on Docker Compose — make demo starts the stack, runs all scenarios, and tears it down.

## Challenges

The hardest part was the approval hold: pausing a live MCP call, notifying a human, and cleanly resuming or expiring — without goroutine leaks or hard failures when Lark is unreachable. We also built a capability cache so the gateway can serve tool metadata to agents even when the upstream MCP server is down.

## What we learned

Enforcing at the protocol layer — not the SDK layer — means policy can't be bypassed by an agent that forgot to import a library. It's harder to build, but coverage is universal. The eval runner consistently caught real policy regressions that unit tests missed.

Built With

Share this project:

Updates