Excel AI Bridge — alpha

Connect a Claude client to the bridge

Tutorial 1 put the add-in in Excel, and the ribbon said no AI was connected. This one fixes that: by the end, a Claude client will be able to read the workbook that is open in front of you, and the ribbon will say so.

The bridge speaks MCP, which is simply a way for a Claude app to call tools that run on this machine — here, tools that read and change the workbook Excel already has open. Nothing is uploaded; Claude asks, the bridge reads the live book, and answers.

Prerequisites

for that downloaded script), AIBridge.xlam is in Excel's XLSTART folder and the AI Bridge tab appears on the ribbon.

so an unsaved Book1 has nothing to bind to. These pages use TutorialDemo.xlsx, which ships in this folder of the release zip.

customers take Route C and press Connect AI; that starts the embedded Python from the unpacked folder. You do not need a venv.

Choosing a route

There are three, and the difference is where Claude runs and who carries the traffic. Take Route A if the Claude app runs on this same machine: the client launches the bridge itself over stdio, and there is no port, no URL and no account to configure. Take Route C if you want claude.ai in a browser: the bridge dials out to a hosted broker, prints one URL, and you paste that URL into claude.ai — no tunnel, no DNS, no cloud console. Route B is the same browser connector run entirely on your own infrastructure; it is the advanced / self-hosted option, and you only need it if you would rather not depend on the hosted broker at all.

Everything from Point it at a workbook onwards is identical on all three routes.

Route A — a Claude app on this machine (stdio)

A local client starts the bridge as a child process and talks to it over that process's own stdin and stdout. That is the default: src\server.py with no --http flag serves stdio and never opens a socket.

Add one entry to the client's MCP configuration. Claude Desktop keeps it in %APPDATA%\Claude\claude_desktop_config.json; Claude Code reads .mcp.json in the project folder, or writes it for you via claude mcp add. The shape is the same either way:

{
  "mcpServers": {
    "excel-ai-bridge": {
      "command": "C:\\path\\to\\excel-ai-bridge\\venv\\Scripts\\python.exe",
      "args": ["C:\\path\\to\\excel-ai-bridge\\src\\server.py"]
    }
  }
}

Replace C:\path\to\excel-ai-bridge with wherever you cloned this repository. Use the interpreter inside venv, not a system python: the bridge imports fastmcp, pywin32 and xlwings, and a system interpreter almost certainly has none of them. The backslashes are doubled because this is JSON.

You can pin a workbook at startup instead of binding it later, by adding "--workbook", "C:\\Users\\you\\Documents\\TutorialDemo.xlsx" to args.

Then restart the client completely — MCP servers are launched at start-up, so reloading a conversation is not enough. When it comes back, the Excel tools appear in its tool list: read_range, write_cells, get_active_selection, analyze_sheet, privacy_report and the rest, alongside bind_workbook. If the list is empty, the client could not launch the command — check the path and the interpreter before anything else.

On stdio there is no token and no sign-in, and the audit records the caller as local. That is not laziness: the client is the parent process, so anything able to write to this bridge's stdin is already inside the machine.

Route C — the hosted broker (recommended)

This is the short way to claude.ai. With the add-in installed, open a saved workbook and press Connect AI. If no bridge is running, the ribbon launches the embedded runtime — python\pythonw.exe with src\server.py --broker from the unpacked folder (the path install.cmd recorded). The tray icon shows it running, then the add-in attaches as today. The invite is already in invite.json at the zip root, so you do not type a code.

From-source developers can still start it by hand:

venv\Scripts\python.exe src\server.py --broker

If you start by hand without invite.json, put the invite in the environment:

set EXCEL_BRIDGE_INVITE=the-code-you-were-given

The bridge registers itself with the broker once, and stores the identity it gets back — DPAPI-protected, so it is readable only by this Windows account on this machine — in %LOCALAPPDATA%\ExcelAIBridge\broker.json. Later starts read that file and need no invite code at all. On the way up it prints four lines on stderr:

AI Bridge: connector URL https://bridge.ram.sh/<id>/mcp
AI Bridge: Google redirect to register: https://bridge.ram.sh/auth/callback
AI Bridge: accounts allowed: you@example.com
AI Bridge: linked to https://bridge.ram.sh

