How to Configure Multiple Auth0 MCP Server Instances for Different Tenants on the Same Machine

The Auth0 MCP server stores tenant credentials in the OS keychain under a single hard-coded service name (auth0-mcp), meaning only one tenant can be active per user session unless you isolate instances using separate OS users, containers, or a patched keychain service name.

The auth0/auth0-mcp-server repository provides a Model Context Protocol (MCP) server for managing Auth0 tenants, but its default architecture limits you to one active tenant per operating system user. Because the server relies on the system keychain to store access tokens, refresh tokens, and tenant domains, running a second instance overwrites the credentials of the first. Below are three battle-tested strategies to run parallel instances for different Auth0 tenants without credential collisions.

Why the Default Setup Limits You to One Tenant

The constraint stems from how the server manages authentication state across several core files:

  • src/utils/keychain.ts – Defines the constant KEYCHAIN_SERVICE_NAME = 'auth0-mcp' and uses the keytar library to store credentials. All token retrieval and storage operations reference this single service identifier.
  • src/utils/config.ts – Calls keychain.getDomain() and keychain.getToken() via loadConfig() to build the Auth0Config object passed to the server.
  • src/commands/init.ts and src/auth/client-credentials-flow.ts – Execute keychain.setDomain(tenantName) after authentication, which overwrites any existing domain entry in the keychain.
  • src/server.ts – Invokes loadConfig() once at startup, binding the entire instance to whichever tenant domain resides in the keychain at that moment.

Since the OS keychain only retains one entry per service name, initializing a second tenant on the same user account automatically replaces the first tenant’s credentials.

Three Methods to Run Parallel Instances

You can bypass the single-tenant limitation by isolating the keychain storage context. Choose the method that aligns with your infrastructure constraints.

Separate OS User Accounts

Each Unix user maintains an independent keychain (or login keychain on macOS). By running each MCP instance under a distinct user, you achieve natural credential isolation without modifying code.


# Create dedicated service accounts

sudo useradd -m mcp-tenant-a
sudo useradd -m mcp-tenant-b

# Initialize each user for their respective Auth0 tenant

sudo -u mcp-tenant-a npx @auth0/auth0-mcp-server init --client claude --tools '*'
sudo -u mcp-tenant-b npx @auth0/auth0-mcp-server init --client claude --tools '*'

# Run both servers simultaneously

sudo -u mcp-tenant-a npx @auth0/auth0-mcp-server run --tools '*' &
sudo -u mcp-tenant-b npx @auth0/auth0-mcp-server run --tools '*' &

This approach is ideal when you can create lightweight service accounts on the host and want zero code changes.

Container or VM Isolation

Running each instance inside its own Docker container provides filesystem and keychain isolation. When keytar cannot access the host OS keychain, it falls back to a file-based store inside the container.

FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm ci && npm run build
ENTRYPOINT ["node", "dist/src/commands/run.js"]

# Build once

docker build -t auth0-mcp .

# Run isolated containers for each tenant

docker run -d \
  -v $HOME/.auth0-mcp-a:/root/.auth0-mcp \
  --name mcp-a \
  auth0-mcp run --tools '*'

docker run -d \
  -v $HOME/.auth0-mcp-b:/root/.auth0-mcp \
  --name mcp-b \
  auth0-mcp run --tools '*'

# Initialize each container separately

docker exec -it mcp-a npx @auth0/auth0-mcp-server init --client claude --tools '*'
docker exec -it mcp-b npx @auth0/auth0-mcp-server init --client claude --tools '*'

Mounting distinct host directories (~/.auth0-mcp-a vs ~/.auth0-mcp-b) ensures that even the fallback file storage remains isolated between instances.

Custom Keychain Service Name (Single-User Patch)

If you must run everything under a single OS user without containers, modify src/utils/keychain.ts to accept an environment variable for the service name.

Apply this patch to src/utils/keychain.ts:

-export const KEYCHAIN_SERVICE_NAME = 'auth0-mcp';
+export const KEYCHAIN_SERVICE_NAME = process.env.AUTH0_MCP_KEYCHAIN_SERVICE ?? 'auth0-mcp';

After rebuilding (npm run build), launch each instance with a unique service identifier:


# Tenant A

