How to Declaratively Separate Team-Based AI Tool Access Permissions Using Claude Code MCP and `.claude/rules/`
When rolling out AI coding tools across an entire team, you hit a familiar concern sooner than you'd expect: "Backend developers need database access, but what if a frontend developer accidentally runs DROP TABLE?" At first, I just pushed the same MCP server configuration to everyone. Then one day I experienced an unexpected change to the staging DB schema, and that's when I finally started thinking seriously about proper permission separation.
The problem turned out to be more complex than I anticipated. I needed to systematically design which tools AI could access, from which paths, and for which operations. What was needed wasn't a simple rule like "this team can't use this tool" — it was a structure that fundamentally closed off the possibility of destructive commands being issued in the first place. At the start, I wasn't even sure where to begin, and once I had configuration files set up, figuring out which rules applied at which layer wasn't easy either.
Claude Code provides a structure that combines the permission blocks in settings.json with team-specific rule files in .claude/rules/, enabling declarative management of MCP tool access permissions at the file system level — per team and per role. This article covers how that structure works, where things break down, and what mistakes are commonly made in practice. By the end, you'll understand the priority order in which MCP permission decisions are made, and you'll be able to configure permission files for backend, frontend, and DevOps teams yourself.
Core Concepts
What Is MCP, and Why Does Permission Management Matter?
MCP (Model Context Protocol) is an open standard that Anthropic released in November 2024. In short, it standardizes the way AI accesses external tools and data sources — like a USB-C port that unifies a single spec for connectivity. Instead of connecting services like GitHub, PostgreSQL, Slack, and AWS each in a different way, a single MCP server standardizes the connection method.
The problem is that this power becomes a risk factor in equal measure. The fact that AI can access external systems means that, if misconfigured, AI could drop a production database, send unintended messages to Slack, or terminate an AWS instance. That's why clearly designing who can access which MCP tools, and under what conditions, is the central challenge of team adoption.
MCP Tool Identifier Format: In Claude Code, MCP tool permissions are expressed in the form
mcp__<server-name>__<tool-name>. For example,mcp__github__list_issuesrefers to thelist_issuestool on the GitHub MCP server. You can also use wildcards (*) to allow or deny an entire server.
Distinguishing the Roles of settings.json and .claude/rules/
This was the most confusing part at first, but clearly separating the two roles makes the overall structure much clearer.
settings.json is the file that actually enforces MCP permissions. It declares which tools to allow and which to block via permissions.allow and permissions.deny blocks.
.claude/rules/ does not directly control MCP permissions. The *.md files inside this directory are rule files that Claude Code selectively loads based on project context, injecting team-specific work guidelines and context into the AI. By specifying a globs pattern at the top of each file, that rule is only activated when working with files at matching paths.
---
globs: ["src/server/**", "src/api/**"]
---
This is the backend development context.
Always get team lead approval before running database migrations.The important point is that activating these rule files does not automatically restrict tool access. Without a deny rule in settings.json, tool access is not blocked. Only by using both together does the structure "when working in this path, only these tools can be used" become complete.
Permission Decision Priority
You need to know which rule wins when permissions conflict in order to design things properly. Priority follows the hierarchy below.
Managed Settings ← centrally managed admin settings (highest)
└── User Settings ← individual user settings
└── Project Settings ← project-wide settings
└── Local Settings ← personal local settings (lowest)
On conflict: deny > ask > allow (first matching rule wins)deny rules are always stronger than allow, regardless of the hierarchy layer. This means that a tool locked down by a security lead via managed-settings.json cannot be unlocked no matter how much a developer digs through their local settings. This is precisely why this structure is especially useful in enterprise environments.
Practical Application
Example 1: Designing the Directory Structure by Team
The first thing to do in practice is to design the .claude/ directory structure to match your team structure.
.claude/
├── settings.json # shared across the project (Git-committed)
├── settings.local.json # personal settings (.gitignore)
├── rules/
│ ├── backend.md # backend team context & work guidelines
│ ├── frontend.md # frontend team context & work guidelines
│ └── devops.md # DevOps team context & work guidelines
└── managed-mcp.json # admin-only (see Example 3)The standard pattern is to commit settings.json to Git for the whole team to share, and to add settings.local.json to .gitignore for personal overrides.
Example 2: MCP Permission Settings by Team (settings.json)
Declare allow/deny rules suited to each team's role. When multiple teams work together in a single repository, it's common to operate separate repositories per team or to place each team's settings.json in a team-specific branch. Since branching by team within a single settings.json is not currently supported, in a monorepo environment you may want to consider using the most restrictive common settings as the default and separating team-specific extensions into separate repositories.
Backend Team:
{
"permissions": {
"allow": [
"mcp__postgres__query",
"mcp__postgres__schema",
"mcp__github__*",
"mcp__slack__read_message"
],
"deny": [
"mcp__postgres__drop_table",
"mcp__slack__send_message",
"mcp__aws__terminate_instance"
]
}
}Frontend Team:
{
"permissions": {
"allow": [
"mcp__playwright__*",
"mcp__github__get_pull_request",
"mcp__github__list_issues",
"mcp__figma__*"
],
"deny": [
"mcp__postgres__*",
"mcp__aws__*",
"mcp__slack__send_message"
]
}
}When I first set up this configuration, the biggest thing I agonized over was "is it okay to give the frontend team all of GitHub?" In the end, I chose to explicitly allow only read-related tools and add more as needed — and that approach turned out to be much safer.
DevOps Team:
{
"permissions": {
"allow": [
"mcp__aws__*",
"mcp__gcp__*",
"mcp__github__*",
"mcp__atlassian__*"
],
"deny": [
"mcp__postgres__drop_table"
]
}
}| Team | Allowed Tools | Explicitly Denied |
|---|---|---|
| Backend | PostgreSQL read & schema, all of GitHub, Slack read | DB DROP, Slack write, AWS instance termination |
| Frontend | All of Playwright, GitHub read & issues, all of Figma | All of PostgreSQL, all of AWS, Slack write |
| DevOps | All of AWS, all of GCP, all of GitHub, all of Atlassian | PostgreSQL DROP |
Example 3: Enterprise Centralized Deployment (managed-mcp.json)
This example is for organizations of 100+ people. For smaller teams, Example 2 is sufficient.
In larger organizations, you'll want to fundamentally block developers from arbitrarily adding MCP servers. The approach here is to deploy managed-mcp.json via MDM (Mobile Device Management).
MDM is the way a company's IT department uniformly distributes and manages settings across all devices. By leveraging this mechanism, Claude Code settings can also be enforced centrally.
You need to be precise about the paths. The in-project .claude/managed-mcp.json and the system-wide path deployed by MDM are separate things. The system-wide application path on macOS is as follows.
/Library/Application Support/ClaudeCode/managed-mcp.json
/Library/Application Support/ClaudeCode/managed-settings.jsonFiles at these paths take precedence over project-level settings, and when deployed by the IT department via MDM, they are enforced across all devices.
managed-mcp.json example:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"]
}
}
}Environment variable references like ${DATABASE_URL} require the IT department to separately configure the environment variable on each device at deployment time. Once this file is deployed, per the official documentation, MCP servers added by developers in their ~/.claude/settings.json will be ignored and only the approved server list will function. This is exactly why it's important to thoroughly review the server list before deployment.
Example 4: OAuth 2.1 Scope-Based Granularity
This section is for readers familiar with OAuth 2.1. If OAuth is new to you, you can skip this section.
With the June 2025 MCP spec update classifying MCP servers as OAuth 2.1 Resource Servers, scope-based access control is also now possible. In this case, scopes use a colon (:) delimiter format.
mcp:tools:weather # access to weather tool only
mcp:resources:customer-data:read # customer data read-only
mcp:exec:workflows:* # full workflow execution permissionThe format using double underscores (__) — as in mcp__github__list_issues — is the layer used internally by Claude Code to identify tools. The colon-delimited format is the scope negotiation layer between the OAuth authorization server and the MCP server; it's representing the same tool differently at different layers. Not confusing the two is important.
When a server specifies a scope parameter in the WWW-Authenticate header, it can prevent clients from requesting more permissions than necessary. However, since not all MCP servers have fully implemented this spec yet, it's a good idea to verify the OAuth implementation level of the server you intend to use before actual adoption.
Pros and Cons Analysis
Pros
| Item | Content |
|---|---|
| Standardized connectivity | Integration with thousands of external services via a single protocol, no separate plugin per service needed |
| Principle of least privilege | deny rules always take top priority regardless of layer, preventing over-granting of permissions |
| Layered control | Managed → User → Project → Local layers naturally separate enterprise, team, and personal permissions |
| Git version control | Committing settings.json distributes consistent permissions to the whole team with change history tracking |
| Fine-grained tool control | Supports both server-level (mcp__github__*) and individual tool-level control |
Cons and Caveats
Claude Code Enterprise offers RBAC (Role-Based Access Control) functionality, but currently it only controls 6 high-level features such as Cowork, web search, and memory. Since it does not directly control MCP server access or individual tool permissions, you need to manage the settings.json permission blocks described in this article in parallel.
| Item | Content | Mitigation |
|---|---|---|
| RBAC limitations | Enterprise RBAC only controls 6 high-level features and doesn't directly control individual MCP tool permissions | Manage settings.json permission blocks in parallel |
| OAuth implementation inconsistency | MCP servers vary in OAuth 2.1 implementation level, making consistency difficult | Review each server's spec compliance before adoption |
managed-mcp.json overwrite |
System-level deployment causes developers' existing MCP server settings to be ignored | Thoroughly review the full server list before deployment, prepare a rollback plan |
| Prompt Injection risk | Malicious MCP servers can steal tokens (partially mitigated in June 2025 spec) | Only include verified official MCP servers in the allowlist |
| Governance overhead | As teams grow, managing distributed configuration files becomes complex | Enforce policy requiring PR review for all configuration file changes |
Prompt Injection: An attack that induces an AI model to execute malicious commands hidden inside content retrieved from external tools. In an MCP environment, external servers may attempt to embed malicious instructions in their responses to steal tokens or session information.
Most Common Mistakes in Practice
-
Defining only
allowwithoutdeny— It's tempting to assume that everything outside of explicitly allowed tools will be blocked by default, but depending on the configuration structure, tools allowed in an upper layer can be inherited as-is. It is safer to always explicitly add dangerous tools todeny. -
Skipping review before deploying
managed-mcp.json— This single file replaces all existing MCP settings for every developer. It's best to fully validate it in a staging environment first and to notify the team in advance before deployment. -
Accidentally committing
settings.local.jsonto Git — Personal config files often contain API tokens or internal server URLs. It's recommended to verify at the start of a project thatsettings.local.jsonis registered in.gitignore.
Closing Thoughts
The combination of MCP and .claude/rules/ is a realistic starting point for safely expanding AI tools across an entire team. A complete RBAC system is still maturing, but adding just a few lines to the deny block in settings.json right now can significantly reduce the risk of incidents.
Three steps you can take immediately:
- Audit your MCP server landscape: Open
~/.claude/settings.json, review the connected MCP server list, and classify dangerous tools with your team. - Define a
denylist: Start from the question "What tools should this team absolutely never use?" Begin by adding destructive tools likemcp__postgres__drop_tableandmcp__aws__terminate_instanceto the deny list. - Write team-specific rules files: Create team-specific
*.mdfiles under.claude/rules/and connect them to working paths viaglobspatterns. Explicitly documenting permission descriptions and operational policies alongside will also help the AI understand the work context.
References
- MCP Official Spec (2025-11-25) | modelcontextprotocol.io
- MCP Authorization Spec | modelcontextprotocol.io
- Claude Code: MCP Integration Official Docs | code.claude.com
- Claude Code: Permission Settings Official Docs | code.claude.com
- Claude Code: settings.json Reference | code.claude.com
- MCP June 2025 Auth Spec Update Analysis | auth0.com
- MCP November Auth Spec Deep Dive | den.dev
- Claude Code Enterprise Security in Practice | truefoundry.com
- 5 Permission Patterns for Locking Down Claude Code | DEV Community
- MCP Auth Claude Code 2026 | truefoundry.com
- Stack Overflow Blog: Authentication and Authorization in MCP | stackoverflow.blog
- CoSAI MCP Security Analysis | github.com/cosai-oasis
- MCP Wikipedia | wikipedia.org