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.
- 1Open the manager
Type
/mcpinside Droid and select Add from Registry. - 2Pick a server
Browse the registry and choose one, such as
linear,sentry, orplaywright. - 3Authenticate
For remote servers that need OAuth, follow the browser prompt. The server is then ready to use.
Representative registry servers include:
| Server | Description |
|---|---|
| linear | Issue tracking and project management |
| sentry | Error tracking and performance monitoring |
| notion | Notes, docs, and project management |
| figma | Generate code with Figma context |
| stripe | Payment processing APIs |
| supabase | Create and manage Supabase projects |
| vercel | Manage projects and deployments |
| playwright | End-to-end browser testing |
The registry includes many more servers than shown here.
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.
droid mcp add <name> <urlOrCommand...> --type <stdio|http|sse>nameis a unique server identifier.--typedefaults tostdiowhen omitted.--env KEY=VALUEsets environment variables (stdio only, repeatable).--header "KEY: VALUE"sets HTTP headers (http/sse only, repeatable).--no-oauthdisables OAuth for a header- or API-key-authenticated remote server (storesoauth: false).
HTTP servers are remote MCP endpoints, the recommended way to connect to cloud services.
droid mcp add linear https://mcp.linear.app/mcp --type httpPass authentication headers with --header, repeating the flag as needed:
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:
droid mcp add internal https://mcp.internal.example.com/mcp --type http \
--header "Authorization: Bearer YOUR_TOKEN" --no-oauthsse 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.
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.
droid mcp add airtable "npx -y airtable-mcp-server" \
--env AIRTABLE_API_KEY=your_keynpx 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.
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:
droid mcp listEach 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:
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:
droid mcp permissions list
droid mcp permissions revoke <server> [tool]
droid mcp permissions clear --confirmlistshows all persistent permissions.revoke <server>removes a server's approval, including all of its per-tool approvals. Add atoolargument to revoke a single tool.clear --confirmremoves every persistent permission.
Configuration file
MCP server configurations are stored in mcp.json files at three levels:
| Level | Location | Purpose |
|---|---|---|
| User | ~/.factory/mcp.json | Your personal servers, available in every project. |
| Folder | .factory/mcp.json in an ancestor directory of the project | Servers shared across nested projects under a common parent. |
| Project | .factory/mcp.json in the project root | Shared 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 addor the registry always go to your user config. - Project servers cannot be removed with
droid mcp removeor the/mcpmanager. To remove them, edit.factory/mcp.jsondirectly. - 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
/mcpmanager 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.
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:
| Field | Type | Description |
|---|---|---|
type | "stdio" | "http" | "sse" | Transport. May be omitted for stdio servers, which default to stdio. |
disabled | boolean | Temporarily disable the server (default: false). |
disabledTools | string[] | Tool names to exclude from this server. Excluded tools are never loaded into context. |
timeout | number | Per-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), andenv(an object of environment variables). - http and sse servers use
url(the endpoint),headers(an object of HTTP headers), andoauth(OAuth overrides, orfalseto 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.
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@some/mcp-server"],
"disabledTools": ["tool_i_dont_need", "another_unused_tool"]
}
}
}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:
envvalues for stdio servers.headersvalues for http and sse servers.oauth.clientIdandoauth.clientSecretfor http and sse servers.
It does not apply to command, args, or url.
{
"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:
| Field | Type | Description |
|---|---|---|
scopes | string[] | OAuth scopes to request instead of the discovered defaults. |
resource | string | false | OAuth resource indicator to send instead of the normalized MCP server URL; set to false to omit it. |
authorizationServerIssuer | string | Authorization server issuer URL. Required when clientId / clientSecret are set. |
clientId | string | Pre-registered OAuth client ID, skipping dynamic registration. |
clientSecret | string | Client secret for the pre-registered client. |
clientMetadataUrl | string | HTTPS 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. |
callbackPort | number | Fixed localhost port for the OAuth callback (1-65535). |
Constraints:
clientMetadataUrlmust be an HTTPS URL with a non-root path and no credentials, query string, fragment, or dot segments.clientMetadataUrlis mutually exclusive withclientId/clientSecret: a metadata document is the client identity, so pre-registered credentials cannot be combined with it.clientMetadataUrldescribes a public client, sotokenEndpointAuthMethodmust be"none"(or omitted) when it is set.clientId/clientSecretrequireauthorizationServerIssuerto be set.
{
"mcpServers": {
"internal-tools": {
"type": "http",
"url": "https://mcp.internal.example.com/mcp",
"oauth": {
"clientMetadataUrl": "https://auth.example.com/oauth/client-metadata.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):
{
"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.
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.
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether policy enforcement is active (default: false). When false or absent, no policy is enforced and configured servers are allowed. |
allowlist | string[] | 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. |
{
"mcpPolicy": {
"enabled": true,
"allowlist": ["mcp.linear.app", "mcp.sentry.dev", "npx"]
}
}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:
| Field | Type | Description |
|---|---|---|
urlPattern | string | Glob 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. |
{
"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 (
httpandssetransports); localstdioservers 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:lowormediumcannot pull a tool that is not read-only (destructive, or missing safety metadata) belowhigh, 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).
mcpAutonomyUrlOverrides is admin-managed (MDM): it is delivered through org-managed settings and users cannot override or weaken it.