Files
vantage-docs/docs/vantage/mcp.md
T
2026-09-10 09:18:57 +00:00

12 KiB

id, title, sidebar_label
id title sidebar_label
mcp Agent access (MCP) Agent access (MCP)

The Model Context Protocol is how an LLM agent - Claude, or any other MCP client - talks to a tool server over a defined wire format instead of a one-off integration. Connecting Vantage to an agent this way lets it answer questions about your fleet and, if you choose to let it, act on it: run a workflow, apply updates, or draft a step for you to review.

:::info Requires the MCP feature on your licence Agent access is a per-instance feature you enable on a paid plan. Without it, /api/mcp answers feature_unavailable and the token form refuses to mint a token carrying an mcp:* scope. See Licensing and entitlements. :::

Minting a token

An agent authenticates the same way any script does: with an API token. Two scopes govern what it can reach on the MCP endpoint specifically, on top of whatever resource scopes (servers:read, workflows:write, and so on) it also needs:

  • mcp:read - permission to reach the MCP endpoint at all and use its read-only tools.
  • mcp:write - permission to use its write tools: running a workflow, applying updates, assigning a key, or creating a step, workflow or monitor.

Without mcp:write, write tools are not merely refused when called - they are left out of the tool listing entirely, so a read-only agent never learns they exist. A tool it cannot see is not one it can talk a user into asking for.

Each tool additionally needs the ordinary resource scope for what it touches

  • run_workflow needs workflows:write, list_servers needs servers:read, and so on, exactly as the scopes table describes for any other token. mcp:read or mcp:write decides whether the MCP surface is open to this token at all; the resource scope decides what it can do once there.

Restricting a token by tag

An agent token benefits from the same tag restriction every API token can carry, and it is the main lever for keeping an agent's blast radius small. A token restricted to env=staging sees only staging hosts from list_servers, gets a not-found error asking about a production host by ID, and cannot run a workflow that would touch one.

Worked example: a staging-only agent token. Create a token with mcp:read, mcp:write, servers:read, workflows:read and workflows:write, restrict it to env=staging, and give it to your agent. It can list and inspect staging servers and run a workflow already configured to target them. Point it at a workflow whose saved targets include even one production host, though, and run_workflow refuses the call outright - see what an agent cannot do below for why that refusal is all-or-nothing rather than "run on the servers it can see."

Connecting a client

Agent access lives at /api/mcp on your instance, over the streamable HTTP transport, and takes a bearer token the same way the REST API does. It has no separate authentication of its own - a browser tab with a signed-in session does not count, only a real API token does.

Point an MCP client at it with a configuration block like this:

{
  "mcpServers": {
    "vantage": {
      "type": "http",
      "url": "https://YOUR-INSTANCE/api/mcp",
      "headers": { "Authorization": "Bearer vt_your_token_here" }
    }
  }
}

The endpoint is stateless and answers POST requests only: it holds no per-connection session, so each call is self-contained and there is nothing to resume. A GET request - a client probing for the endpoint, or a browser navigating to it directly - gets a 405, by design, rather than a page. That is the protocol-correct response from a server that does not offer the GET/SSE half of MCP, not a misconfiguration.

The tool list

Every tool below calls the same service code the REST API and the Vantage UI call. Nothing in this list has its own path to the database - the MCP surface is a presentation layer over existing authority, not a new one.

Tool What it does Scope required
list_servers List servers in the fleet, optionally filtered by tags. mcp:read, servers:read
get_server Get one server's OS, online state and tags. mcp:read, servers:read
list_monitors List monitors and their current state. mcp:read, monitors:read
get_monitor_status Get one monitor's up/down/pending state, last check and last error. mcp:read, monitors:read
list_incidents List monitor incidents (outages), most recent first. mcp:read, monitors:read
get_monitor_samples Get one monitor's recent raw check results. mcp:read, monitors:read
list_workflows List workflows with step count, target count and whether each is scheduled. mcp:read, workflows:read
get_workflow Get one workflow's ordered steps, targets and schedule. mcp:read, workflows:read
get_run Get one workflow run's status and per-server counts. mcp:read, workflows:read
get_run_logs Get the ordered log lines for one server within one run. mcp:read, workflows:read
list_pending_updates List outstanding package updates, fleet-wide or for one server. mcp:read, servers:read
list_vulnerabilities List known CVEs affecting the fleet, one row per CVE/package pair. mcp:read, vulns:read
get_server_packages List installed packages on one server, optionally filtered by name. mcp:read, vulns:read
search_fleet Search every server's installed packages by name across the fleet. mcp:read, vulns:read
list_audit_events List recent audit log events. mcp:read, settings:read
list_secret_names List secret group and key names - metadata only, never a value. mcp:read, secrets:read
run_workflow Run a workflow against the servers it is already saved to target. mcp:write, workflows:write
cancel_run Cancel an in-progress workflow run. mcp:write, workflows:write
apply_updates Apply pending OS package updates on real servers. mcp:write, servers:write
update_agent Trigger the Vantage agent on real servers to update itself. mcp:write, servers:write
assign_key Assign an SSH key to real servers. mcp:write, keys:write
create_step Create a reusable workflow step. mcp:write, workflows:write
create_workflow Create a workflow from existing step IDs. mcp:write, workflows:write
create_monitor Create a monitor, saved disabled. mcp:write, monitors:write

