Skip to content
Français

Connect MCP accounts

Reuse a declared CLI server login or configure client credentials for the built-in harness.

Set oauth on a declared HTTP MCP server to use a saved login or client credentials. This option replaces bearerTokenVariable and any Authorization header; choose the form supported by your harness.

FormHarnessesToken source
oauth: "login"Claude Code, Codex, Kimi CodeThe CLI’s own MCP login, made once on the host
oauth: { client… }Built-in harnessA client credentials grant requested in the sandbox
NeitherCopilot CLI, AntigravityUse bearerTokenVariable with a token you provide

A harness that cannot use the declared form fails when the agent is composed.

Log in on the host with the same server name and URL as your declaration.

Then declare oauth: "login".

import { createAgent, createCodexHarness } from "@elie-laloum/outpost";

const coder = createAgent({
  harness: createCodexHarness({
    authentication: "account",
    mcpServers: {
      linear: { url: "https://mcp.linear.app/mcp", oauth: "login" },
    },
  }),
});
CLIHost loginHost file (relocated by)
Claude Codeclaude mcp add --transport http linear https://mcp.linear.app/mcp, then claude mcp login linear~/.claude/.credentials.json (CLAUDE_CONFIG_DIR)
CodexSet mcp_oauth_credentials_store = "file" in ~/.codex/config.toml, then codex mcp login linear~/.codex/.credentials.json (CODEX_HOME)
Kimi CodeAdd the server to ~/.kimi-code/mcp.json, then authenticate it in a kimi session~/.kimi-code/credentials/mcp/ (KIMI_CODE_HOME)

Before the agent starts, Outpost copies only the matching server entries into the private sandbox home. Your other logins, including the CLI account itself, are not copied by this option. A missing login fails with the host command to run.

With createLocalSandboxProvider(), nothing is copied: the CLI reads your home directly.

For machine-to-machine servers in the built-in harness, name the variables that hold the client ID and secret.

import type { McpServers } from "@elie-laloum/outpost";

const mcpServers: McpServers = {
  internal: {
    url: "https://mcp.example.com/mcp",
    oauth: {
      clientIdVariable: "MCP_CLIENT_ID",
      clientSecretVariable: "MCP_CLIENT_SECRET",
      scopes: ["mcp:read"],
    },
  },
};
// createHarness({ modelProvider, mcpServers })

Declare both variables on the sandbox provider or in .outpost/.env (Environment variables). Without scopes, the bridge requests the scope named in the server’s 401 challenge, if any.

The HTTP bridge in the sandbox obtains the token itself, so the secret stays there and outbound rules apply to the token requests.

Drag to move · Ctrl + scroll to zoom
100 %
  • DiscoverFrom the MCP server URL.
    1. Read the metadataProtected resource metadata, then the authorization server metadata and its token endpoint. sandbox
    (Steps)
    • → Request : then
  • RequestOne client_credentials grant.
    1. Authenticate the clientWith client_secret_basic, or client_secret_post when the server advertises only that. sandbox
    2. Bind the tokenThe server URL is sent as resource. sandbox
    (Steps)
    • → Reuse : then
  • ReuseUntil the token expires.
    1. Retry on 401Discover again, request a new token and retry the request once. sandbox
    (Steps)
  • oauth is for HTTP servers only and cannot be combined with bearerTokenVariable or an Authorization header.
  • The built-in harness refuses "login"; CLI harnesses refuse client credentials.
  • Client credentials support neither private_key_jwt, refresh tokens nor interactive authorization.
  • Outpost never reads a system keychain: a CLI that stores its MCP login there has nothing to copy.

API: McpHttpServer · McpClientCredentials · McpServers.