officeagent-net
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| OfficeAgent__FileSystemConnections__0__RootPath | Yes | ||
| OfficeAgent__FileSystemConnections__0__ConnectionId | Yes |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| list_connectionsA | List the connections you can address documents under. Returns [{connectionId, provider, canCreateDocuments}] where provider is "filesystem" or "sharepoint". Use a connectionId as the connectionId for register_document and the document tools; never ask the user for it. |
| compare_documentsA | Read two Word documents and return paragraph differences, exact input SHA-256 hashes, coverage diagnostics, and a tracked-change plan bound to the original snapshot. Covered: text added, removed or changed in free body paragraphs, and text changed inside a table cell when the table's geometry is unchanged. The same words split differently across equally formatted runs are not a difference, because Word re-segments runs constantly. Refused, with a per-area diagnostic and no plan: changed table geometry, a cell whose formatting changed along with its words, paragraph formatting or style changes, and changes in headers, footers, notes, images, numbering or other parts. Differences found in the areas that are covered are still reported when another area blocks the plan, so a refusal tells you what it saw. Unsupported changes make isComplete false and plan null. This tool writes nothing; preview and apply the returned plan against the original document. |
| preview_document_mergeA | Preview ordered whole-document Word assembly without saving. requestJson contains sources [{connectionId, documentId}] in output order and optional options {title, author}. Returns a merge plan bound to exact input hashes, source counts, identifier remapping decisions, and blocking diagnostics. Source formatting is preserved within the documented compatibility scope; each document starts on a new page. This is assembly, not reconciliation of edited versions. |
| preview_planA | Dry-run a DocumentPlan JSON against (connectionId, documentId). Returns {isValid, committed, receipt, sourceDocumentId, outputConnectionId, outputDocumentId, outputVersion, outputName, outputContentType, changes, errors}; the output fields are null and committed is false. Plan shape: { "snapshot": { "eTag": "" }, "revision": { "author": "Review Bot", "timestampUtc": "2026-09-09T10:00:00Z" }, "operations": [ ... ] }. revision controls Word's displayed revision identity; omit timestampUtc to use one engine timestamp for the whole apply. The snapshot detects drift in Word text-host XML or PowerPoint slide/notes XML; other parts rely on anchors and provider version checks. Omit it only intentionally. Omit contractVersion for legacy 0.2 behavior, or set it to exactly "0.2". Other values fail with contract-mismatch. Unknown properties and enum values fail with invalid-json. Each operation is one object. Concrete examples: // Replace text: { "op": "changeText", "target": { "paraId": "w14:...", "expect": "Acme Corp", "occurrence": 0 }, "with": "Globex Inc.", "mode": "Tracked" } // Unified formatting (paragraph/run/table/row/cell/image): { "op": "format", "target": { "paraId": "w14:...", "expect": "important", "occurrence": 0 }, "highlight": "yellow", "bold": true, "color": "FF0000" } { "op": "format", "target": { "kind": "table", "path": "table#0" }, "styleId": "TableGrid", "borderStyle": "single" } { "op": "format", "target": { "kind": "image", "path": "image#0" }, "widthPx": 320, "heightPx": 200 } // Fill / comment / insert paragraph / setProperty: { "op": "fill", "target": { "tag": "ClientName" }, "value": "Globex" } { "op": "comment", "target": { "paraId": "w14:...", "expect": "..." }, "text": "Confirm this." } { "op": "insert", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "text": "New paragraph." } { "op": "insertParagraphs", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "paragraphs": [{ "text": "First" }, { "text": "Second" }] } { "op": "removeParagraph", "target": { "paraId": "w14:...", "expect": "Complete paragraph text" } } { "op": "setProperty", "target": { "kind": "docProperty", "path": "core/title" }, "value": "My Title" } // Every verb above that changes Word content also takes "mode": "Tracked" (the default - the edit lands as a redline a reviewer accepts or rejects) or "Direct". A deck refuses "Tracked": PresentationML has no revision markup. // Review an existing redline. Revision paths come from inspect_document.nodes (kind "revision"): 'ins#7', 'del#7', 'markIns#7', 'rowIns#7', 'cellDel#7', 'runFormat#7', 'paraFormat#7'. 'all' takes every one; 'author:' takes one person's. An edit that spans a pending revision is refused with revision-overlap; resolve it here first, then re-inspect: { "op": "revision", "target": { "kind": "revision", "path": "all" }, "action": "Accept" } { "op": "revision", "target": { "kind": "revision", "path": "author:Jane Doe" }, "action": "Reject" } // Reply to, resolve, or delete an existing comment (comment paths from inspect_document.nodes, kind "comment"): { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Reply", "text": "Forty-five, per the MSA." } { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Resolve" } { "op": "comment", "target": { "kind": "comment", "path": "comment#1" }, "action": "Remove" } // Define a style once instead of repeating direct formatting on every paragraph. Word only. // Define it first, then apply it with format's styleId - both can sit in the same plan: { "op": "defineStyle", "styleId": "Quote", "name": "Pull Quote", "basedOn": "Normal", "next": "Normal", "fontFamily": "Georgia", "sizeHalfPoints": 24, "italic": true, "color": "444444", "alignment": "center", "indentLeftTwips": 720, "spacingBeforeTwips": 240 } { "op": "format", "target": { "paraId": "w14:...", "expect": "" }, "styleId": "Quote" } // type is paragraph (default), character or table. outlineLevel 1-9 puts a heading in the outline. // Defining a style that exists updates it; properties you leave out keep their values. Styles are // never deleted. A style cannot carry a highlight - w:highlight belongs to a run, so use color here. // Word page geometry, breaks, and notes. All measurements are twips (1440 to the inch). Word only: { "op": "pageSetup", "paperSize": "A4", "orientation": "Landscape", "marginTopTwips": 720, "marginLeftTwips": 1080 } { "op": "insertBreak", "target": { "paraId": "w14:...", "expect": "..." }, "kind": "Page", "position": "After" } { "op": "insertBreak", "target": { "paraId": "w14:...", "expect": "..." }, "kind": "SectionNextPage" } // then pageSetup with a target inside the new section { "op": "note", "target": { "paraId": "w14:...", "expect": "thirty days" }, "kind": "Footnote", "text": "Subject to clause 8.2." } { "op": "note", "target": { "kind": "note", "path": "footnote#1" }, "action": "Update", "text": "Revised wording." } { "op": "note", "target": { "kind": "note", "path": "footnote#1" }, "action": "Remove" } // Insert a whole new table after a paragraph, or remove an entire table (table path from inspect_document.nodes): { "op": "insertTable", "target": { "paraId": "w14:...", "expect": "..." }, "position": "After", "table": { "headers": ["Region", "Q1"], "rows": [["NL", "41850"]] } } { "op": "removeTable", "target": { "kind": "table", "path": "table#0" } } // Add or remove table rows / columns; insert or remove image; copy or clear styles. Paths come from inspect_document.nodes: { "op": "insertTableRows", "target": { "kind": "table", "path": "table#0" }, "rows": [["NL","17","41850"]], "position": "End" } { "op": "repeatTableRow", "target": { "kind": "table", "path": "table#0" }, "templateRowIndex": 1, "records": [{ "Description": "Consulting", "Amount": "1200.00" }] } { "op": "removeTableRows", "target": { "kind": "table", "path": "table#0" }, "onlyIfEmpty": true } { "op": "insertImage", "target": { "paraId": "w14:...", "expect": "..." }, "base64Bytes": "iVBORw0KGgo...", "imageType": "png", "widthPx": 200, "heightPx": 80 } { "op": "insertImage", "target": { "paraId": "w14:...", "expect": "..." }, "imageConnectionId": "images", "imageDocumentId": "", "imageType": "png", "widthPx": 200, "heightPx": 80 } { "op": "removeImage", "target": { "kind": "image", "path": "image#0" } } { "op": "backgroundImage", "base64Bytes": "iVBORw0KGgo...", "imageType": "png", "opacity": 0.2 } { "op": "backgroundImage", "target": { "kind": "slide", "path": "slide#256" }, "base64Bytes": "iVBORw0KGgo...", "opacity": 0.15 } { "op": "headerFooter", "header": "Northwind Traders", "footer": "Confidential", "showPageNumber": true, "alignment": "edges", "differentFirstPage": true } // Native PowerPoint chart with an editable embedded workbook: { "op": "insertChart", "target": { "kind": "slide", "path": "slide#256" }, "kind": "ClusteredColumn", "categories": ["Q1","Q2"], "series": [{ "name": "Revenue", "values": [10,12] }], "title": "Revenue", "description": "Quarterly revenue" } // Excel cells and table rows; sheet ids and table paths come from inspection: { "op": "setCell", "target": { "sheetId": 7, "address": "B2" }, "formula": "SUM(B3:B8)" } { "op": "appendTableRows", "target": { "kind": "spreadsheetTable", "path": "table#7/Sales" }, "rows": [["APAC","15"]] } |
| open_documentA | Open a document the user named by source: registers it and returns its inspection in one call - use this instead of register_document followed by inspect_document. source is connection-specific, exactly as for register_document: a path under a filesystem connection's root, or a SharePoint/OneDrive URL or 'driveId/itemId' pair. Returns {connectionId, documentId, name, contentType, version} followed by the inspect_document payload (snapshot, outline, paragraphs, contentControls, nodes, styles). Keep documentId for follow-up calls; paging works as in inspect_document. |
| apply_planA | Apply a DocumentPlan JSON to (connectionId, documentId) and save through the provider. Returns {isValid, committed, writeOutcome, possibleOutput, receipt, sourceDocumentId, outputConnectionId, outputDocumentId, outputVersion, outputName, outputContentType, changes, errors}; non-applicable values are null. The receipt hashes the effective plan and exact input/output bytes and keeps the host-authenticated actor separate from the plan's display revision author. saveMode: 'Replace' (default, overwrites the source after an optimistic version check), 'NewVersion' (keeps the source and mints a new id under the same connection), 'NewDocument' (mints a fresh id with an optional newName for display). Plan-validation and operation-conflict failures have writeOutcome 'notWritten'. A provider failure after a write began may instead return 'unknown' or 'writtenNotRegistered' with possibleOutput; never retry those blindly or report the document unchanged until the host reconciles the possible output. |
| describe_capabilitiesA | List what this server actually supports before planning an edit: the accepted edit-plan contract version, every registered format with the plan verbs and change modes it takes, the host's document size and expansion ceilings, and the connections you may use with the capabilities you hold on each. A verb missing from a format is not supported there and will be refused. Anchor ids are never listed: they come from inspect_document for the document in hand. |
| edit_documentA | Edit a document the user named by source, in one call: registers it, resolves targets, and applies the operations - use this instead of register_document + find_in_document + apply_plan. planJson is an operations array [ … ] or { "operations": [ … ] }, the same operations preview_plan documents. Targets may name text directly instead of a paragraph id, so no lookup call is needed first: { "op": "changeText", "target": { "find": "Acme Corp" }, "with": "Globex Inc." } If that text matches more than once the call fails with 'ambiguous-anchor' and lists each candidate with its context; re-issue with { "find": "Acme Corp", "match": 2 } (zero-based) or use more surrounding text. Text that matches nothing fails with 'anchor-not-found'. Anchors resolved from inspect_document/find_in_document ({ "paraId": …, "expect": … }) work here too, and can be mixed in the same plan. saveMode and newName behave as in apply_plan. Nothing is written unless every operation validates. Returns the apply_plan shape plus sourceDocumentId - the id of the document that was opened, usable for follow-up calls even when the edit failed. |
| register_documentA | Register an existing document with a host-configured provider connection and return its opaque documentId. source is connection-specific: for a filesystem connection, a path under its root; for a SharePoint connection, the document's SharePoint/OneDrive URL (e.g. 'https://contoso.sharepoint.com/:w:/s/…') or a 'driveId/itemId' pair (e.g. 'b!9a3f…/01ABCDEF'). Never pass credentials. Returns {connectionId, documentId, name, contentType, version}. |
| find_in_documentB | Find content in Word, PowerPoint, or Excel. Excel can search displayed, raw, or both cell representations and returns sheetId plus A1 address anchors. |
| remove_documentA | Remove a document registration from a provider connection by (connectionId, documentId). Only the registration is removed - the underlying file is never deleted. Returns {removed, connectionId, documentId}. |
| inspect_documentB | Inspect a Word, PowerPoint, or Excel document. Excel returns worksheets, tables, and a bounded cell list; use sheetId, range, and maximumCells to narrow it. Other formats return their outline, paragraphs, content controls, nodes, and styles. Copy anchors and node paths from this result. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 12 tools
Most tools have clearly distinct lifecycle roles: discovery, registration, inspection, planning, applying, comparing, merging, and cleanup. The main ambiguity is between list_connections and describe_capabilities, which both expose connection information, and between register_document and the convenience wrappers open_document/edit_document, though the descriptions explain when to prefer each.
The API follows a consistent verb_noun pattern for nearly every tool: list_connections, apply_plan, inspect_document, remove_document, and so on. Minor deviations are find_in_document's prepositional structure and preview_document_merge, which reads as a compound noun next to the simpler preview_plan.
Twelve tools is comfortably within the well-scoped range and each one maps to a real step in the document editing workflow. The set feels substantial but not bloated, with no obvious redundant or purely decorative tools.
The server covers the document editing lifecycle well: registration, inspection, anchor discovery, planning, previewing, applying, comparing, merging, and unregistering. Minor gaps exist—there is no tool to create or upload a brand-new document from scratch, despite list_connections exposing canCreateDocuments—but the NewDocument save mode and merge workflows largely compensate.