MCP and access 8 October 2026 · edition 20 min read

The gates an AI assistant passes before it changes a server, and what each one stops

An AI assistant connected to your servers composes its requests from text it has read, so one permission is too coarse a control. Hostwatch decides each changing call at several independent gates. This article goes through them, says what each one protects against and where it stops, and lists what remains a person's job.

Published 13 November 2026. Hostwatch engineering review; implementation limits are stated below.

A thin beam of light from a glass lens passing through a row of differently shaped dark metal and glass frames on a long stone plinth before reaching a matte dark server miniature
EDITORIAL IMAGEOriginal AI-generated conceptual illustration, not a product screenshot or production measurement. A changing call has to pass several independent checks of different kinds before it reaches the server. Open full size ↗
01 / 10

An assistant composes its requests from what it has read

A person who restarts a service in a web console has read a screen, made a decision and pressed a button. An AI assistant connected to the same servers works differently. It receives a request in ordinary language, reads whatever seems relevant, such as the service inventory, logs, traffic reports, source files and sometimes a web page, and then composes a series of tool calls from all of it. That text has many authors. Some of it was written by the person who asked. Much of it was written by applications, by colleagues, or by strangers on the internet whose requests ended up in a log. Each call the assistant makes is a product of everything it has read, so the statement “the assistant is allowed to” covers far more situations than the person who granted the access had in mind.

Hostwatch connects assistants to servers through the Model Context Protocol, or MCP, the protocol an assistant's application uses to call tools on a remote service. Four terms are used throughout this article. The assistant is the language model doing the work. The MCP client is the application that runs the assistant and holds its connection, for example a desktop assistant or a coding tool. The control plane is the Hostwatch service that keeps accounts, companies and the list of servers. The agent is the Hostwatch program installed on each server. The MCP specification describes tools as controlled by the model and recommends that a person should always be able to deny a tool invocation. That recommendation is addressed to the MCP client. A server cannot see whether anyone looked at a call before it was sent, so it has to decide each call from facts it can check itself.

Hostwatch therefore makes several decisions instead of one. A call that changes a server passes a series of gates, and each gate answers a different question: whether the request can be expressed at all, on whose behalf it is made, whether that person may change things, whether this particular call was meant as a change, whether this server accepts changes through MCP at the moment, whether the server is still in the state that was inspected, and whether the same request has been made before. A last step records what happened. The gates are independent because they are evaluated in different places against different facts: the catalog in the control plane's code, the token and the role in its account data, the policy on the server. A mistaken or manipulated request has to get past every one of them. Hostwatch also checks the installation's license or subscription before a change, which is a commercial condition and is left out here.

02 / 10

Gate one: a short catalog of named operations

The remote MCP server offers the assistant two tools. The tool search finds operations by topic or category and returns their exact names, each with an access level of read or write. The tool execute runs one operation by name. The operations form a fixed catalog inside the control plane. It contains read operations such as overview, sites, tls_site, traffic, errors and storage, and changing operations for certificate renewal, site and job actions, cleanup, build retention, source builds, image publication, deployments, managed components and their ingress, backups and service migration. When execute receives a name that is missing from the catalog, it refuses the call and tells the caller to use search. The catalog changes with the server version, so the assistant reads the current list through search or from the resource hostwatch://operations and does not rely on remembered names.

The catalog matters most for what it replaces. The control plane and the agents have HTTP interfaces with many routes, and the simplest way to connect an assistant would be one tool that accepts a method, a path and a body. Every route would then be reachable from the day it was added, including routes that nobody reviewed with a text-driven caller in mind. In the catalog, each operation builds its own request. The caller supplies named arguments, and the operation checks them and places them into a route that the operation defines. An identifier may contain only letters, digits, dots, underscores, colons and hyphens. A time window is a whole number of hours from 1 to 168. A site action is one of start, stop, restart, pause and unpause, and a cleanup names one of a fixed set of cache kinds. The caller never writes the route or the method, and the request body is assembled by the operation from the named arguments.