AUTH0_MCP_KEYCHAIN_SERVICE=auth0-mcp-a \
  npx @auth0/auth0-mcp-server init --client claude --tools '*'
AUTH0_MCP_KEYCHAIN_SERVICE=auth0-mcp-a \
  npx @auth0/auth0-mcp-server run --tools '*' &

# Tenant B

AUTH0_MCP_KEYCHAIN_SERVICE=auth0-mcp-b \
  npx @auth0/auth0-mcp-server init --client claude --tools '*'
AUTH0_MCP_KEYCHAIN_SERVICE=auth0-mcp-b \
  npx @auth0/auth0-mcp-server run --tools '*'

This method requires maintaining a fork or local patch but offers the most lightweight solution for developer machines.

Step-by-Step Configuration Examples

Bash Script for User-Based Isolation

Save this as start-multi-tenant.sh to automate the creation and startup of two tenant-specific servers:

#!/usr/bin/env bash
set -euo pipefail

# Tenant A

sudo -u mcp-tenant-a bash <<'EOF'
  npx @auth0/auth0-mcp-server init --client claude --tools '*'
  npx @auth0/auth0-mcp-server run --tools '*' &
  echo "Tenant A started (PID $!)"
EOF

# Tenant B

sudo -u mcp-tenant-b bash <<'EOF'
  npx @auth0/auth0-mcp-server init --client claude --tools '*'
  npx @auth0/auth0-mcp-server run --tools '*' &
  echo "Tenant B started (PID $!)"
EOF

Docker Compose for Local Development

Use this docker-compose.yml to define two isolated services:

version: "3.9"
services:
  mcp-a:
    build: .
    environment:
      - AUTH0_MCP_DEBUG=true
    volumes:
      - ~/.auth0-mcp-a:/root/.auth0-mcp
    command: run --tools '*'
    stdin_open: true
    tty: true

  mcp-b:
    build: .
    environment:
      - AUTH0_MCP_DEBUG=true
    volumes:
      - ~/.auth0-mcp-b:/root/.auth0-mcp
    command: run --tools '*'
    stdin_open: true
    tty: true

Run docker compose up -d, then execute the initialization command in each container before connecting your MCP client.

Summary

  • The Auth0 MCP server defaults to a single-tenant architecture because src/utils/keychain.ts hard-codes the service name auth0-mcp, allowing only one set of credentials in the OS keychain per user.
  • OS user isolation provides the cleanest separation by leveraging built-in keychain boundaries—create separate accounts and run init and run commands under each user.
  • Container isolation works best for CI/CD or ephemeral environments; distinct volume mounts prevent credential overlap when keytar falls back to file storage.
  • Custom service names require patching KEYCHAIN_SERVICE_NAME to read from an environment variable like AUTH0_MCP_KEYCHAIN_SERVICE, enabling multiple instances under one user without virtualization.

Frequently Asked Questions

Can I switch between tenants without logging out and re-initializing?

No. The init command in src/commands/init.ts explicitly calls keychain.setDomain() and keychain.setToken(), which overwrites existing entries. To switch tenants, you must either use logout to clear the keychain or isolate instances using one of the three methods described above.

Is it safe to run multiple instances in Docker containers on the same host?

Yes. Each container receives its own filesystem namespace. When the container lacks access to the host keychain, keytar writes to ~/.keytar or the path specified by your volume mount. As long as you mount distinct host directories for each container (e.g., ~/.auth0-mcp-a vs ~/.auth0-mcp-b), credentials remain isolated.

What happens if I try to run two instances without isolation?

The second instance will overwrite the first instance’s credentials in the OS keychain. When the first instance attempts to refresh its access token or make an API call, it will either fail with authentication errors or inadvertently operate against the second tenant’s domain, depending on the state of the token cache.

How do I implement the custom keychain service name patch permanently?

Fork the auth0/auth0-mcp-server repository and modify src/utils/keychain.ts to use process.env.AUTH0_MCP_KEYCHAIN_SERVICE || 'auth0-mcp'. After building with npm run build, you can publish the package to a private registry or install it directly from your fork. This allows you to set AUTH0_MCP_KEYCHAIN_SERVICE=tenant-name per process without maintaining separate OS users or containers.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →