Skip to main content
Glama

ScopeGate

Ephemeral credentials & persistent MCP connections for coding agents โ€” Claude Code, Kimi Code, Cursor, OpenCode.

npm CI License: Apache-2.0

๐Ÿงฉ Nexum.Work Ecosystem

This repo is one of the 4 pillars of Nexum.Work (canonical map: org/ECOSYSTEM.md).

Pillar

Repo

What it is

๐Ÿข Product

NexgenSystemsMX/nexum

The platform โ€” production fork of Huly, 19 services behind the nexum.work edge

๐Ÿค– Agent

NexgenSystemsMX/kimi-tag

The agent workers (@Kimi, Nexo, auditor) โ€” the production ScopeGate gateways are embedded here

๐Ÿ” Credentials

NexgenSystemsMX/scopegate

This repo โ€” ephemeral-credentials MCP gateway + ScopeGate Cloud

โŒจ๏ธ CLI

NexgenSystemsMX/nexum-cli

Agent-first CLI (129 commands) โ€” spawned by ScopeGate as a minted-env stdio upstream

๐Ÿ“– Source of truth: org/ECOSYSTEM.md

The agent never holds credentials โ€” it holds short-lived, minimum-scope capabilities. Secrets live in an AES-256-GCM encrypted local vault and are injected only at the outbound hop. A leaked context leaks nothing of durable value.

Agent/CLI โ”€โ”€(MCP, zero secrets)โ”€โ”€โ–บ ScopeGate โ”€โ”€(creds injected)โ”€โ”€โ–บ GitHub / AWS / your MCPs
                                      โ”‚
                    vault + policy engine + token minter + signed audit

Capability โ‰  credential. What the agent gets expires in minutes and is scoped to one task; what the vault keeps never enters the model's context.

Quickstart (agent-executable, non-interactive)

npm i -g scopegate
scopegate init

or via the installer:

curl -sSL https://scopegate.io/install.sh | sh

init is idempotent and does everything:

  • creates ~/.scopegate/ (encrypted vault, master key, default policies)

  • detects harness configs (Claude Code, Kimi Code, Cursor, OpenCode, .mcp.json)

  • migrates existing MCPs behind the gateway, moving plaintext secrets (env vars, auth headers) into the encrypted vault and leaving only refs

  • rewrites the harness config so scopegate is the single MCP entry point (backup kept as *.pre-scopegate.bak; scopegate rollback restores it)

Deposit secrets โ€” human-only path, never through chat, never via argv:

scopegate secret add github_pat                      # hidden prompt
echo "$TOKEN" | scopegate secret add notion_token    # or piped

Then restart the agent session (once โ€” the harness launches the gateway on startup). From there, the agent operates ScopeGate by itself through the scopegate_* MCP tools (see SKILL.md). Later secret add deposits hot-reload: the running gateway drops its connections and re-injects fresh credentials on the next call โ€” no restart, no context loss.

CLI

Command

What it does

scopegate init [--dry-run] [--harness <id>]

Idempotent setup: vault, policies, harness detection & secret migration

scopegate start

Run the gateway MCP server on stdio (launched by the harness)

scopegate secret add <ref> / ls / rm <ref>

Vault secrets. Value via hidden prompt or piped stdin โ€” never argv

scopegate status

Config, vault ref names and upstream health

scopegate audit verify

Verify seq continuity, hash chain and Ed25519 signatures (exit 1 on tamper)

scopegate audit query [--agent --kind --since --until --limit]

What did an agent/token touch in a window (JSONL)

scopegate audit reindex

Rebuild the derived audit-index.json snapshot

scopegate auth login <upstream>

OAuth device-code re-authorization (human, out-of-band)

scopegate vaultd [--socket <path>]

Run the vault as an isolated process (unix socket / Windows named pipe)

scopegate vault rotate-key [--backend file|dpapi|keychain|secret-service]

Re-encrypt the vault with a fresh master key

scopegate rollback [--harness <id>]

Restore harness configs from *.pre-scopegate.bak

scopegate approve <id> [--ttl <t>] / deny <id> --reason <r>

