How to audit an MCP config: a ten-minute review, server by server

An MCP config file decides what your coding agent can change. Here is a checklist to review one, and a worked example where nine servers graded D became four that graded B.

The short answer

For each server in the file, answer six questions: Is the package still maintained? Is a secret written into the file? Which of its tools can write, delete or move money? What can it reach (folders, projects, repositories)? Is it local or remote? Does it combine private data, untrusted content and a way to send data out? Fix the answers you don’t like, then rerun the check. npx deedglass scan or the in-browser /check answers the first four for the servers it knows.

Each action ends in a signed record: what ran, who approved it, what the check found. Records are chained, each one carrying the fingerprint of the one before, and they can be checked offline. Made-up record.

Find every config first

You can’t audit a file you don’t know about. Each client keeps its own:

Client Project file User file
Claude Code .mcp.json5 ~/.claude.json (local and user scopes)5
Cursor .cursor/mcp.json6 ~/.cursor/mcp.json6
VS Code .mcp.json (portable) or .vscode/mcp.json7 ~/.copilot/mcp-config.json or the profile mcp.json7

Run git ls-files | grep -i mcp in each repository, and check your home directory too. A user-level server applies to every project you open.

The checklist, per server

Copy this and fill it in for each entry under mcpServers (or servers in VS Code).

# Question Bad sign Fix
1 Is it maintained? @modelcontextprotocol/server-postgres Use a maintained server, or a read-only database role
2 Is a secret in the file? postgresql://user:pass@…, sk_live_…, ghp_… in args or env Read it from an environment variable
3 Which tools write? execute_sql, write_file, create_refund Turn on the server’s read-only mode, or limit its tools
4 What can it reach? a filesystem server given / Give it one project folder
5 Local or remote? a url entry you haven’t reviewed Check its sign-in scopes by hand
6 Trifecta? private data + untrusted content + a way out Split it across agents, or drop one leg

On row 1: Anthropic archived its reference Postgres server on 28 May 2025.3 Datadog Security Labs showed that its read-only mode runs each query in a read-only transaction that a stacked COMMIT; ends, after which later statements run with the role’s full rights.2 It’s still in plenty of configs.

On row 4: the reference filesystem server restricts every operation to its allowed directories, and the directories you pass on the command line are the method that works on every protocol version.4 Pass / and the agent can edit anything you can.

On row 6: Simon Willison’s “lethal trifecta” is access to private data, exposure to untrusted content, and the ability to communicate externally.8 An agent with a GitHub server (issues are untrusted content), a database server (private data) and Slack (a way out) has all three.

A worked example: D to B

We wrote a deliberately careless .mcp.json with nine servers: the archived Postgres server with a password in its URL, the filesystem server on /, GitHub with a token in env, Stripe with --tools=all and a live-style key in the arguments, Supabase with an access token, Slack, and remote Notion, Linear and Sentry. Then we ran deedglass 0.13.0’s scan on it, with the home directory isolated so only this file counted.1

Code What the screen or file shows, copied as is.

$ npx deedglass@0.13.0 scan
Blast radius: D · 8 write paths with no check · fix this first: Archived
  Postgres MCP server · database not checked
  A means a small blast radius, not a safe agent.
    −8  medium finding          Archived Postgres MCP server
    −8  medium finding          A database URL sits in a client config
    −4  unchecked write path    filesystem.edit_file · write · .mcp.json
    −4  unchecked write path    filesystem.move_file · destructive · .mcp.json
    −4  unchecked write path    filesystem.write_file · write · .mcp.json
    −4  unchecked write path    postgres.query · write · .mcp.json
    −4  unchecked write path    stripe.create_payment_link · money · .mcp.json
     0  unchecked write path    stripe.create_refund · money · .mcp.json (over the cap)
     0  unchecked write path    supabase.apply_migration · destructive · .mcp.json (over the cap)
     0  unchecked write path    supabase.execute_sql · write · .mcp.json (over the cap)
    64 points

Found
  1 MCP client config · 9 servers · 8 tools that can write

