Rust MCP gateway — shared daemon, progressive tool discovery, per-session instance pools, memory tracking
See the code
Shared-daemon MCP gateway that multiplexes many backend servers behind one stable MCP endpoint.
PrismGate is the runtime and binary name. The source repository and release channel live under the PrismGate GitHub project.
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:
| Capability | What the code does today |
|---|---|
| Shared daemon | Proxy mode connects to a single Unix socket daemon instead of starting backends per session |
| Auto-start and restart | First proxy spawns prismgate serve; prismgate restart drains clients and lets proxies reconnect |
| Progressive discovery | 13 meta-tools: search/list/info, call_tool_chain, session search/notes, execute_file, fetch_and_index, result handles |
| Multiple backend transports | stdio, streamable-http, and cli-adapter backends in one config |
| Health management | Periodic pinging, failure thresholds, internal circuit-breaker tracking, restart backoff, pending-backend retry |
| Tool cache | Cached namespaced tools load before backends reconnect; cache version is currently 4 |
| TypeScript execution | call_tool_chain fast-paths JSON/simple calls and falls back to the V8 sandbox when needed |
| Secrets | Environment interpolation, .env loading, secretref: resolution, and Bitwarden Secrets Manager integration |
Download a release from GitHub Releases, or build from source:
git clone https://github.com/jonwraymond/prismgate.git
cd prismgate
cargo install --path .
The default config path is the platform config directory plus prismgate/config.yaml:
~/.config/prismgate/config.yaml%APPDATA%\\prismgate\\config.yamlMinimal 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.
Example Claude Code configuration:
{
"mcpServers": {
"prismgate": {
"command": "/path/to/prismgate",
"args": ["-c", "/path/to/config.yaml"]
}
}
}
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
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.
Proxy mode is not just a raw byte pipe. It also:
ping liveness probes to reap nonresponsive idle clients whose stdio pipes were left open by a parent process
Backend tools are not exposed as first-class MCP tools. Instead, PrismGate exposes a small discovery and execution surface:
| Meta-tool | Purpose |
|---|---|
search_tools | Search live registry entries by task description |
list_tools_meta | Page through registered tool names |
tool_info | Inspect one tool in brief or full detail |
get_required_keys_for_tool | Show required env keys for the owning backend |
call_tool_chain | Execute JSON, simple TS, or full sandboxed TS |
register_manual | Register a dynamic backend at runtime |
deregister_manual | Remove a dynamic backend |
Resources and prompts round out the MCP surface:
prismgate://overview, prismgate://backends, prismgate://tools, prismgate://recentprismgate://tool/{tool_name}, prismgate://backend/{backend_name}, prismgate://backend/{backend_name}/tools, prismgate://recent/{limit}discover, find_tool, backend_status
Backend state exposed publicly is limited to:
StartingHealthyUnhealthyStoppedCircuit-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:
30s5s3560s1s initial, 30s max30s310s
Config loading is intentionally simple and code-backed:
.env files once.shellexpand::env.secretref: values..env files are loaded from:
~/.env~/.config/prismgate/.envSupported secret modes:
${EXA_API_KEY}secretref:bws:... with environment fallback when BWS is disabledsecrets.providers.bws.enabled: trueThe repo docs were rewritten against the current Rust implementation and diagrams:
See CONTRIBUTING.md for development setup, docs build commands, and review expectations.
Licensed under the Apache License, Version 2.0.
Rust
94.1%
TypeScript
2.5%
HTML
1.2%
Shell
1.0%
Rust MCP gateway — shared daemon, progressive tool discovery, per-session instance pools, memory tracking
See the code
Shared-daemon MCP gateway that multiplexes many backend servers behind one stable MCP endpoint.
PrismGate is the runtime and binary name. The source repository and release channel live under the PrismGate GitHub project.
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:
| Capability | What the code does today |
|---|---|
| Shared daemon | Proxy mode connects to a single Unix socket daemon instead of starting backends per session |
| Auto-start and restart | First proxy spawns prismgate serve; prismgate restart drains clients and lets proxies reconnect |
| Progressive discovery | 13 meta-tools: search/list/info, call_tool_chain, session search/notes, execute_file, fetch_and_index, result handles |
| Multiple backend transports | stdio, streamable-http, and cli-adapter backends in one config |
| Health management | Periodic pinging, failure thresholds, internal circuit-breaker tracking, restart backoff, pending-backend retry |
| Tool cache | Cached namespaced tools load before backends reconnect; cache version is currently 4 |
| TypeScript execution | call_tool_chain fast-paths JSON/simple calls and falls back to the V8 sandbox when needed |
| Secrets | Environment interpolation, .env loading, secretref: resolution, and Bitwarden Secrets Manager integration |
Download a release from GitHub Releases, or build from source:
git clone https://github.com/jonwraymond/prismgate.git
cd prismgate
cargo install --path .
The default config path is the platform config directory plus prismgate/config.yaml:
~/.config/prismgate/config.yaml%APPDATA%\\prismgate\\config.yamlMinimal 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.
Example Claude Code configuration:
{
"mcpServers": {
"prismgate": {
"command": "/path/to/prismgate",
"args": ["-c", "/path/to/config.yaml"]
}
}
}
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
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.
Proxy mode is not just a raw byte pipe. It also:
ping liveness probes to reap nonresponsive idle clients whose stdio pipes were left open by a parent process
Backend tools are not exposed as first-class MCP tools. Instead, PrismGate exposes a small discovery and execution surface:
| Meta-tool | Purpose |
|---|---|
search_tools | Search live registry entries by task description |
list_tools_meta | Page through registered tool names |
tool_info | Inspect one tool in brief or full detail |
get_required_keys_for_tool | Show required env keys for the owning backend |
call_tool_chain | Execute JSON, simple TS, or full sandboxed TS |
register_manual | Register a dynamic backend at runtime |
deregister_manual | Remove a dynamic backend |
Resources and prompts round out the MCP surface:
prismgate://overview, prismgate://backends, prismgate://tools, prismgate://recentprismgate://tool/{tool_name}, prismgate://backend/{backend_name}, prismgate://backend/{backend_name}/tools, prismgate://recent/{limit}discover, find_tool, backend_status
Backend state exposed publicly is limited to:
StartingHealthyUnhealthyStoppedCircuit-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:
30s5s3560s1s initial, 30s max30s310s
Config loading is intentionally simple and code-backed:
.env files once.shellexpand::env.secretref: values..env files are loaded from:
~/.env~/.config/prismgate/.envSupported secret modes:
${EXA_API_KEY}secretref:bws:... with environment fallback when BWS is disabledsecrets.providers.bws.enabled: trueThe repo docs were rewritten against the current Rust implementation and diagrams:
See CONTRIBUTING.md for development setup, docs build commands, and review expectations.
Licensed under the Apache License, Version 2.0.
Rust
94.1%
TypeScript
2.5%
HTML
1.2%
Shell
1.0%