Human-side approval of escalated capability requests (TTY or SCOPEGATE_APPROVAL_TOKEN)

scopegate policies review / accept <n> / reject <n>

Human review of agent-proposed policy rules (policies.pending.yaml)

scopegate cloud serve [--port <n>] [--home <dir>]

Run the ScopeGate Cloud control plane (landing at /, panel at /panel, multi-tenant API at /v1)

scopegate cloud enroll --cloud <url> --token <t>

Enroll this gateway into a control plane (writes cloud.json)

scopegate git-credential

Git credential-helper: git credential fill gets a fresh GitHub App installation token, governed by git:credential:<path> policies

scopegate inject --ref <r> --out <f> [--template โ€ฆ] ยท --refresh <f>

Materialize a vault secret into a legacy config file (approval by default, atomic 0600, sha256-only audit)

scopegate honeytoken plant <name>

Plant a decoy credential (canary:<name>) whose use triggers surgical revocation

Agent tools (MCP)

Exposed by scopegate start; the agent self-manages through them (21 tools).

Tool

Use when

scopegate_request_capability

Before privileged actions โ€” returns a TTL grant, or pending_human_approval with an approval_id; wait: true long-polls the decision inline; execute_on_approval queues the intended call

scopegate_request_capabilities

Batch: up to 20 capability requests in one call, per-item outcomes

scopegate_list_capabilities

Active grants and remaining TTL

scopegate_register_upstream

Connect a new service (never accepts secret values, only secretRef names; also from_registry 1-click)

scopegate_diagnose

Any auth/connection error โ€” self-repair with action_required hints

scopegate_propose_policy

A needed capability was denied โ€” lands in policies.pending.yaml for human review

scopegate_vault_status

Which secretRef names exist (never values)

scopegate_collect / scopegate_wait

Collect / long-poll an approval-continuation outcome

scopegate_upstream_health

Per-upstream liveness, oauth state and circuit-breaker state

scopegate_can_i / scopegate_policy_summary

Read-only policy preflight and session-start digest โ€” plan before acting

scopegate_recall / scopegate_events

Session memory from the signed audit; metadata-only event tail for host UIs

scopegate_open_task_lease / scopegate_renew_capability

Long-task leases (double budget) and agent-driven grant renewal

scopegate_request_plan

Submit a whole task plan โ€” ONE aggregated approval with the full blast radius

scopegate_result_get / scopegate_result_grep

Page/search oversized results via handles (context window never flooded)

scopegate_delegate

Attenuated sub-grants for subagents (scope โІ parent, dies with the parent)

scopegate_inject_file

Materialize a vault secret into a file (governed exception; approval by default)

Library API (embed the gateway in-process)

import { createGatewayServer } from "scopegate";

const gw = await createGatewayServer({ agentId: "my-worker" });
// gw.server is the full agent-facing MCP server โ€” connect any transport.
await gw.close();

No subprocess, no daemons (opt-in), throws instead of process.exit. For consumer integration tests, scopegate/testkit ships a fake upstream and bootFakeGateway() wired to an MCP client over in-memory transport โ€” no real credentials needed. Experimental in v0.x; strict semver from v1.

Configuration

