abhigyanpatwari/GitNexus · error

-32001

-32001

Error message

Unauthorized

What it means

The MCP HTTP transport supports optional Bearer auth: when McpHttpOptions.authToken is configured, every request must carry 'Authorization: Bearer <token>' exactly. The comparison is constant-time (timingSafeEqual with a length-matched dummy), and a missing, malformed, or wrong token gets a JSON-RPC-formatted 401 with code -32001. When no authToken is set, all requests pass through.

Source

Thrown at gitnexus/src/mcp/http-transport.ts:109

    // we create a same-length dummy so the comparison always runs in full.
    let valid = false;
    if (typeof header === 'string') {
      const a = Buffer.from(header);
      const b = Buffer.from(expected);
      if (a.length === b.length) {
        valid = timingSafeEqual(a, b);
      } else {
        // Different lengths — run dummy comparison to preserve constant time.
        timingSafeEqual(Buffer.alloc(b.length), b);
      }
    }

    if (valid) {
      next();
      return;
    }

    res.status(401).json({
      jsonrpc: '2.0',
      error: { code: -32001, message: 'Unauthorized' },
      id: null,
    });
  };
}

/**
 * Returns true when an Origin should be allowed by the no-auth (loopback-only)
 * CORS policy — i.e. it is absent (non-browser caller) or a loopback origin.
 *
 * WHATWG URL keeps the brackets on IPv6 literals
 * (`new URL('http://[::1]/').hostname === '[::1]'`) and canonicalizes the
 * IPv4-mapped loopback to `[::ffff:7f00:1]`; loopback IPv4 is the whole
 * 127.0.0.0/8 block — so all of those forms are matched explicitly.
 */
export function isLoopbackOrigin(origin: string | undefined): boolean {
  if (!origin) return true; // no Origin → non-browser caller; CORS is not the control there

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Send the identical token: header 'Authorization: Bearer <authToken>'
  2. Re-copy the token from the server configuration and watch for trailing newlines or quotes in .env values
  3. If a proxy fronts the server, configure it to forward the Authorization header
  4. For trusted local use, run the server without authToken (loopback-only no-auth mode)

Example fix

# before
client = MCPClient('http://127.0.0.1:4747/mcp')  # no header → 401 -32001

# after
client = MCPClient('http://127.0.0.1:4747/mcp',
                    headers={'Authorization': f'Bearer {TOKEN}'})
Defensive patterns

Strategy: validation

Validate before calling

const headers = authToken
  ? { Authorization: `Bearer ${authToken.trim()}` }
  : {};
await fetch('http://127.0.0.1:4747/mcp', {
  method: 'POST',
  headers,
  body: JSON.stringify(initializeRequest),
});

Try / catch

// on a JSON-RPC 401 with code -32001: refresh the token from config and retry once
if (res.status === 401 && body?.error?.code === -32001) {
  token = loadTokenFresh();
  return request(path, payload, /* attempt */ 2);
}

Prevention

When it happens

Trigger: Connecting an MCP client to the gitnexus streamable-HTTP endpoint with the Authorization header unset, mistyped, or with a scheme/prefix mistake ('token' instead of 'Bearer token'), while the server runs with an authToken configured.

Common situations: Token rotated on the server but the client config kept the old value; a reverse proxy stripping the Authorization header; trailing newline/quote pollution from .env files; browser-based clients that cannot set the header on the first request.

Understand the failure class

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/3e73d1b87ca63e4a. Report an issue: GitHub.