The MCP Control Plane for Agentic Coding
Vision turns MCP servers from a configuration nightmare into a managed, agent-accessible control plane. One daemon. One config. Full agent autonomy with complete operator oversight.
Using MCP servers with AI coding agents today means:
- Scattered configurations — Each project has its own MCP setup, duplicated across machines
- Manual process management — Servers crash silently, requiring manual restarts
- No visibility — Which tools are running? What's failing? No central place to look
- Transport chaos — stdio servers can't be shared across clients without a proxy layer
Vision is a Go-native daemon that provides:
| Capability | What It Means |
|---|---|
| Centralized Registry | One YAML file (~/.config/vision/servers.yaml) defines all your MCP servers |
| Process Supervision | Managed HTTP children run under a suture supervisor with automatic restarts and backoff; the session manager owns and respawns stdio subprocesses without supervision |
| Streamable HTTP Proxy | Each stdio server has a dedicated port. Sessions share one subprocess by default; stateful: true or a slot_groups pool opts into per-session subprocesses |
| Automatic Respawn | An unavailable stdio subprocess can be replaced before dispatch on the next request. Vision never replays a request after uncertain downstream execution; an expired shared-mode session returns 404 and the client must re-initialize |
| Stdio Forwarding | Forwards tool listing and calls, tool-list changes, logging messages, and progress notifications; resources and prompts are not forwarded |
| Agent Self-Management | AI agents can inspect, restart, and remove configured servers through the Admin MCP API |
| Hot Reload | Update configuration without restarting your coding session |
Vision turns any MCP-compatible agent into a high-agency system with guardrails:
You: "Research best practices for React Server Components"
Agent: [Context7 call fails — calls vision_list, context7 reports error]
Agent: [Calls vision_restart("context7")]
Agent: [Context7 is running again — proceeds with research]
No human intervention. No config file edits. The agent repairs the tools it was given.
But you stay in control:
- All servers are defined in your central config
- Agents cannot install new servers; every server comes from your config
- Process lifecycle events are logged; managed HTTP children are supervisor-restarted, and stdio subprocesses respawn on use or on a failed shared-mode health probe
- One
vision daemon statusshows everything
| Feature | Vision | MCP Gateway | Direct Config |
|---|---|---|---|
| Agent self-management | Yes | No | No |
| Process supervision | Managed HTTP children only | Varies | No |
| Automatic restarts | Managed HTTP supervisor; stdio respawn on use | Varies | No |
| Hot reload | Yes | No | No |
| Central config | Yes | Yes | No (per-project) |
| Streamable HTTP proxy | Yes | Some | No |
| Per-session isolation | Opt-in (stateful: true or slot groups) |
No | Per client |
| Admin MCP API | Yes | No | N/A |
| Single binary | Yes | Varies | N/A |
# Install Vision
curl -fsSL https://raw.githubusercontent.com/Sharper-Flow/Vision-MCP-Manager/trunk/scripts/install.sh | bash
# Start the daemon (with example servers)
vision daemon start -d
# Add the Vision remote to OpenCode's project `opencode.jsonc` or global
# `~/.config/opencode/opencode.jsonc` configuration.Your AI agent can now connect to Vision-managed servers at http://localhost:627X/mcp.
curl -fsSL https://raw.githubusercontent.com/Sharper-Flow/Vision-MCP-Manager/trunk/scripts/install.sh | bashThe installer downloads the latest binary, places it in ~/.local/bin by default (or /usr/local/bin with --system), and creates the configuration directory.
When it installs the systemd unit, it also captures your current PATH so shell-managed MCP binaries (for example pyenv, nvm, or uvx tools) remain spawnable under systemd.
Options:
--system— Install system-wide (requires sudo)--no-service— Skip systemd service installation--opencode— Configure OpenCode when no global config exists
git clone https://github.com/Sharper-Flow/Vision-MCP-Manager.git
cd Vision-MCP-Manager
make build
sudo cp bin/vision /usr/local/bin/Requirements: Go 1.24+
For always-on operation, install the systemd user service:
mkdir -p ~/.config/systemd/user
cp scripts/vision-user.service ~/.config/systemd/user/vision.service
systemctl --user daemon-reload
systemctl --user enable --now visionIf your MCP commands live outside the default systemd path, reinstall with scripts/install.sh or add a matching PATH to ~/.config/systemd/user/vision.service before starting the daemon.
Vision maintains a central registry at ~/.config/vision/servers.yaml:
servers:
# Context7 - Library documentation lookup
context7:
port: 6276
command: context7-mcp
args: []
env:
CONTEXT7_API_KEY: "${CONTEXT7_API_KEY}"
autostart: true
session_timeout: 30m # How long idle sessions live (default: 30m)
# Kagi - Web search and summarization
kagi:
port: 6279
command: uvx
args: ["--python", "3.12", "kagimcp"]
env:
KAGI_API_KEY: "${KAGI_API_KEY}"
autostart: true
# Time - Timezone utilities
time:
port: 6282
command: uvx
args: ["mcp-server-time", "--local-timezone=America/New_York"]
autostart: trueSession lifecycle: Idle sessions are reaped after
session_timeout(default 30m). For shared-mode stdio, only structurally valid, non-pingJSON-RPC requests refresh activity, and an expired upstream session requires a new initialize request. A stateful session can respawn its subprocess before dispatch on a later tool call.
Availability profiles: Set
availability_profile: networkedfor servers backed by upstream web/API providers. Vision applies availability defaults for timeouts, retries, circuit breakers, cache, and in-flight limits. The profile does not change the isolation model.
Slot groups: For servers that need concurrent process-per-session isolation (e.g. Playwright browser automation), declare a
slot_groupspool inservers.yaml. Vision expands the pool into identical slots behind a single virtual port and transparently routes each session to the least-loaded healthy slot — agents connect to one endpoint and never see the underlying processes. See Configuration Reference for the full schema and examples.
Store API keys in ~/.config/vision/.env and reference them via ${VAR} in servers.yaml:
# ~/.config/vision/.env (0600 permissions)
CONTEXT7_API_KEY=your-context7-key
KAGI_API_KEY=your-kagi-key# ~/.config/vision/servers.yaml
env:
CONTEXT7_API_KEY: "${CONTEXT7_API_KEY}"Vision loads .env before parsing the config, so ${VAR} expansion works regardless of how the daemon is started (foreground, background, systemd). The .env file should have 0600 permissions since it contains secrets.
Important: After changing
.env, reload is not always sufficient for already-running downstream subprocesses. New spawns will use the updated values, but long-lived MCP server processes may keep the old environment until they are restarted. After rotating API keys or tokens, prefer a fullvision daemon restartflow (vision daemon stop→vision daemon start) or restart the affected server/session before validating the change.
Configure producer-owned remote MCP endpoints directly in your client. Vision accepts transport: http and transport: sse entries in config validation, but their placeholder service binds no port and forwards nothing.
Connect any MCP-compatible client to Vision-managed servers via Streamable HTTP:
{
"mcp": {
"vision": {
"type": "remote",
"url": "http://localhost:6275/mcp",
"enabled": true
},
"context7": {
"type": "remote",
"url": "http://localhost:6276/mcp",
"enabled": true
},
"kagi": {
"type": "remote",
"url": "http://localhost:6279/mcp",
"enabled": true
}
}
}For OpenCode, place this declaration in the project opencode.json/
opencode.jsonc, or in ~/.config/opencode/opencode.jsonc for global use.
When the Vision OpenCode plugin's vision_init omits path, it detects a sole
existing root opencode.jsonc/opencode.json or
.opencode/opencode.jsonc/.opencode/opencode.json; with none it uses root
opencode.jsonc, and with multiple it requires an explicit path. Explicit
relative plugin paths resolve against the project directory, while direct Admin
MCP callers must pass an absolute path. Existing JSONC comments and trailing
commas are preserved during reconciliation.
Vision's ~/.config/vision/servers.yaml can be written by external configuration tools as well as edited by hand.
Contract for external writers:
servers.yamlis authoritative on reload. Vision does not merge with prior state — what's in the file is what runs.- Use atomic writes (write to a temp file in the same directory, then rename).
- Validate against the documented schema (
internal/config/schema.go) before writing. - Preserve unknown but reserved fields (e.g.
source,description,retry.*,circuit_breaker.*) on round-trip when re-rendering from a higher-level source. - The admin HTTP surface at
http://127.0.0.1:6275exposes stable integration endpoints:GET /version(capability contract),GET /health(aggregate status),GET /v1/servers(per-server status), andGET /v1/servers/{name}(single server detail). - Check
GET /versionfor theapi.*capability flags before calling endpoints — this lets external tools feature-detect without pinning Vision versions.
Vision's killer feature: agents can manage their own tools.
The Admin MCP Server (port 6275) exposes these tools to your AI agent:
| Tool | What It Does |
|---|---|
vision_list |
Show all servers with effective status (running, starting, stopped, or error) |
vision_restart |
Restart a configured server, keeping its port |
vision_remove |
Stop and remove a server |
vision_status |
Daemon health, uptime, memory usage |
vision_guidance |
Get recommendations for which tool to use |
Example workflow:
- A
kagiweb search call fails - Agent calls
vision_list→kagireportserrorwith its cause - Agent calls
vision_restart("kagi")→ server restarts on the same port - Agent retries the search
- You see the same state in
vision_list— full visibility
┌─────────────────────────────────────────────────────────────────┐
│ AI Agents │
│ (OpenCode, Claude Code, Cursor, etc.) │
└───────────────────────────────┬─────────────────────────────────┘
│ HTTP POST/GET/DELETE /mcp
▼
┌─────────────────────────────────────────────────────────────────┐
│ Vision Daemon │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Admin MCP Server (:6275) │ │
│ │ vision_list vision_restart vision_status ... │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Streamable HTTP Proxy Layer │ │
│ │ │ │
│ │ :6276/mcp ──[session A]──┐ │ │
│ │ ──[session B]──┴─> shared subprocess │ │
│ │ │ │
│ │ stdio default: shared; stateful: true: per session │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Process Supervisor (managed HTTP children only) │ │
│ │ Automatic restarts · Backoff │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Key components:
- Admin MCP Server — Lets agents manage their own tooling without human intervention
- Streamable HTTP Proxy — Stdio sessions share a subprocess by default;
stateful: truegives each session its own. Tools, resources, and prompts are discovered dynamically. An unavailable subprocess can be respawned before dispatch on a later request, without replaying uncertain operations - Process Supervisor — Uses suture for automatic restarts with backoff for managed HTTP children
- Security Middleware — Bearer auth, origin allowlist, rate limiting, body size caps, and session admission control
High-agency doesn't mean black-box. Vision gives you:
- Centralized config — Know exactly what tools are available (
~/.config/vision/servers.yaml) - Process visibility — Lifecycle events are logged. The supervisor restarts managed HTTP children; stdio subprocesses respawn on use or when a shared-mode health probe detects a dead subprocess
- Single daemon — One place to check status:
vision daemon status - Dedicated ports — Each stdio or managed HTTP server has its own port for security and debugging
- Hot reload — Update config without disrupting active sessions:
vision daemon reload
vision daemon start # Start in foreground
vision daemon start -d # Start daemonized
vision daemon stop # Graceful shutdown
vision daemon status # Health, uptime, memory, failing servers
vision daemon reload # Hot-reload config (SIGHUP)Server management is provided by the Admin MCP tools on port 6275. Use
vision_list, vision_remove, and vision_restart through the
OpenCode plugin or a direct MCP client.
Client configuration generation is provided by the OpenCode plugin's
vision_init tool, not the Vision CLI. With path omitted, the plugin detects a
sole existing recognized project config (root opencode.jsonc/opencode.json
or .opencode/opencode.jsonc/.opencode/opencode.json), uses root
opencode.jsonc when none exists, and requires an explicit path when multiple
exist. Relative plugin paths resolve against the project directory; direct
Admin MCP callers must provide an absolute path.
| Symptom | Solution |
|---|---|
| Server not responding | vision daemon status — check if daemon is running |
| Server keeps crashing | Check logs: journalctl --user -u vision -f |
| Config changes not applied | Run vision daemon reload |
| Port already in use | Check for conflicts: lsof -i :6276 |
| "downstream session unavailable" | The downstream subprocess closed and could not be replaced. A reaped shared-mode session answers 404 instead, and the client initializes a new session. If persistent, check journalctl --user -u vision for respawn errors |
- Configuration Reference — Complete server options
- AI Agents Guide — Deep dive into agent integration
- MCP Transports — Streamable HTTP proxy and subprocess models
- MCP 2026-07-28 Alignment Decision — Stateless transport migration and isolation stance
- Development Guide — Building and contributing
- Structured audit logging for session lifecycle and security events
- Per-session admission controls (max concurrent sessions, idle timeout, TTL)
- Automatic downstream respawn on idle reap or crash
- Document MCP 2026-07-28 alignment and migration trigger
- Usage analytics dashboard
- Multi-machine sync
MIT License — see LICENSE for details.
Built with Go. Designed for agentic coding.
