Blog ·

How to set an MCP allowlist in Claude Code, Cursor and GitHub Copilot

An MCP allowlist limits AI agents to servers you approved. Here is how each major coding agent implements one, how matching works, and the gaps to plan for.

An MCP allowlist is a policy that limits which MCP servers your developers' AI agents may load. Claude Code sets it with allowedMcpServers and deniedMcpServers in managed settings, Cursor Enterprise sets it in the team dashboard under MCP Configuration, and GitHub Copilot sets it in an enterprise managed-settings.json file or by restricting servers to a private registry. In each tool, the entries that hold up match a server by its exact command or its URL, not by its name. An allowlist stops unapproved servers from starting. It does not tell you what is already installed, and it does not notice when an approved server changes.

What an MCP allowlist does

Without one, any developer can add any server. Claude Code's documentation states the default plainly: anyone running it can connect any MCP server they choose. An allowlist flips that default for the machines your policy reaches. Servers that match an entry load; everything else is blocked. Most tools pair it with a denylist for known-bad servers, and in Claude Code and GitHub Copilot a denylist match blocks a server even if the allowlist also matches.

It is the enforcement half of governing shadow MCP servers, the risk OWASP lists as MCP09. The other half is knowing what is out there, which comes first in practice.

How to set an MCP allowlist in Claude Code

Claude Code reads two lists from managed settings. allowedMcpServers permits servers and deniedMcpServers blocks them. Each entry matches in one of three ways: serverUrl for remote servers, with * wildcards; serverCommand for local servers, as the exact command and arguments; or serverName, the label the user gave it.

{
  "allowManagedMcpServersOnly": true,
  "allowedMcpServers": [
    { "serverUrl": "https://api.githubcopilot.com/*" },
    { "serverCommand": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "."] }
  ],
  "deniedMcpServers": [
    { "serverUrl": "https://*.untrusted.example.com/*" }
  ]
}

Three details decide whether the list actually holds. First, set allowManagedMcpServersOnly to true; without it, allowlists from every settings scope merge, so a developer can widen yours in their own settings. Second, do not rely on serverName; the documentation warns it is not a security control, because a user can call any server "github". Third, an empty allowlist array blocks everything, while leaving it unset allows everything. For full control, Claude Code also accepts a managed-mcp.json file at a system path that fixes the exact set of servers users get.

Setting the allowlist in Cursor

Cursor's allowlist lives in the team dashboard under MCP Configuration, which is an Enterprise feature. Administrators add approved servers there; when an allowlist is active, only servers that match an entry can run. Local servers match on the full command string, the command plus all its arguments joined by spaces, and Cursor's documentation shows a leading * wildcard to cover different install paths. Remote servers match on the full URL, with wildcards for subdomains and paths.

Two further controls sit alongside it. A ~/.cursor/permissions.json file, which administrators can distribute through device management, sets which MCP tools may auto-run using server:tool entries. And local servers can run in a sandbox with a network mode of allow all, allowlist, deny all or no sandbox. Sources apply in priority order, dashboard first, and a higher source replaces a lower one rather than merging with it. Note that approving a server does not install it; developers still add it themselves.

Setting the allowlist in GitHub Copilot

GitHub offers two methods. The generally available one is an enterprise managed-settings.json file, usually kept in a .github-private repository or deployed through device management, with allowedMcpServers and deniedMcpServers entries matched by server name, URL or command. The "MCP servers in Copilot" policy must be enabled. GitHub's evaluation order is: built-in default servers such as the GitHub MCP server are always allowed, any deny match blocks, a server that matches no allow entry is blocked, and a server whose URL or command contains an unresolved variable is blocked. A malformed policy is treated as an empty allowlist.

The second method, in public preview, restricts Copilot to servers listed in a private MCP registry. Administrators enter the registry URL and set "Restrict MCP access to registry servers" to "Registry only"; that also blocks Copilot connectors. GitHub's own page says the registry method is not the recommended restriction and points to the allowlist file instead.

How to write entries that hold

