Google Drive and MCP on a Self-Hosted Instance

Turn on the Google Drive mirror and the MCP server for AI tools on your own deployment.

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

In the Google Cloud console, create a project for your deployment and enable the Google Drive API.
Configure the OAuth consent screen. It needs only two scopes, 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.
Create an OAuth client of type Web application. Add 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.
For Open with in Drive, configure the Drive API's Drive UI integration: Open URL https://<your-host>/drive/open, default MIME type application/vnd.livediagram+json, default extension livediagram.
Optionally, create a browser API key for the Google Picker, restricted by HTTP referrer to your host. It lets people show livediagram a folder they made in Drive themselves; without it the mirror works and that one step is not offered.

Set the Variables

VariableWhereWhat it does
GOOGLE_CLIENT_IDapi Worker, [vars]Switches the mirror on. Without it every Drive route answers 503
NEXT_PUBLIC_GOOGLE_CLIENT_IDlive buildThe same client id. Without it the editor shows no Drive option
GOOGLE_CLIENT_SECRETapi Worker, secretLets the server renew access, so syncing never needs a click
DRIVE_TOKEN_KEYapi Worker, secretSeals the stored refresh tokens: base64 of 32 random bytes
NEXT_PUBLIC_GOOGLE_API_KEYlive buildThe 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_KEY invalidates 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.file access 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
VariableWhereSet it to
CONSENT_BASE_URLmcp Worker, [vars] in wrangler.tomlYour editor's origin, where the approval page lives
NEXT_PUBLIC_MCP_ORIGINlive buildYour MCP origin: the approval page sends the new token only there
OAUTH_ISSUERapi Worker, [vars] in wrangler.tomlYour 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_ORIGIN comes from the mcp_origin input in .github/workflows/deploy.yml. Left empty, the live app falls back to https://mcp.livediagram.app, which is not yours, so set it to your MCP origin.
    • NEXT_PUBLIC_GOOGLE_CLIENT_ID is only added for livediagram.app's own repository. Add it to the Build all apps step yourself.
    • NEXT_PUBLIC_GOOGLE_API_KEY is 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?