Model Context Protocol (MCP)

Connect your own tools with Model Context Protocol

Model Context Protocol (MCP) servers extend Droid's capabilities with extra tools and context. You can manage them two ways: an interactive manager inside the TUI for browsing and setup, or droid mcp CLI commands for scripting and automation. Droid supports three transports: stdio (local processes), http (Streamable HTTP, the current MCP standard, which streams responses over SSE internally), and sse (the legacy standalone HTTP+SSE transport, for older servers).

Quick start: add from the registry

The fastest way to start is the built-in server registry.

  1. 1
    Open the manager

    Type /mcp inside Droid and select Add from Registry.

  2. 2
    Pick a server

    Browse the registry and choose one, such as linear, sentry, or playwright.

  3. 3
    Authenticate

    For remote servers that need OAuth, follow the browser prompt. The server is then ready to use.

Representative registry servers include:

ServerDescription
linearIssue tracking and project management
sentryError tracking and performance monitoring
notionNotes, docs, and project management
figmaGenerate code with Figma context
stripePayment processing APIs
supabaseCreate and manage Supabase projects
vercelManage projects and deployments
playwrightEnd-to-end browser testing

The registry includes many more servers than shown here.

Tip

The registry is the quickest path for popular servers. For custom servers or automation, use the CLI commands below.

Manage servers interactively (/mcp)

Type /mcp inside Droid to open the interactive manager. From there you can:

  • Browse servers and see their connection status.
  • View tools that each connected server provides.
  • Enable or disable servers without removing them.
  • Authenticate OAuth-enabled servers via the browser.
  • Clear auth to remove stored credentials for a server.
  • Add from registry for one-click setup of popular servers.
  • Remove user-configured servers.

Run /mcp off to disable every configurable server for the current session. Organization-managed servers are unaffected.

Add servers from the CLI

For scripting and automation, use droid mcp add. The transport flag determines how the rest of the arguments are parsed.

Bash
droid mcp add <name> <urlOrCommand...> --type <stdio|http|sse>
  • name is a unique server identifier.
  • --type defaults to stdio when omitted.
  • --env KEY=VALUE sets environment variables (stdio only, repeatable).
  • --header "KEY: VALUE" sets HTTP headers (http/sse only, repeatable).
  • --no-oauth disables OAuth for a header- or API-key-authenticated remote server (stores oauth: false).

HTTP servers are remote MCP endpoints, the recommended way to connect to cloud services.

Bash
droid mcp add linear https://mcp.linear.app/mcp --type http

Pass authentication headers with --header, repeating the flag as needed:

Bash
droid mcp add twelvelabs https://mcp.twelvelabs.io --type http \
  --header "x-api-key: YOUR_API_KEY"

Use --no-oauth when a server authenticates by header or API key and you do not want Droid to attempt an OAuth flow:

Bash
droid mcp add internal https://mcp.internal.example.com/mcp --type http \
  --header "Authorization: Bearer YOUR_TOKEN" --no-oauth

sse is the legacy HTTP+SSE transport. Prefer http (which already streams over SSE internally) and reach for sse only when a server offers just the older standalone SSE endpoint. Arguments mirror HTTP; only --type changes.

Bash
droid mcp add example-sse https://mcp.example.com/sse --type sse \
  --header "Authorization: Bearer YOUR_TOKEN"

Stdio servers run as local processes, ideal for tools that need direct system access. Quote the command if it contains spaces, and pass environment variables with --env.

Bash
droid mcp add airtable "npx -y airtable-mcp-server" \
  --env AIRTABLE_API_KEY=your_key
Tip

npx examples install the latest published version of a package. For security-sensitive setups, pin an explicit version (for example airtable-mcp-server@1.4.0) so updates are deliberate and auditable.

Tip

Many remote servers require OAuth. After adding one, run /mcp to complete the browser authentication flow.

Manage servers from the CLI

List every configured server with its connection and authentication status:

Bash
droid mcp list

Each server reports its current status: connected, connecting, needs authentication, or failed. Servers that require OAuth show needs authentication until you finish the sign-in flow with /mcp.

Remove a user-configured server:

Bash
droid mcp remove <name>

Persistent tool permissions

When you approve an MCP tool, Droid can remember that approval so it persists across sessions. Each approval is bound to a stable fingerprint of the server's transport configuration (its stdio command and arguments, or its http/sse URL). If a previously trusted server name is later re-pointed at a different command or URL, the stored approval no longer applies and the tool must be approved again.

Manage these approvals with droid mcp permissions:

Bash
droid mcp permissions list
droid mcp permissions revoke <server> [tool]
droid mcp permissions clear --confirm
  • list shows all persistent permissions.
  • revoke <server> removes a server's approval, including all of its per-tool approvals. Add a tool argument to revoke a single tool.
  • clear --confirm removes every persistent permission.

Configuration file

MCP server configurations are stored in mcp.json files at three levels:

