# How do companies restrict which MCP servers employees can run in Claude Code, VS Code and GitHub Copilot (allowedMcpServers, deniedMcpServers, managed-mcp.json), and as an MCP server builder, how do I make my server easy for a security team to allowlist and keep allowlisted?

**Short answer:** Both use the same kind of rules: an allowedMcpServers list and a deniedMcpServers list in managed settings, where each entry matches a remote server by serverUrl (with * wildcards), a local stdio server by serverCommand (the exact command and every argument, in order), or either by serverName. Both vendors warn that a serverName entry doesn't verify which server actually runs, because the name is whatever label the user typed. Denylist matches always win. Claude Code also has managed-mcp.json, a file deployed to a system path that gives administrators exclusive control: users can't add any other server, including plugin servers. In Claude Code an allowlist is only authoritative when allowManagedMcpServersOnly is true; otherwise users can broaden it in their own settings. In GitHub Copilot's enterprise-managed settings, allowlists from several sources intersect and denylists add up. VS Code 1.145 and later puts an enterprise-managed allowlist ahead of registry-only access, so being in an MCP registry doesn't get a server past an allowlist. For you as a builder, this means the URL and launch command you publish are what customers approve. Serve the remote server from a stable https host on the default port, publish one exact launch command for the local version, write the matching allowlist entries in your docs, and treat a change of host, path, port or arguments as a change your customers have to re-approve.

## Checklist
1. Publish the exact allowlist entries for your server in your docs, for example {"serverUrl": "https://mcp.example.com/*"} for the remote server and {"serverCommand": ["npx", "-y", "@example/mcp-server@1.4.2"]} for the local one, so a security team can paste them instead of guessing.
2. Keep the remote endpoint stable: one https host, the default port, and a path you don't move. In Claude Code a pattern with the hostname written in full matches only the scheme's default port, so a server on :8443 needs its own entry, and moving to a new host breaks every allowlist that names the old one.
3. Give the local server one canonical launch command. serverCommand entries match the command and every argument exactly and in order, and GitHub's reference says wildcards and command-line expansion aren't supported, so ["npx", "server"] doesn't match ["npx", "-y", "server"].
4. Decide how you want upgrades approved. A command pinned to a version (pkg@1.4.2) changes every release and needs a new allowlist entry each time, which gives the security team a review point; an unpinned command keeps matching while the code behind it changes. Say which you recommend and why.
5. Don't ask customers to allowlist you by name. Claude Code's documentation says a serverName entry is not a security control, and GitHub's says users choose server names, so use serverUrl or serverCommand to enforce identity.
6. Keep credentials out of the server definition. Claude Code's managed-mcp.json is readable by any user on the machine, and its documentation says not to store API keys in env blocks there; support OAuth, per-user headers or environment variables instead.
7. Don't rely on registry listing alone. In VS Code 1.145 and later, a server that appears in the registry but doesn't match the managed allowlist is blocked, and one that matches the allowlist but isn't in the registry is permitted unless a deny rule or MCP disablement blocks it.
8. Use a host that can't be confused with someone else's. GitHub's clients canonicalise URLs before matching (lowercase scheme and host, Punycode for Unicode host names, percent-decoded host octets, default port and fragment removed), which stops lookalike tricks from matching a pattern but doesn't make a lookalike domain safe to approve.
9. Tell users what a block looks like. Claude Code says a server blocked by policy disappears from /mcp and claude mcp list with no signal that policy is the reason, so list the error messages and the entries to request in your troubleshooting docs.
10. Re-announce changes. When your URL, port or launch command changes, publish the new allowlist entries before you switch, and keep the old endpoint serving or redirecting until customers have updated.

## How do you restrict which MCP servers can run in Claude Code with managed-mcp.json, allowedMcpServers and deniedMcpServers?
- Anthropic's documentation says that by default anyone running Claude Code can connect any MCP server they choose, and that while Anthropic reviews connectors against listing criteria before adding them to its directory, it doesn't security-audit or manage any MCP server. Administrators choose a pattern: disable MCP, deploy a fixed set, provide servers alongside users' own, publish an approved catalog, allow plugin servers only, use a soft allowlist, or a denylist only.
- managed-mcp.json lives at /Library/Application Support/ClaudeCode/ on macOS, /etc/claude-code/ on Linux and WSL, and C:\Program Files\ClaudeCode\ on Windows, and is usually deployed with device management. When it's present, Claude Code loads only the servers it defines plus a few named exceptions (servers provided through managedMcpServers, in-process servers the host app registers, and Claude in Chrome if allowed), and claude mcp add fails with an "enterprise MCP configuration is active" error.
- Before loading any server, Claude Code merges the lists, checks the denylist (nothing overrides a match), then checks the allowlist. A remote server must match a serverUrl entry, and a serverName match counts only when the allowlist has no serverUrl entries; stdio servers work the same way with serverCommand. Leaving allowedMcpServers unset allows everything, while an empty array allows nothing apart from the exempt servers. To stop users broadening the list, set allowManagedMcpServersOnly to true in managed settings; denylists still merge from every scope, so users can always block a server for themselves.

## How do you allowlist or block MCP servers in GitHub Copilot and VS Code with enterprise-managed settings?
- GitHub's enterprise-managed settings reference defines allowedMcpServers (any server not matched is blocked; omit it to allow all; an empty array blocks everything except built-in default servers) and deniedMcpServers (blocked even if also allowlisted). It lists both keys as supported in Copilot CLI, VS Code, the GitHub Copilot app, Copilot in the cloud (sandbox) and JetBrains IDEs, and not in Copilot in the cloud on GitHub Actions.
- When several settings sources define an allowlist, the effective allowlist is their intersection, so a server must be permitted by every source; denylists are the union. First-party Copilot servers, such as the built-in GitHub MCP server, are exempt from deny rules. The reference also says the lists don't apply to MCP servers defined in repository custom agent profiles, and points to the coding agent firewall to block those.
- VS Code's enterprise AI settings page says user settings and workspace server definitions can't broaden the enterprise-managed allowlist or remove its deny rules, that commands and URLs are checked again after variable resolution, and that deny rules and setting chat.mcp.access to "none" take priority over the allowlist. It also warns that a cached GitHub registry policy isn't a startup guarantee and recommends the ChatMCP device policy for restrictions that must apply even when the policy fetch fails.

## How do you make an MCP server easy for a company to allowlist?
- Your server is approved by its address and launch line, not its name or its listing. In both products, the entries that actually constrain what runs are serverUrl and serverCommand, so whatever you publish as the URL and the install command becomes the identity a security team signs off on.
- Those rules check where a server is and how it's started, not what it does once running. A server at an approved URL can still change its tools after approval, so customers who need more than an address check pair the allowlist with version pinning and a check of the tool definitions before each upgrade.
- Small changes have outsized effects. A new subdomain, a non-default port, an added flag or a switch from npx to a binary each stop matching an existing entry, and in Claude Code the server then silently disappears for users. Treat these as breaking changes with notice, the same way you'd treat a removed tool.

## Ask Rightshold (free, no key)
Add the MCP server https://www.rightshold.com/mcp to Claude, Cursor, ChatGPT, Grok or VS Code (one-click setup: https://www.rightshold.com/start?ref=seo), then ask: "Our security team is deciding whether to add this MCP server to our allowedMcpServers list. Is it a listed server, what tools does it expose right now, and have its tool definitions changed since they were recorded?"

```json
{
  "tool": "precall_check",
  "arguments": {
    "url": "<the MCP server's https URL>",
    "tool": "<optional tool name>"
  }
}
```
- Free, no key. The answer combines the external registry entry, a live integrity probe against the recorded tool fingerprint, an invisible-text scan of the definitions, standing security flags and tool-name collision warnings. It's evidence to decide from, never a finding that a server is safe.
- It doesn't write or enforce your allowlist. allowedMcpServers and deniedMcpServers live in your Claude Code or Copilot managed settings. Checking a server doesn't register it.
- For a server registered on Rightshold, check_tool_integrity re-probes it before each upgrade and lists tools added, removed or changed since the recorded fingerprint, which is the part an address-based allowlist can't see.

_Rightshold reports what it has on record about MCP servers and probes the tool definitions they serve. It doesn't manage Claude Code, VS Code or GitHub Copilot settings and isn't affiliated with Anthropic, Microsoft or GitHub. Product behaviour is quoted from each vendor's documentation as checked on November 10, 2026, and changes between versions._

## Sources
- [Claude Code Docs: Control MCP server access for your organization (managed-mcp.json, allowedMcpServers, deniedMcpServers)](https://code.claude.com/docs/en/managed-mcp)
- [Claude Code Docs: Connect Claude Code to tools via MCP (scopes, project approvals, blocked-by-policy status)](https://code.claude.com/docs/en/mcp)
- [GitHub Docs: Enterprise managed settings reference (allowedMcpServers, deniedMcpServers, URL canonicalization)](https://docs.github.com/en/copilot/reference/enterprise-administrators/enterprise-managed-settings)
- [GitHub Docs: Getting started with enterprise-managed settings](https://docs.github.com/en/copilot/how-tos/administer-copilot/manage-for-enterprise/use-managed-settings/get-started)
- [Visual Studio Code Docs: Enterprise AI settings (managed MCP server access, registry precedence, ChatMCP policy)](https://code.visualstudio.com/docs/enterprise/ai-settings)

## Related
- [What does a verified namespace in the official MCP Registry prove?](https://www.rightshold.com/answers/what-does-a-verified-namespace-in-the-official-mcp-registry-prove)
- [How to name your MCP server so it isn't mistaken for a lookalike](https://www.rightshold.com/answers/how-to-name-your-mcp-server-so-it-isnt-mistaken-for-a-lookalike)
- [How to pin MCP server versions and review changes before upgrading](https://www.rightshold.com/answers/how-to-pin-mcp-server-versions-and-review-changes-before-upgrading)
- [How to keep API keys and tokens out of .mcp.json and Claude Desktop config files](https://www.rightshold.com/answers/how-to-keep-api-keys-and-tokens-out-of-mcp-json-and-claude-desktop-config-files)

_Not legal advice. Updated 2026-11-10. JSON: https://www.rightshold.com/answers/how-do-companies-allowlist-mcp-servers-in-claude-code-and-github-copilot-and-how-do-you-make-yours-easy-to-approve.json_