Skip to content

MCP permissions: allow one tool, not a whole server

How Claude Code names MCP tools in permission rules, how to allow a server's read tools while asking before its write tools, and how to keep API keys out of a shared .mcp.json.

Short answer: every MCP tool has a name like mcp__github__create_issue. Put that name in a Claude Code permission rule to allow, ask about or deny that one tool, and put mcp__github on its own to cover every tool of the server.

An MCP server can do whatever its tools do, with your credentials. That is the point of it, and also why I never allow a whole server by reflex. Here is how I set it up instead.

How are MCP tools named?

Claude Code names each tool mcp__<server>__<tool>. The server part is the name you gave it in claude mcp add, so a server added as github with a tool create_issue becomes mcp__github__create_issue. Type /mcp in a session to see each server's tools.

How do I allow only the safe tools?

Permission rules go in .claude/settings.json (shared with the project) or ~/.claude/settings.json (just you). Allow what only reads, ask before what writes:

{
  "permissions": {
    "allow": [
      "mcp__github__get_issue",
      "mcp__github__list_issues",
      "mcp__github__search_code"
    ],
    "ask": [
      "mcp__github__create_issue",
      "mcp__github__create_pull_request"
    ],
    "deny": [
      "mcp__github__delete_repository"
    ]
  }
}

Deny wins over ask, and ask wins over allow, so a tool in two lists gets the stricter answer. Anything not listed is asked about the first time, as usual. Claude Code permissions: allow, ask and deny has the whole order.

A rule with just the server, such as "mcp__notes", covers every tool that server has, including ones added in its next version. I only do that for servers I wrote myself or that cannot change anything.

How do I keep API keys out of .mcp.json?

A project-scoped server is saved in .mcp.json at the root of the repository, which you commit. Never paste a key into it. Claude Code expands environment variables in that file, so write the variable instead:

{
  "mcpServers": {
    "tracker": {
      "type": "http",
      "url": "https://example.com/mcp",
      "headers": { "Authorization": "Bearer ${TRACKER_TOKEN}" }
    }
  }
}

Each person sets TRACKER_TOKEN in their own shell, and the file stays safe to share. ${VAR:-default} gives a fallback when the variable is not set.

How do you share the rules with your team?

Put the server in .mcp.json and the permission rules for its tools in .claude/settings.json, and commit both. Everyone who opens the project then gets the same server with the same allow and ask lists, and each person adds their own key through an environment variable. A personal exception goes in .claude/settings.local.json, which is not committed. When the list of servers itself must be fixed for a whole company, the managed policy can allow or deny servers by name, and nothing in a project can override it.

Where can you check this?

What else should I check before adding a server?

  • Who publishes it. The service's own server is safer than a fork with a similar name.
  • What it can reach. A database server with a read-only flag or a read-only user is a different risk from one with write access.
  • What it sends back. A tool's answer goes into the conversation. A server that reads web pages or emails can carry instructions written by someone else, so be stricter about what Claude may do after calling it.

Config Studio for Claude Code writes these permission rules for you and explains each one, and shows the exact file it would write before it exists, so you can check it before you commit it.

The tool

Do it in your browser.

Claude Code

Config Studio for Claude Code

Every file Claude Code reads, explained: what each setting does, where it lives, which file wins, and an editor that writes it for you.

Keep reading

More from the blog.

Every post

Contact