officeagent-net
This server acts as a translation layer between AI agents and Microsoft Word (.docx) documents, enabling structured, validated edits without the agent ever writing raw XML or file bytes.
Document Management
list_connections: Discover available storage backends (filesystem or SharePoint).register_document: Register an existing Word document and receive an opaque ID for subsequent operations.remove_document: Unregister a document (the underlying file is never deleted).
Inspection & Search
inspect_document: Retrieve a structured map of a document including its outline, paragraphs (with stable IDs), styles, content controls, tables, images, document properties, and tracked revisions. Supports pagination and fidelity levels (outline,structure,content).find_in_document: Search for text using plain text, regex, whole-word, or case-sensitive matching, returning verified anchors usable as edit targets.
Plan-based Editing
preview_plan: Dry-run aDocumentPlanJSON to validate changes and get a before/after report — without writing anything.apply_plan: Execute a validatedDocumentPlanand save via three modes —NewVersion(default),NewDocument, orReplace(with optimistic concurrency).
Supported Edit Operations (within plans)
changeText: Replace text, optionally as a tracked change.format: Apply formatting (bold, highlight, color, style, borders, image dimensions) to paragraphs, runs, tables, rows, cells, or images.fill: Fill content controls by tag name.comment: Add comments to paragraphs.insert: Insert new paragraphs before/after an anchor.setProperty: Set document core properties (e.g., title, author).revision: Accept or reject tracked revisions.insertTable/removeTable: Insert or remove entire tables.insertTableRows/removeTableRows: Add or remove rows from a table.insertImage/removeImage: Insert (from base64 or registered source) or remove images.
OfficeAgent.NET
A translation layer between AI agents and OOXML - the format behind real Microsoft Word documents. Agents express intent; the library turns it into valid Open XML manipulations.
An agent can reason about a document, but it cannot safely produce one: the
things that make a .docx a Word document - styles, numbering, tracked
changes, comments, content controls - live in XML parts no language model
should write by hand. OfficeAgent.NET does that translation. The agent expresses
intent as a typed, JSON-serialisable change plan - "replace this clause as a
tracked change", "add a row to that table" - and the library translates the
plan into the Open XML changes that carry it out. Every change is validated
against the live document, previewed, and applied all-or-nothing. The agent
never writes raw .docx bytes, and Word itself is not automated.
The Word support is built on the Open XML SDK (DocumentFormat.OpenXml).
Use it when you need to:
locate stable targets in a
.docx(paragraphs, runs, tables, content controls, document properties, tracked revisions);ask a language model to return a typed edit plan instead of document bytes;
preview the result before saving;
keep Word semantics intact - runs, styles, content controls, comments, tracked revisions;
reject edits that target the wrong place or that need a layout/calculation engine.
Key concepts
The workflow: inspect → find → preview → commit
Every edit follows the same four steps:
Inspect - read the document and get a structured map of it: the outline, paragraphs (with stable ids), styles, content controls, and nodes (tables, images, document properties, revisions).
Find - search for text and get an address back for each match.
Preview - check a set of changes against the current document. Nothing is written; you get a before/after report and any validation errors.
Commit - apply the changes and save through storage. The operation is all-or-nothing: if any step fails, nothing is written.
Plan
A plan (DocumentPlan) is the list of changes you want to make. It is a
typed, JSON-serialisable object, so a language model can produce one directly.
The library validates the whole plan before it touches the document.
Anchors
An anchor is an address inside the document. The library issues anchors from inspect and find; the caller (or the model) reuses them and never invents one.
Anchors carry the content they expect to find. At commit time the library re-checks each anchor against the live document. If the content has changed, the operation fails safely instead of editing the wrong place.
Operations
Each entry in a plan is one operation - a verb such as changeText,
format, insert, or setProperty. Every operation targets one anchor. The
Word module ships 17 verbs covering text, tables, images, styles, comments,
document properties, and tracked revisions.
Documents are registered with a provider, not uploaded
A document is not edited by file path. It lives behind a document provider
(storage). The provider is a registry of references - it persists only the
path (or URL, drive id, …) the host hands it, not the bytes. You register an
existing document with a connection; the provider returns an opaque document
id. Every later call addresses the document by (connectionId, documentId),
and the provider routes reads and saves back to the referenced location.
The agent never sees a file path or credential and cannot leave the storage you
configured. By default it cannot register documents either - the host stages ids
up front; hosts that want the agent to manage its own registrations opt in to
the register_document / remove_document tools, which stay inside the
connection's boundary and never delete content. Filesystem and SharePoint
providers ship in the box; a database or any other store can implement the same
interface.
Related MCP server: MCP-OPENAPI-DOCX
Quick start
Install the packages:
dotnet add package OfficeAgent.Core
dotnet add package OfficeAgent.Word
dotnet add package OfficeAgent.AgentFramework # only for the Agent Framework path
dotnet add package OfficeAgent.SharePoint # only for the SharePoint providerOver MCP (any agent, any language)
The OfficeAgent.Mcp server exposes the same workflow as Model Context Protocol
tools, so any MCP-capable agent can edit real Word documents without taking a
.NET dependency. It runs over stdio for local hosting or streamable HTTP for the
cloud.
dotnet tool install --global OfficeAgent.Mcp
officeagent-mcp --stdio # local: child process of an MCP client
officeagent-mcp # cloud: streamable HTTP + /healthzPoint it at your documents through configuration (appsettings.json or
OfficeAgent__-prefixed environment variables) and the agent gets
inspect_document, find_in_document, preview_plan, apply_plan, and -
unless you turn registration off - register_document / remove_document /
list_connections.
See the MCP server guide for client config snippets,
SharePoint connections, and cloud hosting.
With Microsoft Agent Framework (MAF)
OfficeAgent.AgentFramework exposes the workflow as four core tools a language
model can call: inspect_document, find_in_document, preview_plan, and
apply_plan. By default the host registers documents up front and threads the
resulting opaque id into the agent's system prompt; the agent never sees a file
path and cannot register or delete storage on its own. Opt in via
OfficeAgentToolsOptions.AllowRegistration to add register_document and
remove_document, which let the agent stage its own ids inside the configured
connections.
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using OfficeAgent.AgentFramework;
using OfficeAgent.Core;
using OfficeAgent.Core.DocumentProviders;
using OfficeAgent.Word;
var services = new ServiceCollection()
.AddWordFormat()
.AddFileSystemDocumentProvider("workspace", "/srv/officeagent/workspace")
.AddOfficeAgent()
.BuildServiceProvider();
var client = services.GetRequiredService<OfficeAgentClient>();
// Register the existing document with the connection. The provider stores only
// the path; the host owns the file's lifecycle.
var seeded = await client.RegisterAsync(
"workspace", "/srv/officeagent/workspace/contract.docx");
var tools = new OfficeAgentTools(client).AsAIFunctions();
var prompt = $"You are editing documentId={seeded.ItemId} on connectionId=workspace.\n\n"
+ OfficeAgentTools.SystemPromptGuidance;
AIAgent agent = new ChatClientAgent(
chatClient, // any Microsoft.Extensions.AI IChatClient
instructions: prompt,
name: "OfficeAgent",
description: "Edits Word documents using OfficeAgent.NET.",
tools: tools.Cast<AITool>().ToList(),
services: services);apply_plan saves the result and returns an outputDocumentId. It does not send
.docx bytes back through the model. The host reads the id with OpenReadAsync
and delivers the file through its own download or attachment API.
A runnable Azure OpenAI example is in samples/AgentEdit.
As a library
Drive the same workflow directly from code:
using Microsoft.Extensions.DependencyInjection;
using OfficeAgent.Abstractions;
using OfficeAgent.Core;
using OfficeAgent.Core.DocumentProviders;
using OfficeAgent.Word;
var services = new ServiceCollection()
.AddWordFormat()
.AddFileSystemDocumentProvider("workspace", "/srv/officeagent/workspace")
.AddOfficeAgent()
.BuildServiceProvider();
var client = services.GetRequiredService<OfficeAgentClient>();
// Register an existing file with the connection; the provider mints the opaque id.
var doc = await client.RegisterAsync(
"workspace", "/srv/officeagent/workspace/contract.docx");
// inspect → find → preview → commit, addressing the document by its id.
var inspect = await client.InspectAsync("workspace", doc.ItemId);
var hit = (await client.FindAsync(
"workspace", doc.ItemId, new FindQuery("Acme Corp"))).First();
var plan = new DocumentPlan
{
Snapshot = inspect.Snapshot, // opt in to drift detection
Operations = new PlanOperation[]
{
new ChangeTextOp { Target = hit.Anchor, With = "Globex Inc.", Mode = ChangeMode.Tracked }
}
};
var preview = await client.PreviewAsync("workspace", doc.ItemId, plan);
if (!preview.IsValid) { /* surface preview.Errors */ return; }
// By default a fresh id is minted for the result; the source is preserved.
var result = await client.CommitAsync("workspace", doc.ItemId, plan);
if (result.Committed)
{
using var saved = await client.OpenReadAsync(result.Document);
// saved.Stream holds the edited bytes; result.Document.ItemId is the new id.
}A runnable version is in samples/QuickEdit.
Documentation
Getting started - one full edit, step by step.
Concepts - providers, inspect, anchors, snapshots, plans, preview/commit, capabilities, transactions.
Document providers -
IDocumentProvider, registration, save modes, optimistic concurrency, the SharePoint provider.Document plans - the JSON contract for every verb.
Agent integration - wiring
OfficeAgentToolsinto Microsoft Agent Framework / MEAI, opt-in registration tools.MCP server - hosting
OfficeAgent.Mcplocally over stdio or in the cloud over streamable HTTP.Deployment & client setup - connecting the MCP server to Claude Code, Codex, Copilot Studio, and Microsoft 365 Copilot, with the identity checklist.
Operations - thread safety, stream ownership, memory, cancellation, telemetry.
Scope
OfficeAgent.NET ships the Word path today. Excel and PowerPoint can plug in
through the same IFormatModule interface but are not implemented yet. Work that
needs a renderer - pagination, field recalculation, table-of-contents rendering,
page-fit checks - is rejected on purpose: the engine can write the OOXML but
cannot compute the displayed value.
Commercial support
OfficeAgent.NET is MIT and free to self-host. dotaction offers a managed, audited, EU-resident hosted service and commercial support — get in touch.
License
MIT. See LICENSE.
Maintenance
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilia-sokolov/OfficeAgent.NET'
If you have feedback or need assistance with the MCP directory API, please join our Discord server