Skip to main content
Glama
kartsan03
by kartsan03

ActGate

ci PyPI Python License: MIT

Local IntentLedger and MCP stdio proxy: propose a tool action, approve or deny in an append-only hash-chained ledger, then let an identical tools/call reach one upstream MCP server.

This is not a SaaS. The ledger path stays on disk. dry-run and approve record decisions only; they do not execute tools. The MCP proxy is what executes, and only after approve.

Install

pip install actgate

Dev:

pip install -e .[dev]

Related MCP server: io.github.AAH20/agent-action-gate

CLI quickstart

actgate init
actgate propose --tool shell.exec --args '{"cmd":"ls"}' --blast-tags fs.read
actgate pending
actgate dry-run <intent_id>
actgate approve <intent_id>
actgate verify
actgate list

MCP proxy

Point your MCP client at ActGate instead of the upstream server:

actgate init
actgate mcp --upstream python -m some_mcp_server

Use the same --root (or the same working directory) for init, approve/deny, and mcp, so they share one ledger.

Flow:

  1. Client tools/list is forwarded to upstream. Only tools/call is gated; other methods are forwarded.

  2. First tools/call for a tool+args writes a propose event and returns ACTGATE_PENDING intent_id=... (upstream is not called).

  3. Human: actgate approve <intent_id> (or actgate deny <intent_id>).

  4. Identical subsequent tools/call (same tool and args) runs upstream once and appends an execute event. A third call returns already-executed.

  5. Denied intents never hit upstream.

Bare verify checks hash-chain integrity only. Set ACTGATE_SEAL_KEY for optional HMAC seals, or pass verify --require-seal.

Human loop (HITL)

Typical MCP approval loop:

  1. Client hits actgate mcp --upstream ... and gets ACTGATE_PENDING.

  2. Human: actgate pending (or actgate pending --watch) to see undecided proposes.

  3. actgate approve <intent_id> or actgate deny <intent_id>.

  4. Client retries the same tools/call; proxy executes once.

pending is the propose-without-decision queue. --watch polls (default 1s) and prints newly pending intents as JSON until Ctrl-C (clean exit 0).

Exit codes

Code

Meaning

0

ok (propose, approve, verify clean, show/list/pending)

1

deny recorded, or verify found a broken chain / bad seal

2

setup error (missing ledger, bad path, invalid args)

Intent shape

{
  "tool": "shell.exec",
  "args": {"cmd": "ls"},
  "args_hash": null,
  "blast_tags": ["fs.read"],
  "requested_mode": "execute",
  "created_at": "2026-09-06T00:00:00+00:00"
}

What this is not

  • Not a hosted approval product

  • Not a policy DSL

  • No network calls in the ledger core path (the MCP proxy talks to a local upstream process)

Development

pip install -e .[dev]
pytest

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    C
    maintenance
    Hash-chained HMAC-signed audit log MCP for A2A (agent-to-agent) calls. Every tool-call, agent-handoff, decision gets a tamper-evident signed record.
    5
    93 PyPI
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server that gates agent tool calls by normalizing intent, denying unknown/unattended destructive actions, and requiring HITL prove approval for high-risk operations. It maintains an append-only hash-chained Action Ledger and exposes gate_check and ledger_verify tools without ever executing tools.
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    Privacy-first, tamper-evident receipts for MCP tool calls. It hashes and signs arguments/results so you can verify what ran, when, without storing raw payloads.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables transparent MCP proxying with a hash-chained effect ledger, classifying agent actions by reversibility, enforcing approval gates, and dry-run previews of sessions.
    MIT