chore: replace em dashes with hyphens, add no-em-dash rule to CLAUDE.md
Deploy / deploy (push) Successful in 2m47s

This commit is contained in:
2026-09-10 09:18:57 +00:00
parent e8455c99fe
commit 7762629634
22 changed files with 126 additions and 122 deletions
+22 -22
View File
@@ -4,8 +4,8 @@ title: Agent access (MCP)
sidebar_label: 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
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.
@@ -24,18 +24,18 @@ An agent authenticates the same way any script does: with an
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
- **`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,
- **`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
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
- `run_workflow` needs `workflows:write`, `list_servers` needs
`servers:read`, and so on, exactly as the [scopes table](../reference/api-tokens.md#scopes)
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
@@ -56,7 +56,7 @@ and cannot run a workflow that would touch one.
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](#what-an-agent-cannot-do)
call outright - see [what an agent cannot do](#what-an-agent-cannot-do)
below for why that refusal is all-or-nothing rather than "run on the
servers it can see."
@@ -64,7 +64,7 @@ servers it can see."
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
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:
@@ -83,15 +83,15 @@ Point an MCP client at it with a configuration block like this:
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
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
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 |
@@ -111,7 +111,7 @@ surface is a presentation layer over existing authority, not a new one.
| `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` |
| `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` |
@@ -132,13 +132,13 @@ 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
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
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.
@@ -184,7 +184,7 @@ This is the section to read before turning the feature on.
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
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.
@@ -193,7 +193,7 @@ This is the section to read before turning the feature on.
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
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
@@ -201,10 +201,10 @@ This is the section to read before turning the feature on.
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
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
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
@@ -219,16 +219,16 @@ many.
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
- 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
`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.