A known limitation worth calling out on search_fleet: its version_below argument is not implemented. Passing it gets you an error explaining that correct version ordering depends on each host's own package manager (dpkg, rpm, apk each order versions differently), which the tool has no way to resolve, so it refuses rather than guess with a naive string comparison. Omit version_below and it returns every matching install instead, for you or the agent to filter.

Running a workflow: targets are fixed, not chosen

run_workflow does not take a target list. A workflow runs the servers and tags it was already saved with - an agent cannot redirect it at a different part of the fleet on the fly. Before starting the run, Vantage checks that those saved targets sit entirely inside the calling token's tag restriction. If even one of them falls outside it, the whole call is refused; there is no partial run against just the servers the token happens to be able to see. A token scoped to env=staging cannot use a production-and-staging workflow to touch only the staging half - it has to be pointed at a workflow whose saved targets are staging-only from the start.

What an agent can create

Three tools let an agent propose new work rather than only look at existing work: create_step, create_workflow and create_monitor. Nothing they create is armed:

  • A created workflow cannot be given a schedule. create_workflow refuses outright if a schedule argument is present at all, so scheduling stays a separate, later decision a human makes in the UI.
  • A created monitor is always saved disabled, regardless of any enabled argument. It checks nothing and alerts nobody until a human turns it on.
  • A created step may not reference a secret. create_step refuses a secret_refs argument, because a script an agent wrote is not something you want run with credentials attached before a person has read it.

create_workflow applies the same two checks run_workflow applies before a run: it refuses to save a workflow whose targets are not entirely inside the token's tag scope, and it refuses (absent confirm:true) to save one whose targets exceed the 25-server fan-out limit. A workflow this token could not later run is never created in the first place.

Steps an agent creates are marked with a source of mcp, which the Vantage UI uses to badge them, so a human reviewing the step library can tell at a glance which scripts came from an agent rather than a person.

There is no tool to update or delete an existing step, workflow or monitor. An agent can add to your instance; it cannot change or remove anything that was already there.

What an agent cannot do

This is the section to read before turning the feature on.

  • It cannot see a secret's plaintext. list_secret_names returns group and key names only; no tool anywhere in the MCP surface returns a secret's value to a model.
  • It cannot open a console or a shell. There is no MCP tool for the browser console, SSH, RDP or VNC. An agent can trigger a workflow step that runs a script, but it cannot open an interactive session on a machine.
  • It cannot exceed its tag restriction. Every tool that resolves servers - by ID, by tag, or through a saved workflow - resolves them through the token's own scope. A server outside that scope is invisible to list_servers and get_server, not-found to anything asking about it by ID, and excluded from what a write tool will act on.
  • It cannot act at all without mcp:write. Every write tool needs it, on top of its own resource scope, and a token that lacks it never even sees those tools in the listing.
  • It cannot touch more than 25 servers in one call without saying so explicitly. Any write tool that would affect more than 25 servers is refused with a message asking for confirm:true before it will proceed - cheap insurance against a mis-parsed tag selector reaching the whole fleet on one badly phrased instruction.
  • It cannot edit or delete anything that already exists. The creation tools only add; there is no MCP tool that updates or removes a step, workflow or monitor a person defined.

A monitor whose runner server sits outside a token's scope is not hidden from that token - it still appears in list_monitors. The REST API reaches that outcome by redacting: it replaces the runner with a RunnerRestricted placeholder when the runner falls outside the caller's visible servers. The MCP tools reach the same outcome a different way - list_monitors and get_monitor_status project a monitor onto a summary that never carries a runner field for any caller, restricted or not, so there is nothing there to redact in the first place. Two mechanisms, chosen so the two surfaces cannot end up disagreeing about what a restricted token learns. A workflow's target list is filtered more directly: servers outside the token's scope are dropped from what get_workflow reports, and a targets_restricted flag says that some were held back, without saying how many.

Every call is audited

Every tool call reaches the audit log, whether it read something or changed something:

  • A successful call - read or write - is recorded as mcp.tool_call.
  • A call refused by policy - missing scope, an out-of-scope target, or a fan-out over 25 servers without confirmation - is recorded as mcp.tool_denied, naming the specific gate that refused it, so a human reading the log can tell "the agent was stopped" from "the agent tried and the underlying action failed."
  • A write tool that reached the underlying service and that service rejected is recorded as mcp.tool_failed.
  • Creating a step, workflow or monitor is recorded separately as mcp.created, naming what was made and its ID - a question like "what has this agent added to my instance" should not require digging through hundreds of read rows to answer.

See the audit log for how to read these alongside everything else on the instance.