> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin MCP servers in Devin

> Declare MCP servers in a Devin plugin and decide who holds the credential: each member, an organization service account, or the enterprise.

A plugin can include MCP servers (for example an issue tracker), so everyone who installs it gets the same server configuration without setting it up from scratch. After installing it, you supply any credentials the server needs, such as an API key or an OAuth sign-in. A connection can be personal or shared, depending on where the plugin is installed and the installation's **Access** setting.

## The declaration

Declare servers in a root `.mcp.json` as an `mcpServers` map. The manifest's inline `mcpServers` field takes the same map without the wrapper.

```json theme={null}
{
  "mcpServers": {
    "example-mcp": {
      "url": "https://mcp.example.com/mcp",
      "tokenScope": "user"
    },
    "example-mcp-service-account": {
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${EXAMPLE_MCP_SERVICE_ACCOUNT_TOKEN}"
      }
    }
  }
}
```

| Field | Type | What it does |
| - | - | - |
| `url` | string | The server's endpoint. Required. |
| `transport` | string | Set `"sse"` for a legacy SSE endpoint. Omit it for Streamable HTTP. |
| `headers` | object | HTTP headers sent with every request. Values may hold placeholders. |
| `oauthClientId` | string | A pre-registered OAuth client, for providers without dynamic client registration. Setting it makes the server OAuth, whatever its headers. |
| `oauthClientSecret` | string | Not accepted from a plugin: the declaration is rejected. The installing admin enters the secret in the server's settings. |
| `oauthScopes` | string\[] | Scopes to request. Requires `oauthClientId`. |
| `oauthResource` | string | Overrides the RFC 8707 `resource` parameter (default: the server URL). `""` omits it; any other value must identify this server. |
| `tokenScope` | string | Default **Access** for an organization or enterprise installation of an OAuth server: `"user"` (each member signs in) or `"org"` (one shared connection). Unset, the marketplace entry's scope applies, otherwise a shared connection. A declared value is reapplied each time the plugin is reconciled. A personal installation is always the member's own. |
| `disabled` | boolean | `true` skips the server. |
| `disabledTools` | string\[] | Tool names hidden from Devin on this server. |
| `description` | string | Shown with the server in Customize. |

**Placeholders.** `${NAME}` in `url` or `headers` is filled in by the installer from the server's Connect sheet. `${NAME:-default}` supplies a fallback when nothing is saved. A plugin server reads only values saved on its installation, not same-named [session secrets](https://docs.devin.ai/product-guides/secrets.md). Never write a real token into a declaration: it is stored as written.

A server can instead run a local command (`command`, `args`, `env`); it takes none of the HTTP credential fields above.

> [!NOTE]
>
> The [MCP servers](https://docs.devin.ai/work-with-devin/mcp.md#configuration-format) page documents the Customize form for a standalone server. A plugin's server uses the field names above, and its URL, transport, and headers show read-only on the installed row.

## Who holds the credential

| Installed by | Credential belongs to | Who connects |
| - | - | - |
| A member (personal scope) | That member | The member, from Customize → MCPs |
| An organization | The organization (`Access: Organization`) or each member (`Access: Personal`) | An org admin, or each member |
| The enterprise | The enterprise (`Access: Enterprise`) or each member in every org (`Access: Personal`) | An enterprise admin, or each member |

## Setups

Each setup combines one entry from the declaration above with where the plugin is installed and how it is distributed: **Required** installs it for everyone in the scope, **Offered** lets each organization or member install it. Both are set on the plugin in [Customize](https://docs.devin.ai/product-guides/plugins.md#mcps).

### 1. Per-user OAuth for everyone

For a server that supports OAuth, use the `example-mcp` entry and install the plugin as **Required** at the enterprise or organization.

`tokenScope: "user"` defaults Access to **Personal**, so each member signs in once, from Customize → MCPs or the first session that needs it.

### 2. One organization service account

Use the `example-mcp-service-account` entry and install the plugin at the organization.

* The `Authorization` header holds a placeholder, so the row shows **Connect**. An org admin enters the token; members never see it.
* If the server rejects the token (401), the row says **Check the credential**. If the server also advertises OAuth, the row adds **Sign in with OAuth instead**.
* For a service account that signs in with OAuth, drop the header, set `tokenScope: "org"`, and connect that account's login.

### 3. One key per organization

Put the `example-mcp-service-account` entry in an enterprise plugin and set it to **Offered to organizations**.

* Each organization that installs it owns its installation, so its admin fills in `${EXAMPLE_MCP_SERVICE_ACCOUNT_TOKEN}` with that organization's key.
* Nothing is connected at the enterprise, and no organization sees another's key.
* A **Required** enterprise plugin creates one enterprise-owned installation instead: one key for all organizations.

### 4. Both in one plugin

Ship both entries, as in the declaration above, and offer the plugin. Each organization that installs it gets two rows: one members sign into, one the org admin connects. Distinct server names let the plugin's skills say which server to use.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.