<id> is this bridge's own 32-hex id, minted at registration and the same on every later start. The Google redirect is fixed at https://bridge.ram.sh/auth/callback and is already registered in the shared OAuth app, so there is nothing for you to add in a Google console.

Then add it in claude.ai:

  1. Settings → Connectors → Add custom connector.
  2. Paste the connector URL exactly as printed —

https://bridge.ram.sh/<id>/mcp.

  1. Press Connect.
  2. Approve the bridge's consent page when it appears.
  3. Sign in with Google, using an account that is on the allowlist. The

allowlist is EXCEL_BRIDGE_ALLOWED, a comma-separated list of email addresses, or the 1Password item Excel AI Bridge - allowed google accounts. It is the same allowlist Route B uses, and an empty one is fatal on purpose.

Nothing on this machine listens on a port. The bridge opens an outbound WebSocket to the broker and keeps it, so claude.ai's request arrives down a connection you dialled — which is why there is no tunnel to run, no port to forward and no firewall rule to write. The broker only relays bytes between claude.ai and your bridge: the Google sign-in is checked against your allowlist, the workbook and the audit log stay on this machine, and the identity in broker.json never leaves it.

On a machine with no access to the shared vault, set EXCEL_BRIDGE_GOOGLE_CLIENT_ID and EXCEL_BRIDGE_GOOGLE_CLIENT_SECRET in the environment instead; those values win over the vault when they are set.

Route B — claude.ai in a browser, self-hosted (advanced)

Route C already gets you a browser connector. Take this route only if you want to host the public side yourself: it needs a public https:// address you own, a tunnel you run, and a Google OAuth app whose redirect you register by hand.

Start the bridge in HTTP mode yourself, from the repository folder:

venv\Scripts\python.exe src\server.py --http --port 8765 --google

--google makes the bridge check who is signing in, because this route is reachable from the internet: it refuses to serve anyone but the Google accounts you have named. (--google implies --http, so that flag is only there to make the port explicit.) On the way up the bridge prints the loopback address, the connector URL and the list of allowed accounts on stderr.

Two things it needs from you before this mode will start:

127.0.0.1 only, deliberately. Exposing it is a separate, deliberate act on your part — a Cloudflare tunnel, an ssh -R to a server you own, ngrok, whatever you trust. Which one you use is your choice and your responsibility; this project does not set one up for you and does not ship one.

can build the OAuth redirect Google has to match exactly. It must begin with https://; plain http:// is refused rather than quietly carrying an authorization code in clear text.

set EXCEL_BRIDGE_PUBLIC_URL=https://excel.example.com

Use your own hostname there, not the example one. EXCEL_BRIDGE_ALLOWED — or the 1Password item Excel AI Bridge - allowed google accounts — holds the comma-separated list of Google accounts allowed in. An empty list is fatal on purpose, because "no allowlist" must never quietly mean "anyone with a Google account who finds the URL".

Now add it in claude.ai: Settings → Connectors → Add custom connector, and give it that same public address with /mcp on the end, for example https://excel.example.com/mcp. Claude registers itself against the bridge's authorization server, you sign in with Google once, and the connector goes green.

About the bearer token. --google and the token are two different doors and you only ever use one of them. claude.ai's connector speaks OAuth and cannot present a bearer token at all, which is exactly why this route uses --google. The token guards --http without --google — the mode for anything you drive yourself, a script or a terminal client. It is minted once and kept in 1Password under the item Excel AI Bridge - connector token, reused across restarts so that a connector you configured once does not break on the next start; rotate it by deleting that item. If you would rather manage it yourself, set EXCEL_BRIDGE_TOKEN in the environment and that value wins, with no vault involved at all. Never paste a token into a chat, a commit or a screenshot.

Point it at a workbook, and prove the link

The screenshots below come from a Route B run against TutorialDemo.xlsx. Route A looks the same from the second step onwards — same tools, same replies — and differs only in that a local client asks for permission in its own way.

  1. Ask Claude for anything that needs the workbook, and it stops to ask

permission first. Here the request was *"Bind the workbook at C:\Users\you\Documents\TutorialDemo.xlsx"*, and Claude will not call bind_workbook until you say so. Choose Allow once: it grants that single call and nothing more. The other button grants the tool for good — a standing permission to reach into your spreadsheet that you will never be reminded about again. The dialog appears once per new tool, so expect a handful of them early on and almost none later.

