Control MCP server access for your organization changedmanaged-mcp
Nearest release: v2.1.288, published 12 hours after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 2 Oct 2026 06:16 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 4 Oct 2026 05:37 UTC.
Upstream edited
Recorded here
Lines+57added
Lines−31removed
From line
244
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits22to this page, all time
#### How `serverName` entries match #### How `serverCommand` entries match #### How `serverUrl` entries match #### Servers that skip the allowlist check #### How policy entries expand
The whole hunk
from line 244, old and new numbered
/
from line 244
244244
245245Allowlists and denylists filter which configured servers are allowed to load. They aren't a registry: a server still has to be added by a user, a plugin, or your organization before either list applies to it.
246246
247Servers your organization delivers through `managedMcpServers` load without an allowlist entry, and [How a server is evaluated](#how-a-server-is-evaluated) covers `managed-mcp.json` servers. The denylist applies to every server regardless of where it came from, other than in-process `type: "sdk"` entries.
247Servers your organization delivers through `managedMcpServers` load without an allowlist entry, and [Servers that skip the allowlist check](#servers-that-skip-the-allowlist-check) covers `managed-mcp.json` servers. The denylist applies to every server regardless of where it came from, other than in-process `type: "sdk"` entries.
248248
249249To deploy servers to users, use [`managed-mcp.json`](#exclusive-control-with-managed-mcp-json) or [`managedMcpServers`](#provide-servers-through-managed-settings). Both lists also filter servers a user passes with the [`--mcp-config` CLI flag](/docs/en/cli-reference#cli-flags), other than in-process `type: "sdk"` entries; `--strict-mcp-config` limits which configuration files load and doesn't bypass either list.
250250
from line 268
268268| :- | :- | :- |
269269| `serverUrl` | A remote server URL, exact or with `*` wildcards | HTTP and SSE servers |
270270| `serverCommand` | The exact command and arguments that start a stdio server | Stdio servers |
271| `serverName` | The user-assigned label. Exact match only; wildcards are not expanded | Either type, but see the Warning below |
271| `serverName` | The user-assigned label. Exact match only; wildcards are not expanded | Either type, but see [How `serverName` entries match](#how-servername-entries-match) |
272272
273273Leaving `allowedMcpServers` unset is different from setting it to an empty array:
274274
275275| Setting | Unset (default) | Empty array `[]` | Populated |
276276| :- | :- | :- | :- |
277| `allowedMcpServers` | All servers allowed | No servers allowed, apart from [those that skip the allowlist check](#how-a-server-is-evaluated) | Only matching servers allowed, apart from [those that skip the allowlist check](#how-a-server-is-evaluated) |
277| `allowedMcpServers` | All servers allowed | No servers allowed, apart from [those that skip the allowlist check](#servers-that-skip-the-allowlist-check) | Only matching servers allowed, apart from [those that skip the allowlist check](#servers-that-skip-the-allowlist-check) |
278278| `deniedMcpServers` | No servers blocked | No servers blocked | Matching servers blocked |
279279
280280See [Invalid entries in managed settings](/docs/en/managed-settings#invalid-entries-in-managed-settings) for what happens when an entry fails schema validation.
281281
282#### How `serverName` entries match
283
284A `serverName` entry matches the user-assigned label exactly, with no wildcards.
285
282286<Warning>
283287 A `serverName` entry, in either list, is not a security control. The name is the label a user assigns when running `claude mcp add` or editing a config file, not the underlying server, so a user can call any server `github`. For claude.ai connectors the name is the display name returned by claude.ai, which can change. To enforce which servers actually run, add `serverCommand` or `serverUrl` entries.
284288</Warning>
from line 294
290294
291295To turn off all the claude.ai connectors Claude Code fetches itself, see [`disableClaudeAiConnectors`](/docs/en/mcp#disable-claude-ai-connectors).
292296
293### How a server is evaluated
297#### How `serverCommand` entries match
294298
295Before loading a server, including one from `managed-mcp.json`, Claude Code runs the three checks below in order. It runs them again when a user reconnects a server or turns a disabled one back on in `/mcp`. In-process `type: "sdk"` servers, which the [app that started the session registers](/docs/en/mcp#how-connectors-reach-claude-code), skip all three.
299A `serverCommand` entry holds the command and its arguments as one array, as in `{ "serverCommand": ["npx", "-y", "server"] }`. Claude Code compares that array with the command and arguments in the server's configuration:
296300
2971. **Merge the lists.** Allowlist and denylist entries from every settings scope combine into one allowlist and one denylist. When `allowManagedMcpServersOnly` is `true`, only the managed allowlist is kept; the denylist always merges from every scope. When more than one managed source is present, [Keys read from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source) says which of them supply the managed scope's lists.
2982. **Check the denylist.** A server that matches any denylist entry, by URL, command, or name, is blocked. Nothing overrides a denylist match.
2993. **Check the allowlist.** If `allowedMcpServers` isn't set anywhere, every server that passed the denylist loads. If it is set, what the server must match depends on its type, shown in the table below.
301* **Commands match exactly.** Every argument, in order. `["npx", "-y", "server"]` does not match `["npx", "server"]` or `["npx", "-y", "server", "--flag"]`.
302* **The `env` block isn't compared.** `["node", "server.js"]` matches a server that runs that command with any `env` values. Some environment variables change what `node` loads at startup. To set the `env` values yourself, define the server in [`managed-mcp.json`](#exclusive-control-with-managed-mcp-json).
300303
301 Three groups of servers skip this check:
304#### How `serverUrl` entries match
302305
303 * The organization's own servers: every `managedMcpServers` entry, and any `managed-mcp.json` entry whose values use no `${VAR}` expansion.
304 * Built-in servers, such as Claude in Chrome, the `ide` server Claude Code connects to in a running VS Code or JetBrains IDE, and servers the CLI itself configures.
305 * A [Claude Tag](/docs/en/claude-tag) session's Slack tools: the servers it uses to read the thread and post its replies load without an allowlist entry.
306URLs support `*` wildcards anywhere in the pattern, including the scheme. Hostname matching is case-insensitive and ignores a trailing FQDN dot, so `https://Mcp.Example.com/*` matches `https://mcp.example.com/api`. Paths stay case-sensitive.
306307
307 A `managed-mcp.json` server that uses `${VAR}` expansion in its command, arguments, `env`, URL, or headers is still checked. So is every server a user, a plugin, or claude.ai adds, and every server a user passes with `--mcp-config`.
308The table shows what common patterns allow:
308309
309| Server type | Allowed when it matches |
310| :- | :- |
311| Remote (HTTP or SSE) | A `serverUrl` entry. A `serverName` match counts only when the allowlist contains no `serverUrl` entries |
312| Stdio | A `serverCommand` entry. A `serverName` match counts only when the allowlist contains no `serverCommand` entries |
313
314Three matching rules apply inside those checks:
315
316* **Commands match exactly.** Every argument, in order. `["npx", "-y", "server"]` does not match `["npx", "server"]` or `["npx", "-y", "server", "--flag"]`.
317* **`serverCommand` and `serverUrl` values expand before matching.** Both the policy entry and the server's configured value go through [`${VAR}` and `${VAR:-default}` expansion](/docs/en/mcp#environment-variable-expansion-in-mcp-json), so an entry written as `["${HOME}/bin/server"]` matches a server config that uses either the same reference or the expanded path. On Windows, reference an environment variable that is set there, such as `${USERPROFILE}` instead of `${HOME}`. `serverName` values match literally and never expand. The two sides read different environments; [How policy entries expand](#how-policy-entries-expand) covers which, and how allowlist and denylist entries differ.
318* **URLs support `*` wildcards** anywhere in the pattern, including the scheme. Hostname matching is case-insensitive and ignores a trailing FQDN dot, so `https://Mcp.Example.com/*` matches `https://mcp.example.com/api`. Paths stay case-sensitive.
319
320310| Pattern | Allows |
321311| :- | :- |
322312| `https://mcp.example.com/*` | All paths on a specific domain |
from line 315
325315| `http://localhost:*/*` | Any port on localhost |
326316| `*://mcp.example.com/*` | Any scheme to a specific domain |
327317
328#### How policy entries expand
318<h4 id="how-policy-entries-expand">
319 Environment variables in `serverCommand` and `serverUrl` entries
320</h4>
329321
330The server's configured value expands from the live process environment, like the rest of `.mcp.json`. A policy entry expands from a pinned environment instead, so a variable set by a project or user settings file can't change what an allowlist entry means. Because a policy entry still depends on the launching shell's value for any variable it references, use literal URLs and commands for entries you rely on for enforcement.
322`serverCommand` and `serverUrl` values expand before matching. Both the policy entry and the server's configured value go through [`${VAR}` and `${VAR:-default}` expansion](/docs/en/mcp#environment-variable-expansion-in-mcp-json), so an entry written as `["${HOME}/bin/server"]` matches a server config that uses either the same reference or the expanded path. `serverName` values match literally and never expand.
331323
324The two sides read different environments:
325
326* **The server's configured value**: expands from the live process environment, like the rest of `.mcp.json`
327* **A policy entry**: expands from a pinned environment, so a variable set by a project or user settings file can't change what an allowlist entry means
328
329Because a policy entry still depends on the launching shell's value for any variable it references, use literal URLs and commands for entries you rely on for enforcement.
330
331On Windows, reference an environment variable that is set there, such as `${USERPROFILE}` instead of `${HOME}`.
332
333The two lists expand differently:
334
332335| Entry list | Expands from | Expansion that would change a URL entry's scheme, host, or path scope |
333336| - | - | - |
334337| `allowedMcpServers` | The environment Claude Code started with, plus `env` values from managed settings | Claude Code ignores the entry |
335338| `deniedMcpServers` | The same, and a variable with no startup value and no `:-default` fills from settings files outside the repository, such as user or managed settings, which only ever widens what the entry matches | The entry still matches |
336339
337Requires Claude Code v2.1.219 or later.
340The pinned environment and the rules in this table require Claude Code v2.1.219 or later.
341
342### How a server is evaluated
343
344Before loading a server, including one from `managed-mcp.json`, Claude Code runs the three checks below in order. It runs them again when a user reconnects a server or turns a disabled one back on in `/mcp`. In-process `type: "sdk"` servers, which the [app that started the session registers](/docs/en/mcp#how-connectors-reach-claude-code), skip all three.
345
3461. **Merge the lists.** Allowlist and denylist entries from every settings scope combine into one allowlist and one denylist. When `allowManagedMcpServersOnly` is `true`, only the managed allowlist is kept; the denylist always merges from every scope. When more than one managed source is present, [Keys read from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source) says which of them supply the managed scope's lists.
3472. **Check the denylist.** A server that matches any denylist entry, by URL, command, or name, is blocked. Nothing overrides a denylist match.
3483. **Check the allowlist.** [Some servers skip this check](#servers-that-skip-the-allowlist-check). If `allowedMcpServers` isn't set anywhere, every server that passed the denylist loads. If it is set, what the server must match depends on its type, shown in the table below.
349
350| Server type | Allowed when it matches |
351| :- | :- |
352| Remote (HTTP or SSE) | A `serverUrl` entry. A `serverName` match counts only when the allowlist contains no `serverUrl` entries |
353| Stdio | A `serverCommand` entry. A `serverName` match counts only when the allowlist contains no `serverCommand` entries |
354
355#### Servers that skip the allowlist check
356
357Three groups of servers skip the allowlist check, in addition to the in-process `type: "sdk"` servers that skip [all three checks](#how-a-server-is-evaluated):
358
359* The organization's own servers: every `managedMcpServers` entry, and any `managed-mcp.json` entry whose values use no `${VAR}` expansion.
360* Built-in servers, such as Claude in Chrome, the `ide` server Claude Code connects to in a running VS Code or JetBrains IDE, and servers the CLI itself configures.
361* A [Claude Tag](/docs/en/claude-tag) session's Slack tools: the servers it uses to read the thread and post its replies load without an allowlist entry.
362
363A `managed-mcp.json` server that uses `${VAR}` expansion in its command, arguments, `env`, URL, or headers is still checked. Claude Code also checks every server a user, a plugin, or claude.ai adds, and every server a user passes with `--mcp-config`.
338364
339365### Example configuration
340366
No line in this hunk matches that.