MCP servers
Reference for ivar MCP server configuration: declare servers in ivar.json, sync provider configs, and manage credentials and accounts per hall.
A hall declares its MCP servers once, in ivar.json, and ivar sync
materialises them for every provider configured in the hall. The definitions are
hall-scoped: a harness finds them by walking up from the view directory, so
every session in the hall sees the same servers.
Declare them in ivar.json
A complete v5 hall manifest declaring all three harnesses (claude-code,
opencode, and omp) and both HTTP endpoints (linear and figma) alongside
a local tool. ivar graph index also declares the hall's own server, ivar (ivar graph mcp), which every provider gets as <hall>-ivar beside your servers. See Code graph over MCP.
{
"$schema": "https://ivar.run/schema/5.json",
"name": "acme",
"providers": {
"available": ["claude-code", "opencode", "omp"],
"default": "claude-code"
},
"mcp": [
{
"name": "linear",
"type": "http",
"url": "https://mcp.linear.app/mcp"
},
{
"name": "figma",
"type": "http",
"url": "https://mcp.figma.com/mcp"
},
{
"name": "local-tools",
"type": "local",
"command": "npx",
"args": ["-y", "@acme/tools-mcp"],
"env": {
"TOOLS_ENDPOINT": "ACME_TOOLS_ENDPOINT"
}
}
],
"repos": [],
"integration": {
"via": "local",
"strategy": "squash"
},
"version": 5
}Configuration types
ivar.json strictly enforces canonical http and local definitions:
{
"name": "linear",
"type": "http",
"url": "https://mcp.linear.app/mcp"
}{
"name": "local-tools",
"type": "local",
"command": "npx",
"args": ["-y", "@acme/tools-mcp"],
"env": {
"TOOLS_ENDPOINT": "ACME_TOOLS_ENDPOINT"
}
}| Field | Description | Applies to |
|---|---|---|
name | The canonical unqualified name of the server in the hall (e.g. figma, linear). | http, local |
type | Canonical transport: http for remote servers or local for spawned processes. Provider spellings like remote, stdio, and sse are rejected. | http, local |
url | Remote endpoint HTTP/HTTPS URL. | http |
command | Executable or binary spawned by the harness. | local |
args | Optional argument array passed to the command. | local |
env | Optional mapping of environment variables injected into the process (KEY: ENV_VAR_NAME reference). | local |
oauth | Optional persisted OAuth client and endpoint metadata generated/updated by ivar mcp auth. | http |
The manifest carries no secrets
ivar.json is committed. env holds references — variable names resolved
at runtime — never plain secrets. OAuth credentials live in provider credential
stores or .ivar/secrets/mcp.env.
Provider translation table
ivar sync translates canonical manifest definitions into provider-native
configurations:
Canonical (ivar.json) | Claude Code (.mcp.json) | OpenCode (opencode.json) | OMP (.omp/mcp.json) |
|---|---|---|---|
type: "http" | type: "http" | type: "remote" | type: "http" |
type: "local" | type: "stdio" | type: "local" | type: "stdio" |
command, args | command, args | command: ["cmd", ...args] | command, args |
url | url | url | url |
env | env | environment | env |
| Server name | <hall>-<name> | <hall>-<name> | <hall>-<name> |
Add, edit and remove
ivar mcp add declares a server in ivar.json and writes it into every
provider's config. figma and linear are known names; any other HTTP
server takes --url, and a stdio server takes --command with its
arguments after --:
ivar mcp add figma
ivar mcp add sentry --url https://mcp.sentry.dev/mcp
ivar mcp add files --command npx -- -y @modelcontextprotocol/server-filesystem .
ivar mcp edit sentry --url https://eu.mcp.sentry.dev/mcp
ivar mcp remove filesivar mcp edit replaces a server's URL or command. When the URL or the
transport changes, the OAuth registration no longer applies: ivar drops it,
deletes its client secret from .ivar/secrets/mcp.env unless another server
uses it, and returns next: "ivar mcp auth <name>". ivar mcp remove takes
the server out of ivar.json and every provider config and deletes its client
secret on the same terms. Tokens a provider keeps in its own credential store
stay there.
Naming and authentication commands
The name stored in ivar.json is canonical and unqualified (figma, linear).
At every provider boundary, ivar qualifies the name with the hall name:
<hall>-<server> (for example, acme-figma or acme-linear).
Use ivar mcp auth with the canonical name:
ivar mcp auth figma --provider claude-code # authenticate specific provider
ivar mcp auth linear --provider opencode
ivar mcp auth figma --provider omp
ivar mcp auth figma --all-providers # authenticate all configured providers
# Inspect credential status
ivar mcp status # all servers across all providers
ivar mcp status figma # specific server
ivar mcp status --provider claude-code # specific provider
ivar mcp status --live # query provider harnesses live
ivar mcp status --json # emit JSON status matrixDirect provider commands take the hall-qualified name only where the provider CLI natively exposes MCP login commands:
claude mcp login acme-figma # Claude Code native login
opencode mcp auth acme-linear # OpenCode native authOMP exposes no MCP login command; authentication for OMP always runs through ivar mcp auth and persists credentials per hall under mcp_oauth_ivar:<hall>-<server> via omp auth-broker.
Provider support matrix
| Service | Provider | OAuth Owner | Preregistration | Credential Owner | Config Path |
|---|---|---|---|---|---|
| Linear | Claude Code | Claude Code (claude mcp login) | Not needed (public client) | Claude Code keychain | .mcp.json |
| Linear | OpenCode | OpenCode (opencode mcp auth) | Not needed (public client) | OpenCode (mcp-auth.json) | opencode.json |
| Linear | OMP | Ivar (internal OAuth PKCE) | Dynamic registration (/register) | omp auth-broker | .omp/mcp.json |
| Figma | Claude Code | Claude Code (claude mcp login) | Not needed (Claude Code allowlisted) | Claude Code keychain | .mcp.json |
| Figma | OpenCode | Ivar (internal OAuth PKCE) | Yes (client_name: "Codex") | OpenCode (mcp-auth.json) | opencode.json |
| Figma | OMP | Ivar (internal OAuth PKCE) | Yes (client_name: "Codex") | omp auth-broker | .omp/mcp.json |
Claude Code
Claude Code reads .mcp.json at the hall root. ivar sync materialises
hall-qualified names. When launching sessions, ivar
supplies process-scoped settings --settings '{"enabledMcpjsonServers":["acme-linear","acme-figma",...]}'
so declared servers are enabled without modifying global state. Claude Code owns
its OAuth lifecycle directly via claude mcp login.
{
"mcpServers": {
"acme-linear": {
"type": "http",
"url": "https://mcp.linear.app/mcp"
},
"acme-figma": {
"type": "http",
"url": "https://mcp.figma.com/mcp"
},
"acme-local-tools": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@acme/tools-mcp"
],
"env": {
"TOOLS_ENDPOINT": "ACME_TOOLS_ENDPOINT"
}
}
}
}OpenCode
OpenCode reads opencode.json at the hall root. For standard services like
Linear, OpenCode manages OAuth directly via opencode mcp auth acme-linear. For
Figma, Ivar performs prerequisite registration and OAuth token acquisition,
storing tokens in OpenCode's credential store (mcp-auth.json).
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"acme-linear": {
"type": "remote",
"url": "https://mcp.linear.app/mcp"
},
"acme-figma": {
"type": "remote",
"url": "https://mcp.figma.com/mcp",
"oauth": {
"clientId": "<generated_client_id>",
"clientSecret": "{env:IVAR_MCP_ACME_FIGMA_SECRET}",
"redirectUri": "http://127.0.0.1:19876/callback"
}
},
"acme-local-tools": {
"type": "local",
"command": [
"npx",
"-y",
"@acme/tools-mcp"
],
"environment": {
"TOOLS_ENDPOINT": "{env:ACME_TOOLS_ENDPOINT}"
}
}
}
}OMP
OMP reads .omp/mcp.json at the hall root, ahead of opencode.json's mcp entries.
Because OMP has no built-in mcp login CLI command, ivar mcp auth always runs
Ivar's internal OAuth PKCE engine for OMP, then imports the resulting tokens
per hall under mcp_oauth_ivar:<hall>-<server> directly via omp auth-broker.
ivar sync writes an auth block for every http server in .omp/mcp.json, with
type: "oauth" and credentialId: "mcp_oauth_ivar:<hall>-<server>". When
persisted OAuth metadata contains a token_url, the block also carries
clientId, clientSecret (as ${VAR}), tokenUrl, and resource.
{
"mcpServers": {
"acme-linear": {
"type": "http",
"url": "https://mcp.linear.app/mcp",
"auth": {
"type": "oauth",
"credentialId": "mcp_oauth_ivar:acme-linear",
"clientId": "<generated_client_id>",
"tokenUrl": "<discovered-token-endpoint>"
}
},
"acme-figma": {
"type": "http",
"url": "https://mcp.figma.com/mcp",
"auth": {
"type": "oauth",
"credentialId": "mcp_oauth_ivar:acme-figma",
"clientId": "<generated_client_id>",
"clientSecret": "${IVAR_MCP_ACME_FIGMA_SECRET}",
"tokenUrl": "<discovered-token-endpoint>"
}
},
"acme-local-tools": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@acme/tools-mcp"
],
"env": {
"TOOLS_ENDPOINT": "ACME_TOOLS_ENDPOINT"
}
}
}
}OAuth metadata and secrets
When ivar mcp auth discovers endpoints or performs dynamic client
registration, it persists client and endpoint metadata back to ivar.json under
the server entry:
{
"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": "<discovered-resource>"
}
}| Field | Purpose |
|---|---|
client_id | Registered OAuth client identifier. |
client_secret_env | Name of the environment variable holding the client secret (for confidential clients). |
token_url | Discovered OAuth token endpoint URL. When present, OMP's auth block also carries clientId, clientSecret, tokenUrl, and resource so omp can refresh the token. |
resource | Optional RFC 8707 / RFC 9728 protected resource indicator URI. |
Secrets remain outside version control
Ivar writes only non-sensitive metadata (client_id, token_url, client_secret_env) to ivar.json. Confidential client secrets are stored in .ivar/secrets/mcp.env or the provider's credential vault, never committed in plain text.
Service nuances: Linear vs. Figma
Linear
Linear implements standard RFC 8414 OAuth 2.0 authorization server metadata and RFC 7591 dynamic client registration for public clients (token_endpoint_auth_method: "none"). No pre-shared client credentials or allowlist workarounds are required. Claude Code and OpenCode authenticate natively, while OMP utilizes Ivar's generic PKCE registration and token installation.
Figma
Figma restricts Dynamic Client Registration (DCR) to allowlisted client_name values (such as "Claude Code" and "Codex"). Generic or unrecognized client names receive 403 Forbidden. Furthermore, Figma requires a client secret during token exchange despite advertising public authentication.
To support OpenCode and OMP:
ivar mcp authregisters a client using an allowlisted client name (Codex).- Ivar persists the registration metadata in
ivar.jsonand saves the secret reference to.ivar/secrets/mcp.env. - Ivar runs the browser OAuth PKCE exchange and imports credentials directly to the respective harness stores.
External DCR policy caveat
Figma's dynamic client registration policy is server-controlled and external. Changes to upstream allowlists or registration rules may require updating client identifiers or registration parameters.