Then we applied the checklist:

  • Removed the archived Postgres server (rows 1 and 2).
  • Limited the filesystem server to ./docs (row 4).
  • Ran GitHub in read-only mode with GITHUB_READ_ONLY=1, which offers only read-only tools, and passed the token from the environment instead of the file (rows 2 and 3).9
  • Replaced the Supabase entry with its hosted URL scoped by project_ref, with read_only=true, which runs all queries as a read-only Postgres user.10
  • Dropped Stripe, Slack, Notion and Linear, which this project didn’t need.

The rescan:1

Code What the screen or file shows, copied as is.

Blast radius: B · 3 write paths with no check · fix this first:
  filesystem.edit_file · database not checked
    −4  unchecked write path    filesystem.edit_file · write · .mcp.json
    −4  unchecked write path    filesystem.move_file · destructive · .mcp.json
    −4  unchecked write path    filesystem.write_file · write · .mcp.json
    88 points

From 64 points to 88. The three that remain are honest: the filesystem server can still write inside ./docs. That’s its job. The scan’s own line puts it well: A means a small blast radius, not a safe agent.

What the automated check misses

The scan and /check are useful and narrow, and the gaps are worth knowing before you trust a grade. From the same two runs:11

  • It didn’t flag the tokens. The GitHub token in env, the Slack token and the Stripe key in the arguments got no finding. Only the database URL did. Review row 2 by eye, or run a secret scanner over the file.
  • It counted write tools for four servers only: filesystem, Postgres, Stripe and Supabase’s local package. GitHub and Slack contributed no write paths, though both can write.
  • Remote servers are opaque to it. Notion, Linear, Sentry and the hosted Supabase URL added no write paths in either run. A url entry can be anything its sign-in allows; check row 5 by hand.
  • The database part needs a connection. “Database not checked” means it hasn’t looked at what the database role can change. --postgres-dsn-env DATABASE_URL adds that.

/check runs deedglass’s own scan, compiled to WebAssembly, in your browser: nothing you paste is uploaded, and a config gets the grade deedglass scan gives a folder holding only that file.11 When we wrote this it ran the 0.12.0 build, which gave our first sample the same D.1

Make it a habit

A config file changes whenever someone adds a server for a demo and forgets it. Three habits keep it honest:

  1. Review it in pull requests. Scanning MCP configs in CI shows the GitHub Action that comments when a pull request changes the grade.
  2. Prefer project files to user files, so a server’s reach is visible in the repository. Where each client keeps its MCP config has the paths.
  3. Re-read the basics every few months: our MCP security checklist and the filesystem server post go deeper on single servers, and blast radius explains what the grade measures.

To try it, run npx deedglass scan in a repository, or paste a single config into /check, which runs in the browser and uploads nothing. What the grade means explains the scan’s letter. To watch the checks without installing anything, open the playground.

Written with AI assistance and checked against our claims register.

The takeaway

Our sample went from D (64 points, 8 write paths) to B (88, 3) by dropping an archived server, moving secrets out and narrowing scope.

Read nextScan MCP and agent configs on every pull request with a GitHub Action Try it: install in 7 s

Related on this site

Terms

In the docs

More posts

Sources

  1. 1Deedglass docs: scan · docs.deedglass.com · checked 27 October 2026
  2. 2Datadog Security Labs: SQL injection in the Postgres MCP server · securitylabs.datadoghq.com · checked 14 October 2026
  3. 3modelcontextprotocol/servers-archived · github.com · checked 14 October 2026
  4. 4Filesystem MCP server README · github.com · checked 26 October 2026
  5. 5Claude Code docs: MCP · code.claude.com · checked 27 October 2026
  6. 6Cursor docs: MCP · cursor.com · checked 27 October 2026
  7. 7VS Code docs: MCP servers · code.visualstudio.com · checked 27 October 2026
  8. 8Simon Willison: The lethal trifecta for AI agents · simonwillison.net · checked 14 October 2026
  9. 9GitHub MCP server README · github.com · checked 27 October 2026
  10. 10Supabase docs: Model context protocol (MCP) · supabase.com · checked 25 October 2026

Published 27 October 2026, sources last checked 27 October 2026. If something here is out of date, write to hello@deedglass.com.

Try it on your own setup

npx deedglass scan

Grades only your own setup. Nothing is uploaded.

Pricing