Security Engineering

Reviewing Third-Party MCP Servers Before You Install Them

David Guzenburg/ / 8 min read

Installing a browser extension shows you a permissions warning. Installing an MCP server is three lines in a config file — and it is the larger decision.

MCPsupply chainreview processgovernance

An install is a trust decision that does not feel like one

Adding an MCP server is three lines in a config file. Installing a browser extension involves a permissions screen, a warning, and a deliberate click. The second is a smaller decision than the first, and it is presented far more seriously.

With over 18,000 servers listed publicly by early 2026 and thirty-plus CVEs filed against them in a two-month window, the gap between how the decision feels and what it commits you to is where most real exposure lives.

What follows is a review process short enough that people will actually run it. A checklist nobody completes is worth nothing.

Tier the review to the access

Not every server warrants the same scrutiny. Sort by what it can reach.

TierExamplesReview
LowFormatters, calculators — no I/O, no credentialsSkim the descriptions
MediumRead-only APIs, docs lookupsFull checklist below
HighFilesystem, shell, write access to any systemFull checklist plus source read
CriticalProduction, deploy, payments, customer dataAll the above plus a second reviewer

Most servers land in medium. The tiering matters because it stops the process collapsing under its own weight — the alternative is one heavy checklist that gets skipped entirely.

The checklist

Publisher

The second question resolves a surprising number of cases quickly. An official server from the company whose service it wraps is a materially different proposition from a third-party wrapper — they have a reputational stake and you already have a relationship with them.

Source

Behaviour

Descriptions

Dump the tool list and read the descriptions as text:

# List every tool and description from a server, for human reading
mcp-inspect list-tools --server "$1" --format json \
  | jq -r '.tools[] | "── \(.name)\n\(.description)\n"'

You are looking for one thing: instructions addressed to the model rather than descriptions addressed to you. A description says what the tool does. Anything telling the agent to do something first, to read something else, or to behave in a particular way, is a finding — regardless of how benign the stated reason.

Thirty seconds, best ratio in the process

Of everything on this list, reading the descriptions takes the least time and catches the most obviously hostile servers. If your team adopts one habit, adopt this one.

After approval

Review establishes what the server looked like at one moment. Three things keep that from decaying:

Pin the version. Not latest. A specific version or digest, upgraded deliberately.

Pin the tool fingerprint. Hash the definitions at approval, compare on connect, and require re-review when they change.

Scope the runtime. A container, minimal mounts, egress limited to the hosts the server actually needs. This is the control that keeps working when the review turns out to have been wrong.

What internal servers change, and what they don't

A server your own team wrote removes the publisher question and the supply -chain question. It removes neither of the other two.

Scope still matters. An internal server wrapping your production database with full write access is the highest-risk thing on your list regardless of who wrote it. Trustworthy authorship does not shrink blast radius.

Descriptions still enter the context. An internal server returning customer-supplied content — support tickets, uploaded documents, form submissions — is a channel for untrusted text even though the code is yours. The server is trusted; its output is not.

The practical adjustment is to review internal servers on the second half of the checklist only: what does it reach, what credentials does it need, and what untrusted content can flow through it. That takes minutes and catches the case teams reliably miss, which is a well-written internal tool that faithfully delivers hostile input into an agent's context.

Keep a register

A file in a repository, reviewed like anything else:

| Server        | Tier     | Publisher    | Approved   | Reviewer | Pin      |
|---------------|----------|--------------|------------|----------|----------|
| github        | high     | GitHub       | 2026-03-11 | @jsung   | v0.4.2   |
| postgres-ro   | high     | internal     | 2026-04-02 | @jsung   | v1.1.0   |
| jira          | medium   | Atlassian    | 2026-05-20 | @mchen   | v2.0.1   |
| pdf-extract   | medium   | third party  | 2026-06-14 | @mchen   | v0.9.3   |

Removed:
| slack-unofficial | 2026-05-02 | removed: telemetry to undisclosed host |

The removals section is worth as much as the approvals. It records what you learned and stops the same server being re-added in six months by someone who was not there.

Removal is part of the process

Server lists only grow, for the same reason context files only grow: adding is easy to justify and removing is not. But an unused server is pure cost — its tool definitions occupy context on every session, and its capabilities remain reachable if it is ever compromised.

Give the register a review cadence. Quarterly is enough. Three questions per row:

The third is the one that catches real drift. A server approved as a read-only lookup that added write tools in version 2 is not the server you approved, and nothing in the upgrade will have told you.

The uncomfortable question to end on

Ask periodically: if this server were malicious, what would happen? Not "is it malicious" — you cannot know that. Assume it is, and trace the consequence.

If the answer is "it could read our source and send it anywhere", the containment is inadequate regardless of how trustworthy the publisher looks. If it is "it could return misleading text into the context, and it cannot reach anything else", you have built something that survives being wrong about the publisher. That is the only kind of safety available here.

Takeaway

Tier review by access so the process actually gets run. Read the tool descriptions looking for instructions rather than descriptions — thirty seconds, best return in the whole process. Then pin the version and the fingerprint, contain the runtime, and keep a register that records removals as well as approvals.

Keep reading
Security Engineering

Capability Attestation and Tool Poisoning: Trusting What a Server Claims

MCP has no way to verify a server does what it declares, and tool definitions are re-fetched every connection. How to pin them, review them, and contain what a server can reach.

Security Engineering

Implicit Trust Propagation: Why Provenance Dies in the Context Window

Content loses its origin the moment it enters the context, and tool chains launder it further. The tainted-session model, and how to split research from action.

Security Engineering

Unauthenticated Sampling: When an MCP Server Drives Your Model

MCP sampling lets a server request completions on your account, inverting the usual direction of control. Why it is a documented attack vector and how to constrain it.

Security Engineering

The MCP Threat Model: Where Trust Actually Breaks Down

Why the Model Context Protocol attracted 30+ CVEs and a DoD advisory within eighteen months: three protocol-level weaknesses, and why the whole context window is one trust domain.

← Securing a Local Agent Daemon: Loopback Is Not a Boundary  ·  Capability Attestation and Tool Poisoning: Trusting What a Server Claims →

All security engineering articles  ·  Every article