Skip to content

Revision: 2026-04-25

MCP Auth Error Codes

The CLI surfaces structured authentication errors as instances of MCPAuthError (exported from @deposium/cli's internal client). Programmatic callers should switch on errorCode, which is stable across server versions. The human-readable message and hint may change wording.

Stable enum

Mirrors the upstream server's ApiKeyErrorCode enum.

errorCode Meaning
key_missing No X-API-Key and no Authorization: Bearer header
format_invalid Key doesn't match dep_(live\|test)_<43 b64url>
key_invalid Format OK but revoked / expired / not in DB
permission_denied Key valid but lacks scope or tool permission
rate_limited Upstream 429
auth_unavailable Upstream auth circuit breaker OPEN
auth_timeout Upstream auth >8s
auth_internal_error Upstream 5xx / 404
accept_invalid Bad Accept header (CLI bug — should never reach the user)
unknown Catch-all (legacy responses, unexpected shapes)

Class shape

import { MCPAuthError, MCPAuthErrorCode } from '@deposium/cli';
//      ↑ exported from src/client/mcp-client.ts

class MCPAuthError extends Error {
  readonly errorCode: MCPAuthErrorCode;
  readonly hint?: string;
  readonly docsUrl?: string;
}

The message field already includes the hint (prefixed 💡) and docs link (prefixed 📖) on separate lines, so printing error.message is fine for end-user output.

import { MCPClient, MCPAuthError } from '@deposium/cli';

const client = new MCPClient(baseUrl, apiKey);

try {
  await client.callTool('search_hub', { query: 'x' });
} catch (e) {
  if (e instanceof MCPAuthError) {
    switch (e.errorCode) {
      case 'format_invalid':
        console.error(`API key is malformed. ${e.hint}`);
        process.exit(2);
      case 'key_invalid':
        console.error(`API key was rejected. ${e.hint}`);
        console.error('Run `deposium auth` to refresh.');
        process.exit(2);
      case 'permission_denied':
        console.error(`Permission denied. ${e.hint}`);
        process.exit(3);
      case 'rate_limited':
        console.error(e.message);
        process.exit(4);
      default:
        // auth_unavailable, auth_timeout, auth_internal_error, unknown
        console.error(e.message);
        process.exit(1);
    }
  }
  throw e;
}

When the error is NOT an MCPAuthError

If the server returns a 401 with a non-structured body (older server, or non-/api/cli/mcp endpoint), the CLI throws a plain Error with the message Authentication failed (401)\n<body.message>. The caller can still recover with instanceof MCPAuthError checks (which will fall through to the generic catch).

Server reference

Wire shape is defined by the API gateway's /api/cli/mcp route handler on HTTP 401 responses; the JSON envelope carries { error, message, error_code, hint, docs }.