Match on what runs, not what it is called. For local servers, put the pinned version in the command itself, for example a package name with an exact version number. Claude Code matches commands argument by argument, so a developer who switches to an unpinned or different version no longer matches the entry. For remote servers, allow the vendor's exact host rather than a broad wildcard.

Keep the list small and reviewed. Each entry should have an owner and a reason, and each server should pass our MCP security checklist before it goes on.

Treat changes to the list like code. Keep the managed settings file in a repository, require a second reviewer for every new entry, and write the reason in the commit message. When a version bump is needed, the change is one line, and the history shows who approved what and when. The same file can then be pushed to every machine by your device management tool, so the list developers get is always the reviewed one.

Finally, check the result on a real machine. Claude Code's documentation suggests two tests after deploying managed configuration: listing servers to confirm only approved ones appear, and trying to add an unapproved one to confirm the policy rejects it.

What an MCP allowlist does not cover

An allowlist checks a server's identity at load time. It does not check behavior after approval. In Invariant Labs' WhatsApp research, the malicious server kept its name and command and swapped in a poisoned tool description on its second launch; an allowlist would have let it through. A remote server can change behind the same URL. Claude Code also notes that the env block is not compared, and environment variables can change what a command loads.

Coverage has limits too. Each tool's allowlist governs that tool only, and only on machines that receive your managed settings. It says nothing about servers on unmanaged laptops, servers in other agents, or MCP servers deployed as services. And some servers skip the check by design, such as GitHub Copilot's built-in defaults and Claude Code's own managed and built-in servers.

Rolling out an allowlist without breaking work

Start with an inventory, because an allowlist written without one blocks tools people depend on. Our guide on how to find MCP servers on developer machines covers each agent. Then add a denylist for anything clearly bad, publish the approved list where developers will see it, and switch the allowlist on with notice. Claude Code's documentation warns that blocked servers disappear with no explanation, so tell users which servers are affected first. After rollout, watch which servers are invoked; Claude Code can export that through its OpenTelemetry monitoring. Expect a burst of requests in the first week as developers find what is blocked, and plan time to review them quickly, so the list grows to fit real work instead of being worked around.

An allowlist works best alongside safe defaults. Our mcp.json example shows a safer config for each tool, and our guide to the --dangerously-skip-permissions flag in Claude Code explains why it should stay off on developer machines.

Next step: build the MCP allowlist from real usage

The hardest part of an MCP allowlist is knowing what to put on it. Run a Discovery Scan to list every MCP server your developers already use, with a risk score for each, so the approved list starts from what your teams actually need and leaves out the servers that should never have been there.

MCP allowlist questions

Does an MCP allowlist remove servers developers already installed?

It stops them from loading. In Claude Code, a configured server that policy now blocks disappears from /mcp and claude mcp list, with no message saying why. In Cursor, once an allowlist is active only matching servers can run. Tell developers before you switch it on.

Can developers get around it?

Sometimes. In Claude Code, an allowlist without allowManagedMcpServersOnly merges with users’ own settings, so they can broaden it, and a name-based entry can be matched by any server given that name. Lock the list to managed settings and match by command or URL.

Should entries match by name, command or URL?

By command for local servers and by URL for remote ones. Claude Code’s documentation warns that a name entry is not a security control, because the name is whatever label the user typed. Commands and URLs describe what actually runs.

Is an allowlist enough on its own?

No. It controls which servers may load, not what an approved server does after an update, and it does nothing on machines your policy does not reach. Pair it with version pinning, a review when tools change, and a regular inventory of what is running.

Sources

  1. Claude Code Docs: Control MCP server access for your organization
  2. Cursor Docs: Model and integration management (MCP allowlist)
  3. GitHub Docs: Configuring an MCP server allowlist for your enterprise
  4. GitHub Docs: Restrict MCP server access to a custom registry
  5. Invariant Labs: WhatsApp MCP exploited (April 7, 2025)
  6. OWASP MCP Top 10 (2025, beta)

Related reading

Build your approved server list from what your teams actually run.