MCP, plugins, skills, and hooks changedthird-party/claude-desktop/extensions
Nearest release: v2.1.302, published an hour before 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 16 Oct 2026 18:33 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 22 Oct 2026 18:07 UTC.
Upstream edited
Recorded here
Lines+40added
Lines−36removed
From line
2
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits25to this page, all time
The whole hunk
from line 2, old and new numbered
/
from line 2
22
33> Extend Claude Desktop on 3P with connectors, plugin marketplaces, organization plugins, skills, and hooks for administrators and end users
44
5Claude Desktop on third-party (3P) supports the same extensibility model as standard Claude Desktop ([MCP connectors](/docs/connectors/getting-started), [skills](/docs/skills/overview), and [plugins](/docs/plugins/overview)), with the key difference that administrators provision them through managed configuration and the filesystem rather than the claude.ai admin console.
5Claude Desktop on third-party (3P) supports the same extensibility model as standard Claude Desktop ([MCP connectors](/docs/connectors/getting-started.md), [skills](/docs/skills/overview.md), and [plugins](/docs/plugins/overview.md)), with the key difference that administrators provision them through managed configuration and the filesystem rather than the claude.ai admin console.
66
77There are three layers, in order of precedence:
88
from line 16
1616
1717## Managed MCP servers (admin)
1818
19Use the `managedMcpServers` configuration key to deploy MCP servers (remote HTTP/SSE or local stdio command) to every device. These appear in the user's connector list automatically, can't be removed by the user, and support per-tool policy locks (`allow` / `ask` / `blocked`). The same key also activates the servers bundled inside the app (Microsoft 365, web search, and GitHub); see [Built-in connectors](/docs/third-party/claude-desktop/built-in-connectors).
19Use the `managedMcpServers` configuration key to deploy MCP servers (remote HTTP/SSE or local stdio command) to every device. These appear in the user's connector list automatically, can't be removed by the user, and support per-tool policy locks (`allow` / `ask` / `blocked`). The same key also activates the servers bundled inside the app (Microsoft 365, web search, and GitHub); see [Built-in connectors](/docs/third-party/claude-desktop/built-in-connectors.md).
2020
21The **Connectors** section of the [in-app configuration window](/docs/third-party/claude-desktop/in-app-configuration) provides a form for each server: name, per-tool policy, headers or a headers helper script, transport, and URL.
21The **Connectors** section of the [in-app configuration window](/docs/third-party/claude-desktop/in-app-configuration.md) provides a form for each server: name, per-tool policy, headers or a headers helper script, transport, and URL.
2222
2323
2424
25A managed MCP server in the Connectors section of the in-app configuration window.
26
2527In the exported configuration, each server is one entry in the `managedMcpServers` array:
2628
2729```json theme={null}
from line 47
4547
4648> [!NOTE]
4749>
48> Every entry other than a [built-in server](/docs/third-party/claude-desktop/built-in-connectors) needs a `transport`. Claude Desktop doesn't read `type`, the field name that a plugin's `.mcp.json` file uses. It drops an entry that has no `transport` and reports a configuration error.
50> Every entry other than a [built-in server](/docs/third-party/claude-desktop/built-in-connectors.md) needs a `transport`. Claude Desktop doesn't read `type`, the field name that a plugin's `.mcp.json` file uses. It drops an entry that has no `transport` and reports a configuration error.
4951
5052See the [`managedMcpServers` schema](/docs/third-party/claude-desktop/configuration#managedmcpservers) in the configuration reference for every field, including static headers, OAuth, and the headers-helper executable for short-lived tokens.
5153
from line 63
6163http://127.0.0.1:53280/callback
6264```
6365
64The value is the same on every device and for every delivery method (device management, a local configuration file, or a [bootstrap server](/docs/third-party/claude-desktop/bootstrap)). On identity providers that accept any port on a loopback redirect URI (the [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) native-app pattern), a registration of `http://127.0.0.1/callback` also matches.
66The value is the same on every device and for every delivery method (device management, a local configuration file, or a [bootstrap server](/docs/third-party/claude-desktop/bootstrap.md)). On identity providers that accept any port on a loopback redirect URI (the [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252#section-7.3) native-app pattern), a registration of `http://127.0.0.1/callback` also matches.
6567
66With `"oauth": true`, Claude Desktop registers its own public client through dynamic client registration and lists this URI as the client's only redirect URI, so the authorization server must offer a registration endpoint and accept an `http` loopback redirect URI. With a client you registered yourself, set `oauth.clientId` and add the URI to that registration. If the registration uses `localhost` or another port, set `oauth.callbackHost` or `oauth.callbackPort` to match; both require `clientId`. [Set up sign-in for managed MCP servers](/docs/third-party/claude-desktop/mcp-sign-in) explains how to tell which servers need a client that you register, when a client secret is also required, and where the secret goes.
68With `"oauth": true`, Claude Desktop registers its own public client through dynamic client registration and lists this URI as the client's only redirect URI, so the authorization server must offer a registration endpoint and accept an `http` loopback redirect URI. With a client you registered yourself, set `oauth.clientId` and add the URI to that registration. If the registration uses `localhost` or another port, set `oauth.callbackHost` or `oauth.callbackPort` to match; both require `clientId`. [Set up sign-in for managed MCP servers](/docs/third-party/claude-desktop/mcp-sign-in.md) explains how to tell which servers need a client that you register, when a client secret is also required, and where the secret goes.
6769
68An `http` or `sse` entry with no `oauth`, no `headersHelper`, and no `Authorization` header is treated as `"oauth": true` when its server asks for authentication (Claude Desktop 1.24012.0 or later). This redirect URI applies to MCP server sign-in only. [Gateway single sign-on](/docs/third-party/claude-desktop/gateway#set-up-single-sign-on) and [bootstrap sign-in](/docs/third-party/claude-desktop/bootstrap#provider-notes) register their own loopback redirect URI.
70An `http` or `sse` entry with no `oauth`, no `headersHelper`, and no `Authorization` header is treated as `"oauth": true` when its server asks for authentication (Claude Desktop 1.24012.0 or later). This redirect URI applies to MCP server sign-in only. [Gateway single sign-on](/docs/third-party/claude-desktop/gateway.md#set-up-single-sign-on) and [bootstrap sign-in](/docs/third-party/claude-desktop/bootstrap.md#provider-notes) register their own loopback redirect URI.
6971
7072#### How OAuth sign-in works
7173
from line 85
8385
8486To name the authorization server yourself instead of discovering it, set `oauth.clientId` together with one of `oauth.tenantId` plus `oauth.scope` (Microsoft Entra ID), a single `oauth.authorizationServer` entry (the issuer URL exactly as that server's metadata states it), or `oauth.authorizationUrl` and `oauth.tokenUrl` for a provider that serves no discovery document. With several `oauth.authorizationServer` entries, discovery runs as in step 2 and the discovered authorization server must match one of them.
8587
86Tokens are stored on the device, encrypted with the operating system's secure storage (see [Credentials](/docs/third-party/claude-desktop/data-storage#credentials)), and refreshed in the background before they expire. When the authorization request carries a scope and the authorization server's metadata lists `offline_access`, Claude Desktop adds `offline_access` so that a refresh token is issued; see `oauth.scope` and `oauth.appendOfflineAccess` in the [configuration reference](/docs/third-party/claude-desktop/configuration#managedmcpservers) to change the requested scopes. If the authorization server rejects a refresh, or issued no refresh token and the access token expires, the server returns to the **Connect** state and the user signs in again. A stored sign-in belongs to the server's `url`, so after you change the `url`, each user signs in again.
88Tokens are stored on the device, encrypted with the operating system's secure storage (see [Credentials](/docs/third-party/claude-desktop/data-storage.md#credentials)), and refreshed in the background before they expire. When the authorization request carries a scope and the authorization server's metadata lists `offline_access`, Claude Desktop adds `offline_access` so that a refresh token is issued; see `oauth.scope` and `oauth.appendOfflineAccess` in the [configuration reference](/docs/third-party/claude-desktop/configuration.md#managedmcpservers) to change the requested scopes. If the authorization server rejects a refresh, or issued no refresh token and the access token expires, the server returns to the **Connect** state and the user signs in again. A stored sign-in belongs to the server's `url`, so after you change the `url`, each user signs in again.
8789
88If sign-in fails (the callback does not arrive within 120 seconds, the authorization server rejects the registration or the redirect URI, or the identity provider completes sign-in from a host other than the authorization endpoint's), the user sees a connection error, the server keeps its **Connect** button, and `main.log` in the [logs directory](/docs/third-party/claude-desktop/data-storage#where-data-lives) records the reason. For an identity provider that completes sign-in from a different host than its authorization endpoint, list that host in `oauth.additionalRedirectReferrerHosts`. The log names the rejected host.
90If sign-in fails (the callback does not arrive within 120 seconds, the authorization server rejects the registration or the redirect URI, or the identity provider completes sign-in from a host other than the authorization endpoint's), the user sees a connection error, the server keeps its **Connect** button, and `main.log` in the [logs directory](/docs/third-party/claude-desktop/data-storage.md#where-data-lives) records the reason. For an identity provider that completes sign-in from a different host than its authorization endpoint, list that host in `oauth.additionalRedirectReferrerHosts`. The log names the rejected host.
8991
90For a server whose OAuth sign-in goes to Microsoft Entra ID, you can run that sign-in through the [OS identity broker](/docs/third-party/claude-desktop/entra-broker) instead of the system browser by setting `authFlow` to `broker` inside the entry's `oauth` object, alongside `tenantId`, `clientId`, and `scope`. On a device where the broker is unavailable, sign-in for that server falls back to the system browser, so keep the loopback redirect URI registered as well if any devices lack the broker.
92For a server whose OAuth sign-in goes to Microsoft Entra ID, you can run that sign-in through the [OS identity broker](/docs/third-party/claude-desktop/entra-broker.md) instead of the system browser by setting `authFlow` to `broker` inside the entry's `oauth` object, alongside `tenantId`, `clientId`, and `scope`. On a device where the broker is unavailable, sign-in for that server falls back to the system browser, so keep the loopback redirect URI registered as well if any devices lack the broker.
9193
9294### Short-lived credentials with a headers helper
9395
from line 121
119121
120122> [!NOTE]
121123>
122> Some connectors return [MCP Apps](/docs/connectors/building/mcp-apps/getting-started), interactive widgets that Claude Desktop renders in place of a plain-text tool result. Each widget loads in a sandboxed iframe on `*.claudemcpcontent.com`, and setting [`disableNonessentialServices`](/docs/third-party/claude-desktop/configuration#disablenonessentialservices) to `true` blocks that origin, so Claude Desktop shows the connector's text result instead of the widget. The same key also blocks artifact previews and connector favicons. To keep MCP Apps rendering, leave `disableNonessentialServices` unset or `false`, and allow the widget hosts listed under [Required egress paths](/docs/third-party/claude-desktop/telemetry#required-egress-paths) at your perimeter firewall.
124> Some connectors return [MCP Apps](/docs/connectors/building/mcp-apps/getting-started.md), interactive widgets that Claude Desktop renders in place of a plain-text tool result. Each widget loads in a sandboxed iframe on `*.claudemcpcontent.com`, and setting [`disableNonessentialServices`](/docs/third-party/claude-desktop/configuration#disablenonessentialservices) to `true` blocks that origin, so Claude Desktop shows the connector's text result instead of the widget. The same key also blocks artifact previews and connector favicons. To keep MCP Apps rendering, leave `disableNonessentialServices` unset or `false`, and allow the widget hosts listed under [Required egress paths](/docs/third-party/claude-desktop/telemetry.md#required-egress-paths) at your perimeter firewall.
123125
124126### Productivity suites
125127
from line 131
129131>
130132> Gmail, Calendar, Drive, Docs, and more via Google's own Workspace MCP servers. See [Google's setup guide](https://developers.google.com/workspace/guides/configure-mcp-servers) to get started.
131133
132> **[Microsoft 365](/docs/third-party/claude-desktop/connectors-m365)**
134> **[Microsoft 365](/docs/third-party/claude-desktop/connectors-m365.md)**
133135>
134136> Outlook, OneDrive, SharePoint, and Teams. Requires registering an app in your Entra tenant. The remote connector also needs an Anthropic allowlist step.
135137
136138## Plugin marketplaces (admin)
137139
138A **plugin marketplace** is a catalog file (`marketplace.json`) that lists one or more Claude plugins. You host it either as a git repository or as a plain file over HTTPS. Claude Desktop fetches it on each device, lists its plugins under **Customize → Plugins → Discover → Organization** in both **Cowork** and [**Code**](/docs/third-party/claude-desktop/code), and keeps them in sync with the revision you pin. You control which plugins are available, which install automatically, and which are required.
140A **plugin marketplace** is a catalog file (`marketplace.json`) that lists one or more Claude plugins. You host it either as a git repository or as a plain file over HTTPS. Claude Desktop fetches it on each device, lists its plugins under **Customize → Plugins → Discover → Organization** in both **Cowork** and [**Code**](/docs/third-party/claude-desktop/code.md), and keeps them in sync with the revision you pin. You control which plugins are available, which install automatically, and which are required.
139141
140142This is the recommended way to distribute organization plugins. For a git-hosted marketplace, Claude Desktop clones with the git already installed on each device, so include git in your device baseline (Git for Windows on Windows; the Xcode Command Line Tools provide it on macOS); devices without git can use a [marketplace hosted over HTTPS](#host-the-marketplace-over-https-instead-of-git) instead. Use the [system-wide directory](#organization-plugins-admin) path when end-user devices cannot reach a git server or an HTTPS file host.
141143
from line 195
193195
194196### Configure the marketplace
195197
196You can add marketplaces directly in the [in-app configuration window](/docs/third-party/claude-desktop/in-app-configuration): in the **Plugins** section, click **Add marketplace** and choose **Blank**, **GitHub repo**, **Git URL**, or **Marketplace URL**. The form validates the entry and exports the encoded JSON for you.
198You can add marketplaces directly in the [in-app configuration window](/docs/third-party/claude-desktop/in-app-configuration.md): in the **Plugins** section, click **Add marketplace** and choose **Blank**, **GitHub repo**, **Git URL**, or **Marketplace URL**. The form validates the entry and exports the encoded JSON for you.
197199
198200
199201
200To write the configuration yourself instead, add the repository to the [`allowedPluginMarketplaces`](/docs/third-party/claude-desktop/configuration#allowedpluginmarketplaces) configuration key. The key is read from an MDM profile, local configuration, or the [bootstrap server](/docs/third-party/claude-desktop/bootstrap) response. In an MDM profile the value is a JSON array encoded as a string (see [Value types](/docs/third-party/claude-desktop/configuration#value-types)). In a local configuration file or the bootstrap response the value is a native JSON array.
202The Plugins section of the in-app configuration window, with the Add marketplace menu and the organization plugins folder.
201203
204To write the configuration yourself instead, add the repository to the [`allowedPluginMarketplaces`](/docs/third-party/claude-desktop/configuration#allowedpluginmarketplaces) configuration key. The key is read from an MDM profile, local configuration, or the [bootstrap server](/docs/third-party/claude-desktop/bootstrap.md) response. In an MDM profile the value is a JSON array encoded as a string (see [Value types](/docs/third-party/claude-desktop/configuration.md#value-types)). In a local configuration file or the bootstrap response the value is a native JSON array.
205
202206```xml .mobileconfig (macOS) theme={null}
203207<key>allowedPluginMarketplaces</key>
204208<string>[{"source":"github","repo":"acme-corp/claude-plugins","ref":"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0","credentialKind":"userGit","installationPreference":"auto_install"}]</string>
205209```
206210
207On Windows, write the same string to the `allowedPluginMarketplaces` value in the registry policy key your deployment already uses (`HKLM\SOFTWARE\Policies\Claude` for machine policy). Keep the value in the same hive as the rest of your configuration: when machine policy is present, the app ignores user policy entirely; see [Deploy the configuration](/docs/third-party/claude-desktop/mdm#4-deploy-the-configuration) for the exact rule. For GitLab, Bitbucket, or a self-hosted git server, use `"source": "git"` with a full HTTPS `url` instead of `repo`. For a [marketplace hosted over HTTPS without git](#host-the-marketplace-over-https-instead-of-git), use `"source": "url"` with `url` pointing at the `marketplace.json` file:
211On Windows, write the same string to the `allowedPluginMarketplaces` value in the registry policy key your deployment already uses (`HKLM\SOFTWARE\Policies\Claude` for machine policy). Keep the value in the same hive as the rest of your configuration: when machine policy is present, the app ignores user policy entirely; see [Deploy the configuration](/docs/third-party/claude-desktop/mdm.md#4-deploy-the-configuration) for the exact rule. For GitLab, Bitbucket, or a self-hosted git server, use `"source": "git"` with a full HTTPS `url` instead of `repo`. For a [marketplace hosted over HTTPS without git](#host-the-marketplace-over-https-instead-of-git), use `"source": "url"` with `url` pointing at the `marketplace.json` file:
208212
209213```json theme={null}
210214[{"source":"url","url":"https://plugins.acme.example.com/claude/marketplace.json","credentialKind":"inferenceCredential","installationPreference":"available"}]
from line 243
239243
240244#### Per-plugin auto-install from a trusted origin
241245
242A `url` marketplace served from your deployment's own [inference gateway](/docs/third-party/claude-desktop/gateway) origin (`inferenceGatewayBaseUrl`) or [bootstrap server](/docs/third-party/claude-desktop/bootstrap) origin (`bootstrapUrl`) can mark individual plugins for automatic installation inside `marketplace.json` itself, without a `manifestSha256` pin in configuration. Leave the entry's `installationPreference` at `"available"` and set `installationPreference` on each plugin you want installed automatically:
246A `url` marketplace served from your deployment's own [inference gateway](/docs/third-party/claude-desktop/gateway.md) origin (`inferenceGatewayBaseUrl`) or [bootstrap server](/docs/third-party/claude-desktop/bootstrap.md) origin (`bootstrapUrl`) can mark individual plugins for automatic installation inside `marketplace.json` itself, without a `manifestSha256` pin in configuration. Leave the entry's `installationPreference` at `"available"` and set `installationPreference` on each plugin you want installed automatically:
243247
244248```json marketplace.json theme={null}
245249{
from line 275
271275| - | - |
272276| `"anonymous"` | No credential is sent. Use for public repositories or unauthenticated file hosts. |
273277| `"userGit"` | Uses the git credential helpers already configured for the signed-in OS user (for example, `git-credential-manager`, macOS Keychain, or a GitHub CLI credential helper). Use when each user already has read access through their own account. For `url` sources, the same credential is sent as HTTP Basic on the manifest and archive requests. |
274| `"credentialHelper"` | Runs the executable at `credentialHelper`. If it prints a bare token, the token is used as the git password for username `x-access-token` (accepted by GitHub, GitLab, and Azure DevOps) and, for `url` sources, sent as `Authorization: Bearer <token>` on the manifest and archive requests. For hosts that need a particular username, print git-credential lines `username=<user>` and `password=<token>` instead (for example `x-token-auth` for Bitbucket Data Center access tokens, or `gitlab+deploy-token-N` for a GitLab deploy token); `url` sources then use HTTP Basic. Print `authtype=Bearer` and `credential=<token>` to force a bearer header. For `url` sources, the helper can instead print a flat JSON object of HTTP headers, such as `{"Authorization": "Bearer …", "X-Tenant": "acme"}` (the form a managed MCP server's `headersHelper` prints, not an inference credential helper's `{"token": …}` object), and Claude Desktop sends every header in it on each request to that marketplace. `github` and `git` sources refuse this form. Output that opens with `{` must be a valid header object, or the fetch is refused. Username forms require Claude Desktop 1.37937.0 or later. Otherwise follows the execution model of an [inference credential helper](/docs/third-party/claude-desktop/credential-helper). |
275| `"inferenceCredential"` | `url` sources only. Sends the credentials Claude Desktop already sends to your inference gateway or to your [bootstrap server](/docs/third-party/claude-desktop/bootstrap), so a marketplace hosted on either is private to signed-in members without a separate credential. On the gateway's origin it sends the same `Authorization` bearer as inference and works for [gateway single sign-on](/docs/third-party/claude-desktop/gateway#single-sign-on-with-your-identity-provider), a [credential helper](/docs/third-party/claude-desktop/credential-helper), and bearer-scheme API keys. On the bootstrap server's origin (Claude Desktop 1.37937.0 or later) it sends the bootstrap sign-in token or your `bootstrapHeaders` and `bootstrapHeadersHelper` headers. Claude Desktop sends a credential only when the marketplace URL is on one of those two origins. When there is nothing to send yet (no sign-in held and no bootstrap headers configured, or a gateway API key sent as `x-api-key` rather than a bearer), no request is made and the entry reports why in the diagnostic report. |
278| `"credentialHelper"` | Runs the executable at `credentialHelper`. If it prints a bare token, the token is used as the git password for username `x-access-token` (accepted by GitHub, GitLab, and Azure DevOps) and, for `url` sources, sent as `Authorization: Bearer <token>` on the manifest and archive requests. For hosts that need a particular username, print git-credential lines `username=<user>` and `password=<token>` instead (for example `x-token-auth` for Bitbucket Data Center access tokens, or `gitlab+deploy-token-N` for a GitLab deploy token); `url` sources then use HTTP Basic. Print `authtype=Bearer` and `credential=<token>` to force a bearer header. For `url` sources, the helper can instead print a flat JSON object of HTTP headers, such as `{"Authorization": "Bearer …", "X-Tenant": "acme"}` (the form a managed MCP server's `headersHelper` prints, not an inference credential helper's `{"token": …}` object), and Claude Desktop sends every header in it on each request to that marketplace. `github` and `git` sources refuse this form. Output that opens with `{` must be a valid header object, or the fetch is refused. Username forms require Claude Desktop 1.37937.0 or later. Otherwise follows the execution model of an [inference credential helper](/docs/third-party/claude-desktop/credential-helper.md). |
279| `"inferenceCredential"` | `url` sources only. Sends the credentials Claude Desktop already sends to your inference gateway or to your [bootstrap server](/docs/third-party/claude-desktop/bootstrap.md), so a marketplace hosted on either is private to signed-in members without a separate credential. On the gateway's origin it sends the same `Authorization` bearer as inference and works for [gateway single sign-on](/docs/third-party/claude-desktop/gateway.md#single-sign-on-with-your-identity-provider), a [credential helper](/docs/third-party/claude-desktop/credential-helper.md), and bearer-scheme API keys. On the bootstrap server's origin (Claude Desktop 1.37937.0 or later) it sends the bootstrap sign-in token or your `bootstrapHeaders` and `bootstrapHeadersHelper` headers. Claude Desktop sends a credential only when the marketplace URL is on one of those two origins. When there is nothing to send yet (no sign-in held and no bootstrap headers configured, or a gateway API key sent as `x-api-key` rather than a bearer), no request is made and the entry reports why in the diagnostic report. |
276280
277281Because the fetch happens on the host, the marketplace host does not need to be on the [`coworkEgressAllowedHosts`](/docs/third-party/claude-desktop/configuration#coworkegressallowedhosts) allowlist. It does need to be reachable from end-user devices.
278282
from line 290
286290>
287291> For most deployments, distribute organization plugins via a [plugin marketplace](#plugin-marketplaces-admin) instead. Marketplaces let you manage plugin content in git or on any HTTPS file host and roll out updates by changing a single configuration value, rather than pushing files to every device. Use the directory path below when end-user devices cannot reach a git server or an HTTPS file host.
288292
289[Plugins](/docs/plugins/overview) bundle MCP connectors, skills, slash commands, hooks, and sub-agents into a single directory. On this path, admins distribute plugins by placing them in a system-wide directory on each device, typically via the same MDM or software-distribution channel used for the app itself. Plugins distributed this way are available in Cowork sessions and Chat conversations. Code sessions do not load their skills, commands, sub-agents, or hooks, so a plugin that must reach Code sessions has to be distributed through a [plugin marketplace](#plugin-marketplaces-admin) instead.
293[Plugins](/docs/plugins/overview.md) bundle MCP connectors, skills, slash commands, hooks, and sub-agents into a single directory. On this path, admins distribute plugins by placing them in a system-wide directory on each device, typically via the same MDM or software-distribution channel used for the app itself. Plugins distributed this way are available in Cowork sessions and Chat conversations. Code sessions do not load their skills, commands, sub-agents, or hooks, so a plugin that must reach Code sessions has to be distributed through a [plugin marketplace](#plugin-marketplaces-admin) instead.
290294
291295### Plugin directory location
292296
from line 328
324328| `.mcp.json` | MCP servers bundled with this plugin. A JSON object keyed by server name: `{"mcpServers": {"<name>": {"type": "http", "url": "...", "oauth": true}}}`. A remote entry uses `type` (`http` or `sse`), not `transport`, and supports `url`, `headers`, and `oauth` only. `toolPolicy`, `headersHelper`, and `headersHelperTtlSec` are not read from this file. A local entry gives a `command` with optional `args` and `env` (`type` is `"stdio"` or omitted). Give `command` as a program name on `PATH` or an absolute path, using `${CLAUDE_PLUGIN_ROOT}` for the plugin's directory under `org-plugins/`. Claude Desktop starts these local servers itself, including when [`isLocalDevMcpEnabled`](/docs/third-party/claude-desktop/configuration#islocaldevmcpenabled) is `false`. Local entries require Claude Desktop 1.49585.0 or later. A local entry that references `${user_config.<key>}` is skipped, because per-user plugin settings are not available to organization plugins. The diagnostic report's **MCP servers** section lists each server, with the reason for any it skipped. |
325329| `agents/` | Sub-agent definitions. |
326330| `commands/` | Slash-command definitions. |
327| `skills/` | [Skill](/docs/skills/overview) directories. |
331| `skills/` | [Skill](/docs/skills/overview.md) directories. |
328332| `hooks/` | Hook definitions that run on agent lifecycle events. See [Plugin hooks](#plugin-hooks) for where they run. |
329333
330334> [!NOTE]
from line 381
377381[Hooks](https://code.claude.com/docs/en/hooks) bundled in a plugin, under `hooks/` or declared in its manifest, run wherever the plugin itself loads:
378382
379383* **Cowork sessions** run hooks from marketplace plugins, from plugins in the `org-plugins/` directory, and from plugins users add themselves.
380* **Code sessions** run hooks from marketplace plugins (Claude Desktop 1.32352.0 or later) and from plugins the user installed for Claude Code. Hooks from plugins in the `org-plugins/` directory do not run in Code sessions. In [remote SSH sessions](/docs/third-party/claude-desktop/ssh-remote-sessions#managed-configuration-on-the-remote-host), hooks from the plugins Claude Desktop copies to the host do not run.
384* **Code sessions** run hooks from marketplace plugins (Claude Desktop 1.32352.0 or later) and from plugins the user installed for Claude Code. Hooks from plugins in the `org-plugins/` directory do not run in Code sessions. In [remote SSH sessions](/docs/third-party/claude-desktop/ssh-remote-sessions.md#managed-configuration-on-the-remote-host), hooks from the plugins Claude Desktop copies to the host do not run.
381385* **Chat conversations** run hooks from the same plugins as Cowork sessions, on Claude Desktop 1.52386.0 or later.
382386
383With [Unified Claude](/docs/third-party/claude-desktop/unified-claude) on, a Cowork session started from the home screen runs the same hooks as any other Cowork session.
387With [Unified Claude](/docs/third-party/claude-desktop/unified-claude.md) on, a Cowork session started from the home screen runs the same hooks as any other Cowork session.
384388
385389A `UserPromptSubmit` hook that blocks a prompt stops that turn and shows the hook's reason to the user. When a conversation or session is created, Claude Desktop also sends its first message to your inference provider in a separate request, without tools, to generate the title shown in the sidebar. That request does not pass through plugin hooks, so a first message that a hook blocks still reaches your provider for titling.
386390
387Claude Code [managed settings](/docs/third-party/claude-desktop/code#interaction-with-claude-code%E2%80%99s-own-managed-settings) deployed on the device govern these hooks as they do in the Claude Code CLI: `disableAllHooks` turns them off, and `allowManagedHooksOnly` keeps only the hooks those managed settings define.
391Claude Code [managed settings](/docs/third-party/claude-desktop/code.md#interaction-with-claude-code%E2%80%99s-own-managed-settings) deployed on the device govern these hooks as they do in the Claude Code CLI: `disableAllHooks` turns them off, and `allowManagedHooksOnly` keeps only the hooks those managed settings define.
388392
389393### Hooks on Windows devices without Git for Windows
390394
from line 396
392396
393397A [`PreToolUse`](https://code.claude.com/docs/en/hooks#pretooluse) hook that runs this way and has no `onFailure` field blocks the tool call when it fails or times out. The hook error that Claude receives includes `blocking because Git Bash wasn't found`.
394398
395If your Windows devices have hooks, in a plugin or in Claude Code [managed settings](/docs/third-party/claude-desktop/code#interaction-with-claude-code%E2%80%99s-own-managed-settings), make one of these changes:
399If your Windows devices have hooks, in a plugin or in Claude Code [managed settings](/docs/third-party/claude-desktop/code.md#interaction-with-claude-code%E2%80%99s-own-managed-settings), make one of these changes:
396400
397401* **Keep a hook written for Bash**: install Git for Windows in its default location (`C:\Program Files\Git`) on each device, then quit and reopen Claude Desktop
398402* **Run the hook without a shell**: write the hook in [exec form](https://code.claude.com/docs/en/hooks#exec-form-and-shell-form), with the program in `command` and its arguments in `args`
from line 408
404408Unless restricted by an admin, end users can add their own extensions through the in-app UI:
405409
406410* **Plugins:** install plugins (which can bundle skills, hooks, slash commands, and sub-agents) from the Plugins settings page
407* **Skills:** create and upload their own [skills](/docs/skills/overview), including by asking Claude to save one in a conversation
411* **Skills:** create and upload their own [skills](/docs/skills/overview.md), including by asking Claude to save one in a conversation
408412* **Local MCP servers:** add local MCP server processes from **Settings → Developer**
409413
410End users cannot add remote MCP servers from the app's settings or install desktop extension files (`.mcpb`) themselves. Remote servers come from admin-provisioned `managedMcpServers`, from organization plugins, and from other plugins that bundle them, including plugins users install. A Code session can also load the servers a user defines in Claude Code's own configuration (`~/.claude.json`, a project's `.mcp.json`, or `claude mcp add`). To limit plugin-bundled servers, see [Controlling user extensions](#controlling-user-extensions). To limit the servers a Code session loads, see [Applied as managed policy](/docs/third-party/claude-desktop/code#applied-as-managed-policy).
414End users cannot add remote MCP servers from the app's settings or install desktop extension files (`.mcpb`) themselves. Remote servers come from admin-provisioned `managedMcpServers`, from organization plugins, and from other plugins that bundle them, including plugins users install. A Code session can also load the servers a user defines in Claude Code's own configuration (`~/.claude.json`, a project's `.mcp.json`, or `claude mcp add`). To limit plugin-bundled servers, see [Controlling user extensions](#controlling-user-extensions). To limit the servers a Code session loads, see [Applied as managed policy](/docs/third-party/claude-desktop/code.md#applied-as-managed-policy).
411415
412User-added extensions are stored in the user's [local data directory](/docs/third-party/claude-desktop/data-storage) and apply only to that device.
416User-added extensions are stored in the user's [local data directory](/docs/third-party/claude-desktop/data-storage.md) and apply only to that device.
413417
414418Claude Desktop keeps its own record of the skills each user creates or uploads, and it removes a skill folder that the record doesn't list. To deliver skills to users, use [organization plugins](#organization-plugins-admin) or a [plugin marketplace](#plugin-marketplaces-admin).
415419
from line 430
426430| `userPluginMarketplacesEnabled` | `true` | Users cannot add plugin marketplaces of their own, and the add-marketplace options are hidden. Marketplaces your organization did not [provision](#plugin-marketplaces-admin) are hidden too, and the app neither installs nor loads their plugins. The organization plugins directory, plugins users uploaded, and marketplaces you provision with `allowedPluginMarketplaces` are unaffected. |
427431| `userPluginUploadsEnabled` | `true` | Users cannot upload plugin files or create plugins with Claude; every in-app option for adding a plugin of their own is hidden. Plugins from your marketplaces and the organization plugins directory are unaffected. |
428432
429Setting `isLocalDevMcpEnabled` to `false` and leaving `isDesktopExtensionEnabled` at `false` restricts MCP servers and connectors to those delivered through `managedMcpServers` and `org-plugins/`, plus any that installed plugins bundle, whether from your marketplaces or added by users. To limit plugin-bundled servers to ones you name, or to none, set [`allowedPluginMcpServers`](/docs/third-party/claude-desktop/configuration#allowedpluginmcpservers) to a list of URL patterns. An empty list admits no plugin-bundled server. Setting [`skillCreationEnabled`](/docs/third-party/claude-desktop/configuration#skillcreationenabled) to `false` turns off skill creation and upload in the app. Skills already on the device keep working, as do skills from [organization plugins](#organization-plugins-admin). Users can still install plugins from the marketplaces you provision regardless of these settings. Setting `userPluginUploadsEnabled` to `false` removes only users' options for adding plugins themselves. Plugins a user uploaded earlier stay in place. See the [Locked down profile](/docs/third-party/claude-desktop/configuration#recommended-security-profiles) for a complete example.
433Setting `isLocalDevMcpEnabled` to `false` and leaving `isDesktopExtensionEnabled` at `false` restricts MCP servers and connectors to those delivered through `managedMcpServers` and `org-plugins/`, plus any that installed plugins bundle, whether from your marketplaces or added by users. To limit plugin-bundled servers to ones you name, or to none, set [`allowedPluginMcpServers`](/docs/third-party/claude-desktop/configuration#allowedpluginmcpservers) to a list of URL patterns. An empty list admits no plugin-bundled server. Setting [`skillCreationEnabled`](/docs/third-party/claude-desktop/configuration#skillcreationenabled) to `false` turns off skill creation and upload in the app. Skills already on the device keep working, as do skills from [organization plugins](#organization-plugins-admin). Users can still install plugins from the marketplaces you provision regardless of these settings. Setting `userPluginUploadsEnabled` to `false` removes only users' options for adding plugins themselves. Plugins a user uploaded earlier stay in place. See the [Locked down profile](/docs/third-party/claude-desktop/configuration.md#recommended-security-profiles) for a complete example.
430434
431435Setting [`userPluginMarketplacesEnabled`](/docs/third-party/claude-desktop/configuration#userpluginmarketplacesenabled) to `false` also hides every marketplace already on the device that your organization didn't [provision](#plugin-marketplaces-admin), whether a user added it in the app earlier or Claude Code registered it from a terminal on the same device. By default, Claude Code adds [Anthropic's official marketplace](https://code.claude.com/docs/en/plugins/anthropic-marketplaces) the first time a user starts an interactive terminal session, so that marketplace is hidden too unless you provision it. The app doesn't install or update plugins from a hidden marketplace. Plugins already installed from a hidden marketplace stay on the device, but they don't appear in the app or load in its sessions until you remove the key or set it back to `true`.
432436
from line 438
434438
435439## Related topics
436440
437> **[Code](/docs/third-party/claude-desktop/code)**
441> **[Code](/docs/third-party/claude-desktop/code.md)**
438442>
439443> How extensions and managed settings reach the embedded Claude Code engine.
440444
No line in this hunk matches that.