Authentication
Complete end-to-end guide to MCP OAuth authentication, credential separation, provider flows, and token lifecycle across Claude Code, OpenCode, and OMP.
Model Context Protocol (MCP) servers using remote HTTP transports frequently require OAuth 2.0 authentication to securely access user resources. In Ivar, MCP authentication balances central management with provider-native security models: authentication is coordinated across providers while preserving strict isolation between public metadata, client secrets, and runtime tokens.
The end-to-end OAuth lifecycle
OAuth authentication in Ivar proceeds through a clear multi-stage lifecycle separating discovery, registration, browser authorization, storage, and runtime materialisation.
Discover endpoints
Inspect the canonical server HTTP endpoint in ivar.json and query RFC 8414 / OAuth 2.0 metadata to discover authorization, token (token_url), and dynamic registration endpoints.
Resolve or reuse client registration
Determine client credentials by either performing Dynamic Client Registration (DCR) for supported public clients (e.g. Linear) or reusing pre-registered client IDs and configured secrets for allowlisted services (e.g. Figma).
Browser authorization with PKCE
Launch the local loopback callback server and open a browser to the authorization endpoint using Authorization Code Flow with PKCE (S256 code challenge).
Token exchange and data placement
Exchange the authorization code and PKCE verifier at the token endpoint, then partition credentials across public manifest metadata (ivar.json), secrets (.ivar/secrets/mcp.env), and provider/broker token stores.
Configuration materialisation and runtime refresh
Materialise provider configuration files (.mcp.json, opencode.json, mcp.json) with qualified server names, enabling native token managers or OMP auth brokers to maintain and refresh active tokens.
1. Endpoint discovery
For Ivar-managed flows (OMP for both services, OpenCode for Figma), running ivar mcp auth <name> inspects the server's canonical HTTP endpoint defined in ivar.json (such as https://mcp.linear.app/mcp or https://mcp.figma.com/mcp). Ivar sends discovery requests (RFC 8414 / OAuth 2.0 Protected Resource Metadata) to identify authorization endpoints, token exchange endpoints (token_url), supported code challenge methods (S256), and dynamic client registration (DCR) endpoints. Provider-native flows (Claude Code and OpenCode with Linear) manage discovery independently and remain opaque to Ivar.
2. Client registration (optional)
Depending on the service and provider:
- Dynamic Client Registration (DCR): Services supporting open public DCR (such as Linear) allow Ivar or native providers to register a client ID on the fly.
- Pre-registered OAuth Apps: Services enforcing strict redirect URL allowlists (such as Figma) reject dynamic public client registration. Ivar preregisters or provisions app credentials with predetermined client IDs and redirect URIs.
3. Browser authorization and PKCE
All interactive authentication managed by Ivar uses the OAuth 2.0 Authorization Code Flow with PKCE (Proof Key for Code Exchange, RFC 7636) using the S256 code challenge method:
- A cryptographically random code verifier and code challenge are generated.
- A browser window opens directing the user to the service's authorization endpoint with requested scopes.
- The user approves access, and the service redirects back to a local loopback callback server (e.g.
http://localhost:<port>/callback).
4. Token exchange
The authorization code received at the callback server is exchanged with the service's token_url alongside the PKCE code verifier (and client secret if confidential client credentials are required). The authorization server returns access and refresh tokens.
5. Multi-store data placement
Credentials and configuration parameters are partitioned across three distinct storage tiers:
- Public configuration (
ivar.json): Non-sensitive client and endpoint metadata. - Secret environment (
.ivar/secrets/mcp.env): Sensitive client secrets (if any). - Runtime token stores: Short-lived access tokens and refresh tokens stored exclusively in provider-managed credential stores or OMP auth brokers.
6. Configuration materialisation
Running ivar sync or completing an authentication command materialises the provider-specific configurations (.mcp.json, opencode.json, or hall-root mcp.json) using hall-qualified server names (<hall>-<name>).
7. Runtime execution and token refresh
When an agent session runs, the provider uses stored tokens to sign MCP requests. Token refresh behavior depends on the flow owner:
- OMP: OMP's auth broker relies on the persisted
token_urland bound credentials to renew expiring tokens. - Claude Code & OpenCode: Native token managers maintain and refresh tokens using their internal provider mechanisms.
Provider × Service ownership matrix
Different providers and services handle registration and authentication with distinct levels of native support.
| Service | Provider | Registration | Auth flow owner | Token storage |
|---|---|---|---|---|
| Linear | claude-code | Public DCR | Native (claude mcp login) | Claude Code internal store |
| Linear | opencode | Public DCR | Native (opencode mcp auth) | OpenCode internal store (mcp-auth.json) |
| Linear | omp | Ivar generic registration | Ivar internal PKCE | omp auth-broker profile binding |
| Figma | claude-code | Provider-owned / Preconfigured | Native (claude mcp login) | Claude Code internal store |
| Figma | opencode | Ivar preregistration | Ivar internal PKCE | OpenCode internal store (mcp-auth.json) |
| Figma | omp | Ivar preregistration | Ivar internal PKCE | omp auth-broker profile binding |
Service architectural differences
Why Figma differs from Linear
- Linear (
https://mcp.linear.app/mcp): Linear supports standard public-client Dynamic Client Registration (RFC 7591). Claude Code and OpenCode can register ephemeral client IDs and execute their built-in native login flows directly without prior setup. - Figma (
https://mcp.figma.com/mcp): Figma enforces server-controlled redirect URI allowlists and strict OAuth application registration. OpenCode's dynamic registration attempts are rejected by Figma. Consequently, Ivar handles Figma authentication via internal preregistered OAuth metadata and executes an internal PKCE flow for OpenCode before injecting the resulting token into OpenCode's credential storage (mcp-auth.json). Claude Code maintains its own first-party integration and manages Figma natively.
Why OMP always uses Ivar's flow
Unlike Claude Code and OpenCode, Oh My Pi (OMP) has no native interactive MCP login command or built-in OAuth browser orchestrator. OMP expects pre-configured MCP endpoints in its hall-root mcp.json accompanied by credentials bound through omp auth-broker.
For every service on OMP (both Linear and Figma):
- Ivar manages discovery and OAuth client registration.
- Ivar executes the local PKCE browser flow.
- Ivar binds the resulting tokens to the OMP profile and endpoint via
omp auth-broker. - In
mcp.json, Ivar generates the auth configuration with typeoauth, ensuringtoken_urlis persisted for runtime token maintenance.
Data-placement table
To guarantee security and avoid credential leakage, Ivar strictly partitions MCP configuration and secrets:
| Artifact | Location | Contains | Committed to Git? |
|---|---|---|---|
| Manifest metadata | ivar.json (oauth block) | client_id, client_secret_env, token_url, resource | Yes |
| Client secrets | .ivar/secrets/mcp.env | Client secret values referenced by client_secret_env | No (.gitignore) |
| Claude tokens | Claude config directory / Keychain | Access and refresh tokens for claude-code | No |
| OpenCode tokens | OpenCode auth storage (mcp-auth.json) | Access and refresh tokens for opencode | No |
| OMP tokens | OMP auth broker store | Bound credentials per profile and endpoint | No |
Supported OAuth metadata fields
The oauth block under an HTTP server entry in ivar.json supports only canonical fields. In this example, the Figma server entry uses a confidential client secret environment variable:
{
"name": "figma",
"type": "http",
"url": "https://mcp.figma.com/mcp",
"oauth": {
"client_id": "<generated_client_id>",
"client_secret_env": "IVAR_MCP_ACME_FIGMA_SECRET",
"token_url": "<discovered_token_endpoint>",
"resource": "https://mcp.figma.com/mcp"
}
}No unsupported fields or plain secrets
auth_urlis rejected: Authorization URLs are dynamically discovered from the server endpoint. Do not configureauth_urlinivar.json.- No secrets in
ivar.json: Useclient_secret_envto name the environment variable containing the secret. Store the raw secret in.ivar/secrets/mcp.env.
Running authentication
Authenticate individual providers or all configured providers using the ivar mcp auth CLI command.
Authenticate a specific provider
# Authenticate Linear for Claude Code
ivar mcp auth linear --provider claude-code
# Authenticate Figma for OpenCode (uses Ivar PKCE + OpenCode store injection)
ivar mcp auth figma --provider opencode
# Authenticate Linear for OMP (uses Ivar PKCE + omp auth-broker binding)
ivar mcp auth linear --provider ompBatch authentication (--all-providers)
# Run authentication across all configured providers in the hall
ivar mcp auth figma --all-providers
ivar mcp auth linear --all-providersRunning ivar mcp auth <server> --all-providers orchestrates authentication across every provider in providers.available:
- Provider ordering: Runs
claude-codefirst (via nativeclaude mcp login), followed by remaining providers sequentially. - Skip authenticated: Any provider already in the
authenticatedstate is skipped automatically. - Automatic browser opening: For Ivar-driven OAuth legs, Ivar opens the authorization URL directly in the default browser (
xdg-open/open/start) and prints the URL to terminal output (as an OSC 8 clickable link when stderr is a TTY). - Post-run grant verification: When two or more legs were not skipped, Ivar performs a post-run dropped-grant check (live for Claude Code and OpenCode,
omp tokenfor OMP) to verify earlier grants were not revoked by subsequent authorizations. If an earlier grant is dropped, anmcp.grant_droppedwarning is emitted.
Token refresh and reauthentication
Token maintenance is governed by the owner of the authentication flow:
- OMP: The OMP auth broker uses the persisted
token_urland refresh token stored in its profile binding to renew expired access tokens. - Provider-native tools: Claude Code and OpenCode refresh tokens through their own internal token storage and upstream exchange endpoints.
- Reauthentication: If a refresh token expires or is revoked upstream, run
ivar mcp auth <name> --provider <provider>(or the provider's native auth command) to trigger a new browser PKCE authorization cycle. - Provider Sync: After updating authentication or adding new endpoints, execute
ivar syncto re-materialise configuration files across all provider harnesses.
Troubleshooting
Browser authorization fails or times out
- Port Conflicts: Ensure the local loopback port for the OAuth callback is not blocked by a local firewall or another running process.
- Browser Not Opening: In headless or remote development environments, copy the printed authorization URL from the terminal into your local browser, complete the consent prompt, and ensure redirect traffic reaches the callback listener.
Figma authentication error in OpenCode
- Symptom: OpenCode native auth fails with an unauthorized client or redirect URI mismatch.
- Resolution: Do not use
opencode mcp auth acme-figma. Runivar mcp auth figma --provider opencode. Ivar will use its preregistered application metadata and store the issued token directly in OpenCode's credential repository (mcp-auth.json).
Missing token URL on OMP
- Symptom: OMP session fails to refresh tokens or reports missing OAuth token endpoint.
- Resolution: Verify that
token_urlis populated in theoauthsection ofivar.jsonor discovered during authentication. Runivar mcp auth <name> --provider ompandivar sync. If the upstream service updated its OAuth endpoints or registration policy, re-runivar mcp authto diagnose and obtain updated endpoints.
Related documentation
- MCP Overview Reference — Complete manifest schema, supported transports, and provider translation.
- MCP Providers Guide — Provider-specific details for Claude Code, OpenCode, and OMP.
- Figma Integration — Setting up and authenticating the Figma MCP server.
- Linear Integration — Setting up and authenticating the Linear MCP server.
- Ivar CLI Reference — CLI commands for
ivar mcp authandivar sync.
Linear
Configure the canonical Linear MCP server in ivar.json, synchronize provider configurations, and authenticate via public-client Dynamic Client Registration (DCR).
Code graph
Index every repo in the hall into one local graph, and let agents ask it for source, callers and blast radius instead of grepping and reading file by file.