OxagenDocs
MCP server

Credentials

How external MCP server credentials are stored, resolved, and refreshed.

External MCP servers that require authentication need credentials — bearer tokens, API keys, or OAuth tokens. The credential system resolves these from multiple sources without requiring secrets to be committed to version control.

Resolution order

When the runtime needs a credential for a server, it checks these sources in order (first match wins):

  1. Environment variable — the envToken field names a variable that holds the token
  2. Credential file — stored at ~/.config/oxagen/credentials/<server-name>.json
  3. Remote API — fetches the credential from the platform (requires oxagen auth login)

Environment variables

The simplest approach for CI/CD and local development:

{
  "mcpServers": {
    "linear": {
      "transport": "sse",
      "url": "https://mcp.linear.app/sse",
      "auth": "bearer",
      "envToken": "LINEAR_MCP_TOKEN"
    }
  }
}

Set the variable in your shell:

export LINEAR_MCP_TOKEN="lin_api_..."

For header-based auth, use ${VAR} expansion in headers:

{
  "mcpServers": {
    "internal": {
      "transport": "streamable-http",
      "url": "https://mcp.internal.acme.com/v1",
      "auth": "header",
      "headers": { "X-API-Key": "${ACME_MCP_KEY}" }
    }
  }
}

Credential files

Credential files are stored at ~/.config/oxagen/credentials/<server-name>.json with 0600 permissions (owner-read-write only). They are never committed to version control.

Structure

{
  "accessToken": "ghp_abc123...",
  "refreshToken": "ghr_xyz789...",
  "tokenType": "Bearer",
  "expiresAt": "2026-07-01T12:00:00.000Z",
  "scopes": ["repo", "read:org"],
  "updatedAt": "2026-06-25T10:30:00.000Z"
}
FieldDescription
accessTokenThe bearer/access token sent in the Authorization header
refreshTokenOAuth refresh token for automatic renewal
tokenTypeToken type (default: "Bearer")
expiresAtISO timestamp when the access token expires
scopesOAuth scopes that were granted
headersFor header-auth servers: the resolved header key-value pairs
updatedAtWhen this credential was last written

Storing a credential

Write the credential file directly at ~/.config/oxagen/credentials/<server-name>.json using the structure above, with 0600 permissions:

# Write the credential file
cat > ~/.config/oxagen/credentials/linear.json <<'EOF'
{
  "accessToken": "lin_api_abc123",
  "tokenType": "Bearer",
  "updatedAt": "2026-06-29T00:00:00.000Z"
}
EOF
chmod 600 ~/.config/oxagen/credentials/linear.json

For OAuth flows, tokens are stored by the platform runtime after completing the browser-based OAuth authorization flow.

OAuth flow

For servers with "auth": "oauth" (like GitHub MCP), the full OAuth 2.1 + PKCE flow is available through the web app:

  1. Navigate to Workspace → Settings → Integrations
  2. Click the server's "Connect" button
  3. Complete the OAuth authorization in your browser
  4. Tokens are stored encrypted on the platform (for the web/API runtime)

For CLI-only usage, you can paste an access token obtained from another flow directly into the credential file:

cat > ~/.config/oxagen/credentials/github.json <<'EOF'
{
  "accessToken": "gho_abc123...",
  "tokenType": "Bearer",
  "updatedAt": "2026-06-29T00:00:00.000Z"
}
EOF
chmod 600 ~/.config/oxagen/credentials/github.json

Token expiry and refresh

The runtime checks token expiry before connecting to a server:

  • Not expired: uses the token as-is
  • Expired + has refresh token: the platform's OAuth refresh watcher (runs every 30 minutes) automatically refreshes tokens. For CLI-only usage, the next connection attempt will fail and prompt re-authentication.
  • Expired + no refresh token: server is skipped with a warning. Update the credential file at ~/.config/oxagen/credentials/<server-name>.json with a fresh token.

Check which servers need attention:

oxagen mcp check
# ● github: healthy (42ms)
# ◐ linear: auth_required — token expired
# ● filesystem: healthy

Security considerations

  • Credential files use 0600 permissions (owner only)
  • Tokens are stored in plaintext in credential files — protect your home directory
  • Never commit .oxagen/settings.local.json (add it to .gitignore)
  • For team-shared secrets, use environment variables backed by a secret manager
  • The envToken field stores the variable name, not the value — safe to commit in .oxagen/settings.json
  • Platform-stored credentials (via OAuth) use AES-256-GCM encryption at rest

Credential file location

# List the credential directory
ls ~/.config/oxagen/credentials/

# View a specific credential (be careful in shared terminals)
cat ~/.config/oxagen/credentials/github.json

# Delete a credential (keeps the server config in place)
rm ~/.config/oxagen/credentials/github.json

On this page