Files
overleaf-mcp/README.md
2026-04-13 13:45:38 +02:00

265 lines
8.1 KiB
Markdown

# Running OverLeaf_MCP in Docker with Authentik Authentication
Run the [OverLeaf_MCP](https://github.com/Sahith59/OverLeaf_MCP) server in Docker, secured with OAuth 2.1 via your existing Authentik instance, using [mcp-auth-proxy](https://github.com/sigbit/mcp-auth-proxy). Only authenticated Qumo users can access your Overleaf account.
## What this sets up
A single Docker container running:
- **OverLeaf_MCP** — the MCP server (stdio)
- **mcp-auth-proxy** — wraps it with OAuth 2.1 + automatic HTTPS (Let's Encrypt)
`mcp-auth-proxy` acts as the OAuth 2.1 authorization server toward Claude.ai (handling Dynamic Client Registration, PKCE, token issuance). It delegates user authentication to Authentik via standard OIDC. Authentik never touches the MCP protocol — it only answers "who is this person?".
```
Claude.ai ──OAuth 2.1──► mcp-auth-proxy ──stdio──► OverLeaf_MCP
(OIDC client)
Authentik
(identity only)
```
## Prerequisites
- A server with a **public IP** and ports **80 + 443 open**
- A **domain** pointed at that IP (e.g. `overleaf-mcp.qumo.io`)
- Docker and Docker Compose
- Your existing **Authentik** instance (e.g. `auth.qumo.io`)
- A free [Overleaf](https://overleaf.com) account
- Claude Pro/Team/Enterprise subscription
## Step 1: Create the Authentik provider and application
In the Authentik admin UI at `https://auth.qumo.io`:
### Create the provider
1. Go to **Applications → Providers → Create**
2. Select **OAuth2/OpenID Provider** (not Proxy Provider)
3. Configure:
- **Name**: `Overleaf MCP Provider`
- **Authentication flow**: default
- **Authorization flow**: `default-provider-authorization-implicit-consent`
- **Redirect URI (strict)**: `https://overleaf-mcp.qumo.io/oauth/callback`
- **Signing key**: select any available key
- **Scopes**: make sure `email`, `profile`, and `openid` are included
4. Click **Finish**
5. Copy the **Client ID** and **Client Secret**
### Create the application
1. Go to **Applications → Applications → Create**
2. Configure:
- **Name**: `Overleaf MCP`
- **Slug**: `overleaf-mcp`
- **Provider**: select the provider you just created
3. Click **Create**
### Find the issuer URL
The OIDC issuer URL for Authentik follows this pattern:
```
https://auth.qumo.io/application/o/overleaf-mcp/
```
Where `overleaf-mcp` is the application slug. You can verify it works by visiting:
```
https://auth.qumo.io/application/o/overleaf-mcp/.well-known/openid-configuration
```
This should return a JSON document with `authorization_endpoint`, `token_endpoint`, etc.
## Step 2: DNS
Create an **A record** for the MCP server subdomain:
```
overleaf-mcp.qumo.io → A → <your-server-ip>
```
If you're running this on the same VPS as Caddy, see the note at the bottom about using Caddy instead of Let's Encrypt.
## Step 3: Configure the project
```bash
mkdir ~/apps/overleaf-mcp && cd ~/apps/overleaf-mcp
```
Place the `Dockerfile`, `docker-compose.yml`, and `.env.example` in this directory, then:
```bash
cp .env.example .env
nano .env
```
Fill in all values:
```
OVERLEAF_EMAIL=your@email.com
OVERLEAF_PASSWORD=your-overleaf-password
MCP_DOMAIN=overleaf-mcp.qumo.io
AUTHENTIK_ISSUER_URL=https://auth.qumo.io/application/o/overleaf-mcp/
AUTHENTIK_CLIENT_ID=<from step 1>
AUTHENTIK_CLIENT_SECRET=<from step 1>
ALLOWED_USER=you@qumo.io
```
The `ALLOWED_USER` field matches against the OIDC claims returned by Authentik. This is typically the email address. You can also use glob patterns like `*@qumo.io` to allow all users in your Authentik instance with a Qumo email.
## Step 4: Build and start
```bash
docker compose up -d --build
```
Check logs:
```bash
docker compose logs -f
```
You should see mcp-auth-proxy provision a Let's Encrypt certificate and start listening on port 443.
## Step 5: Connect Claude.ai
1. Open [claude.ai](https://claude.ai) → **Settings****Integrations**
2. Add a new MCP integration:
```
https://overleaf-mcp.qumo.io/mcp
```
3. Claude initiates the OAuth flow → you're redirected to Authentik to log in
4. After authenticating, Claude is connected
Test it:
> Call the ping tool
## Step 6: First-time Overleaf login
If Overleaf shows a CAPTCHA during headless login:
1. Install OverLeaf_MCP locally and log in once (outside Docker)
2. Copy the session data into the Docker volume:
```bash
docker volume inspect overleaf-mcp_browser-data
sudo cp -r ~/.overleaf-mcp/browser-data/* \
/var/lib/docker/volumes/overleaf-mcp_browser-data/_data/
docker compose restart
```
## Running on the same VPS as Caddy
If this runs on the same VPS where Caddy already occupies ports 80/443, you have two options:
### Option A: Let mcp-auth-proxy handle its own TLS on different ports
Not ideal — Claude.ai expects standard HTTPS on 443.
### Option B: Put it behind Caddy (recommended)
Remove the port bindings and Let's Encrypt from the container, and let Caddy handle TLS and proxying:
1. In `docker-compose.yml`, remove the `ports:` section entirely and add the shared network:
```yaml
services:
overleaf-mcp:
# ... everything else stays the same ...
# Remove ports: section
networks:
- qumo_services_proxy_network
command:
- --external-url
- https://${MCP_DOMAIN}
- --no-tls
- --port
- "8080"
- --oidc-issuer
- ${AUTHENTIK_ISSUER_URL}
- --oidc-client-id
- ${AUTHENTIK_CLIENT_ID}
- --oidc-client-secret
- ${AUTHENTIK_CLIENT_SECRET}
- --allowed-user
- ${ALLOWED_USER}
- --
- node
- /app/dist/index.js
networks:
qumo_services_proxy_network:
external: true
```
2. Add to your Caddyfile (no `import authentik` — mcp-auth-proxy handles auth):
```caddyfile
overleaf-mcp.qumo.io {
reverse_proxy overleaf-mcp:8080
}
```
3. Reload Caddy:
```bash
cd ~/networking/caddy
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
```
> **Note:** Check whether `mcp-auth-proxy` supports `--no-tls` and `--port` flags. If not, you can bind it to a high port with TLS disabled by using `--tls-cert-file` and `--tls-key-file` with self-signed certs, and let Caddy terminate real TLS in front. Consult the [mcp-auth-proxy docs](https://sigbit.github.io/mcp-auth-proxy/) for current flags.
## Fallback: password-only auth
If the OIDC flow doesn't work cleanly with Claude.ai's Dynamic Client Registration, you can fall back to password auth (confirmed working with Claude.ai):
```yaml
command:
- --external-url
- https://${MCP_DOMAIN}
- --tls-accept-tos
- --password
- ${MCP_PASSWORD}
- --
- node
- /app/dist/index.js
```
Add `MCP_PASSWORD=a-strong-random-password` to `.env`. Claude.ai will prompt for this password when connecting.
## Useful commands
```bash
# Logs
docker compose logs -f
# Restart
docker compose restart
# Full rebuild
docker compose down && docker compose build --no-cache && docker compose up -d
# Shell into the container
docker compose exec overleaf-mcp bash
# Extract PDFs
docker compose cp overleaf-mcp:/data/resumes/. ./my-resumes/
```
## Troubleshooting
**Let's Encrypt certificate fails** — Ports 80 and 443 must be open and DNS must resolve. If Caddy already holds these ports, use the "behind Caddy" setup above.
**OAuth callback error** — Verify the redirect URI in Authentik matches exactly: `https://overleaf-mcp.qumo.io/oauth/callback`
**"User not allowed"** — Check that `ALLOWED_USER` matches what Authentik returns in its OIDC claims. Try `*@qumo.io` as a glob pattern, or check the claims by decoding the JWT token.
**"Browser closed unexpectedly"** — The compose file sets `shm_size: "2gb"` for Chromium. Make sure it's there.
**Overleaf login times out** — CAPTCHA issue. Use the session-copying approach from Step 6.
**Claude.ai can't connect** — Visit `https://overleaf-mcp.qumo.io/.well-known/oauth-authorization-server` in your browser. You should see a JSON metadata document. If not, the container isn't running or TLS isn't working.