Two optional features need more than one variable to switch on: the Google Drive mirror, which copies people's documents into their own Drive, and the MCP server, which lets AI tools such as Claude work on their documents. Both are off until you set them up, both need sign-in to be configured, and leaving either off changes nothing else about the editor.
Google Drive
Drive traffic goes from each person's browser straight to Google. Your api Worker only brokers tokens and keeps a few small rows in your database, so the mirror costs you next to nothing to run.
Create the Google Cloud Project
drive.file (the files livediagram creates or is shown) and drive.install (the Open with entry in Drive). Both are non-sensitive, so Google asks for no verification or security assessment.https://<your-host> as an authorised JavaScript origin and https://<your-host>/drive/connected as an authorised redirect URI. If your site redirects one host to another (as livediagram.app sends its bare domain to www), register both hosts.https://<your-host>/drive/open, default MIME type application/vnd.livediagram+json, default extension livediagram.Set the Variables
| Variable | Where | What it does |
|---|---|---|
GOOGLE_CLIENT_ID | api Worker, [vars] | Switches the mirror on. Without it every Drive route answers 503 |
NEXT_PUBLIC_GOOGLE_CLIENT_ID | live build | The same client id. Without it the editor shows no Drive option |
GOOGLE_CLIENT_SECRET | api Worker, secret | Lets the server renew access, so syncing never needs a click |
DRIVE_TOKEN_KEY | api Worker, secret | Seals the stored refresh tokens: base64 of 32 random bytes |
NEXT_PUBLIC_GOOGLE_API_KEY | live build | The Picker's browser key (optional) |
The api Worker and the live build must carry the same client id. Set the two secrets with:
pnpm --filter @livediagram/api exec wrangler secret put GOOGLE_CLIENT_SECRET
pnpm --filter @livediagram/api exec wrangler secret put DRIVE_TOKEN_KEY # openssl rand -base64 32
Once all of this is in place, signed-in people find the mirror in Settings, under Account, then Cloud Sync. The folder it creates in each person's Drive is named livediagram (self-hosted), so someone who also uses livediagram.app never gets two folders with the same name.
Browser-Only Mode
You can run the mirror with only the client id, leaving out GOOGLE_CLIENT_SECRET and DRIVE_TOKEN_KEY. The browser then holds short-lived Google tokens, which Google cannot renew without the person clicking. When one lapses, syncing pauses and a small banner says Google Drive sync is paused, with Resume sync. One click carries on, and nothing is lost in between. Add the secret and key later to make syncing silent.
Things to Know
- Changing
DRIVE_TOKEN_KEYinvalidates every stored connection, so each person has to reconnect. Set it once and keep it. - One Google project per environment. A project has one Drive Open with URL, and
drive.fileaccess belongs to the project, so a staging copy beside production should have its own project, client id, secret, key and Picker key. Files another deployment's project created are foreign to yours, and import as copies. - Your privacy policy must describe the Google user data your deployment handles.
The MCP Server
The MCP server is its own Cloudflare Worker, apps/mcp. It carries no AI model and makes no model calls: the connected tool does the thinking, and the server forwards its requests to your api Worker. It needs sign-in, because the page where someone approves a tool is a signed-in page, and every connection becomes an ordinary API token that people can see and revoke.
Create the KV namespace the Worker keeps its OAuth state in, and put its id in the OAUTH_KV
binding in apps/mcp/wrangler.toml. The command is below.
Give the Worker a hostname of its own, such as mcp.diagrams.example.com: in the Cloudflare
dashboard, open the livediagram-mcp Worker and add a custom domain under Domains & Routes.
The deploy token only uploads Workers, so hostnames are attached by hand, as for every other
Worker.
Point the pieces at each other with the three variables in the table below. Each ships with livediagram.app's value, so a fork changes all three.
Deploy the mcp Worker after the api Worker, since it reaches the api over a service binding. The bundled workflow already deploys them in that order.
pnpm --filter @livediagram/mcp exec wrangler kv namespace create OAUTH_KV
| Variable | Where | Set it to |
|---|---|---|
CONSENT_BASE_URL | mcp Worker, [vars] in wrangler.toml | Your editor's origin, where the approval page lives |
NEXT_PUBLIC_MCP_ORIGIN | live build | Your MCP origin: the approval page sends the new token only there |
OAUTH_ISSUER | api Worker, [vars] in wrangler.toml | Your MCP origin (https only), where the CLI signs in |
People then add a connector in their AI tool pointing at https://<your MCP host>/mcp.
If you do not run the MCP server, remove OAUTH_ISSUER from the api Worker's wrangler.toml too. The CLI then offers no browser or device sign-in on your instance, and people sign it in with an API token instead.
If telemetry is on, also set the same INTERNAL_EVENTS_KEY secret on both the api and mcp Workers, so the MCP server's anonymous usage counts are not throttled as one busy visitor. Without telemetry, skip it.
Deploying With GitHub Actions
The bundled deploy workflow builds every app, then deploys the Workers. Two things in it matter here:
- It always deploys the mcp Worker. If you are not running the MCP server, remove that job from
.github/workflows/deploy-reusable.yml, or create the KV namespace first so the deploy succeeds. - It does not read most
NEXT_PUBLIC_*values from repository secrets. These are baked into the live build, so they must be in the build step's environment:NEXT_PUBLIC_MCP_ORIGINcomes from themcp_origininput in.github/workflows/deploy.yml. Left empty, the live app falls back tohttps://mcp.livediagram.app, which is not yours, so set it to your MCP origin.NEXT_PUBLIC_GOOGLE_CLIENT_IDis only added for livediagram.app's own repository. Add it to the Build all apps step yourself.NEXT_PUBLIC_GOOGLE_API_KEYis the exception: the workflow passes a repository secret of that name through to the build.
The wrangler.toml values and Worker secrets are read at runtime, so they do not need the workflow at all: edit the file, or run wrangler secret put.
The repository's docs/operations/self-hosting.md, and the .env.example file in apps/api,
apps/live and apps/mcp, list every variable these features read, for local development as well
as production.
Was this article helpful?