MCP Servers for DevOps: The Install Line Is the Security Boundary
Setup guides tell you to run npx -y @anthropic-ai/github-mcp-server. That package does not exist. The useful part of an MCP setup is not the list of servers, it is how you resolve which artifact is really the vendor's.
Every MCP guide is a list of servers, and every list is stale in a quarter. The part that keeps its value is duller: before you paste a command into your agent config, how do you know that the thing about to run on your laptop, holding a token for your production cluster, is the artifact the vendor actually publishes?
That question has a cheap, repeatable answer. It is worth more than any ranking of servers, because it is the step where MCP setups go wrong.
Start with a live example. Guides in circulation, including the earlier version of this page, tell you to run this:
npx -y @anthropic-ai/github-mcp-server
That package does not exist. npm view @anthropic-ai/github-mcp-server returns a 404 from the registry, checked on 23 August 2026. GitHub’s actual MCP server is a Go program in github/github-mcp-server, and the way GitHub tells you to use it is a hosted endpoint at https://api.githubcopilot.com/mcp/ with OAuth, or a local binary or container image. There has never been an npm package under that name.
A command that installs nothing is the harmless version of this failure. The harmful version is a command that installs something, because npx -y resolves a name at the moment you run it and executes whatever is behind it. That is the same mechanism behind the install-script problem npm v12 was built to blunt, except here you are handing the result a cloud credential on purpose.
The name that sounds official usually is not
Terraform is the clean case, because both things exist and they are not the same thing.
There is an npm package called terraform-mcp-server. Ask npm who publishes it:
$ npm view terraform-mcp-server repository.url maintainers time.modified
maintainers = 'thrashr888 <thrashr888@gmail.com>'
time.modified = '2025-03-30T02:43:55.123Z'
No repository URL, one individual maintainer, and nothing published in seventeen months. It is somebody’s early experiment, and there is nothing wrong with that. It is just not what a guide means when it says “HashiCorp’s official Terraform MCP server.”
That one lives at hashicorp/terraform-mcp-server, is MPL 2.0, is written in Go, and had commits this week. It ships as a container image, not an npm package.
The general shape: a vendor with a security team ships a signed artifact under a namespace it controls, usually an OCI image or a hosted endpoint. A registry name that merely reads like the vendor’s is a name, and names are first come, first served.
The registry that resolves identity
The official MCP registry exists to answer exactly this, and it is a plain JSON API. Names are reverse-DNS and tied to a namespace the publisher had to prove control of, and each entry lists the artifacts it actually ships:
$ curl -s "https://registry.modelcontextprotocol.io/v0/servers?search=terraform&limit=5" \
| jq -r '.servers[].server | "\(.name) \(.version) \(.packages // [] | map(.identifier) | join(","))"'
io.github.RajeevSirohi/mcp-server-terraform 0.2.1 @rajsir/mcp-server-terraform
io.github.hashicorp/terraform-mcp-server 0.3.2 docker.io/hashicorp/terraform-mcp-server:0.3.2
io.github.hashicorp/terraform-mcp-server 0.3.3 docker.io/hashicorp/terraform-mcp-server:0.3.3
io.github.hashicorp/terraform-mcp-server 0.4.0 docker.io/hashicorp/terraform-mcp-server:0.4.0
io.github.hashicorp/terraform-mcp-server 0.5.0 docker.io/hashicorp/terraform-mcp-server:0.5.0
Five rows, two publishers, and the namespaces tell you which is which without reading a README. Note that the top hit for the word “terraform” is somebody’s npm package, not HashiCorp’s. The same query for Kubernetes returns io.github.containers/kubernetes-mcp-server with its npm, PyPI, and ghcr.io artifacts side by side, so you can pick the distribution you want and still know it came from the same publisher.
This is the check worth building a habit around. It takes one request and it replaces “this blog said so.”
Remote and OAuth beats a token in a dotfile
Where a vendor offers a hosted server, take it. GitHub’s is https://api.githubcopilot.com/mcp/ and Sentry’s is mcp.sentry.dev. Both authenticate through a browser OAuth flow, which means no personal access token sitting in a config file, no environment variable leaking into a shell history or a crash log, and revocation that works from the vendor’s own UI rather than by editing JSON on every machine.
Local servers still need secrets, so scope them. A GitHub fine-grained token limited to the repositories the agent should see. A Datadog application key with read scopes. For Kubernetes, containers/kubernetes-mcp-server takes a --read-only flag, and behind it a kubeconfig pointing at a ServiceAccount that can do nothing else:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mcp-viewer
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "deployments", "services", "jobs", "configmaps"]
verbs: ["get", "list", "watch"]
Diagnosing a crashloop needs get, list, and watch. It does not need create. If you later decide the agent should apply manifests, that is a separate decision with a separate credential, not a flag you forgot to set.
“Supports MCP” is not a version
The protocol is still moving, and the spec repository keeps its revisions in dated directories: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25, and 2026-07-28. Five revisions in under two years, the most recent one about a month old.
That matters when a server and a client disagree about what they implement. A server pinned to an older revision may not speak the transport your client now prefers, and the failure looks like a hang rather than an error. When something will not connect, the revision each side implements is the first thing to compare, and it is usually in the server’s README rather than its version number.
It is also why pinning matters more here than in ordinary dependencies. npx -y something@latest in an agent config means the tool your agent uses can change under you between two runs of the same prompt, and the thing on the other end holds a credential.
What I would actually set up
Start with one server for a week before adding a second. Each has its own auth model and its own idea of what a tool description should say, and adding five at once means you cannot tell which one is producing the wrong answer.
The order that makes sense for most DevOps work is GitHub first, because reading PRs, workflow runs, and failing job logs is where an agent saves the most time and where read access is genuinely enough. Then whichever of Sentry, Datadog, or Grafana holds your error and metric data, again read-only. Then Terraform’s registry lookups, which are documentation queries rather than state access and cannot break anything. Kubernetes last, read-only, pointed at a cluster you would not mind explaining.
Before each one, the same three lines: search the MCP registry for the canonical name, check the artifact belongs to a namespace the vendor controls, and pin the version. If a guide gives you a bare npx -y line and no way to check who publishes it, that is the tell.