Skip to content
All articles

MCP · Developer Tools

Read an MCP server before you trust it

List the tools of the MCP reference server and you find a read-only tool that hands over your secrets and another that fetches any URL from your machine. How to pin, inspect and allow.

· 5 min read

Four steps for a new MCP server. 1, pin a version: tool descriptions are instructions a model reads, and an unpinned install fetches whatever was published last. 2, list what it offers with the Inspector's tools/list before any model can; the reference server exposes fourteen tools. 3, read the hints and doubt them: get-env is marked readOnlyHint true and returned DEMO_API_KEY; gzip-file-as-resource is marked openWorldHint true and fetches any URL from your machine, even 169.254.169.254. 4, allow only what you decided: a denied tool is removed from the model's context, and an allow list is safer because tools a later version adds stay off. Read-only describes side effects, not confidentiality.

The quickest way to learn what an MCP server owes its users is to be one first. The reference server that the MCP maintainers publish to exercise every protocol feature is a good place to start: it is safe to run, and it shows exactly why you read a server before you trust it.

Pin the version

An MCP server's tool descriptions are instructions that a model reads. Start a server with npx some-server and no version, and every start fetches whatever was published last, so a later release can change what those instructions say without you noticing. Pin an exact version, and a change reaches you only when you choose to upgrade and read what changed.

List what it offers

The MCP Inspector, the protocol's own debugging client, has a command-line mode that connects, sends one request and prints the answer. Asked for tools/list, the reference server returns fourteen tools, each with a description, an input schema and four annotations: readOnlyHint, destructiveHint, idempotentHint and openWorldHint.

Two of them deserve a second look.

ToolAnnotationWhat it actually does
get-envreadOnlyHint: trueReturns every environment variable, including the DEMO_API_KEY set for the test
gzip-file-as-resourceopenWorldHint: trueFetches whatever URL it is given, from the machine the server runs on

get-env really does change nothing, so its annotation is honest. Read-only describes side effects, not confidentiality. Annotations are also claims a server makes about itself, and the specification tells clients to treat them as untrusted unless the server itself is trusted.

Engineering Insight

gzip-file-as-resource is not marked destructive, yet a model, or text an attacker planted somewhere the model reads, can give it any URL: a router's admin page, a service on localhost, or a cloud metadata endpoint such as 169.254.169.254. The response lands in the model's context. That is server-side request forgery, and openWorldHint: true is the only clue in the annotations.

Allow only what you decided

In Claude Code, add the server and then deny the tools you do not want a model to have, in the project's .claude/settings.local.json:

{ "permissions": { "deny": ["mcp__everything__get-env", "mcp__everything__gzip-file-as-resource"] } }

A denied MCP tool is removed from the model's context entirely, not merely refused when called. In Codex, list the only tools the server may expose with enabled_tools. Of the two, the allow list is safer when a server can grow, because a tool added in a later version stays off until you choose to enable it.

A stdio server runs as you, with your files, your network and your environment variables. Installing one is running a program, not adding a bookmark.

Get one diagram a week

A short article built around one engineering diagram, from the same library as these courses.

One diagram-led article a week on AI and systems engineering. We email you once to confirm, and every newsletter has an unsubscribe link. Privacy policy