Configuration Reference

Everything lives under ~/.scopegate/ (override with SCOPEGATE_HOME). No config file ever contains a secret value — only secretRef names that point into the encrypted vault.

scopegate.yaml — upstream registry

version: 1
agentId: agent-luis-nexgen        # default identity for policy + audit
upstreams:
  - name: notion                  # tools exposed as notion__*
    transport: { kind: http, url: "https://mcp.notion.com/mcp" }
    auth: { type: bearer, secretRef: notion_token }

Full annotated file: scopegate.example.yaml.

transport

path) becomes a governed upstream: one tool per operation, executed by the gateway itself (auth bearer\|none; spec cached 24h; https outside localhost)

auth types

typeshapewhat reaches the upstream
none{type:"none"}nothing
bearer{type:"bearer", secretRef, header?, scheme?}header (default Authorization: Bearer <secret>)
env{type:"env", env:{ENV_VAR: secretRef}}env vars into the spawned stdio server
oauth2{type:"oauth2", secretRef, header?, scheme?, authErrorPattern?}access token; refresh handled by the daemon
jwt{type:"jwt", secretRef, ttl?, claims?}gateway-minted HS256 token (vault holds the HMAC key)
github_app{type:"github_app", appId, installationId, secretRef, apiUrl?, permissions?, repositories?}installation token (~1h), minted from the App PEM
aws_sts{type:"aws_sts", secretRef, roleArn?, region?, durationSeconds?}session credentials; secretRef is a base name for <ref>_ACCESS_KEY_ID / <ref>_SECRET_ACCESS_KEY

Optional per-upstream: exposeTools: [...] (allowlist) and enabled: false.

policies.yaml — policy engine

Only humans edit this file. Agents propose changes via scopegate_propose_policypolicies.pending.yaml.

version: 1
limits:                    # global hard ceilings — fail-closed, beat any rule
  max_ttl: 1h              #   no grant ever exceeds this
  deny: ["aws:*:production", "\\*:*"]   # checked before auto_approve
  rate_limit: 30/m         #   capability requests per agent
  approval_ttl: 10m        #   human-approval request expiry
agents:
  agent-luis-nexgen:
    default_ttl: 15m
    limits: { max_ttl: 30m, deny: ["stripe:write:*"] }   # per-agent, wins over global
    capabilities:
      - match: "github:call:{get_*,list_*,search_*}"
        auto_approve: true
      - match: "github:call:*"
        auto_approve: true
        ttl: 5m
      - match: "support:call:get_customer"
        auto_approve: true
        redact: [pii]      # mask PII in upstream responses (best-effort)
      - match: "github:call:create_or_update_file"
        auto_approve: true
        ttl: 5m
        when: { branch: "kimi/*" }   # argument guard: auto-approve only on kimi/*
      - match: "github:call:create_or_update_file"
        require: human_approval      # every other branch escalates
      - match: "aws:*:production"
        require: human_approval   # → pending_human_approval + approvals.pending.jsonl
  "*":                     # fallback for unknown agents
    default_ttl: 5m
    capabilities:
      - match: "*:call:{get_*,list_*,search_*,read_*}"
        auto_approve: true

when: values: strings are picomatch globs, numbers/booleans strict equality; a call without the guarded argument never matches the rule (fail-closed), and the guard sticks to the issued grant. vault:inject:<ref> capabilities escalate to human approval BY DEFAULT (a rule must explicitly auto_approve).

Annotated copy: policies.example.yaml.

Environment variables

VariableValuesPurpose
SCOPEGATE_HOMEpathBase dir instead of ~/.scopegate
SCOPEGATE_LOG_LEVELdebugStack traces + gateway debug logs
SCOPEGATE_CONNECT_TIMEOUT_MSms (default 10000)Upstream connect timeout
SCOPEGATE_VAULT_MODEauto (default) · local · daemonVault access: in-process vs via vaultd IPC
SCOPEGATE_VAULT_SOCKETpathOverride the vaultd socket/pipe path
SCOPEGATE_MASTER_KEY_BACKENDauto · file · dpapi · keychain · secret-serviceMaster-key storage
SCOPEGATE_AGENT_IDstringAgent identity for policy/audit (the harness sets this per entry)
SCOPEGATE_APPROVAL_TOKENstringNon-interactive approve/deny/`policies accept\reject` (human-held, out of the agent's reach)
SCOPEGATE_HONEYTOKEN_MODEenforce (default) · alertCanary response: revoke vs alert-only
SCOPEGATE_TELEMETRY1Opt in to anonymous telemetry (default off)
SCOPEGATE_TELEMETRY_ENDPOINTURLOverride the telemetry collector
SCOPEGATE_HTTP_TOKENstringBearer token — required in --http mode
SCOPEGATE_TAINT_MODEalert (default) · enforce · offReturn-path taint scoring: enforce degrades cross-upstream writes to human approval
SCOPEGATE_ENV_PASSTHROUGH1Restore legacy full-inherit of process.env into spawned upstreams (default: scrubbed minimal env + envPassthrough)
SCOPEGATE_CLOUD_DATABASE_URLpostgres://…Cloud control plane: use PostgresStore instead of the JSON FileStore
SCOPEGATE_CLOUD_AUDIT_RETENTION_DAYSdaysCloud: purge audit events older than N days (unset/0 = keep everything)

HTTP transport notes: GET /health is a public readiness probe (status, uptime_s, upstreams, upstreams_detail, vault_mode, pending_approvals); GET /events (bearer) returns an NDJSON metadata-only event tail; X-ScopeGate-Agent on MCP requests selects the logical agent identity (must be in the policies allowlist).

Files in ~/.scopegate/

scopegate.yaml · policies.yaml · policies.pending.yaml (agent proposals) · approvals.pending.jsonl (human-approval queue) · vault.enc (AES-256-GCM) · master.key (mode 0600, unless an OS backend is used) · audit.jsonl + audit-index.json (derived) · reauth-required.json (oauth2 re-auth signal) · telemetry.json (opt-in state).