Skip to main content
Glama
ImKevinLe

MCP OAuth Gateway

by ImKevinLe

MCP OAuth Gateway (multi-tenant)

One deploy that lets any client connect their own ChatGPT or Claude to their brand's n8n MCP toolkit with a one-click "Sign in" — no token to paste, no CLI.

It speaks the OAuth flow the AI apps require, authenticates the human with a passwordless magic-link email, then transparently proxies MCP traffic to the brand's n8n endpoint with the n8n bearer token injected server-side. n8n is untouched. Each brand is a tenant served at its own subdomain; a single gateway instance serves them all.

client's ChatGPT / Claude  →  https://<brand>.mcp.lucyboo.io/mcp
        │  OAuth: discover → register → sign in (email link) → token
        ▼
  ┌──────────────────────────────┐
  │  MCP OAuth Gateway (this app) │   one Coolify service, many tenants
  │  • per-host OAuth server      │
  │  • magic-link sign-in         │
  │  • tenant registry (SQLite)   │
  └───────────────┬──────────────┘
                  │  Authorization: Bearer <that tenant's n8n token>
                  ▼
   n8n MCP endpoint for that brand  (lucyboo.io/mcp/<brand>)

Client prerequisite

Custom MCP connectors need a paid plan:

  • ChatGPT: Plus, Pro, Business, or Enterprise (Developer mode / connectors).

  • Claude: Pro, Max, Team, or Enterprise.

Free tiers can't add any connector. Confirm before onboarding.

Related MCP server: mcpgate

One-time setup

  1. Wildcard DNS: point *.mcp.lucyboo.io at the server.

  2. Wildcard TLS: in Coolify, use a wildcard cert (DNS challenge) for *.mcp.lucyboo.io, or add each brand subdomain to the app so Coolify issues a cert per host. Wildcard means zero per-client cert steps.

  3. Deploy this repo in Coolify: New Resource → Application → Dockerfile.

    • Persistent volume mounted at /data.

    • Env vars from .env.example: BASE_DOMAIN, SESSION_SECRET, the SMTP_* values, DB_PATH=/data/gateway.db.

    • Bind the app to *.mcp.lucyboo.io (or the wildcard domain).

  4. Deploy. https://anything.mcp.lucyboo.io/healthz should return {"ok":true,...} once DNS resolves.

Onboard a client (per brand)

Two steps, no redeploy:

1. Stand up the brand's n8n workflow — clone the Le Design MCP workflow, swap in that client's tools, credentials, brand data, and a fresh bearer token, activate it. (This is the real per-client work; it's the brand's actual toolkit.)

2. Register the tenant — run the admin CLI in the container (Coolify → the service's Terminal), or over SSH:

node src/admin.js add \
  --slug a1grass \
  --brand "A-1 Grass" \
  --n8n https://lucyboo.io/mcp/a1-grass \
  --token <that-workflow's-n8n-bearer-token> \
  --emails owner@a1grass.com,ops@a1grass.com

The client's connector URL is then https://a1grass.mcp.lucyboo.io/mcp.

Other commands: node src/admin.js list, node src/admin.js remove --slug a1grass. (You can also seed tenants on boot with a TENANTS_SEED JSON file — see tenants.json.example.)

What you send the client

  • Connector URL: https://<brand>.mcp.lucyboo.io/mcp

  • In Claude: Add custom connector → that URL → Sign in now → OAuth client Register automatically. (Not "Use Claude's published identity".)

  • In ChatGPT: add a custom MCP server with that URL, complete the sign-in.

They enter an approved email, click the link in their inbox, and it's live.

Security

  • Tenants are isolated by subdomain; a token issued for one brand can't call another. Sessions, codes, and tokens are all tagged by tenant.

  • allowed_emails per tenant is the allowlist — only those addresses can sign in or hold a token. Remove one to revoke that person (tokens fail on next check).

  • The n8n token never reaches the client; the proxy injects it server-side.

  • Access tokens last 1 hour; refresh tokens are issued. HTTPS only; cookies are Secure + HttpOnly.

  • The DB (on the private /data volume) holds each tenant's n8n token. Keep the volume private; it's the one secret store.

Known limitations (v1)

  • Magic link is same-device — open the email link in the browser that started the connect flow so the AI app's callback resumes cleanly.

  • SQLite on a mounted volume — right for this scale, not multi-node.

  • All of a tenant's tools are exposed to any signed-in user for that brand; no per-user tool scoping yet.

Local smoke test

npm install
BASE_DOMAIN=mcp.local SESSION_SECRET=dev DB_PATH=./dev.db \
  SMTP_HOST=localhost SMTP_PORT=25 SMTP_USER=x SMTP_PASS=x npm start
# add a tenant, then curl with a Host header:
node src/admin.js add --slug demo --brand Demo --n8n https://example.com/mcp --token t --emails you@x.com
curl -s -H 'Host: demo.mcp.local' http://localhost:8080/.well-known/oauth-authorization-server

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Production-ready MCP server that brings N8N workflow automation to both Claude.ai and ChatGPT. Supports multi-tenant OAuth/SSE integration with dynamic N8N instance configuration.
    54 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Self-hosted MCP gateway that connects Claude, ChatGPT, and other AI agents to 20+ enterprise tools (GitLab, Jira, Notion, Google Workspace, Slack, Grafana, …) with OAuth, audit logs, and zero data leaving your infrastructure
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables management of n8n workflows, executions, credentials, tags, and variables via MCP tools. Supports stdio, Claude Code, and Claude Web with optional Authentik OAuth.
    22
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables Claude.ai to connect to a Hermes MCP server via OAuth 2.1 authorization code flow with PKCE, acting as a reverse proxy and single-user authorization gateway.
    -