Home · Guides

Reviewing an MCP server before you run it

A stdio MCP server is a program the client launches with your user account. It can read what you can read and delete what you can delete. VS Code's own documentation puts it plainly: local MCP servers can run arbitrary code on your machine. Everything below follows from that being literally true.

What the specification requires of a server

For streamable HTTP, these are stated as requirements rather than suggestions:

The reason is named in the specification: without these, an attacker can use DNS rebinding to interact with a local MCP server from a remote website. A local server with no Origin check is reachable by any page the user has open.

The consent gates the clients give you

ClientGate
VS CodeAsks you to confirm you trust the server and its capabilities before it starts. Nothing runs until you answer.
Claude CodeA project-scoped server from .mcp.json waits for approval, and since v2.1.196 the approval is not read from files inside the repository until you trust the workspace yourself.
Claude DesktopAn .mcpb install dialog lists the tools declared in the manifest before installing.
ClineTool calls are confirmed unless the tool name is in that server's autoApprove array.
WindsurfTools are toggled per server on its settings page.

Two of these are worth using deliberately rather than clicking through. autoApprove decides which tools run without you seeing the call, so read-only tools are reasonable candidates and anything that writes, sends or spends is not. And VS Code offers "sandboxEnabled": true for local stdio servers on macOS and Linux, restricting a server to the file paths and network domains you permit, with a top-level sandbox object for the rules.

Checks worth doing on someone else's server

  1. Read the tool list before the README. The tools are the capability surface. A server whose description says "read your calendar" and whose tool list includes a generic shell execution tool is a different program from the one described.
  2. Find out where it sends things. Grep the source for the HTTP client it uses. A tool that claims to work locally and opens a socket is the single highest-value thing to catch.
  3. Check what it writes, and where. A path built from a tool argument without normalisation is a directory traversal waiting for a plausible-looking filename.
  4. Check the input bounds. Anything that unpacks an archive, parses a document or follows a link handles input the user did not write. Refusal ratios and total-size ceilings belong there.
  5. Prefer a pinned version to a floating one. An install line that resolves the latest package at every launch is a supply chain you re-accept every morning.

Untrusted input is the part people skip

Most review attention goes to the server's own code. The larger surface is usually the data it is pointed at, because that comes from someone else. The zip server in this repository refuses an archive on the declared total size and the compression ratio read from the central directory, before anything is inflated: a 500 MB decompression bomb is refused in 3 ms with nothing written and the output directory not even created. A library that hands back a decompressed map has already inflated the bomb by the time you can inspect it.

The ratio ceiling is set at 100x rather than 50x for a measured reason: a real monthly export of plain-text records compressed at 1,022x in testing, so a ceiling tuned comfortably below a bomb would refuse ordinary work, and the user would learn to pass an override on everything. A guard people routinely disable is not a guard.

What to check on your own server

Sources: the streamable HTTP transport binding of specification revision 2026-07-28 for the Origin, binding and authentication requirements; each vendor's own documentation, read 2026-09-08, for the consent gates. The archive figures are measured in servers/zip/README.md in this repository, whose 30 servers run 1,518 tests with 1,507 passing and 0 failing at v0.20.0, recorded in data/tests.json.

Questions

Is a hosted MCP server safer than a local one?

It is safer for your machine and worse for your data. A remote server cannot read your disk, and everything you send it is now on someone else's. Which risk you prefer depends on whether the sensitive thing is the machine or the content.

Does the protocol authenticate anything?

Not by itself. The transport binding says servers SHOULD implement proper authentication and requires Origin validation, and OAuth is layered on by clients for remote servers. A stdio server has no authentication at all, because it is already running as you.

What is DNS rebinding in this context?

A remote page resolving a hostname to 127.0.0.1 so that a request from that page reaches a service listening on your machine. Validating Origin and rejecting anything unexpected with 403 is the defence the specification requires, which is why it is a MUST rather than a suggestion.

Should I autoApprove read-only tools?

It is the defensible case, and it is worth being sure they are read-only first. A tool that fetches a URL is not read-only in the sense that matters, because the argument decides where the request goes.

Related

All MCP servers and prices · All guides · Buy the bundle $39