chore: replace em dashes with hyphens, add no-em-dash rule to CLAUDE.md
Deploy / deploy (push) Successful in 2m47s
Deploy / deploy (push) Successful in 2m47s
This commit is contained in:
+22
-22
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user