# How to Handle Bearer Token Authentication for Remote MCP Servers in MetaMCP

> Learn to handle bearer token authentication for MetaMCP remote servers using OAuth or static tokens. Securely connect your MCP servers with automatic HTTP header injection.

- Repository: [metatool-ai/metamcp](https://github.com/metatool-ai/metamcp)
- Tags: how-to-guide
- Published: 2026-03-07

---

**MetaMCP supports bearer token authentication for remote MCP servers through either OAuth access tokens or static bearer tokens configured in the database, automatically injecting them into HTTP headers during transport initialization.**

MetaMCP is an open-source platform that unifies access to multiple Model Context Protocol (MCP) servers. When integrating remote MCP servers that require authentication, understanding how to configure and manage bearer token authentication ensures secure API communication without exposing credentials in client-side code.

## Authentication Architecture Overview

MetaMCP implements a dual-strategy authentication system that prioritizes OAuth tokens while providing static bearer tokens as a fallback mechanism.

The platform supports two distinct authentication methods:

- **OAuth access tokens** – Generated through the MetaMCP OAuth flow and stored in `serverParams.oauth_tokens?.access_token`. These are automatically added to the `Authorization: Bearer …` header when the client initializes.
- **Static bearer tokens** – Entered by users or stored in the database via `serverParams.bearerToken`. These serve as a fallback when OAuth tokens are unavailable and can be injected manually through UI hooks.

## Configuring Static Bearer Tokens in the Database

Static bearer tokens are persisted in the PostgreSQL database schema defined in [`apps/backend/src/db/schema.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/db/schema.ts). The `bearer_token` column stores optional authentication credentials for each MCP server definition.

```typescript
// apps/backend/src/db/schema.ts
bearerToken: text("bearer_token"),

```

When servers are queried through the MetaMCP backend, the `getMcpServers` function in [`apps/backend/src/lib/metamcp/fetch-metamcp.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/fetch-metamcp.ts) includes the bearer token in the `ServerParameters` object:

```typescript
// apps/backend/src/lib/metamcp/fetch-metamcp.ts
bearerToken: server.bearerToken,

```

This ensures that static tokens are available during client initialization while maintaining separation between database storage and transport logic.

## Implementing Token Injection in Backend Transports

The MetaMCP backend handles bearer token injection automatically during transport creation. Both **SSE** and **STREAMABLE_HTTP** transports in [`apps/backend/src/lib/metamcp/client.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/client.ts) implement identical authentication logic.

The client creation process prioritizes OAuth tokens while falling back to static bearer tokens:

```typescript
// apps/backend/src/lib/metamcp/client.ts (lines 84-94)
const headers: Record<string, string> = {
  ...(serverParams.headers || {}),
};

const authToken =
  serverParams.oauth_tokens?.access_token || serverParams.bearerToken;
if (authToken) {
  headers["Authorization"] = `Bearer ${authToken}`;
}

```

The same pattern applies to `STREAMABLE_HTTP` transport initialization (lines 115-124), ensuring consistent authentication behavior across transport types. This implementation allows seamless switching between OAuth and static authentication without requiring code changes in consuming applications.

## Frontend Token Management with React Hooks

For frontend applications requiring manual token injection, MetaMCP provides the `useConnection` hook in [`apps/frontend/hooks/useConnection.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/frontend/hooks/useConnection.ts). This hook supports explicit bearer token configuration alongside OAuth flows.

The hook resolves authentication tokens using a priority-based approach:

```typescript
// apps/frontend/hooks/useConnection.ts (lines 55-73)
const token =
  bearerToken || (await authProvider.tokens())?.access_token;
if (token) {
  const authHeaderName = headerName || "Authorization";

  if (authHeaderName.toLowerCase() !== "authorization") {
    headers[authHeaderName] = token;
    headers["x-custom-auth-header"] = authHeaderName;
  } else {
    headers[authHeaderName] = `Bearer ${token}`;
  }
}

```

This implementation supports custom header names for non-standard authentication schemes while maintaining RFC 6750 compliance for standard Bearer token usage.

## Complete Implementation Examples

### Database Configuration Example

Configure a remote MCP server with a static bearer token using Drizzle ORM:

```typescript
// Example using Drizzle ORM
await db
  .insert(mcpServersTable)
  .values({
    uuid: "123e4567-e89b-12d3-a456-426614174000",
    name: "Remote SSE Server",
    type: "SSE",
    url: "https://remote-mcp.example.com/events",
    bearerToken: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", // <-- static token
    headers: {}, // optional extra headers
  });

```

### Frontend Hook Usage

Implement bearer token authentication in a React component:

```tsx
import { useConnection } from "@/hooks/useConnection";

function RemoteMcpConnector() {
  const { connectionStatus } = useConnection({
    mcpServerUuid: "123e4567-e89b-12d3-a456-426614174000",
    transportType: "SSE",
    url: "https://remote-mcp.example.com/events",
    command: "",
    args: "",
    env: {},
    // Provide a static token that will be used instead of OAuth
    bearerToken: "my‑static‑bearer‑token",
    // Optional custom header name
    headerName: "X‑My‑Auth",
    isMetaMCP: false,
    enabled: true,
  });

  return <div>Status: {connectionStatus}</div>;
}

```

### Server-Side Client Creation

Create an authenticated MCP client on the backend:

```ts
import { createMetaMcpClient } from "@/lib/metamcp/client";
import { getMcpServers } from "@/lib/metamcp/fetch-metamcp";

async function connectToRemote(uuid: string) {
  const servers = await getMcpServers(uuid);
  const serverParams = servers[uuid];

  // The function automatically chooses OAuth or bearer token.
  const { client, transport } = createMetaMcpClient(serverParams);

  // `client` can now be used to issue MCP requests.
  await client.initialize(transport!);
}

```

## Summary

- **MetaMCP supports dual authentication strategies**: OAuth access tokens take precedence over static bearer tokens stored in the database.
- **Static tokens are persisted** in the `bearer_token` column defined in [`apps/backend/src/db/schema.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/db/schema.ts) and retrieved via `getMcpServers` in [`apps/backend/src/lib/metamcp/fetch-metamcp.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/fetch-metamcp.ts).
- **Automatic header injection** occurs in [`apps/backend/src/lib/metamcp/client.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/client.ts), where the transport layer checks `serverParams.oauth_tokens?.access_token` before falling back to `serverParams.bearerToken`.
- **Frontend flexibility** is provided by the `useConnection` hook in [`apps/frontend/hooks/useConnection.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/frontend/hooks/useConnection.ts), supporting custom header names and explicit token overrides.
- **Both SSE and STREAMABLE_HTTP transports** implement identical authentication logic, ensuring consistent behavior across connection types.

## Frequently Asked Questions

### Can I use both OAuth and static bearer tokens simultaneously?

No, MetaMCP implements a priority-based fallback system rather than combining tokens. According to the logic in [`apps/backend/src/lib/metamcp/client.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/client.ts), the system first checks for `serverParams.oauth_tokens?.access_token` and only falls back to `serverParams.bearerToken` if the OAuth token is undefined or empty. This ensures that OAuth tokens take precedence when available, while static tokens provide a reliable backup for servers that don't support OAuth flows.

### How do I configure a custom authentication header name?

You can specify a custom header name through the `useConnection` hook in [`apps/frontend/hooks/useConnection.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/frontend/hooks/useConnection.ts). Pass the `headerName` parameter (e.g., `X-API-Key`), and the hook will use that header instead of the standard `Authorization` header. When a custom header is specified, the hook also sets the `x-custom-auth-header` metadata header to inform the backend of the custom field name, allowing for flexible authentication schemes beyond standard Bearer tokens.

### Where are bearer tokens stored securely in MetaMCP?

Static bearer tokens are stored in the PostgreSQL database in the `bearer_token` column, defined in [`apps/backend/src/db/schema.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/db/schema.ts) as a text field. The tokens are retrieved server-side via the `getMcpServers` function in [`apps/backend/src/lib/metamcp/fetch-metamcp.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/fetch-metamcp.ts) and injected into transport headers before any client-side exposure. This architecture ensures that sensitive tokens remain on the backend unless explicitly provided through the frontend hook for specific use cases.

### What transport types support bearer token authentication?

MetaMCP supports bearer token authentication across both **SSE** (Server-Sent Events) and **STREAMABLE_HTTP** transports, as implemented in [`apps/backend/src/lib/metamcp/client.ts`](https://github.com/metatool-ai/metamcp/blob/main/apps/backend/src/lib/metamcp/client.ts). The authentication logic at lines 84-94 (SSE) and lines 115-124 (STREAMABLE_HTTP) follows identical patterns, checking for OAuth tokens before falling back to static bearer tokens. This ensures consistent authentication behavior regardless of whether your remote MCP server uses event streams or standard HTTP request-response patterns.