jonwraymond/PrismGate

Rust MCP gateway — shared daemon, progressive tool discovery, per-session instance pools, memory tracking

Rust

2

236 commits

updated Sep 14, 2026

See the code

README

PrismGate

Shared-daemon MCP gateway that multiplexes many backend servers behind one stable MCP endpoint.

CI License Release

PrismGate is the runtime and binary name. The source repository and release channel live under the PrismGate GitHub project.

Why this exists

Most MCP clients launch one process tree per session. If you configure a few dozen backends, each new terminal or editor session pays the same startup and memory cost again.

PrismGate changes that model:

  • One daemon owns the backend connections.
  • Lightweight proxy processes bridge each client session over stdio.
  • The daemon is reused until it has been idle for the configured timeout.
  • Agents discover backend tools through 13 gateway meta-tools instead of receiving every schema up front.

PrismGate IPC architecture

What it provides

CapabilityWhat the code does today
Shared daemonProxy mode connects to a single Unix socket daemon instead of starting backends per session
Auto-start and restartFirst proxy spawns prismgate serve; prismgate restart drains clients and lets proxies reconnect
Progressive discovery13 meta-tools: search/list/info, call_tool_chain, session search/notes, execute_file, fetch_and_index, result handles
Multiple backend transportsstdio, streamable-http, and cli-adapter backends in one config
Health managementPeriodic pinging, failure thresholds, internal circuit-breaker tracking, restart backoff, pending-backend retry
Tool cacheCached namespaced tools load before backends reconnect; cache version is currently 4
TypeScript executioncall_tool_chain fast-paths JSON/simple calls and falls back to the V8 sandbox when needed
SecretsEnvironment interpolation, .env loading, secretref: resolution, and Bitwarden Secrets Manager integration

Quick start

Install

Download a release from GitHub Releases, or build from source:

git clone https://github.com/jonwraymond/prismgate.git
cd prismgate
cargo install --path .

Configure

The default config path is the platform config directory plus prismgate/config.yaml:

  • macOS/Linux: ~/.config/prismgate/config.yaml
  • Windows: %APPDATA%\\prismgate\\config.yaml

Minimal example:

log_level: info

daemon:
  idle_timeout: 5m

backends:
  exa:
    command: npx
    args: ["-y", "exa-mcp-server"]
    env:
      EXA_API_KEY: "${EXA_API_KEY}"

  github:
    transport: streamable-http
    url: "https://api.githubcopilot.com/mcp/"
    headers:
      Authorization: "Bearer ${GITHUB_PAT_TOKEN}"

For a fuller example covering secrets, CLI adapters, admin settings, and health tuning, see config/example.yaml.

Register PrismGate as an MCP server

Example Claude Code configuration:

{
  "mcpServers": {
    "prismgate": {
      "command": "/path/to/prismgate",
      "args": ["-c", "/path/to/config.yaml"]
    }
  }
}

CLI modes

prismgate            # Proxy mode (default)
prismgate --direct   # Single-process direct mode, no daemon or socket
prismgate serve      # Run the daemon in the foreground
prismgate status     # Read PID/socket state
prismgate stop       # Gracefully stop the daemon
prismgate restart    # Stop, drain clients, let proxies reconnect

Runtime model

The daemon binds its socket early, before the heavier initialization path completes. That means proxies can connect while the daemon is still loading config, resolving secrets, restoring cache, and starting backends.

PrismGate daemon lifecycle

Proxy mode is not just a raw byte pipe. It also:

  • acquires a flock lock to avoid duplicate daemon startup
  • reconnects with backoff if the daemon disappears, while keeping the client stdio session open
  • caches the MCP initialize request and initialized notification
  • replays that cached handshake when reconnecting
  • tracks in-flight JSON-RPC request IDs so daemon restarts become retryable request errors instead of transport loss
  • preserves quiet clients while work is in flight, then uses MCP ping liveness probes to reap nonresponsive idle clients whose stdio pipes were left open by a parent process

PrismGate proxy startup

Discovery model

Backend tools are not exposed as first-class MCP tools. Instead, PrismGate exposes a small discovery and execution surface:

Meta-toolPurpose
search_toolsSearch live registry entries by task description
list_tools_metaPage through registered tool names
tool_infoInspect one tool in brief or full detail
get_required_keys_for_toolShow required env keys for the owning backend
call_tool_chainExecute JSON, simple TS, or full sandboxed TS
register_manualRegister a dynamic backend at runtime
deregister_manualRemove a dynamic backend

Resources and prompts round out the MCP surface:

  • Static resources: prismgate://overview, prismgate://backends, prismgate://tools, prismgate://recent
  • Resource templates: prismgate://tool/{tool_name}, prismgate://backend/{backend_name}, prismgate://backend/{backend_name}/tools, prismgate://recent/{limit}
  • Prompts: discover, find_tool, backend_status

PrismGate progressive discovery

Health and lifecycle behavior

Backend state exposed publicly is limited to:

  • Starting
  • Healthy
  • Unhealthy
  • Stopped

Circuit-breaker timing is tracked internally by the health checker and surfaced through those states rather than a separate public enum.

Current default health settings come from src/config.rs:

  • interval: 30s
  • timeout: 5s
  • failure threshold: 3
  • max restarts per window: 5
  • restart window: 60s
  • restart backoff: 1s initial, 30s max
  • restart timeout: 30s
  • recovery multiplier: 3
  • drain timeout: 10s

PrismGate health checker

Configuration and secrets

Config loading is intentionally simple and code-backed:

  1. Load .env files once.
  2. Read YAML.
  3. Expand environment variables with shellexpand::env.
  4. Deserialize config.
  5. Resolve secretref: values.
  6. Validate required fields and supported transport combinations.

.env files are loaded from:

  1. ~/.env
  2. the standard PrismGate config directory, for example ~/.config/prismgate/.env
  3. the config file's sibling directory

Supported secret modes:

  • direct environment references such as ${EXA_API_KEY}
  • secretref:bws:... with environment fallback when BWS is disabled
  • Bitwarden Secrets Manager when secrets.providers.bws.enabled: true

Documentation

The repo docs were rewritten against the current Rust implementation and diagrams:

Contributing

See CONTRIBUTING.md for development setup, docs build commands, and review expectations.

License

Licensed under the Apache License, Version 2.0.

Contributors

jonwraymond/PrismGate

Rust MCP gateway — shared daemon, progressive tool discovery, per-session instance pools, memory tracking

Rust

2

236 commits

updated Sep 14, 2026

See the code

README

PrismGate

Shared-daemon MCP gateway that multiplexes many backend servers behind one stable MCP endpoint.

CI License Release

PrismGate is the runtime and binary name. The source repository and release channel live under the PrismGate GitHub project.

Why this exists

Most MCP clients launch one process tree per session. If you configure a few dozen backends, each new terminal or editor session pays the same startup and memory cost again.

PrismGate changes that model:

  • One daemon owns the backend connections.
  • Lightweight proxy processes bridge each client session over stdio.
  • The daemon is reused until it has been idle for the configured timeout.
  • Agents discover backend tools through 13 gateway meta-tools instead of receiving every schema up front.

PrismGate IPC architecture

What it provides

CapabilityWhat the code does today
Shared daemonProxy mode connects to a single Unix socket daemon instead of starting backends per session
Auto-start and restartFirst proxy spawns prismgate serve; prismgate restart drains clients and lets proxies reconnect
Progressive discovery13 meta-tools: search/list/info, call_tool_chain, session search/notes, execute_file, fetch_and_index, result handles
Multiple backend transportsstdio, streamable-http, and cli-adapter backends in one config
Health managementPeriodic pinging, failure thresholds, internal circuit-breaker tracking, restart backoff, pending-backend retry
Tool cacheCached namespaced tools load before backends reconnect; cache version is currently 4
TypeScript executioncall_tool_chain fast-paths JSON/simple calls and falls back to the V8 sandbox when needed
SecretsEnvironment interpolation, .env loading, secretref: resolution, and Bitwarden Secrets Manager integration

Quick start

Install

Download a release from GitHub Releases, or build from source:

git clone https://github.com/jonwraymond/prismgate.git
cd prismgate
cargo install --path .

Configure

The default config path is the platform config directory plus prismgate/config.yaml:

  • macOS/Linux: ~/.config/prismgate/config.yaml
  • Windows: %APPDATA%\\prismgate\\config.yaml

Minimal example:

log_level: info

daemon:
  idle_timeout: 5m