Two files in ~/.scopegate/ (both secret-free; secrets live only in the vault):

  • scopegate.yaml โ€” upstream registry (example), transports stdio / http / openapi (OpenAPI 3 spec โ†’ one governed tool per operation, no bridge needed)

  • policies.yaml โ€” policy engine rules (example): limits (max_ttl, deny globs, rate_limit, approval_ttl), auto_approve, require: human_approval, redact: [pii], when: (argument guards โ€” e.g. auto-approve only on kimi/* branches)

Auth types per upstream:

upstreams:
  - name: notion
    transport: { kind: http, url: "https://mcp.notion.com/mcp" }
    auth: { type: bearer, secretRef: notion_token }

  - name: github
    transport: { kind: stdio, command: npx, args: ["-y", "@modelcontextprotocol/server-github"] }
    auth:
      type: env
      env: { GITHUB_PERSONAL_ACCESS_TOKEN: github_pat }

All auth types: bearer (header injection), env (env vars into spawned stdio servers), composite (several sources fused into one stdio upstream: static refs + provider mints โ€” multi-service MCPs 100% minted), oauth2 (refresh daemon + device-code re-auth), jwt (gateway-minted HS256), github_app (installation tokens minted from the App key), aws_sts (session credentials via AssumeRole/GetSessionToken), huly (workspace token minted via login + selectWorkspace against a Huly account service โ€” URL discovery through /config.json), google_sa (Google service account JWT โ†’ access token), none. Minted credentials on stdio respawn proactively at 80% of their TTL, and spawned children only inherit a secret-scrubbed env (SCOPEGATE_ENV_PASSTHROUGH=1 restores legacy full-inherit). See scopegate.example.yaml for commented examples of each.

Native connectors (bridges in src/upstreams/)

Ready-to-run MCP bridges; each runs as a stdio upstream and is also available in the signed registry (scopegate_register_upstream {from_registry}):

Upstream

Tools

Auth

huly

16 tools: tracker (create/read/update/comment/search issues incl. comments, milestone/dueDate, assignee filter; projects), documents, chunter (post/edit messages, threads, thinking flag), contacts

huly (vault blob {email,password,workspace} โ†’ minted workspace token)

railway

7 tools: list/status/deploy/redeploy/logs/variables(names only)/domains

env (RAILWAY_TOKEN account-scoped)

cloudflare

8 tools: zones, DNS list/create/update/delete, workers, pages, R2

env (scoped API token)

google

7 tools: Drive list/search/read, Gmail send/list, Calendar list/create

google_sa (SA JWT โ†’ access token)

Plus: github-official in the registry (GitHub's own remote MCP with github_app auth โ€” ~1h installation tokens, no PAT), and the openapi transport that turns any OpenAPI 3 spec into a governed upstream.

Their manifests ship signed in registry/.

Environment variables:

Variable

Purpose

SCOPEGATE_HOME

Base dir instead of ~/.scopegate (tests, portable installs)

SCOPEGATE_LOG_LEVEL

debug for stack traces and gateway debug logs

SCOPEGATE_CONNECT_TIMEOUT_MS

Upstream connect timeout (default 10000)

SCOPEGATE_VAULT_MODE

auto (default) | local | daemon

SCOPEGATE_VAULT_SOCKET

Override the vaultd IPC socket/pipe path

SCOPEGATE_MASTER_KEY_BACKEND

auto | file | dpapi | keychain | secret-service

SCOPEGATE_AGENT_ID

Agent identity for policy/audit (set per harness entry)

SCOPEGATE_APPROVAL_TOKEN

Lets approve/deny/`policies accept

SCOPEGATE_HONEYTOKEN_MODE

enforce (default) | alert โ€” canary response mode

SCOPEGATE_TELEMETRY

1 opts in to anonymous telemetry (default off)

SCOPEGATE_TELEMETRY_ENDPOINT

Override the telemetry collector URL

SCOPEGATE_HTTP_TOKEN

Bearer token โ€” required in --http mode

Production deployment (Railway)

The gateway also speaks Streamable HTTP: scopegate start --http --port <n> --host <h> (bearer SCOPEGATE_HTTP_TOKEN on every request except a public GET /health). This repo deploys as-is to Railway:

  • railway.toml pins the build (Nixpacks: npm run build) and the start command (seed-demo idempotente + start --http), with /health as the healthcheck. A root Dockerfile (multi-stage, non-root) is kept for plain Docker builds outside Railway.

  • Persistent state lives on a volume mounted at /data (SCOPEGATE_HOME=/data): vault, identity, policies, config.

  • With SCOPEGATE_SEED_DEMO=1 and an empty home, a clearly-marked demo seed provisions a fake upstream + fake secret so the deployment is self-contained (zero real credentials).

  • Live proof: SCOPEGATE_PROD_URL=<url> SCOPEGATE_HTTP_TOKEN=<token> node e2e-prod.mjs runs the production e2e (8 assertions: health, auth 401s, initialize, listTools, grant, authenticated proxied call, diagnose, deny path).

ScopeGate Cloud (management plane)

scopegate cloud serve runs the optional multi-tenant control plane โ€” metadata-only by design (no secret values ever cross it), and the gateway keeps enforcing its local policy + last signed team policy when the cloud is down (local-first). One process serves three things:

  • GET / โ€” the public landing page (site/)

  • GET /panel โ€” the product panel (vanilla SPA, no build step): Overview (fleet health, security events), Fleet (revocation with explicit blast-radius confirmation, including team-wide), Approvals (the human queue: approve/deny from the browser and the gateway applies it in seconds via the approval-sync loop โ€” no terminal needed), Capabilities (live grants with TTLs), Audit (query + signed JSONL export), Policy (signed, versioned, with line diff), Billing (active-agent metering), Settings (enroll snippets, Slack alerts).

  • /v1/* โ€” the management API: enroll, signed policy distribution, audit ingest (hash-chain + per-event Ed25519 verified, looksLikeSecret guard), revocation feed, approval decisions feed, billing usage, admin overview/queue/export endpoints. GET /health is a public probe.

Gateway side: scopegate cloud enroll --cloud <url> --token <enrollToken> links a gateway to a team; from there four background loops run โ€” policy-sync (signed, restrictive intersection), audit-export, revocation-sync and approval-sync (all fail-soft: a dead cloud never blocks a tool call).

Access today: the panel authenticates with the control plane's admin token (env ADMIN_TOKEN) โ€” dev-grade by design; SSO with per-team roles (owner/approver/viewer) plugs into the same API via the SsoAdapter interface (src/cloud/server/sso.ts). Persistence: the FileStore (default) or PostgresStore when SCOPEGATE_CLOUD_DATABASE_URL is set โ€” both behind the Store interface, with configurable audit retention (SCOPEGATE_CLOUD_AUDIT_RETENTION_DAYS). Verify the whole plane: node e2e-cloud.mjs (enroll โ†’ sync โ†’ central audit โ†’ panel approval loop โ†’ fleet revocation โ†’ local-first) and node e2e-landing.mjs (static routing contract).

Security model (summary)

  1. Secrets never enter the model's context (CLI/stdin only, encrypted at rest).

  2. Capability โ‰  credential: grants expire in minutes, scoped per task.

  3. Write asymmetry: agents propose policy, humans approve (policies.pending.yaml โ†’ human review).

  4. looksLikeSecret() guard rejects raw secrets smuggled as refs by agents.

  5. Hard limits are fail-closed: deny globs and max_ttl beat any rule.

  6. Every action lands in audit.jsonl โ€” append-only, hash-chained, signed Ed25519; inputs are hashed, never stored. Verify with scopegate audit verify.

Full detail: docs-site/security-model.md.

Telemetry (opt-in, anonymous)

ScopeGate collects nothing by default. If you explicitly opt in (SCOPEGATE_TELEMETRY=1 or {"enabled": true} in ~/.scopegate/telemetry.json), it sends a minimal anonymous event on install, init completion and first tool call: version, OS/arch, Node version, detected harness ids, a random anonymous install id. Never agentId, paths, upstream names, tool args, inputs, or anything derived from your config. Fail-silent by design โ€” telemetry can never break a run. Endpoint: https://telemetry.scopegate.dev/v1/event (override with SCOPEGATE_TELEMETRY_ENDPOINT for self-hosting). The full payload contract lives in src/telemetry/telemetry.ts.

Documentation

Contributing & license

See CONTRIBUTING.md for dev setup, tests and e2e.

Licensed under Apache-2.0 (LICENSE). Deliberate choice: the gateway core is open and permissive because adoption by agents and enterprises demands zero legal friction โ€” the future commercial moat is the cloud management plane, not the proxy. Dependency licenses (@modelcontextprotocol/sdk, commander, picomatch, yaml, @aws-sdk/client-sts) are all permissive (MIT/Apache-2.0) and compatible.

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/NexgenSystemsMX/scopegate'

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