LevelLocationPurpose
User~/.factory/mcp.jsonYour personal servers, available in every project.
Folder.factory/mcp.json in an ancestor directory of the projectServers shared across nested projects under a common parent.
Project.factory/mcp.json in the project rootShared team servers, committed to the repo.

Organizations can also provide servers centrally and restrict which ones are allowed through managed settings (see Enterprise: MCP policy).

Behaviors to know:

  • Servers you add with droid mcp add or the registry always go to your user config.
  • Project servers cannot be removed with droid mcp remove or the /mcp manager. To remove them, edit .factory/mcp.json directly.
  • When you enable or disable a project-defined server, Droid writes a copy to your user config with the new state and leaves the project file untouched, so your teammates are unaffected.
  • When the same server name is defined at more than one level, Droid loads one definition for it. Organization-managed servers and the MCP policy always take precedence. The /mcp manager shows which file each server comes from.

OAuth tokens are stored globally in your system keyring (or a fallback file), not per project, so authenticating with a server in one project authenticates it everywhere that server is configured. Use the /mcp manager's Clear Auth action to remove stored credentials.

Warning

Project-level .factory/mcp.json is committed to the repo. Never put secrets there: header auth tokens (such as Authorization), oauth.clientSecret, or API keys. Keep them in your user-level config (~/.factory/mcp.json), supply them through environment variables, and rely on Droid's keyring for OAuth tokens.

Droid reloads automatically when an mcp.json file changes, so new servers are available immediately.

{
  "mcpServers": {
    "linear": {
      "type": "http",
      "url": "https://mcp.linear.app/mcp",
      "disabled": false
    }
  }
}

Schema reference

Each server entry accepts these common fields:

FieldTypeDescription
type"stdio" | "http" | "sse"Transport. May be omitted for stdio servers, which default to stdio.
disabledbooleanTemporarily disable the server (default: false).
disabledToolsstring[]Tool names to exclude from this server. Excluded tools are never loaded into context.
timeoutnumberPer-server MCP tool call timeout in milliseconds. Falls back to the built-in default when omitted.

Transport-specific fields:

  • stdio servers use command (the executable), args (an array of arguments), and env (an object of environment variables).
  • http and sse servers use url (the endpoint), headers (an object of HTTP headers), and oauth (OAuth overrides, or false to disable OAuth entirely).

Tool filtering

A server can expose many tools, and you may not want all of them in every session. Use disabledTools to exclude specific tools persistently in mcp.json. Every tool the server reports is loaded except the listed names, and excluded tools are never registered with the model, so they do not consume context tokens.

mcp.json
{
  "mcpServers": {
    "my-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@some/mcp-server"],
      "disabledTools": ["tool_i_dont_need", "another_unused_tool"]
    }
  }
}
Tip

Run /mcp to see the exact tool names a server exposes, then copy them into disabledTools.

Secrets and variable expansion

Droid expands ${NAME} references in mcp.json against your current shell environment when it connects to a server. This keeps secrets out of the file itself so you can source them from a secret manager, a .env loader, or your shell profile. Only the ${NAME} form is supported; there is no default-value syntax.

Expansion applies to credential-bearing fields only:

  • env values for stdio servers.
  • headers values for http and sse servers.
  • oauth.clientId and oauth.clientSecret for http and sse servers.

It does not apply to command, args, or url.

mcp.json
{
  "mcpServers": {
    "context7": {
      "type": "http",
      "url": "https://mcp.context7.com/mcp",
      "headers": {
        "CONTEXT7_API_KEY": "${CONTEXT7_API_KEY}"
      },
      "disabled": false
    },
    "airtable": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "airtable-mcp-server"],
      "env": {
        "AIRTABLE_API_KEY": "${AIRTABLE_API_KEY}"
      }
    }
  }
}

If a referenced variable is unset, the connection to that server fails with an error naming the missing variable. The raw mcp.json file is never rewritten with expanded values; expansion happens in memory at connection time, so secrets stay out of disk and version control.

OAuth overrides

For most remote servers, OAuth works with zero configuration: Droid discovers the authorization server, registers a client automatically via Dynamic Client Registration (DCR), and uses Factory's published client metadata when the server supports Client ID Metadata Documents (CIMD). Prefer these defaults. Only set oauth overrides when a provider requires a custom trust or compatibility policy. Set oauth: false to disable OAuth for a server entirely.

The oauth object on an http or sse server supports:

FieldTypeDescription
scopesstring[]OAuth scopes to request instead of the discovered defaults.
resourcestring | falseOAuth resource indicator to send instead of the normalized MCP server URL; set to false to omit it.
authorizationServerIssuerstringAuthorization server issuer URL. Required when clientId / clientSecret are set.
clientIdstringPre-registered OAuth client ID, skipping dynamic registration.
clientSecretstringClient secret for the pre-registered client.
clientMetadataUrlstringHTTPS URL of a custom Client ID Metadata Document (CIMD) to use as the public client identity.
tokenEndpointAuthMethod"none" | "client_secret_basic" | "client_secret_post"Force a token endpoint authentication method instead of the discovered one.
callbackPortnumberFixed localhost port for the OAuth callback (1-65535).

