BOUNDPORT
Public Docs

Boundport puts a policy boundary between AI agents and the systems they touch.

Boundport acts as an agent access gateway between an MCP client and the tools or MCP servers it calls. Each request is evaluated against policy before it reaches the target system, and governed requests leave an audit trail around what was requested, why it was allowed or blocked, and whether approval was required.

Available Now

Local CLI and stdio gateway, file-based policy and tool registry, observe and enforce modes, local exact-request approvals, local SQLite-backed audit receipts, and governed GitHub profile examples.

Primary User

Platform, security, or AI infrastructure engineers who need agents to use real systems without granting broad unchecked authority.

What Boundport Sits Between

An MCP client over stdio, an upstream MCP server launched as a subprocess by Boundport, and the real downstream system behind that server such as GitHub.

Getting Started

Start with policy evaluation before a live proxy session.

The recommended first run is a deterministic policy test. It exercises the governance path without requiring a real upstream server or live credentials.

Prerequisites

  • Node.js `>=22.13.0`
  • pnpm `10.33.0`
  • A local checkout of the Boundport repository

First-run command

pnpm install
pnpm run build
node apps/cli/dist/index.js policy test \
  --config examples/boundport-governed.yaml \
  --request examples/policy-request.json

Expected success signal

The command should print a JSON decision payload to stdout. A successful result includes fields such as `effect`, `rule_id`, `reason_code`, `policy_revision`, and `request_digest`.

First live proxy run

node apps/cli/dist/index.js proxy --config ./boundport.yaml

For a live run, `upstream.command` and `upstream.args` must point to a real MCP server. The example config is useful for policy testing, but its upstream path is illustrative and should not be treated as a ready-to-run production profile.

Common failure modes: missing dependencies, nonexistent upstream command paths, required environment variables not allowlisted, schema digest drift in enforce mode, or unwritable local SQLite paths for audit and approvals.
Deployment Modes

Use the local gateway today. Treat managed control-plane features as planned, not current.

Local development

One local Node.js process runs the Boundport gateway, launches the upstream MCP server as a subprocess, and stores audit plus approval state in local SQLite files.

Self-hosted in customer infrastructure

The open-source gateway can be self-hosted using the same one-process pattern inside customer infrastructure. Today the documented model is a gateway process running close to the protected environment, rather than a separate multi-node or Kubernetes control-plane deployment.

Managed or enterprise direction

Centralized policy distribution, authenticated approvals, searchable hosted audit retention, and gateway fleet control belong to the enterprise product direction rather than the current open-source release.

Data Flow
  1. MCP client sends JSON-RPC over stdio.
  2. Boundport normalizes and evaluates the request.
  3. Boundport records a receipt.
  4. Allowed calls are forwarded once to the upstream subprocess.
  5. Approval-gated calls wait for a local operator decision.
Trust Boundaries
  • The agent and its arguments are untrusted.
  • Upstream tool descriptions and schemas are untrusted until classified.
  • Local config and SQLite state are inside the trust boundary only if owned and protected by the operator.
Policy Authoring

Policies are deterministic, ordered, and bound to exact tool schemas.

Rules are evaluated in order and the first matching rule wins. Supported match conditions today include `server_id`, `tool_name`, `tool_risk`, `environment`, and `principal_id`. Current effects are `allow`, `deny`, and `require_approval`.

Minimal starter policy

schema_version: 1

rules:
  - id: allow-reads
    match:
      tool_risk: read
    effect: allow

  - id: gate-writes
    match:
      tool_risk: write
    effect: require_approval
    approver_groups:
      - platform
    ttl_seconds: 300

  - id: default-deny
    match: {}
    effect: deny
    reason_code: no_matching_rule

A good first policy classifies all known tools, allows low-risk reads, requires approval for writes, and ends with an explicit default deny.

Representative tool registry entry

schema_version: 1

tools:
  - server_id: example
    tool_name: read_file
    schema_digest: sha256:a2c799262a3ce3c19ef5cdd983bf3d12b43ab3c426227091b909dcb7054738c0
    risk: read
    idempotent: true
    secret_fields:
      - authorization

`observe` always forwards and records the would-be decision. `enforce` forwards only classified allow decisions and fails closed on unclassified tools.

Argument-level conditions are not currently supported by the implemented matcher, so docs and examples should not imply that Boundport can inspect arbitrary nested arguments in policy rules today.

Approval Workflows

Approval is exact-request, single-use, and local today.