The tool-permission dialog, with Allow once offered

  1. Claude calls bind_workbook and answers with what it bound: the full path,

the transport, the port, and whether the file was locked on disk. Give it the full path, always. bind_workbook accepts nothing else — not a file name, not "the workbook I have open" — and a path that is not currently open in Excel is refused rather than guessed at. That refusal is the whole point: with two revisions of the same budget open, "the active workbook" is whichever one you happened to click last, and a write can land silently in the wrong copy. A full path cannot be ambiguous.

Claude reporting the workbook it bound, by full path

  1. Switch to Excel. The AI Bridge tab now reads AI connected with a green

dot, and the tab strip itself says AI Bridge - connected. That light is not the button remembering it was pressed: the bridge republishes its state every few seconds and the ribbon only reports what it reads, so a bridge that dies goes dark on its own. Two neighbouring states are worth learning now. Waiting for AI, amber, means this workbook was offered but nothing has picked it up yet. Connect here, red, means a bridge is live but holding a different workbook — press it to move the binding to this one.

The Excel ribbon reading AI connected

  1. Ask "Which workbooks are you holding right now?". list_bound_workbooks

answers with a name, a full path and a session id for each one. Binding is additive: a second bind_workbook does not replace the first, it adds to it, and once more than one workbook is bound every other tool needs a workbook= argument saying which. This is the call to make whenever you are unsure what Claude is actually looking at.

Claude listing the workbooks it currently holds

  1. Back in Excel, select a few cells — here the headcount column, Budget!C3:C7.

Do not tell Claude which cells you picked. The point of the next step is that it can find out for itself.

Cells selected by hand in the demo workbook

  1. Ask "What cells do I have selected in Excel right now?".

get_active_selection comes back with the address you just dragged over and the values inside it. This is the clearest proof the link is live in both directions: nothing about that selection was ever typed into the chat, so the only way Claude can know it is by reading the workbook you are sitting in front of, at the moment you asked.

Claude naming the selection that was made in Excel

  1. Finish with a plain read: "Read Budget!A2:E7 and show me the rows."

read_range returns the values, the formulas behind them, and — if any of those cells were marked private — a masked list of the addresses whose values were replaced by [redacted], plus one sentence saying so. The contents of a private cell never leave the machine; only the fact that something was hidden does. Every one of these calls is appended to %LOCALAPPDATA%\ExcelAIBridge\audit\<workbook-key>.jsonl with the caller's identity, so you can go back later and see exactly what was read.

Claude reading a range of the workbook back

When it does not work

and nothing has answered it. Either no bridge is running, or the one that is running is bound to a different file. Press Status on the AI Bridge tab for the state in words, and read the bridge's own console output.

workbook. This is the wrong-workbook case the whole project exists to prevent, which is why it is the loud one. Press the button, or ask Claude to call bind_workbook with this file's full path.

"offline" nearly always means the tunnel rather than the bridge. Fetch https://<your-host>/mcp from outside your own network: if that fails, the tunnel is down and restarting the bridge will not help. Setting EXCEL_BRIDGE_TUNNEL_CMD to the command that publishes the bridge makes the bridge supervise and restart it for you. On Route C there is no tunnel to blame: read the bridge's own console for AI Bridge: linked to https://bridge.ram.sh. If it says `broker link down`, the bridge is already retrying by itself and will link again on its own. If it never links at all, the invite or the id in %LOCALAPPDATA%\ExcelAIBridge\broker.json may have been revoked — delete that file and restart with EXCEL_BRIDGE_INVITE set to a fresh code, which registers this bridge again.

After the bridge gains or loses a tool, disconnect and reconnect the connector in Settings so that it fetches the list again.

the allowlist. Signing in with Google proves you are somebody; the allowlist is what makes this your bridge rather than everyone's. Add the address to EXCEL_BRIDGE_ALLOWED and restart.

fresh bridge holds nothing and refuses to guess. Every tool refuses until something binds a workbook: bind_workbook with a full path, the ribbon's connect button, or --workbook at launch.

Next: Work back and forth — reading, writing, formatting, undo, and watching the privacy guard refuse.