backends:
  exa:
    command: npx
    args: ["-y", "exa-mcp-server"]
    env:
      EXA_API_KEY: "${EXA_API_KEY}"

  github:
    transport: streamable-http
    url: "https://api.githubcopilot.com/mcp/"
    headers:
      Authorization: "Bearer ${GITHUB_PAT_TOKEN}"

For a fuller example covering secrets, CLI adapters, admin settings, and health tuning, see config/example.yaml.

Register PrismGate as an MCP server

Example Claude Code configuration:

{
  "mcpServers": {
    "prismgate": {
      "command": "/path/to/prismgate",
      "args": ["-c", "/path/to/config.yaml"]
    }
  }
}

CLI modes

prismgate            # Proxy mode (default)
prismgate --direct   # Single-process direct mode, no daemon or socket
prismgate serve      # Run the daemon in the foreground
prismgate status     # Read PID/socket state
prismgate stop       # Gracefully stop the daemon
prismgate restart    # Stop, drain clients, let proxies reconnect

Runtime model

The daemon binds its socket early, before the heavier initialization path completes. That means proxies can connect while the daemon is still loading config, resolving secrets, restoring cache, and starting backends.

PrismGate daemon lifecycle

Proxy mode is not just a raw byte pipe. It also:

  • acquires a flock lock to avoid duplicate daemon startup
  • reconnects with backoff if the daemon disappears, while keeping the client stdio session open
  • caches the MCP initialize request and initialized notification
  • replays that cached handshake when reconnecting
  • tracks in-flight JSON-RPC request IDs so daemon restarts become retryable request errors instead of transport loss
  • preserves quiet clients while work is in flight, then uses MCP ping liveness probes to reap nonresponsive idle clients whose stdio pipes were left open by a parent process

PrismGate proxy startup

Discovery model

Backend tools are not exposed as first-class MCP tools. Instead, PrismGate exposes a small discovery and execution surface:

Meta-toolPurpose
search_toolsSearch live registry entries by task description
list_tools_metaPage through registered tool names
tool_infoInspect one tool in brief or full detail
get_required_keys_for_toolShow required env keys for the owning backend
call_tool_chainExecute JSON, simple TS, or full sandboxed TS
register_manualRegister a dynamic backend at runtime
deregister_manualRemove a dynamic backend

Resources and prompts round out the MCP surface:

  • Static resources: prismgate://overview, prismgate://backends, prismgate://tools, prismgate://recent
  • Resource templates: prismgate://tool/{tool_name}, prismgate://backend/{backend_name}, prismgate://backend/{backend_name}/tools, prismgate://recent/{limit}
  • Prompts: discover, find_tool, backend_status

PrismGate progressive discovery

Health and lifecycle behavior

Backend state exposed publicly is limited to:

  • Starting
  • Healthy
  • Unhealthy
  • Stopped

Circuit-breaker timing is tracked internally by the health checker and surfaced through those states rather than a separate public enum.

Current default health settings come from src/config.rs:

  • interval: 30s
  • timeout: 5s
  • failure threshold: 3
  • max restarts per window: 5
  • restart window: 60s
  • restart backoff: 1s initial, 30s max
  • restart timeout: 30s
  • recovery multiplier: 3
  • drain timeout: 10s

PrismGate health checker

Configuration and secrets

Config loading is intentionally simple and code-backed:

  1. Load .env files once.
  2. Read YAML.
  3. Expand environment variables with shellexpand::env.
  4. Deserialize config.
  5. Resolve secretref: values.
  6. Validate required fields and supported transport combinations.

.env files are loaded from:

  1. ~/.env
  2. the standard PrismGate config directory, for example ~/.config/prismgate/.env
  3. the config file's sibling directory

Supported secret modes:

  • direct environment references such as ${EXA_API_KEY}
  • secretref:bws:... with environment fallback when BWS is disabled
  • Bitwarden Secrets Manager when secrets.providers.bws.enabled: true

Documentation

The repo docs were rewritten against the current Rust implementation and diagrams:

Contributing

See CONTRIBUTING.md for development setup, docs build commands, and review expectations.

License

Licensed under the Apache License, Version 2.0.

Contributors

Languages

Rust

94.1%

TypeScript

2.5%

HTML

1.2%

Shell

1.0%