MCP
Model Context Protocol (MCP) works in both directions in PlanVault™. Inbound, PlanVault™ is itself an MCP server: an AI assistant such as Cursor, Claude Code or Claude Desktop sees exactly four tools and drives your whole governed tool catalog through them. Outbound, PlanVault™ is an MCP client: third-party MCP servers are registered once at organisation level, their tools are synced into the catalog and executed under the same policy, secret, approval and audit boundaries as OpenAPI tools and webhooks.
PlanVault™ as an MCP server (agent server)
Instead of exposing every catalog tool as a separate MCP tool and pushing hundreds of JSON schemas into the assistant's context, PlanVault™ publishes one MCP server with exactly four meta-tools. The assistant describes a task in natural language; planning, tool selection, policy gates, approvals, the execution FSM, diagnostics and audit all stay inside PlanVault™. The MCP layer is only a bridge to the Runtime API.
This keeps the assistant's context small regardless of catalog size — one MCP server, a thousand tools, none of their schemas in the model context — and guarantees that an MCP client can never bypass a gate the console enforces.
The four tools
- discover_capabilitiesReturns a compact, token-bounded map of capability groups with short summaries and operation counts (optional query and depth). It never returns tool JSON schemas.
- executeRuns one task described in natural language (task, optional context, session_id, external_user_id, idempotency_key, max_wait_ms). Call it once per task: the response blocks up to max_wait_ms and then returns a status.
- check_statusPolls a run by run_id, with an optional wait_ms long-poll. Use it after awaiting_approval, awaiting_input or running instead of calling execute again.
- provide_inputSupplies the inputs a run asked for (run_id plus an inputs map). It is not an approve or deny tool.
Run statuses
Every execute and check_status response carries run_id, session_id, a short plan_summary (tool names only), trace_url and one of six statuses:
{
"status": "awaiting_approval",
"run_id": "6f1c…",
"session_id": "0b9a…",
"plan_summary": ["crm.find_customer", "billing.issue_refund"],
"pending_action": "billing.issue_refund",
"display_params": { "customer_id": "C-1042", "amount": "49.00 EUR" },
"approval_url": "https://console.<your-host>/app/orgs/…/sessions/0b9a…",
"poll_after_ms": 5000,
"trace_url": "https://console.<your-host>/app/orgs/…/sessions/0b9a…",
"deduplicated": false
}Connect an MCP client
Hosted Streamable HTTP is the primary transport: one URL, one Bearer key, nothing to install. In the PlanVault™ console (as OWNER or ADMIN) create a project API key scoped to only hrn:project:mcp:execute, then point your client at the MCP endpoint of your deployment (the self-hosted stack serves it at BASE_URL/mcp). The server resolves your project and organisation from the key itself, so nothing tenant-specific lives in the client config.
Cursor — .cursor/mcp.json in the repository or ~/.cursor/mcp.json for all projects; the key is read from the environment so it never sits in the file:
{
"mcpServers": {
"planvault": {
"url": "https://mcp.<your-host>/mcp",
"headers": {
"Authorization": "Bearer ${env:PLANVAULT_MCP_KEY}"
}
}
}
}Claude Code:
claude mcp add --transport http planvault https://mcp.<your-host>/mcp \ --header "Authorization: Bearer sk_live_..."
Claude Desktop — claude_desktop_config.json has no url field and the default Connectors dialog only accepts OAuth, so bridge the remote server through mcp-remote and keep the Bearer value in env:
{
"mcpServers": {
"planvault": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.<your-host>/mcp",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer sk_live_..."
}
}
}
}For local development against a sidecar built from source, the same server also runs over stdio with a fixed PLANVAULT_API_KEY and PLANVAULT_PROJECT_ID per process. Restart the client after saving its config; the four tools appear once the connection is established.
Try it on the demo sandbox
Human-in-the-loop over MCP
Approvals are never granted through MCP. When execute or check_status returns awaiting_approval, a person with the OWNER, ADMIN or DEVELOPER role opens approval_url in the PlanVault™ console, reviews the pending action with its parameters, and approves or rejects it there. The assistant keeps polling check_status until the run reaches a terminal status. Server-side integrators can subscribe to project lifecycle webhooks (session.requires_action, session.completed, session.failed) instead of polling.
A pause survives an API restart: the run resumes from its journal, a repeated approval is idempotent, and exactly one side-effecting tool execution happens per approved action.
No approve/deny tool by design
Idempotency
Every execute is idempotent. Pass idempotency_key explicitly or let PlanVault™ derive one from task, context and session; a repeat inside the deduplication window (15 minutes by default) returns the current status of the same run with deduplicated: true instead of starting a second run. The façade requires Redis for this and refuses to start without it.
Security boundary
Façade endpoints (for your own integrations)
The MCP server is a thin adapter over an opt-in HTTP façade (PLANVAULT_MCP_ENABLED=true) under the project Runtime API. Server-side integrations can call it directly with the same scoped key; the wire format is snake_case.
/api/v1/projects/{projectId}/mcp/executeIdempotent task execution; blocks up to max_wait_ms (cap 60 s) and returns the status union/api/v1/projects/{projectId}/mcp/runs/{runId}/statusRun status with an optional wait_ms long-poll (cap 30 s)/api/v1/projects/{projectId}/mcp/runs/{runId}/inputProvide required inputs; there is no approve or reject on this surface/api/v1/projects/{projectId}/mcp/capabilitiesGrouped, token-bounded capability map without tool JSON schemas/api/v1/mcp/whoamiResolves project_id and org_id from the key aloneConnecting MCP servers as tools
MCP servers are registered in Organisation settings → MCP. Each registered server becomes a source of governed tools: after Sync, every remote tool is a normal catalog entry with a stable identifier, can be enabled per project, participates in adaptive tool selection, and executes through the same FSM, approval gates, secret boundary, diagnostics and audit trail as an OpenAPI tool.
Transports and authentication
Over Streamable HTTP, PlanVault™ performs the MCP initialize handshake, keeps the server session id, and reads the tool list with its annotations and output schemas. It is a headless client: it does not offer sampling, elicitation or roots to the remote server.
Lifecycle in the console
What the planner receives from an MCP server
Credential custody
When a grant lapses
Tokens are refreshed silently before expiry with a one-time retry on 401. If the provider revokes the grant, the tool call fails closed with reconnect_required and the server has to be reconnected in the console; an optional governed re-auth pause can hold the run instead (feature-gated, off by default).
Self-hosted note
The public self-hosted distribution ships both roles of the MCP sidecar image (ghcr.io/planvault/mcp) as optional Compose profiles: mcp publishes the agent server at BASE_URL/mcp through the edge proxy, and mcp_outbound adds the internal-only outbound connector required for oauth servers. stdio, bearer and headers modes work without any profile. If a third-party server accepts a long-lived API key, you can also register it with bearer and a vault reference such as secret:KEY_NAME
Not yet (honest scope)
Related pages
Security & complianceAPI & dataAPIArchitecture