Constraints:

  • clientMetadataUrl must be an HTTPS URL with a non-root path and no credentials, query string, fragment, or dot segments.
  • clientMetadataUrl is mutually exclusive with clientId / clientSecret: a metadata document is the client identity, so pre-registered credentials cannot be combined with it.
  • clientMetadataUrl describes a public client, so tokenEndpointAuthMethod must be "none" (or omitted) when it is set.
  • clientId / clientSecret require authorizationServerIssuer to be set.
mcp.json
{
  "mcpServers": {
    "internal-tools": {
      "type": "http",
      "url": "https://mcp.internal.example.com/mcp",
      "oauth": {
        "clientMetadataUrl": "https://auth.example.com/oauth/client-metadata.json"
      }
    }
  }
}
mcp.json
{
  "mcpServers": {
    "partner-api": {
      "type": "http",
      "url": "https://mcp.partner.example.com/mcp",
      "oauth": {
        "tokenEndpointAuthMethod": "none"
      }
    }
  }
}

MCP call timeout

Droid applies a built-in default timeout to every MCP tool invocation. Long-running tools (large data exports, browser automations, model-backed servers) can exceed that default and fail with a timeout error.

Override it per server with timeout (milliseconds):

mcp.json
{
  "mcpServers": {
    "slow-server": {
      "type": "stdio",
      "command": "my-long-running-server",
      "timeout": 120000
    }
  }
}

A server's timeout overrides the built-in default; there is no global timeout setting.

Note

Increasing the timeout only changes how long Droid waits for a response. It does not extend any timeouts enforced by the MCP server itself or its upstream APIs.

Per-droid server selection

Custom droids can choose which configured MCP servers they may use through the mcpServers field in their frontmatter. This scopes a subagent to specific servers (for example mcpServers: ["linear", "github"]) instead of inheriting every server in the session. For finer-grained control, a droid's tools list can name exact registered MCP tool IDs. See Selecting MCP servers for details.

Enterprise: MCP policy

Organizations can centrally control which MCP servers are allowed through the mcpPolicy setting in org-managed settings, so users can only connect to vetted servers.

FieldTypeDescription
enabledbooleanWhether policy enforcement is active (default: false). When false or absent, no policy is enforced and configured servers are allowed.
allowliststring[]Allowed server matchers, applied only when the policy is enabled. Entries match the hostname of a remote http/sse server's URL, or the command and arguments of a stdio server, not the configured server name. When the policy is enabled with an empty or absent allowlist, all servers are blocked.
JSON
{
  "mcpPolicy": {
    "enabled": true,
    "allowlist": ["mcp.linear.app", "mcp.sentry.dev", "npx"]
  }
}
Note

mcpPolicy is enforced through managed settings, and individual users cannot override it. Servers disallowed by policy remain in mcp.json and are still loaded into your configuration, but they are filtered out from running or connecting and do not appear as available in the /mcp manager.

Enterprise: MCP autonomy URL overrides

Administrators can assign a default autonomy risk level to remote MCP servers by URL with the mcpAutonomyUrlOverrides org-managed setting, controlling how much confirmation a matching server's tools require before Droid runs them.

Each rule maps a URL pattern to a risk level:

FieldTypeDescription
urlPatternstringGlob pattern (picomatch syntax) matched against the server's URL.
defaultLevel"low" | "medium" | "high"Risk level for the matching server's tools, compared against the user's Autonomy Level to decide auto-run vs. confirm.
JSON
{
  "mcpAutonomyUrlOverrides": [
    { "urlPattern": "https://mcp.internal.example.com/**", "defaultLevel": "low" },
    { "urlPattern": "https://*.partner.example.com/**", "defaultLevel": "medium" },
    { "urlPattern": "https://**", "defaultLevel": "high" }
  ]
}

Matching and precedence:

  • Remote servers only. Rules match remote servers that have a URL (http and sse transports); local stdio servers are unaffected.
  • First match wins. Rules are checked in order, so list the most specific patterns first.
  • Safety floor. A rule sets a tool's risk classification, not an absolute prompt: high-classified tools still follow the normal Autonomy Level comparison. The floor is one-directional: low or medium cannot pull a tool that is not read-only (destructive, or missing safety metadata) below high, so you can relax confirmation for read-only tools but never auto-approve destructive ones.
  • Fallback. Servers with no matching rule use Droid's built-in tool risk classification (read-only hints and curated defaults).
Note

mcpAutonomyUrlOverrides is admin-managed (MDM): it is delivered through org-managed settings and users cannot override or weaken it.