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 constantKEYCHAIN_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– Callskeychain.getDomain()andkeychain.getToken()vialoadConfig()to build theAuth0Configobject passed to the server.src/commands/init.tsandsrc/auth/client-credentials-flow.ts– Executekeychain.setDomain(tenantName)after authentication, which overwrites any existing domain entry in the keychain.src/server.ts– InvokesloadConfig()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.tshard-codes the service nameauth0-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
initandruncommands under each user. - Container isolation works best for CI/CD or ephemeral environments; distinct volume mounts prevent credential overlap when
keytarfalls back to file storage. - Custom service names require patching
KEYCHAIN_SERVICE_NAMEto read from an environment variable likeAUTH0_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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →