Skip to main content
Glama
TH07008

agentic-governance-gateway

by TH07008

Agentic Governance Gateway

An open-source governance layer that sits between coding agents and your systems. Policies, provenance, validation and human-in-the-loop — with optional transparent proxy enforcement, agent identity, privilege rings, and Prometheus observability.

CI License: MIT Node OPA

Why does this exist?

Agentic coding tools (Claude Code, Cursor, Copilot, …) generate code faster than humans can review it. The 2026 industry reports agree on one thing: governance is the bottleneck, not code generation.

  • 92 % of enterprises report governance challenges with AI-generated code.

  • 82 % had at least one production incident caused by AI-generated code in the last six months.

  • 60 % deploy untested AI-generated code.

  • 43 % cannot reliably tell whether code was written by a human or an agent.

agentic-governance-gateway is a small, framework-agnostic control plane that sits in front of any tool an agent wants to call. Every action flows through one canonical pipeline:

AgentAction
  → Budget check          (cost estimation, daily/monthly caps)
  → Policy evaluation      (OPA/Rego when available, JS fallback otherwise)
  → Validation             (pluggable checkers: semgrep, npm test, checkov, …)
  → Human-in-the-loop      (review for sensitive actions, hash-verified execution)
  → Execution              (injected tool executor)
  → Audit + provenance     (W3C PROV-O records, immutable trail)

Related MCP server: mcp-governance-proxy

Features

  • Policy-as-code with OPA/Rego, plus a TypeScript fallback so the gateway works with zero external dependencies.

  • Traceability with W3C PROV-O provenance and an in-memory or SQL store.

  • Validation orchestration with pluggable checkers (StaticChecker and ScriptChecker ship out of the box).

  • Human-in-the-loop with hash-verified execution: the action the human approved is the action that runs, or it is denied.

  • Budget & cost control with per-agent daily/monthly caps.

  • MCP server that drops into Claude Code, Cursor and any MCP-compatible client — no API key required.

  • REST API for non-MCP clients with X-API-Key authentication, CORS, security headers, and request body size limits.

  • CLI for ad-hoc policy checks from the terminal.

  • Rate limiting with a configurable per-agent sliding window (default: 60 actions/minute, set via RATE_LIMIT_PER_MINUTE).

  • REST API authentication via X-API-Key header. The API is fail-closed: without GATEWAY_API_KEY, all non-healthz routes return 401.

  • PostgreSQL persistence for audit trail and budget state via DATABASE_URL. Falls back to in-memory storage when unset.

  • CORS support configurable via CORS_ORIGIN (default: *).

  • Data retention with a POST /admin/purge endpoint to delete audit records older than a given date.

  • Security headers (X-Content-Type-Options, X-Frame-Options, Referrer-Policy) on all REST responses.

  • Log redactionprompt and params fields are automatically redacted in structured log output.

  • Proxy mode (enforcement) — transparent MCP stdio proxy that intercepts every tools/call, runs it through the governance pipeline, and only forwards to the backend on allow. The agent cannot bypass the gateway. See Proxy Mode below.

  • Agent discovery — the proxy tracks every connected agent (ID, version, session, tool-call count, deny count). Unknown agents are flagged via AGENT_ALLOWLIST.

  • Agent identity — optional token/certificate authentication with SHA-256 credential hashing and per-agent privilege rings (0 = full, 1 = sandboxed, 2 = read-only).

  • Privilege rings (containment) — policy-level containment: Ring 2 agents cannot use mutating tools, Ring 1 agents are path-confined to WORKSPACE_ROOT. Per-agent tool allowlists via AGENT_TOOL_ALLOWLIST.

  • Observability — Prometheus metrics at /metrics, an inline HTML dashboard at /dashboard, and a live agent list at /agents.

Quick start

npm install
npm run build
npm test            # unit + integration + rego tests
npm run test:e2e    # MCP handler end-to-end tests

Run the CLI:

node dist/cli/index.js policies              # list built-in rules
node dist/cli/index.js status               # show active evaluator
node dist/cli/index.js evaluate \
  --tool write_file \
  --params '{"path":"prod/secrets.yml"}' \
  --prompt "rotate the password"
# → decision: require_review / deny / allow

Start as a transparent proxy:

