Office Live MCP
One MCP server that lets an AI assistant read and edit live, open PowerPoint, Word and Excel documents on macOS/Windows through Office.js — 86 typed tools across three apps plus raw execute_*js escape hatches.
PowerPoint (27 tools): list/inspect decks, slides, layouts and shapes; scan shapes; screenshot slides and preview decks; read deck text and search; add/duplicate/copy slides; edit shape paragraphs, formatting, speaker notes, charts and images; raw OOXML slide XML/zip read-write; add connectors; transform slide bands; run layout QA checks;
execute_officejs.Word (26 tools): list/inspect documents; read, insert, set, delete and format paragraphs; search and replace; tables (insert, read, set cells, add/delete columns); page breaks; comments; read tracked changes; read selection; save; list/fill content controls; get/set document properties;
execute_wordjs.Excel (32 tools): list/inspect workbooks; read/write ranges (values, formulas, number formats); format ranges, dimensions, merges, autofit; add/update/delete worksheets; sort, find, replace, clear and copy ranges; tables, charts, conditional formatting, named ranges, data validation; recalculate, refresh PivotTables; threaded comments (read/reply/resolve); sheet protection; hyperlinks; freeze panes;
execute_exceljs.Architecture: one shared auto-started bridge daemon (stdio or HTTP MCP) that any MCP client can connect to; multiple harnesses share the same live documents.
Multi-document support: tools accept
presentationId/documentId/workbookIdto target one of several open files.Reverse bridge (optional): an OpenCode Chat taskpane tab that chats with a local agent and applies replies into the live document.
Safety/QA:
verify_slides, screenshot-based visual checks, and per-host escape hatches for anything the typed tools don't cover.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Office Live MCP Add a total row to my open Excel sheet and make it bold."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Office Live MCP
One MCP server that drives live, open Word, Excel and PowerPoint documents on macOS and Windows through Office.js.
This started as a fork of kzarzycki/powerpoint-mcp and grew into something bigger. The original idea is brilliant: instead of parsing files on disk, an Office.js add-in inside the running Office app talks to a local bridge server over WebSocket. Your AI assistant edits the document you have open right now, and you watch it happen.
I asked the original author whether he planned to extend this to Word and Excel (issue #173). While waiting for an answer I built it myself, on this branch. Same architecture, two more apps.
What it does
One bridge server, one add-in taskpane, three Office apps. The add-in detects which host it runs in (PowerPoint, Word or Excel) and every tool call executes inside the live document.
PowerPoint: 27 tools from the upstream project. Inspect decks, edit shapes and text, raw OOXML access, charts, screenshots, speaker notes, and an
execute_officejsescape hatch.Excel: 32 new tools. Read and write ranges with values, formulas and number formats, inspect workbooks, format cells, manage worksheets, sort and find, tables, charts, conditional formatting, named ranges, data validation, comments, pivot refresh, sheet protection, plus
execute_exceljs.Word: 26 new tools. Read and edit paragraphs, styles and formatting, search and replace, tables, comments, page breaks, tracked changes (read), selection, save, plus
execute_wordjs.
That is 86 tools on one server. Anything the typed tools do not cover, the execute escape hatch handles with raw Office.js in the right host.
There is also a reverse direction for opencode users (optional): an OpenCode Chat tab inside the taskpane that chats with your local OpenCode agent and applies its replies straight into the live document (see OpenCode Chat below).
Related MCP server: MCP Office
Why live matters
File-based tools (openpyxl, python-docx, python-pptx) read and write bytes on disk. They cannot refresh a PivotTable, they silently drop charts and macros, and you only see the result after reopening the file. This server works inside the running app instead: formulas are calculated by Excel itself, edits appear on screen while the agent works, and nothing that Excel owns gets lost.
There is a second advantage that matters just as much. Everything here runs locally on your machine, next to your agent, not inside some hosted sandbox. Cloud Office agents lock you into their environment: your files go up, the tools they offer are the tools you get, and combining them with anything else is a fight against the platform. Here the Office tools are just one part of what the agent can reach. In the same session it can read your mail, query a database, drive a browser, call any other MCP server or plain script, and then put the results straight into the live document. The Office control is a capability, not a cage. That combination is where most of the real value showed up while building and testing this.
Quick start
macOS / Linux:
npm install -g office-live-mcp
# install the add-in into the Office apps + print your server path
office-live-mcp setupWindows — one line in PowerShell (finds/installs Node, installs the package, runs setup):
irm https://raw.githubusercontent.com/benjaminfrombe/office-live-mcp/main/install.ps1 | iexsetup is idempotent — run it again any time. On macOS it sideloads the manifest into each installed Office app (needs Full Disk Access for your terminal; it tells you if macOS blocks it). Then open a document, click the add-in button in the Home ribbon, and add the server to your MCP client as shown under Connecting an MCP client. No bridge to start manually.
git clone https://github.com/benjaminfrombe/office-live-mcp.git
cd office-live-mcp
npm install
npm run build
node dist/index.cjs setupConnecting an MCP client
The default mode is stdio: the client (Claude Code, OpenCode, Claude Desktop, …) spawns the server, and the server makes sure a shared bridge daemon is running.
{
"mcpServers": {
"office-live-mcp": { "command": "npx", "args": ["office-live-mcp"] }
}
}(or point node at the installed dist/index.cjs — npm root -g shows where that is)
What happens on connect:
If no daemon is up, one is started detached (
--http --bridge: taskpane on :8790, MCP on :8792) and it stays up after the client session ends — the Office add-in needs it even when no AI session is open.If a daemon is already up (another harness, an earlier session, the machine just rebooted), it is reused. Multiple harnesses share one daemon and see the same live documents.
If the daemon crashed or died with a reboot, the next client connect brings it back.
Useful extras:
office-live-mcp --stop-daemon— stop the shared daemon (however it was started).~/.office-live-mcp/daemon.log— daemon log;~/.office-live-mcp/daemon.env— optionalKEY=VALUElines merged into the daemon environment (e.g.BRIDGE_TLS=1).Prefer an HTTP MCP client? Start the daemon once (
office-live-mcp --http --bridge) and connect tohttp://127.0.0.1:8792/mcp.Legacy in-process mode (
--stdio --bridge, everything in one process) still exists; if the bridge port is already owned by another office-live-mcp process (e.g. Claude Desktop's extension host), it relays MCP to that bridge instead of failing.
Connect your harness
office-live-mcp setup prints your exact server path and node executable. Use them in one of these:
OpenCode — ~/.config/opencode/opencode.jsonc (Windows: %USERPROFILE%\.config\opencode\opencode.jsonc), "mcp" section:
"office-live-mcp": {
"type": "local",
"command": ["<node>", "<server path>"],
"enabled": true
}Claude Code — one command:
claude mcp add office-live-mcp --scope user -- <node> "<server path>"Claude Desktop — ~/Library/Application Support/Claude/claude_desktop_config.json (Windows: %APPDATA%\Claude\claude_desktop_config.json), "mcpServers" section:
"office-live-mcp": {
"command": "<node>",
"args": ["<server path>"]
}ChatGPT Desktop & Codex — the ChatGPT desktop app shares its MCP configuration with Codex: ~/.codex/config.toml (Windows: %USERPROFILE%\.codex\config.toml):
[mcp_servers.office-live-mcp]
command = "<node>"
args = ["<server path>"](ChatGPT on the web only reaches remote HTTPS servers, so it needs a tunnel for a local bridge like this one.)
OpenCode Chat in the taskpane (reverse bridge)
Besides acting as an MCP client of this server, OpenCode can also be driven from inside Office: the taskpane has an OpenCode Chat tab that connects to your running OpenCode service, renders the conversation, and applies replies to the live document. The MCP bridge keeps running in the background — the two directions work side by side.
Quick setup:
npm run opencode-proxyThis local proxy (http://127.0.0.1:4096) reads the OpenCode service URL + password from ~/.local/state/opencode/service.json, injects the auth header, and follows service restarts automatically. Then open the OpenCode Chat tab in the taskpane and point it at https://127.0.0.1:4096 (Office's WKWebView blocks plain-http fetches from an HTTPS taskpane — a "Load failed" status usually means exactly this).
What it gives you:
Chat with live context — the first prompt of a session carries an invisible preamble (open document, live-MCP instructions) and every prompt carries the active slide + selected shapes, so "this slide" just works.
+ Selection — paste the current document selection into the input as context.
Image paste — paste screenshots into the input as inline attachments.
Reasoning strip — live streaming of the model's reasoning while it works; click it mid-stream to expand the full text, click again to collapse.
Question forms — when the agent calls the
questiontool, the pending form surfaces as an answerable card in the pane (works across sessions: a question asked in another OpenCode window shows up here too; answering or dismissing settles it everywhere).Model picker — switch the session's model from the action row under the input; the choice is remembered per session.
Full details (SSE handling, session model, testing): docs/opencode-mode.md.
Optional: the ribbon icon (HTTPS)
Everything works over plain HTTP except one cosmetic detail: Office refuses to load the ribbon icon over HTTP, so the button shows a generic placeholder. The add-in, taskpane and bridge connection are unaffected.
On macOS, setup now handles this for you when mkcert is installed: it generates the localhost certificate, trusts it, flips BRIDGE_TLS=1 in the daemon env, and installs the HTTPS manifests — the daemon then serves https://localhost:8791. So:
brew install mkcert && mkcert -install # one-time CA trust (asks your password)
office-live-mcp setup # re-run: switches everything to HTTPSIf mkcert is not installed, setup prints these commands as a hint and keeps running over HTTP. To undo, remove the BRIDGE_TLS=1 line from ~/.office-live-mcp/daemon.env and rerun setup.
On Windows, setup asks whether you want the real ribbon icon. Answering yes generates a localhost + hostname TLS certificate, trusts it via certutil (Windows shows a one-time confirmation dialog — choose Yes), flips BRIDGE_TLS=1 in the daemon env, and installs the HTTPS manifests. Plain HTTP never shows the real icon on Windows — verified across every combination of headers, hosts and cache states on Office 16.0.20527 — so the question is the only supported path to the icon. To undo, remove the BRIDGE_TLS=1 line from %USERPROFILE%\.office-live-mcp\daemon.env and rerun setup.
Windows installation
Open PowerShell (Start → type "powershell" → Enter) and paste this one line — it finds or installs Node.js, installs the package, and runs setup:
irm https://raw.githubusercontent.com/benjaminfrombe/office-live-mcp/main/install.ps1 | iexAlready installed the package yourself? Then all you need is:
office-live-mcp setupVerified on Windows 11 (ARM64, Office Insider 16.0.20527). Recent Windows Office builds reject the old sideload shortcuts (Developer-registry manifests only load under a debugger, the new "Apps" storefront never queries custom catalogs, and neither the classic nor the new dialog offers an "Upload My Add-in" option), so the supported route is a shared folder catalog — setup automates all of it.
What it does:
Copies
dist/andaddin/to%LOCALAPPDATA%\office-live-mcp, keeping only the manifest variants that match the daemon transport (HTTPS or plain) so the catalog lists exactly one add-in per Office app.Registers a trusted add-in catalog in the registry (HKCU, no elevation needed) pointing at that folder through a UNC path. Office only trusts network paths for custom add-ins — that is a Microsoft requirement. In practice no share has to be created: setup uses, in order, an
OLM_CATALOG_UNCoverride → a dedicatedOfficeLiveMCPshare (created automatically in an elevated terminal) → the built-in admin share (\\localhost\C$), which exists by default on admin machines.Asks whether you want the real ribbon icon: HTTPS bridge + trusted certificate (one-time Windows trust dialog). Plain HTTP always renders the generic placeholder icon on Windows, so this is the only way to get the real one.
Offers to register the MCP server in your OpenCode config (
~/.config/opencode/opencode.json(c)) when one is detected — plain-JSON files are merged, JSONC files with comments are left untouched with a manual hint.Prints your server path and node executable, plus the link with copy-paste MCP client examples for every harness.
Then the one step no installer can do, because Office requires it:
Close and reopen the Office app → Home → Add-ins → Advanced... → SHARED FOLDER tab → select Office Live MCP → Add.
Why not an HTTPS catalog (no UNC at all)? The bridge can emulate a SharePoint app catalog over
https://localhost:8791(OLM_HTTPS_CATALOG=1, seeserver/sharepoint-catalog.ts), and Office would then list the add-in under MY ORGANIZATION. This worked on Office builds up to 16.0.20430, but Microsoft fully retired SharePoint add-in catalogs on April 2, 2026 — current builds still probe the catalog yet discard the results, so the route is dead on modern Office. The UNC route above is the only supported one.
Notes:
The daemon's environment file lives at
%USERPROFILE%\.office-live-mcp\daemon.env, its log at%USERPROFILE%\.office-live-mcp\daemon.log.Use
manifest.xmlfor PowerPoint,manifest.word.xmlfor Word,manifest.excel.xmlfor Excel. All point the taskpane athttp://localhost:8790.As on macOS, the ribbon icon stays a placeholder unless the bridge runs over HTTPS and the manifests point at
https://localhost:8791— on Windows, setup's icon question arranges all of that for you (see "Optional: the ribbon icon" above). Verified: over plain HTTP the icon never renders on Windows, whatever the response headers say.If a build refuses plain-HTTP catalogs, the bridge can also emulate a SharePoint-style HTTPS catalog (
server/sharepoint-catalog.ts, enabled withBRIDGE_TLS=1): Office enumerateshttps://<host>:8791as a corporate catalog and the same manifests are served from there.
How it is tested
Two layers, because they catch different bugs.
The mock suite (428 tests) verifies tool registration, argument handling and the generated Office.js code, plus the stdio→daemon proxy (auto-start, discovery, session handling, SSE parsing, stop). It is fast and runs on every change.
The live suite runs every tool against a real open document. This is where the mock tests turned out to be insufficient: live testing caught three real API bugs the mocks could never find. Range.findAllOrNullObject does not exist on this host, DataValidationRule takes a type-keyed object rather than a { type, ... } envelope, and calculation lives on workbook.application, not workbook. All fixed and now covered by both layers.
Credits
This project stands on the work of others.
kzarzycki/powerpoint-mcp (MIT): the bridge architecture, the PowerPoint tool modules and the add-in are his. This fork exists because of it.
mindstone/mcp-servers (FSL-1.1-MIT): studied as a reference for Word and Excel add-in design. No code from it is included, its license does not allow that, so the Word and Excel tools here are an independent implementation.
The live Word MCP projects (kennypeh85/word-mcp, HelloWorld-Open/word-mcp-server, Han-ops-dev/word-mcp-server, all MIT) and sbroenne/mcp-server-excel (MIT) shaped which tools were worth building. Design references only, no code.
The icon uses the Tabler Icons bridge glyph as a starting point for the ring mark (MIT).
Full attribution in NOTICE.
Status
Working on macOS with desktop Word, Excel and PowerPoint, and verified on Windows 11 ARM64 with PowerPoint: stdio auto-daemon, OpenCode and Claude Desktop as MCP clients, and live edits through the add-in. PowerPoint Web works for the upstream tool set. The Word and Excel tool surfaces are young: they cover what I actually needed, and the escape hatch covers the rest. Expect rough edges and please open issues.
License
MIT, like the upstream project. See LICENSE.
Available Tools
88 toolsadd_chartB
Create a chart from a range. Chart types: ColumnClustered, ColumnStacked, BarClustered, BarStacked, Line, LineMarkers, Pie, Doughnut, Area, XYScatterLines. Returns the chart name and title.
Inputs: range (required), title, chartType, sheetName, +1 more.
add_commentC
Add a threaded comment to a cell.
Inputs: text (required), cellAddress (required), workbookId.
add_conditional_formatB
Add a conditional formatting rule to a range. Supports cellValue (compare with a formula and fill on match), colorScale (min/max gradient), dataBar, and iconSet rules.
Inputs: range (required), ruleType (required), formula1, formula2, +7 more.
add_connectorA
Draw a line or curved connector between two shapes or points, with all OOXML bounding-box math (off/ext/flips, bezier path) computed for you. For bezier curves the path leaves and arrives horizontally — no flip attributes are used, avoiding the custGeom double-mirror pitfall. The shape is appended on top of the slide.
Inputs: to (required), from (required), slide (required), color, +6 more.
add_nameC
Define a named range (named formula) in the workbook, e.g. name "TaxRate" for "=Sheet1!$B$1".
Inputs: ref (required), name (required), comment, workbookId.
add_slideA
Add a new slide from a layout at a specific position, with placeholder text pre-filled and shapes renamed to layout names. Use inspect_layouts to find available layout names and placeholder names. Returns the new slide number (1-based) and its placeholder shapes with semantic names.
Inputs: layoutName (required), position, placeholders, presentationId.
add_tableB
Create an Excel table (ListObject) over a range. Returns the table name and range.
Inputs: range (required), name, style, sheetName, +2 more.
add_worksheetA
Add a new worksheet to the workbook, optionally at a specific position, and activate it. Returns the new sheet name and position.
Inputs: name, position, workbookId.
autofit_rangeB
Autofit column widths and/or row heights of a range to their content.
Inputs: range (required), rows, columns, sheetName, +1 more.
calculate_workbookA
Force Excel to recalculate the workbook. Use after writes when you need formula results to be current before reading them back.
Inputs: type, workbookId.
clear_rangeA
Clear the contents and formatting of a range in the live workbook.
Inputs: range (required), sheetName, workbookId.
comment_on_paragraphC
Add a comment to a paragraph (anchored on its text).
Inputs: text (required), index (required), documentId.
copy_rangeB
Copy a source range to a target range in the live workbook. Copies values, formulas and formatting by default; valuesOnly copies just the results.
Inputs: source (required), target (required), sheetName, valuesOnly, +1 more.
copy_slidesA
Copies slides between two open presentations entirely server-side — the Base64 data never enters Claude context. Exports from the source presentation and inserts into the destination in a single operation. Both presentations must be connected to the bridge. Requires PowerPointApi 1.8.
Inputs: sourceSlide (required), sourcePresentationId (required), destinationPresentationId (required), formatting, +1 more.
delete_paragraphB
Delete one paragraph (text and paragraph mark) from the document.
Inputs: index (required), documentId.
delete_worksheetA
Delete a worksheet from the workbook. This removes its contents permanently and can break formulas referencing it.
Inputs: sheetName (required), workbookId.
duplicate_slideA
Duplicate a slide within the same presentation. Exports the slide and reimports it at the specified position. Data stays server-side. The reimport makes PowerPoint view jump to the first slide.
Inputs: slide (required), presentationId, insertAfterSlide.
edit_shape_paragraphsA
Replace paragraph content of a shape with raw OOXML <a:p> XML. Preserves <a:bodyPr> and <a:lstStyle>. Use read_shape_paragraphs first to get the current XML, modify it (using /pptx skill knowledge), then write it back. The slide is exported, modified server-side, and reimported — data never enters Claude's context. NOTE: the reimport deletes and reinserts the slide, but the view is restored to the edited slide afterwards. For text-only changes, execute_officejs still avoids the reimport entirely (in place via shape.textFrame.textRange).
Inputs: xml (required), slide (required), shapeId (required), presentationId.
edit_slide_chartB
Create a chart on a slide from structured data. Generates all OOXML automatically (chart XML, rels, graphic frame, Content_Types). Supports column, bar, line, pie, doughnut, and area charts with multiple series.
Inputs: slide (required), title (required), series (required), chartType (required), +4 more.
edit_slide_xmlA
Edit slide XML and reimport. Two modes: (1) xml mode — provide finished XML string (use read_slide_xml first to get current XML), (2) code mode — provide JS code that manipulates the pre-parsed DOM (receives: doc, findShapeById, NS_P, NS_A, escapeXml, serializeXml, DOMParser). Code mode preserves untouched attributes. The slide is exported, modified server-side, and reimported — data never enters Claude's context. NOTE: the reimport deletes and reinserts the slide, but the view is restored to the edited slide afterwards — reserve this for structural changes (new shapes, layout rebuilds). BULK EDITS: apply ALL edits across slides first, then verify with a single screenshot — do NOT alternate screenshot and edit_slide_xml calls; rapid reimport cycles crash PowerPoint for Mac (reimports are throttled server-side, so interleaving only wastes time).
Inputs: slide (required), xml, code, shapeId, +2 more.
edit_slide_zipA
Update multiple files in the slide zip and reimport in a single operation. Accepts a map of { path: content } — can modify existing files or add new ones (e.g. chart XML + rels). Auto-registers Content_Types for new chart files. Use read_slide_zip first to get the current content.
Inputs: files (required), slide (required), presentationId.
edit_speaker_notesA
Set speaker notes on one or more slides. Accepts markdown text (paragraphs, bold, italic). Converts to OOXML server-side and injects via single-slide reimport. Replaces all existing notes on the specified slides.
Inputs: notes (required), presentationId.
edit_table_columnsA
Add or delete columns of a table. Add: position "Before" inserts left of the first column, "After" right of the last column; optionally pre-fill with values (2D array, one column per entry). Delete: remove count columns starting at columnIndex (0-based). Note: some Word builds reject column operations with InvalidArgument.
Inputs: action (required), tableIndex (required), count, values, +3 more.
execute_exceljsB
Execute arbitrary Office.js code inside the live Excel workbook. The code runs inside Excel.run(async (context) => { ... }) with 'context' available as a variable. Use 'await context.sync()' after loading properties. Return a value to get it back as the tool result. Common operations: read/write ranges (workbook.worksheets), formulas, tables, charts. Cell references use A1 notation; values/formulas are returned as arrays matching the range shape.
Inputs: code (required), workbookId.
execute_officejsA
Execute arbitrary Office.js code inside the live PowerPoint presentation. The code runs inside PowerPoint.run(async (context) => { ... }) with 'context' available as a variable. Use 'await context.sync()' after loading properties. Return a value to get it back as the tool result. For positioning, all values are in points (1 point = 1/72 inch). Common operations: add shapes, set text, change colors, add/delete slides. Edits run in place without reimporting the slide, so PowerPoint's current view position is preserved — prefer this over edit_shape_paragraphs / edit_slide_xml for text-only or formatting-only changes. Host limitations (live-tested on PowerPoint for Mac): (1) slide.shapes.getItemById and getItemByName do NOT exist — load shapes.load("id"), sync, then iterate shapes.items and match String(sh.id). (2) Loading textFrame paths (textFrame/hasText, textFrame/textRange/text) on shapes without text frames (Graphic/image shapes) fails the whole context.sync() with a bare InvalidArgument — load "id" first, then load textFrame paths only on shapes known to be text shapes, or wrap per-shape loads in separate syncs with try/catch.
Inputs: code (required), presentationId.
execute_wordjsB
Execute arbitrary Office.js code inside the live Word document. The code runs inside Word.run(async (context) => { ... }) with 'context' available as a variable. Use 'await context.sync()' after loading properties. Return a value to get it back as the tool result. Common operations: read the body (context.document.body), insert paragraphs, search and replace, work with tables, read tracked changes.
Inputs: code (required), documentId.
find_in_rangeA
Find text in a range or the whole used range. Returns the address of the first match, or all matches as a (possibly multi-area) address string.
Inputs: text (required), all, range, matchCase, +3 more.
format_paragraphA
Format one paragraph: style, alignment, and font (name, size, bold, italic, color, highlight color). Only provided properties are changed.
Inputs: index (required), bold, color, style, +6 more.
format_rangeA
Format a range: font (name, size, bold, italic, underline, color), fill color, borders (all/outline with style, weight, color), alignment, wrap, and number format. Only the provided properties are changed.
Inputs: range (required), bold, italic, borders, +13 more.
format_shapesA
Apply formatting to multiple shapes on a slide in one call. Generates Office.js code internally. Use for fill color, font bold/italic/size/color/name. Cannot set corner radius or borders (use edit_slide_xml code mode for those). Runs in place (no slide reimport), so PowerPoint view position is preserved.
Inputs: slide (required), shapes (required), presentationId.
freeze_panesA
Freeze rows and columns of a worksheet at a cell (everything above and left of the cell stays visible), or unfreeze. E.g. freezeAt "A2" freezes the first row, "B2" freezes row 1 and column A.
Inputs: freezeAt (required), sheetName (required), workbookId.
get_document_propertiesB
Read the document metadata: title, author, subject, keywords, comments, category, creation and last-save dates.
Inputs: documentId.
get_local_copyA
Returns a local file path for the presentation. For local files, returns the existing path. For SharePoint/cloud files, exports server-side and saves to a temp .pptx. Caches by revision number — re-exports only when the presentation has been saved since last export.
Inputs: presentationId.
get_paragraphB
Read one paragraph in full: text, style, alignment and font properties (name, size, bold, italic, color).
Inputs: index (required), documentId.
get_selectionB
Read the current user selection (cursor) in the document.
Inputs: documentId.
get_tracked_changesA
List tracked changes (revisions) in the document: type (insertion/deletion), author, date and a text snippet. Read-only; Office.js cannot create tracked changes.
Inputs: documentId.
insert_imageA
Inserts an image onto a slide using Office.js setSelectedDataAsync with CoercionType.Image. Accepts a file path, URL, or raw base64 data. Optionally target a specific slide (the view stays there so the user sees the insert; call show_slide first per the view etiquette) and control position/size in points.
Inputs: source (required), sourceType (required), top, left, +5 more.
insert_or_delete_rangeA
Insert or delete a range, shifting existing cells. For insert, shift is Down or Right; for delete, Up or Left.
Inputs: range (required), action (required), shift, sheetName, +1 more.
insert_page_breakB
Insert a page break at the end of the document body.
Inputs: documentId.
insert_paragraphA
Insert a new paragraph into the document, optionally with a style (e.g. "Heading 1", "Title", "Quote"). Insert at the start or end of the body, or before/after a given paragraph index. Returns the new paragraph count.
Inputs: text (required), index, style, location, +1 more.
insert_tableA
Insert a table at the end of the document, optionally pre-filled from a 2D array of strings. Returns row and column counts.
Inputs: rows (required), columns (required), values, documentId.
inspect_deckA
Deck overview: slide dimensions, theme (colors + fonts), and all slides with slide number (1-based), ID, and shape count. Use as the first call to understand deck structure. Theme is cached after the first call. For shape details, follow up with scan_slide or inspect_slide on specific slides. For available layouts, use inspect_layouts.
Inputs: presentationId.
inspect_documentA
Overview of the live document: paragraph count, section count, table count, inline picture count, and a preview of the first paragraphs with their styles. Use this first to orient yourself in an unfamiliar document.
Inputs: documentId, previewParagraphs.
inspect_layoutsA
Returns slide layouts with names, OOXML type (e.g. blank, twoObj, secHead), master/layout indices, and detailed placeholders. Use fields to control which data is returned. By default reads all layouts from every slide master in OOXML (complete list, requires file access — may take a moment on first call for cloud files). Layouts sharing a name across different masters are distinguished by masterIndex. Set usedOnly to return only layouts assigned to existing slides (fast, Office.js only, no file access).
Inputs: fields, usedOnly, presentationId.
inspect_slideA
Detailed slide inspector (~80 tokens/shape): returns every shape with text content, positions, sizes, and fill colors, plus slide dimensions. Supports slideRange for multiple slides. For just positions without text/fills, use scan_slide instead.
Inputs: slideRange (required), presentationId.
inspect_workbookA
Overview of the live workbook: all worksheets (name, position, visibility, used-range address), all Excel tables (name, sheet, range), all named ranges, and all PivotTables (name, sheet). Use this first to orient yourself in an unfamiliar workbook.
Inputs: workbookId.
list_content_controlsA
List all content controls (template fields) in the document: id, title, tag, type, current text and placeholder. Use set_content_control_text with the id to fill them.
Inputs: tag, title, documentId.
list_documentsA
Lists all Word documents currently connected to the bridge server. Shows document IDs (file paths for saved files, generated IDs for unsaved) and connection status. Use this to find the documentId to pass to other Word tools when multiple documents are open.
Inputs: no named parameters.
list_presentationsA
Lists all PowerPoint presentations currently connected to the bridge server. Shows presentation IDs (file paths for saved files, generated IDs for unsaved) and connection status. Use this to find the presentationId to pass to other tools when multiple presentations are open.
Inputs: no named parameters.
list_workbooksA
Lists all Excel workbooks currently connected to the bridge server. Shows workbook IDs (file paths for saved files, generated IDs for unsaved) and connection status. Use this to find the workbookId to pass to other Excel tools when multiple workbooks are open.
Inputs: no named parameters.
preview_deckA
Deck preview: batch overview of all/selected slides with optional thumbnails + text. With images: ~900 tokens/slide; text-only (includeImages=false): ~35 tokens/slide. Use for visual review or content audit. Do NOT use to inspect one slide — use inspect_slide or screenshot_slide instead.
Inputs: imageWidth, slideRange, includeImages, presentationId.
read_commentsA
Read all comments in the document body: id, author, text, resolved state, date, and replies. Note: adding replies is not supported by the current Word.js API set.
Inputs: documentId.
read_deck_textA
Lightweight text extractor: returns slide titles and body text as plain strings (~20x smaller than inspect_slide). Use for content review, narrative analysis, or any read-only text task. Supports slideRange and optional speaker notes.
Inputs: slideRange, includeNotes, presentationId.
read_paragraphsA
Read paragraphs of the document with their styles, paginated by offset and limit. Returns total count plus the requested slice.
Inputs: limit, offset, documentId.
read_rangeA
Read values, formulas and number formats from a range of the live workbook. Returns a 2D array (rows x columns) plus the range address and dimensions. Use "usedRange": true to read the whole used range of the sheet.
Inputs: range, sheetName, usedRange, workbookId, +2 more.
read_shape_paragraphsA
Read raw OOXML <a:p> paragraphs from a shape's text body. Returns the paragraph XML as a string — preserves all formatting (bold, colors, bullets, etc.) that textRange.text strips. Use with the /pptx skill's OOXML knowledge to understand and modify the XML.
Inputs: slide (required), shapeId (required), presentationId.
read_slide_xmlB
Read the full raw OOXML of a slide, or filter to a specific shape. Returns the slide's ppt/slides/slide1.xml content. Use with the /pptx skill's OOXML knowledge to understand the XML structure.
Inputs: slide (required), shapeId, presentationId.
read_slide_zipA
Read multiple files from the exported slide zip. Returns slide XML, relationships, chart XMLs, and Content_Types. Use this to inspect chart data, rels, or other zip contents beyond what read_slide_xml provides. When no paths specified, auto-discovers all text/XML files in the zip.
Inputs: slide (required), paths, presentationId.
read_speaker_notesA
Read speaker notes from slides. Uses full-deck export (cached by revision) to parse notes from OOXML — Office.js has no notes API. Returns plain text per slide.
Inputs: slideRange, presentationId.
read_tableB
Read all cell texts of a table as a 2D array.
Inputs: tableIndex (required), documentId.
read_threaded_commentsA
Read all threaded comments in the workbook: content, author, creation date, resolved state, and replies. Use reply_to_comment or resolve_comment with a comment id from this output.
Inputs: workbookId.
refresh_pivottablesA
Refresh all PivotTables in the workbook. Use after data changes when pivot summaries must be current.
Inputs: workbookId.
replace_in_sheetA
Find and replace text across a whole worksheet (substring match per cell by default). Returns the number of cells changed. Uses findAll so merged/hidden cells behave like the Excel UI.
Inputs: find (required), replace (required), matchCase, sheetName, +2 more.
replace_textB
Find and replace text throughout the document. Returns the number of replacements made.
Inputs: find (required), replace (required), matchCase, documentId.
reply_to_commentB
Add a reply to an existing threaded comment. Use the comment id from read_comments.
Inputs: text (required), commentId (required), workbookId.
resolve_commentA
Resolve or reopen a threaded comment. Use the comment id from read_comments.
Inputs: resolved (required), commentId (required), workbookId.
save_documentB
Save the document. If it has never been saved, Word applies its default save behavior (may prompt).
Inputs: documentId.
scan_slideA
Lightweight shape scanner (~40 tokens/shape): lists shape IDs, types, and positions on slides, plus slide dimensions. Supports slideRange for multiple slides. For text content and fills, use inspect_slide instead.
Inputs: slideRange (required), shapeType, namePattern, presentationId.
screenshot_slideA
Slide screenshot (~1000 tokens): captures one slide as PNG image. Use to visually verify layout after changes. Do NOT loop over all slides — use preview_deck instead. WARNING: renders with whatever font the host webview substitutes when the deck font is not system-installed (e.g. Century Gothic) — substituted fonts have different metrics, so text width, overflow and centering judgments from these screenshots are UNRELIABLE. For font-faithful QA export via PowerPoint itself (AppleScript: save pres in POSIX file "/tmp/x.pdf" as save as PDF, then pdftoppm) and measure geometry with Python (PIL pixel measurement) rather than judging by eye.
Inputs: slide (required), width, height, presentationId.
search_documentB
Search the document body for text. Returns up to 50 matches with a text snippet around each hit.
Inputs: text (required), matchCase, documentId.
search_fluent_iconsA
Search Microsoft Fluent UI icon library. Returns matching icons with svgBase64 ready for insert_image (sourceType: "base64") — the SVG content is fetched server-side so dead icon URLs can never break the workflow. Prefer mono (_M) variants for professional decks. Retry with synonyms if no good matches (e.g. "innovation" → "lightbulb", "security" → "shield").
Inputs: query (required), top, style, includeSvg.
search_textA
Search for text across all slides (or a slide range) in the presentation — like grep for slides. Searches shape text, table cells, and speaker notes. Returns matching shapes with context at the chosen level. Case-insensitive substring by default; supports regex.
Inputs: query (required), regex, context, slideRange, +3 more.
set_content_control_textA
Replace the text of a content control (template field) identified by its id from list_content_controls. Optionally update its title and tag.
Inputs: id (required), text (required), tag, title, +1 more.
set_data_validationC
Set a data validation rule on a range. Supports list, wholeNumber, decimal, textLength, and date rules.
Inputs: type (required), range (required), list, formula1, +5 more.
set_dimensionsB
Set column widths and/or row heights for a range, in points. Optionally autofit columns or rows to their content.
Inputs: range (required), rowHeight, sheetName, workbookId, +3 more.
set_document_propertiesA
Set document metadata (title, author, subject, keywords, comments, category). Only provided fields are changed.
Inputs: title, author, subject, category, +3 more.
set_hyperlinkA
Set a hyperlink on a cell (address, display text, tooltip). The cell text is replaced by textToDisplay when provided. Pass address as null to remove the hyperlink.
Inputs: address (required), cellAddress (required), tooltip, workbookId, +1 more.
set_mergeC
Merge or unmerge cells in a range.
Inputs: range (required), action (required), across, sheetName, +1 more.
set_paragraph_textA
Replace the text of one paragraph, keeping the paragraph itself (and optionally its style).
Inputs: text (required), index (required), documentId.
set_table_cellB
Write text into one table cell (replacing its content).
Inputs: row (required), text (required), column (required), tableIndex (required), +1 more.
set_table_cellsA
Set the text of multiple table cells in one call. Rows and columns are 0-based indices into the table.
Inputs: cells (required), tableIndex (required), documentId.
set_worksheet_protectionB
Protect or unprotect a worksheet. Protection restricts user edits; cells formatted as locked are affected.
Inputs: protect (required), sheetName (required), password, workbookId.
show_slideA
Bring a slide into view in the live presentation (navigates the user to that slide). Call this BEFORE editing a slide so the user can watch the changes happen; also useful to walk the user through a deck slide by slide.
Inputs: slide (required), presentationId.
sort_rangeB
Sort a range by one or more columns. Fields are given as zero-based column offsets within the range.
Inputs: range (required), fields (required), sheetName, hasHeaders, +1 more.
transform_slideA
Vertically rescale a band of shapes (e.g. shrink the content of a slide by 30%) in ONE atomic operation. Shapes whose top falls inside [topPt, bottomPt] are remapped to start at newTopPt with factor scaleY. Connector-like shapes (cxnSp, line/connector geometries, single-stroke bezier custGeom) get their height rescaled too so endpoints stay attached; all other shapes keep their height unless listed in scaleHeightShapeIds. Text, images and footers outside the band are untouched.
Inputs: slide (required), topPt (required), scaleY (required), bottomPt (required), +3 more.
update_worksheetA
Update an existing worksheet: rename it, move it to a position, change visibility, set the tab color, or activate it. Only provided properties are changed.
Inputs: sheetName (required), newName, activate, position, +3 more.
verify_slidesA
Run programmatic checks on a slide: detect overlapping shapes, out-of-bounds shapes, empty text, tiny shapes, unused placeholders, placeholder drift from layout defaults, and full-bleed background covers. Returns a list of issues found. Uses the same shape data as inspect_slide — no OOXML needed.
Inputs: slide (required), checks, presentationId.
write_rangeA
Write values and/or formulas into a range of the live workbook. Accepts a 2D array (rows x columns) or a single scalar that fills the whole range. Formulas are set separately from values. Also supports setting the number format. Content in the target range is overwritten.
Inputs: range (required), values, formulas, sheetName, +2 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 88 tools
Across Word, PowerPoint, and Excel the tool purposes are mostly separable, but the PowerPoint inspection cluster (inspect_slide, scan_slide, preview_deck, read_deck_text, inspect_deck) and the XML/edit escape-hatch cluster (edit_slide_xml, edit_slide_zip, edit_shape_paragraphs, execute_officejs) have overlapping use cases. Descriptions help, but misselection is still plausible with 88 tools.
Names are overwhelmingly snake_case with a verb_noun pattern, and domain-specific terms are used consistently within Word, PowerPoint, and Excel. There are minor deviations such as screenshot_slide, freeze_panes, and get_local_copy, but the convention remains readable.
88 tools is an extreme tool count for an MCP surface, even for a multi-application Office server. Many fine-grained operations could be consolidated or handled by the generic execute_* escape hatches, so the set is far beyond a well-scoped count.
Coverage is strong across all three Office domains: Word paragraphs, tables, comments, properties, and content controls; PowerPoint slides, shapes, notes, charts, images, and XML; Excel ranges, sheets, tables, charts, formatting, comments, protection, and PivotTables. A few lifecycle gaps, such as slide/table deletion, likely require the generic execute_* fallback.
Maintenance
Related MCP Connectors
An agent-first office suite Claude & ChatGPT read and write over one MCP URL.
Online office suite for AI agents: edit docs, sheets, slides and PDFs in browser or via MCP.
Convert, create and edit Word, PowerPoint, Excel and PDF documents from any AI agent.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceMCP server for driving Office add-ins (Excel, Word, Outlook, PowerPoint, OneNote) through high-level workflow tools and queries, enabling LLM agents to automate document tasks across Microsoft Office applications via a single Go binary.4-
- AlicenseNot gradedqualityBmaintenanceSuite of MCP servers for local-first, governed automation of Microsoft Office files (Excel, PowerPoint, Word) via structured tool calls.90 PyPI8MIT
- AlicenseNot gradedqualityBmaintenanceLets any AI agent read and edit the Excel and Word documents a user already has open, attaching through COM so it sees unsaved edits, recalculated formulas, pivot tables, slicers and charts, and can bridge content between the two apps with journaling, undo, read-only mode and allowed-folder limits.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to read and edit live PowerPoint presentations on Windows through a real, visible desktop PowerPoint window, covering slides, text, shapes, notes, tables, and file operations. Supports MCP over stdio and HTTP, plus HTTP/OpenAPI and CLI access, with readback, screenshots, and a Chinese operation log for verifying results.PolyForm Noncommercial 1.0.0