This gate protects against two things. The first is reach. An assistant that guesses an administrative route, or is told about one by something it read, has no way to express the request. The second is review. A catalog of named entries with a read or write label on each can be read by the person who is about to connect an assistant and by whoever examines the connection later. The access level belongs to the operation and does not depend on its arguments, so a read cannot become a change through a cleverly chosen value. Two tools also keep the tool list that the assistant carries in its context short. The cost is that the assistant must search before it acts, and that a task outside the catalog stays impossible through MCP until an operation exists for it.

A matte dark server miniature with a short row of identical unmarked metal cartridges on its front rail, one drawn halfway out, next to a bundle of loose cable ends sealed under a glass cover
EDITORIAL IMAGEOriginal AI-generated conceptual illustration, not a product screenshot or production measurement. The assistant chooses from a short catalog of named operations, while the server's other routes stay out of reach. Open full size ↗
03 / 10

Gate two: OAuth access for one user in one company, with separate read and write scopes

The connection is authorized with OAuth and needs no API key. The MCP client discovers the authorization endpoints from the server's metadata and opens the Hostwatch sign-in page. The person signs in with the configured second factor, or approves a QR code in a Hostwatch iPhone app that is already signed in, chooses one company and approves the access the client asked for. Hostwatch uses the authorization code flow with PKCE, a mechanism that lets only the client which started the sign-in exchange the resulting code for tokens. A code works once and expires after five minutes. An access token lasts one hour, and a refresh token is replaced every time it is used. The result is an authorization for that user in that company. It is separate from the key that enrolls a server's agent and from an installation license, and the assistant receives neither of those.

There are two scopes. The scope hostwatch:read is part of every connection and covers the read operations. The scope hostwatch:write is requested in addition when the assistant should be able to change things, and only an owner of the company can approve it; the consent step refuses the request from any other member. Most of what an assistant does on infrastructure is investigation: it reads health, traffic, errors and certificates and reports what it found. A connection that holds only the read scope cannot be argued into a change by anything the assistant reads, because its token does not permit one. For monitoring and incident review the read scope is enough, and a write-scoped connection can be kept for the sessions that need it.

A token tied to a person behaves differently from a shared key in a configuration file. Hostwatch checks the user's membership in the company and the user's session version on every request, so removing the membership or changing the password ends the assistant's access. A single client can be revoked under Workspace, Connected MCP clients, which leaves other clients, the agents and all service data as they were. Each call is attributable to the person who authorized the connection. Tokens are accepted only in the Authorization header and a browser's session cookie never authorizes an MCP tool request, which closes off the case where a page open in the person's browser borrows their signed-in session. A machine key has no owner, no scope and no end date unless someone remembers to rotate it.

04 / 10

Gates three and four: the owner role and a confirmation on each changing call

A token records who authorized the connection and with which scopes. The role is read from the company's current membership each time a call arrives. A changing operation needs the write scope and the owner role together at that moment. A person who approved a write-scoped connection as an owner and was later made an administrator or a viewer still holds the token and can no longer change anything with it. The owner role is also required for a group of reads: a component's source files, its upload status and build log, the preview of a source build, the list of managed components and their ingress, the durable history of operations and private application measurements. An owner may read these over a read-only connection. Any other member is refused before the agent is contacted. Source code and deployment details can be private without being credentials, and this gate keeps the assistant of a viewer away from them.

Every changing operation also requires the argument confirm with the value true on that same call. Without it the control plane answers that an explicit confirmation is required and forwards nothing to the server. The confirmation belongs to one call. No earlier call, session setting or remembered approval carries over, and a call that leaves the argument out counts as unconfirmed. This protects against changes made by omission or by exploration. An assistant that calls an operation to see what it returns gets a refusal where it might have caused an effect. The argument also puts a plain field into the request, so an MCP client that displays tool inputs has something unambiguous to display.

The limit of this gate should be stated plainly. The assistant's side sets the argument, and the server cannot tell whether a person saw the call. The MCP specification recommends that clients prompt the user for confirmation on sensitive operations and show tool inputs before sending them, and that prompt in the MCP client is where a person actually decides. The two parts work together: the argument marks which calls are changes, and the prompt puts those calls in front of someone. An MCP client configured to approve every call automatically removes the second part. For a connection that holds the write scope, that setting deserves a deliberate choice.

