Search nomadLab

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.

Updated

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.

Four ways to install an MCP server, split into two groups. The first group names an owner you can verify: the HashiCorp Terraform MCP server as an OCI image in HashiCorp's namespace, and GitHub's hosted endpoint at api.githubcopilot.com slash mcp, which uses OAuth and leaves no token on disk. The second group names only a string on a registry: npx of terraform-mcp-server, which resolves to a single npm account whose last publish was 30 March 2025, and npx of at anthropic-ai slash github-mcp-server, which does not exist and returns a 404. The same setup step, four different trust chains Names an owner you can verify hashicorp/terraform-mcp-server:0.5.0OCI image in HashiCorp's namespace api.githubcopilot.com/mcp/GitHub's endpoint, OAuth, no local token Names a string on a registry npx -y terraform-mcp-serverone npm account, last publish Mar 2025 npx -y @anthropic-ai/github-...no such package, npm returns 404 Both bottom rows appear in setup guides. Neither resolves to the vendor you think.
Checked against the npm registry, the MCP registry, and each vendor's repository on 23 August 2026.

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.

Keep reading