Auth & security
The DFL MCP never has its own “god mode” view of the data. Every request runs as you. This page explains how that works so you know exactly what an AI assistant can — and can’t — do on your behalf.
The auth flow
Section titled “The auth flow”-
Your DFL login.
dfl-auth loginprompts for your DFL email and password. Supabase returns a JWT access token and a refresh token. -
Bearer on every call. Your client sends
Authorization: Bearer <access_token>with each MCP request. The endpoint validates the JWT’s signature and expiry. -
Per-session Supabase client. The endpoint builds a Supabase client using your JWT for the lifetime of that session — not a service key. So every read and write is executed with your identity.
-
RLS decides. PostgreSQL Row-Level Security policies and your IAM role determine which rows you can see and which mutations you can make.
dfl-auth login ──▶ DFL email/password (Supabase) ──▶ JWT (access + refresh) │ client ── Authorization: Bearer <JWT> ──▶ MCP endpoint ─┤ ▼ Supabase client bound to YOUR JWT ▼ RLS + your IAM role = what you can doGlobal fleet prerequisite
Section titled “Global fleet prerequisite”Use your existing global DFL login. OpenPencil accepts the same current Supabase user JWT as the other fleet MCPs. It does not require a separate account or a token collected from a browser session.
If this PC does not have the global DFL login yet, configure the client once:
npx @devfellowship/dfl-auth configurenpx @devfellowship/dfl-auth loginUse your own DFL email and password in the CLI prompts. The current login prompt
shows the password while you type; use a private terminal. These commands keep
the existing global human workflow under ~/.dfl-mcp/.
Load the current global JWT into the client environment
Section titled “Load the current global JWT into the client environment”The existing global login stores access_token in
~/.dfl-mcp/credentials.json. Load that token into DFL_MCP_JWT when you start
your MCP client. The command below reads the existing credential in memory;
it does not print it or create another credential file.
On macOS, Linux or WSL, in Bash or Zsh:
export DFL_MCP_JWT="$(node -e 'const fs=require("node:fs");const path=require("node:path");const os=require("node:os");const c=JSON.parse(fs.readFileSync(path.join(os.homedir(),".dfl-mcp","credentials.json"),"utf8"));process.stdout.write(c.access_token);')"codex# Or run claude instead.unset DFL_MCP_JWTOn Windows PowerShell:
$credentialPath = Join-Path ([Environment]::GetFolderPath("UserProfile")) ".dfl-mcp/credentials.json"$env:DFL_MCP_JWT = (Get-Content -Raw $credentialPath | ConvertFrom-Json).access_tokentry { codex # Or run claude instead.} finally { Remove-Item Env:DFL_MCP_JWT -ErrorAction SilentlyContinue}The configuration below stores only the environment reference. Preserve any fleet servers that are already configured. Configure each endpoint once in global user scope, so the connection is available across your projects. Each human uses their own global DFL login; scope does not grant extra access.
Global OpenPencil connection: Codex
Section titled “Global OpenPencil connection: Codex”codex mcp add openpencil --url https://openpencil.devfellowship.com/mcp --bearer-token-env-var DFL_MCP_JWTThis stores the variable name in the user’s global Codex MCP configuration.
Start Codex from the terminal that holds the current DFL_MCP_JWT.
Global OpenPencil connection: Claude Code
Section titled “Global OpenPencil connection: Claude Code”claude mcp add --transport http --scope user --header 'Authorization: Bearer ${DFL_MCP_JWT}' -- openpencil https://openpencil.devfellowship.com/mcpThe single quotes preserve the literal reference in Bash, Zsh and PowerShell.
User scope makes the connection available in all your projects. Start Claude
Code with DFL_MCP_JWT in its environment and check /mcp.
The client should call list_projects on OpenPencil to confirm access. Then
follow the native canvas tool-call guide or the
Portuguese first-interaction tutorial.
OpenPencil Desktop and extra skills are optional for this flow.
The same JWT can authenticate multiple fleet endpoints. Each endpoint has its own MCP transport session. Browser SSO does not automatically authenticate a separate MCP transport. OpenPencil currently requires the bearer token and does not offer MCP OAuth login or automatic client-side token refresh.
Client references: Claude Code global scope and headers and Codex MCP configuration.
OpenPencil stores canonical FIG documents on its resident service volume. It verifies the same caller JWT, then applies project ownership and current IAM; its document bytes are not rows in a Supabase table.
What you can see and change
Section titled “What you can see and change”Because the MCP acts as you under RLS:
- You see your data and anything your role is allowed to read.
- You can mutate only what your role permits.
- A
403 Forbiddenmeans your permissions don’t allow it — the MCP is faithfully enforcing your access, not malfunctioning.
Where your credentials live
Section titled “Where your credentials live”| Path | Contents | Notes |
|---|---|---|
~/.dfl-mcp/project.json | Supabase project config | Written by dfl-auth configure |
~/.dfl-mcp/credentials.json | access_token, refresh_token, expires_at | Written by dfl-auth login; auto-refreshed |
Token lifetime & refresh
Section titled “Token lifetime & refresh”Access tokens are short-lived by design. Refresh without re-doing the browser login:
- CLI:
npx @devfellowship/dfl-auth refresh - JS/TS:
getValidAccessToken()from@devfellowship/dfl-authauto-refreshes
The OpenPencil endpoint does not expose /auth/refresh. Renew your shared global
DFL credential, then restart the client with the updated environment variable.
A future expiry does not prove a live session
Section titled “A future expiry does not prove a live session”The current dfl-auth status command checks the stored expiry time only.
A revoked session can still display Active with hours remaining. The current
login and refresh commands can also skip renewal while that time is valid.
If a fleet endpoint returns 401, obtain a fresh global login:
npx @devfellowship/dfl-auth logoutnpx @devfellowship/dfl-auth loginlogout removes the local stored credential; it does not revoke every existing
session. login then prompts for your DFL email and password. Reload the new
access_token into DFL_MCP_JWT and restart the MCP client. Existing client
processes and manually copied headers keep their old token until you update them.
Confirm recovery with an authenticated tool call, such as OpenPencil’s
list_projects. A stored expiry time, configuration entry or HTTP status alone
does not establish the caller’s usable session. A new global DFL email/password
login restored OpenPencil access in the human review on 7 October 2026.
Transport security
Section titled “Transport security”- Fleet MCP endpoints use HTTPS.
- MCP calls require the current caller’s credential.
- Keep actual tokens out of client configuration, prompts, screenshots and shared links.
- OpenPencil authorizes the project owner or a current global IAM level of at least 80.