05 / 10

Gate five: a governance policy on each server that the MCP client cannot change

The gates described so far are decided in the control plane. The next one is decided on the server. Before the control plane forwards an operation to an agent, it asks that agent for authorization. It sends the operation's name, whether the operation reads or changes, the names of the arguments without their values, and who is asking: the user, the name of the MCP client and its client identifier. The agent answers from its MCP governance policy, a small group of settings stored on that server. The policy can turn MCP off for the server, allow or deny reads and changes separately, block individual operations by name and cap the number of changes accepted per hour. A denied request comes back with its reason, for example that changes are disabled, that a named tool is blocked or that the hourly change limit has been reached. The agent consults the policy again when the operation itself arrives, and for several groups of operations it also checks that the operation's name matches the route and method being used.

The policy applies to one server and sits outside the assistant's reach. The catalog contains mcp_governance, a read operation that returns the current permissions and restrictions, and it contains no operation that changes them. The agent refuses a request that identifies itself as MCP and tries to change governance or to read the history of other clients. The operator, meaning the person who administers the server and its agent, edits the policy in the agent's settings. This gives the person responsible for a server a control that does not depend on who holds which token. A production server can accept reads only while a test server accepts changes. Changes can be switched off for the duration of a migration or a holiday. A single operation such as deployment_delete can be blocked where nobody should remove a deployment through an assistant. The hourly cap limits what an assistant stuck in a loop can do, since a correct-looking change repeated many times is still a fault.

Three limits are worth knowing. As the agent ships, the policy allows both reads and changes and sets no hourly cap, so the restrictions exist only after an operator has set them. The policy governs requests that arrive as MCP. The agent's own credential also authorizes its administrator interface directly, so governance is no barrier against someone who holds that credential and deliberately goes around MCP. An assistant on the remote connection never receives that credential, which should be protected as an administrator secret and kept out of prompts. Finally, operations that run inside the control plane for the whole company, such as the list of servers, have no single server to ask. A service migration asks every server it involves, and compute jobs are checked in the control plane against the machines enrolled in the company.

A glowing light conduit running from a glass lens on one stone plinth to a second plinth, where a dark metal shutter block with a hand lever on the server's side stops the light in front of a matte dark server miniature
EDITORIAL IMAGEOriginal AI-generated conceptual illustration, not a product screenshot or production measurement. The governance policy sits on the server itself, where the MCP client cannot change it. Open full size ↗
06 / 10

Gates six and seven: the preview revision and the idempotency key

The next two gates deal with time and are applied to the change itself. An assistant's work is spread over many calls. It locates a component, reads its state, perhaps waits for a person's approval, and then acts. The state can move in the meantime, because another operator published an image or an urgent fix replaced a container. Hostwatch previews therefore return concrete identities, such as an image digest, together with a revision that stands for the inspected state. The changing call has to carry those values back. The operation deployment_update takes the source digest and the revision from deployment_preview. The operation component_ingress takes the revision from its own preview, a retention run takes the revision of the retention preview, and an update of a registry tag takes the published digest that the preview reported. When the state no longer matches, the call is refused and the assistant previews again.

This matters for an assistant because an approval refers to what was shown. A person who reads a preview and agrees has agreed to that change against that state. Without the binding, the approval would pass silently to whatever the server looks like when the call arrives. For a new managed component the revision covers the request as well, so a call whose fields differ from the previewed ones is refused. The check has a stated limit. For registry publication the agent rechecks the source image and the registry immediately before it acts and verifies the result afterwards, which detects a stale preview and does not amount to a registry-wide lock against other publishers. A refusal caused by changed state is information to read, and the article on service placement describes how to act on it.