```bash
node dist/cli/index.js proxy \
  --backend-command npx \
  -- mcp-server-filesystem /workspace
# → agent connects, every tool/call is intercepted

## Configuration

All configuration is via environment variables (Twelve-Factor). See
`.env.example` for a complete list.

| Variable | Default | Description |
|----------|---------|-------------|
| `LOG_LEVEL` | `info` | Log level: trace, debug, info, warn, error |
| `OPA_POLICY_DIR` | `./policies` | Directory with Rego policy files |
| `OPA_WASM_PATH` | — | Path to pre-built OPA WASM bundle. When set, OPA is the primary evaluator |
| `POLICY_FALLBACK_JS` | `true` | Fall back to TypeScript evaluator when OPA unavailable |
| `DATABASE_URL` | `memory` | PostgreSQL connection string. When unset or `memory`, uses in-memory storage |
| `DEFAULT_DAILY_BUDGET_USD` | `50` | Default per-agent daily budget cap |
| `DEFAULT_MONTHLY_BUDGET_USD` | `1000` | Default per-agent monthly budget cap |
| `HITL_TIMEOUT_SECONDS` | `300` | Review request timeout before auto-deny |
| `GATEWAY_API_KEY` | — | REST API key. **Required** for REST API to function. Without it, all non-healthz routes return 401 |
| `CORS_ORIGIN` | `*` | Allowed CORS origin for REST API |
| `RATE_LIMIT_PER_MINUTE` | `60` | Max actions per agent per minute |
| `MCP_SERVER_NAME` | `agentic-governance-gateway` | MCP server name reported to clients |
| `MCP_SERVER_VERSION` | `0.1.0` | MCP server version |
| `BACKEND_COMMAND` | — | Backend MCP server command (e.g. `npx`). When set, the gateway runs as a transparent proxy |
| `BACKEND_ARGS` | — | JSON array of arguments for the backend command (e.g. `["mcp-server-filesystem","/workspace"]`) |
| `BACKEND_ENV` | — | JSON object of environment variables for the backend process |
| `BACKEND_CWD` | — | Working directory for the backend process (optional) |
| `AGENT_AUTH_ENABLED` | `false` | Enable agent identity verification on MCP `initialize` |
| `AGENT_ALLOWLIST` | — | Comma-separated list of allowed agent IDs (e.g. `claude-code,cursor`) |
| `SHADOW_AGENT_POLICY` | `warn` | Policy for unknown agents: `warn` (log only) or `deny` (block) |
| `DEFAULT_PRIVILEGE_RING` | `1` | Default privilege ring for unauthenticated agents (0=full, 1=sandboxed, 2=read-only) |
| `WORKSPACE_ROOT` | `.` | Root directory for path confinement (Ring 1 agents cannot write outside this) |
| `AGENT_TOOL_ALLOWLIST` | — | Per-agent tool allowlist (format: `agentId:tool1,tool2;agentId2:tool3`) |
| `METRICS_ENABLED` | `true` | Collect Prometheus metrics |
| `METRICS_PORT` | `9090` | Port for the `/metrics` endpoint |
| `DASHBOARD_ENABLED` | `true` | Enable the HTML dashboard at `/dashboard` |

### Production checklist

- [ ] Set `GATEWAY_API_KEY` (generate with `openssl rand -hex 32`)
- [ ] Set `DATABASE_URL` with `?sslmode=require` for TLS
- [ ] Set `CORS_ORIGIN` to your actual origin (not `*`)
- [ ] Place behind a TLS-terminating reverse proxy (nginx, Caddy, Traefik)
- [ ] Configure log aggregation (Pino outputs JSON to stdout)
- [ ] Set up a retention cron for `/admin/purge`

## Connecting an MCP client

`~/.cursor/mcp.json` (Cursor) or the equivalent for Claude Code:

```json
{
  "mcpServers": {
    "agentic-governance-gateway": {
      "command": "node",
      "args": ["/absolute/path/to/dist/mcp/main.js"]
    }
  }
}

The gateway then exposes three tools to the agent:

Tool

Purpose

governed_tool_call

Submit a tool call through the governance pipeline

governance_status

Report evaluator + budget snapshot

governance_audit_lookup

Fetch an audit record by action id

Agents are expected to call governed_tool_call instead of touching files, git or shell commands directly.

Proxy Mode (Enforcement)

The cooperative mode above relies on the agent choosing to route its calls through the gateway. Proxy mode eliminates that assumption: the gateway intercepts every tool call transparently — the agent cannot bypass it.

How it works