Approval is triggered only when a matching policy rule uses `effect: require_approval`. The current approval surface is the local CLI against the approvals SQLite database. Approval identity is based on local configuration, not authenticated SSO or hosted RBAC.

node apps/cli/dist/index.js approvals list --config examples/boundport-governed.yaml
node apps/cli/dist/index.js approvals approve <approval-id> --config examples/boundport-governed.yaml
node apps/cli/dist/index.js approvals reject <approval-id> --config examples/boundport-governed.yaml
Lifecycle outcomes
  • `approval_required` - request is held pending a decision
  • `approval_consumed` - approved request is forwarded once
  • `approval_rejected` - request is denied and not forwarded
  • `approval_expired` - TTL elapsed before approval
  • `approval_cancelled` - client cancelled before release
  • `duplicate_request_id` - request replay is rejected
Security Posture

Boundport reduces unchecked agent authority by making execution conditional.

Boundport evaluates each request before it reaches the target system. In enforce mode, unclassified tools fail closed, denied decisions are blocked, and approval-gated decisions stay on hold until a valid exact-request approval is consumed.

Registry schema digests tie decisions to exact tool schemas, helping prevent silent drift between what operators reviewed and what tools actually expose at runtime.

Secret handling is conservative: fields marked in `secret_fields` are redacted in receipts and approval summaries, and untrusted upstream stderr is discarded instead of being logged as audit evidence.

Current boundary
  • Transport today is stdio inbound and stdio upstream.
  • Identity today is configured local operator identity, not enterprise auth.
  • Hosted approvals, hosted audit search, and centralized policy are planned, not available in this repo.
  • Supported public claims should distinguish between what exists now and what is directional.
Audit and Observability

Local receipts answer who requested what, which rule decided it, and what happened next.

The local audit store writes receipts to SQLite and exports append-only JSONL. Events include request identity, routing context, decision effect, matched rule, reason code, tool classification, argument summary, and receipt-chain linkage.

Current storage is local by default. Operators can export JSONL and use their own tooling for deeper inspection, while centralized hosted search and retention controls belong to the enterprise direction.

With current receipts, operators should be able to answer which principal invoked which tool, whether the call was allowed, denied, or approval-gated, which policy revision made the decision, and whether the receipt chain still verifies.

Representative receipt fields

schema_version
event_id
occurred_at
request_id
request_digest
previous_receipt_digest
receipt_digest
principal
client_id
gateway_id
environment
server_id
tool_name
tool_schema_digest
policy_revision
decision
tool_risk
execution
argument_summary
redaction_profile
Integrations

GitHub is the concrete governed integration called out in the current public material.

The governed GitHub profile targets `github/github-mcp-server` `v1.7.0` over stdio. Live smoke runs require an inherited `GITHUB_PERSONAL_ACCESS_TOKEN`, and enforce mode fails closed if the schema or tool classification drifts.

Current quickstarts also document configuration examples for Claude Desktop and Claude Code, but those examples are configuration-schema validated rather than backed by published external UAT results.

Do not present as current
  • Hosted approval delivery
  • Slack approvals
  • Postgres integration as a supported product integration
  • Additional SaaS or cloud provider governed profiles not yet checked in
Configuration Reference

The minimum governed config includes upstream execution, identity, audit, and approvals.

schema_version: 1

upstream:
  command: "node"
  args:
    - "/absolute/path/to/your-mcp-server.js"
  cwd: "."
  env:
    allow:
      - "PATH"

governance:
  mode: observe
  policy: "./policy.yaml"
  registry: "./tool-registry.yaml"
  server_id: example
  identity:
    principal_id: "local:operator"
    principal_type: local_profile
    client_id: "local-mcp-client"
    gateway_id: "local-gateway"
    environment: development
  audit:
    database: "../.boundport/receipts.sqlite"
    observe_failure: deny
  approvals:
    database: "../.boundport/approvals.sqlite"
    poll_ms: 100
    operator:
      id: "operator:local"
      groups:
        - platform
Key upstream settings
  • `upstream.command` - executable launched as the upstream MCP server
  • `upstream.args` - arguments passed to the upstream command
  • `upstream.cwd` - working directory for the upstream subprocess
  • `upstream.env.allow` - allowlist of inherited environment variable names
Key governance settings
  • `governance.mode` - `observe` or `enforce`
  • `governance.policy` - path to the policy file
  • `governance.registry` - path to the tool registry
  • `governance.audit.database` - local SQLite audit path
  • `governance.approvals.database` - local SQLite approvals path