I. The Approach
GARRISON · v0.1 · MIT · PRE-RELEASE

HALBERD

Every request must pass the gate.

A JSON-RPC firewall for MCP agents.

tools/call → policy → audit → upstream

The Sentry's Challenge

§Try Halberd in the browser

State your purpose, traveller.

The real internal/policy engine compiled to WebAssembly and running client-side. Pick a rule pack, paste a JSON-RPC envelope, and see what the sentry would do.

Raising the gate… (4.5 MiB engine, ~1 MiB over the wire)

The Threats at the Gate

§The five named threat categories

Halberd v0.1 ships request- and response-side coverage for four of the five threats below, on both the HTTP and stdio transports.

T1

Tool poisoning

covered, v0.1

A compromised MCP server slips role-tag spoofs, ANSI escapes, or zero-width Unicode into a tool response to hijack the agent's next turn.

The garrison: Response inspector strikes ANSI and zero-width Unicode in place.

T2

Argument injection

covered, v0.1

The agent is induced to call a legitimate tool with hostile arguments: DROP TABLE, --upload-pack=…, statement chaining via ;--.

The garrison: Per-tool regex denylist, type checks, max-length, and allowlist enums.

T3

Out-of-scope I/O

v0.2 roadmap

A narrow-purpose tool gets pushed to read /etc/shadow, hit a private IP, or write outside its sandbox.

The garrison: Path-traversal, absolute-path, and home-expansion patterns already deny on filesystem and git packs.

T4

Capability creep

covered, v0.1

Mid-session, an MCP server pushes "tools/list_changed" and adds a tool the agent calls before any human reviews it.

The garrison: Tool inventory pinned to the bundle; any unknown tool is denied by default.

T5

Exfiltration via response

covered, v0.1

A tool response carries AWS keys, GitHub tokens, or RSA private keys back into the model context.

The garrison: Built-in scanners redact aws_access_key, github_token, and rsa_private_key on the wire.

The Armory

§Bundled rule packs

Pre-forged bundles. Carry one to the gate, or forge your own.

Each pack is a YAML policy bundle calibrated against a specific MCP server. The DSL is intentionally narrow: type · max_length · allow_values · deny_patterns · response-side secret scanners.

The Gatehouse Keys

§Install Halberd at your own gate

Take these and stand a watch of your own.

Pre-built binaries ship for linux and darwin × amd64 and arm64. Each archive bundles all four binaries plus every rule pack.

Download a release

curl -L https://github.com/Builder106/Halberd/releases/latest/download/\
  halberd_${VERSION}_${OS}_${ARCH}.tar.gz | tar -xz
./halberd version

Build from source

brew install go
git clone https://github.com/Builder106/Halberd && cd Halberd
go build -o bin/ ./cmd/...
./bin/halberd lint policies/mcp-server-postgres.yaml

Wrap a local stdio server (Claude Desktop)

Edit ~/Library/Application Support/Claude/claude_desktop_config.json — point at halberd-stdio instead of the real server:

"mcpServers": {
  "postgres": {
    "command": "/usr/local/bin/halberd-stdio",
    "args": [
      "--policy", "/etc/halberd/postgres.yaml",
      "--audit",  "/var/log/halberd/postgres.jsonl",
      "--", "mcp-server-postgres", "--conn-string", "postgresql://..."
    ]
  }
}

HTTP transport (remote MCP)

Sit between your agent and a remote MCP server:

halberd-http \
  --policy policies/mcp-server-postgres.yaml \
  --target http://upstream:8080 \
  --listen :9090 \
  --audit  halberd.jsonl