Operations that start a job also take an idempotency key, an identifier the caller chooses once for one intended change. A network failure can lose the response to a request that the server accepted. Retrying is the right reflex for a read and the wrong one for a deployment, and an assistant retries readily. With a stable key the retry is harmless: the same arguments with the same key return the existing job, and a key reused with different arguments is rejected. After a lost response the assistant reads the job by its key, using image_publish_status for builds, publications and deployments, and reports the state it finds. An agent restart or an uncertain write is reported as outcome_unknown. That state calls for inspecting the registry or the runtime first, and an unknown outcome is never replayed blindly under a new key. For changing operations on releases, services and traffic protection, the control plane also marks a result whose state is failed, rejected, rolled back, rollback failed or unknown as an error, so the MCP client does not receive it looking like a success.

07 / 10

The eighth gate refuses nothing: the audit log and the server's own history

Simple actions, such as restarting a site, running a scheduled job or requesting a certificate renewal, have neither a preview revision nor an idempotency key, and pass only the first five gates. Every changing call reaches the last gate, which refuses nothing. When a changing call has passed the others and returned, the control plane writes an entry to the Hostwatch audit log with the user, the company, the operation's name and the server the call was addressed to. For an operation that runs as a job, the entry marks that the change was accepted. The outcome is in the job's own durable record, which is one more reason to follow a job to its final state. Revoking a connected MCP client is written to the same log. Separately, the agent on each server keeps a bounded history of the MCP requests it was asked to authorize, allowed and denied, with the client's identity, the operation's name and the names of its arguments. Argument values are left out, so the history cannot turn into a store of sensitive data.

A record prevents nothing, and its value lies in making the other gates reviewable. An owner can see which changes arrived through an assistant and under whose authorization. An operator can see on the server which client asked for what and which requests were turned away, and can then judge whether the policy on that server is too loose or too strict. Both records describe requests. They show that a deployment was asked for and by whom, and they leave the question of whether the application works afterwards to verification. The MCP specification asks clients to log tool usage as well. Where the MCP client keeps such a log, a session has three accounts that can be compared.

08 / 10

What the catalog deliberately leaves out

Several things have no operation in the remote catalog, and each absence is a decision. Secret values and environment exports are unavailable. No operation accepts a shell command. Responses from an agent are limited in size, and before they reach the MCP client the control plane removes fields whose names indicate passwords, secrets, tokens, private keys, cookies or authorization data, and redacts bearer tokens and credential assignments that appear inside text. The process view reports CPU, memory and ownership for each process and leaves out command-line arguments, environment variables and executable paths. Source inspection excludes credential paths, and a source upload that contains them is rejected.

Changing operations work on things the operator has configured in advance. A release is addressed to a target, which is the operator's profile for one component with its build recipe, registry destination, container settings and health check. The caller selects the target and cannot supply a registry address, an image reference, a credential, a mount, a port mapping or a command. Cleanup takes the name of a previewed cache kind and accepts neither a file path nor a general prune. Backups run an installed profile and take no path, command, host or secret. A new site is derived from a template the operator approved, which the article on managed components describes in detail. Where a path does appear as an argument, its use is narrow: the disk usage report accepts a path to measure, and source operations take relative paths inside the component's own approved source tree.

The reasoning goes back to the first section. An operation that accepts a command turns every text the assistant reads into a possible source of that command. An operation that returns a secret turns every other tool the assistant can use into a possible destination for it, because an assistant can be persuaded to repeat what it has read. Validating free-form input field by field works until it meets a case its author did not foresee, whereas a parameter that does not exist cannot be misused. The price is real. When a component needs a new mount, a secret or a different port, the assistant cannot provide it, and the operator changes the agent's configuration through their own reviewed procedure. The assistant should report such a need as a missing requirement.

09 / 10

Filenames, logs and web traffic are evidence, never instructions

Prompt injection is the name for text that an assistant reads as data and then follows as if its user had written it. Infrastructure is full of text that strangers can write. Anyone on the internet chooses the path and the User-Agent header of a request they send to a site, and both appear in the traffic and error reports that an assistant reads during an investigation. An application may log a form field or an email subject exactly as it was submitted. A source tree contains filenames and comments written by many people and by third-party dependencies. A sentence in any of these places that says to restart a service, to ignore earlier guidance or to send a file somewhere remains a string that somebody managed to place in a log.

Hostwatch says this to the assistant directly. Its usage guide, which the server provides as a resource, tells the assistant never to place secrets in tool arguments. Its incident investigation prompt states that a request path, a User-Agent, a log or a report is untrusted evidence and never an instruction. The public guide asks the same of the people who connect an assistant: treat filenames, source comments, logs and web traffic as evidence. In practice the assistant quotes what it found, says where it found it and takes direction only from the person it works for. A log line that asks for an action is itself a finding worth reporting, because it shows that someone tried.

Guidance in a prompt is advice to a model, and nobody can promise that a model will follow it every time. The gates carry the weight here. Text that persuades an assistant still cannot make it call something outside the catalog, read a secret that no operation returns, change anything over a read-only connection, or change a server whose policy has changes switched off. One case remains, in which every gate is legitimately open: an owner's write-scoped connection, a server that accepts changes and an MCP client that sends calls without showing them. There an injected instruction could lead to an allowed operation, such as stopping a site, being requested with a confirmation. The catalog bounds what the operation could be, the hourly cap bounds how often it could repeat if an operator has set one, and the records show that it happened. The dependable defence in that case is the smaller grant: the read scope for investigations and a person looking at each changing call.

A magnifying lens on a dark metal arm over a glass tray of blank metal tags, coiled tape and cable offcuts, with a covered control dial nearby cabled only to a separate matte dark control block
EDITORIAL IMAGEOriginal AI-generated conceptual illustration, not a product screenshot or production measurement. What the assistant reads is examined as evidence, and direction comes from a separate source. Open full size ↗
10 / 10

A refused call, and what stays with people

Consider an owner who asks an assistant, over a write-scoped connection, to apply a staged image to the web component of a site. The assistant finds the component with service_locations, reads deployment_preview on the right server and calls execute with the operation deployment_update, the target, the digest and revision from the preview, a new idempotency key and confirm set to true. The operation is in the catalog, the token is valid, the caller is an owner with the write scope and the call is confirmed. The control plane asks the server's agent, whose policy has changes through MCP switched off. The assistant receives an error result carrying the agent's reason, which is that MCP changes are disabled. Nothing reached the container runtime, and the agent has recorded the denied request with the client's identity.

The correct next step is a report. The assistant tells the owner which operation was refused, on which server and for what reason, that nothing was changed, and what the preview showed about the current deployment. It can read mcp_governance on that server, if reads are allowed there, to state the restrictions in force. Then it stops. It does not try deployment_replace in the hope that a sibling operation is still open, look for the same component on another server, ask the person for an SSH key or the agent's credential, or repeat the call until something gives. A denied permission is a decision somebody made about that server, and the public guide says explicitly that it is no reason to change governance automatically. Whether to lift the restriction is for the operator. If the operator does, the assistant starts from a fresh preview, because the state may have moved while the question was open. Other refusals have equally plain answers: an unknown operation means searching the catalog, a missing scope or role means asking an owner to decide about the connection, and a stale revision means previewing again and comparing.

The gates decide whether a requested change may proceed. Whether it should have been requested is a separate matter, and several responsibilities stay outside the catalog altogether. DNS records are changed by whoever controls the domain; Hostwatch checks where a name resolves and does not edit it. Operating-system administration, including package updates, SSH access and the agent's own credential, belongs to the server owner. Backups can be run and verified through the catalog only where an operator has installed a reviewed backup profile. Choosing what to protect, where the copies are kept and whether a restore is good enough remains human work, and the article on recovery evidence for manual releases covers it. Operators install the targets, templates and secrets that make any operation possible. Someone also has to decide what is worth changing. An assistant can collect the evidence and propose a plan, while the person who owns the service accepts the risk and judges the result.

THE TAKEAWAY

Decide an assistant's access in several independent places: a catalog that limits what can be asked, a token that says who is asking and with which scope, a role, a confirmation on each change, a policy on each server, and state and retry checks on the change itself. Keep a record, grant the read scope by default, and treat a refusal as an answer to report.

Further reading

UP NEXT / Engineering / distributed AIWeavatrix Hetero and Hostwatch: private distributed AI across Mac and Linux