┌──────────┐    MCP (stdio)     ┌──────────────────────────────┐
│  Agent   │ ◄─────────────────►│      GATEWAY PROXY           │
│ (Claude) │   tools/list → fwd │                              │
│          │   tools/call →     │  Governance Pipeline         │
│          │     intercept      │  Rate-Limit → Budget →       │
│          │   initialize → fwd │  Policy → Validation → HITL  │
│          │                    │                              │
│          │                    │   allow → forward to backend │
│          │                    │   deny  → MCP error response │
└──────────┘                    └──────────────┬───────────────┘
                                               │ MCP (stdio)
                                               ▼
                                    ┌──────────────────┐
                                    │  Backend MCP     │
                                    │  Server (real)   │
                                    │  filesystem,     │
                                    │  git, bash, ...  │
                                    └──────────────────┘

The proxy implements both sides of the MCP protocol:

  1. Server side (toward the agent): uses StdioServerTransport. The agent thinks it is talking to the real backend.

  2. Client side (toward the backend): spawns the real MCP server as a child process via StdioClientTransport.

  3. Interception: tools/list, resources/*, prompts/*, and initialize are forwarded 1:1. Only tools/call is intercepted — the tool name and arguments are mapped to an AgentAction, run through the governance pipeline, and forwarded only on allow. On deny, the agent receives a MCP-conformant error response with the reason.

Deployment

Start the proxy from the CLI:

agentic-gateway proxy \
  --backend-command npx \
  -- mcp-server-filesystem /workspace

Or via environment variables:

BACKEND_COMMAND=npx BACKEND_ARGS='["mcp-server-filesystem","/workspace"]' \
  node dist/proxy/proxy-main.js

Agent configuration

Point the agent at the proxy instead of the backend. The agent never sees the backend server:

// ~/.config/claude-code/mcp.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "agentic-governance-gateway", "proxy",
        "--backend-command", "npx",
        "--", "mcp-server-filesystem", "/workspace"
      ]
    }
  }
}

The agent sees the backend's tools (e.g. read_file, write_file, bash) via tools/list — the proxy forwards this transparently. When the agent calls a tool, the proxy intercepts and runs the governance pipeline. On deny, the agent receives:

Tool call denied: Path outside workspace root: /etc/passwd

Limitation: prompt-based policies

In proxy mode, the gateway sees the tool call but not the user's prompt. Policies that rely on prompt content (SSN detection, AWS key detection) are skipped gracefully — the proxy logs a warning and continues. Tool- and parameter-based policies (path confinement, rm -rf blocking, DROP TABLE detection, prod-path protection) work fully in proxy mode.

Discovery & identity

The proxy registers every agent that connects via MCP initialize:

Field

Source

agentId

clientInfo.name from the initialize request

agentVersion

clientInfo.version

connectedAt

Timestamp at connection

toolCalls

Incremented on each intercepted tools/call

denyCount

Incremented on each denied call

When AGENT_AUTH_ENABLED=true, the proxy verifies a token from the initialize request's _meta.auth field against the configured credential store. On success, an AgentIdentity with a privilege ring is created and attached to every subsequent action.

Unknown agents (not in AGENT_ALLOWLIST) are flagged. The response is governed by SHADOW_AGENT_POLICY: warn (log and continue) or deny (reject the connection).

Privilege rings (containment)

Ring

Name

Capabilities

0

Full

All tools, all paths (trusted CI agents)

1

Sandboxed

All tools, but paths confined to WORKSPACE_ROOT (default for interactive agents)

2

Read-only

Non-mutating tools only (read_file, list_files, …)

Ring assignment comes from the credential store (when authenticated) or from DEFAULT_PRIVILEGE_RING (default: 1). Per-agent tool allowlists can further restrict which tools an agent may call:

AGENT_TOOL_ALLOWLIST=claude-code:write_file,read_file,bash;ci-agent:read_file

Observability

The proxy exposes three endpoints (when METRICS_ENABLED and DASHBOARD_ENABLED are set):

  • GET /metrics — Prometheus text format with counters (gateway_tool_calls_total{agent,tool,decision}), latency histograms, budget gauges, and active-agent gauges.

  • GET /dashboard — inline HTML dashboard (no external dependencies, auto-refreshing) showing active agents, decision rates, budget consumption, and the last 20 tool calls.

  • GET /agents — JSON array of active agent connections with tool-call and deny counts.

REST API

The REST API is optional (MCP is the primary transport). Start it with npm run start:api (requires dist/ to be built).

Method

Path

Description

POST

/process

Full governance pipeline (budget → policy → validation → HITL → execute → audit)

POST

/evaluate

Policy evaluation only — no execution, no budget charge, no audit record

GET

/status/:agent

Budget snapshot for an agent

GET

/audit/:id

Audit record by action id

GET

/healthz

Liveness probe (no auth required)

GET

/metrics

Prometheus exposition format (text/plain, no auth)

GET

/dashboard

Inline HTML dashboard (requires proxy mode with registry + metrics)

GET

/agents

List active agent connections (JSON)

POST

/admin/purge

Delete audit records older than a given date (requires API key)

All non-healthz routes require X-API-Key header. Request bodies are limited to 1 MiB.

Example: evaluate an action

curl -X POST http://localhost:3000/evaluate \
  -H "content-type: application/json" \
  -H "x-api-key: $GATEWAY_API_KEY" \
  -d '{
    "agentId": "claude-code",
    "sessionId": "s1",
    "tool": "write_file",
    "params": {"path": "prod/secrets.yml"},
    "prompt": "rotate the password"
  }'
# → { "decision": "require_review", "reasons": [...] }

Example: process an action (full pipeline)

curl -X POST http://localhost:3000/process \
  -H "content-type: application/json" \
  -H "x-api-key: $GATEWAY_API_KEY" \
  -d '{
    "agentId": "claude-code",
    "sessionId": "s1",
    "tool": "write_file",
    "params": {"path": "src/utils.ts"},
    "prompt": "add a helper function"
  }'
# → { "decision": "allow", "audit": { "id": "...", ... } }

Testing without an API key

The project is explicitly designed to be developed and tested with no Claude/OpenAI account:

  • The policy engine has a pure TypeScript evaluator (JsPolicyEvaluator) that mirrors the Rego policies exactly — no LLM involved.

  • The MCP server is exercised end-to-end via a fake in-process server in tests/e2e/mcp-handlers.test.ts.

  • Rego policies are unit-tested with opa test policies/ (the CI job installs OPA automatically).

  • A cross-implementation parity test (tests/integration/policy-parity.test.ts) verifies the TS and Rego evaluators agree on a shared set of inputs. It is skipped automatically when opa is not on PATH.

  • For full agent loops, point the gateway at a local Ollama model (model: "llama3:70b") — cost estimation returns 0 and no external API is called.

Docker

# Set the API key first
export GATEWAY_API_KEY=$(openssl rand -hex 32)

docker compose up -d

The Dockerfile runs as non-root (USER node), includes a healthcheck, and mounts a persistent volume for database files. See docker-compose.yml.

To run the proxy in Docker, set BACKEND_COMMAND and BACKEND_ARGS in the compose service or environment.

Project layout

agentic-governance-gateway/
├── src/
│   ├── core/
│   │   ├── policy-engine/   OPA + JS evaluator, rules
│   │   ├── traceability/    Audit store, PROV-O provenance
│   │   ├── validation/      Pluggable checkers + orchestrator
│   │   ├── hitl/            Human-in-the-loop gateway
│   │   ├── budget/          Cost controller
│   │   ├── gateway.ts        Canonical pipeline façade
│   │   ├── config.ts
│   │   ├── rate-limiter.ts
│   │   └── logger.ts
│   ├── proxy/               Transparent MCP proxy (enforcement mode)
│   ├── identity/            Agent identity + credential store
│   ├── observability/       Prometheus metrics + HTML dashboard
│   ├── mcp/                 MCP server + entrypoint
│   ├── api/                 REST API
│   ├── cli/                 CLI
│   └── types/                Shared TypeScript types
├── policies/                Rego policies + tests
├── tests/
│   ├── unit/                Per-module unit tests
│   ├── integration/         Gateway + parity tests
│   └── e2e/                 MCP handler tests
├── docs/                    Architecture + ADRs
├── examples/                Runnable example policies & configs
├── Dockerfile
├── docker-compose.yml
└── .github/workflows/ci.yml

Architecture

See docs/architecture.md for the full design and docs/decisions/ for the ADRs that explain the trade-offs:

License

MIT — see LICENSE.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    An MCP server that acts as a governance proxy for AI agents, evaluating each tool call against policies before execution, enabling secure and controlled access to systems like Slack, GitHub, and AWS without exposing credentials to the agent.
    Apache 2.0
  • A
    license
    -
    quality
    B
    maintenance
    A self-hosted MCP server that enables AI coding agents to read, edit, search, and run code in local projects with human review loops and policy controls.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    MCP server that enables a coordinator AI agent to spawn, control, and supervise local coding agents with interactive gating for high-risk operations.
    10
    38
    1
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage

  • Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/TH07008/agentic-governance-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server