You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Enhancement: Safe Automation of SharePoint/OneDrive Workbooks via Attach-to-Running-Instance
Status: Proposed enhancement with working implementation and verified test results. I would welcome the opportunity to discuss this with the project maintainer, as I am not as familiar with the full codebase and may have missed nuances that someone with deeper knowledge would catch.
The problem
Excel automation tools that create a new Excel.Application process cannot operate on files that are already open. They demand exclusive file access. For workbooks hosted on SharePoint or synced through OneDrive, this creates a serious gap: the tool either fails with a file-lock error, or it works around the lock by replacing the file on disk, which silently destroys the file's SharePoint identity.
When a file is replaced rather than edited in place, SharePoint treats it as a deletion followed by a creation. The filename stays the same. The content looks correct. But from SharePoint's perspective, it is a different file. Every sharing link breaks. Every permission disappears. Every version history entry is lost. Co-authoring state is destroyed. Power Automate flows pointed at the original file's item ID stop triggering. The user gets no warning that any of this happened.
Why this matters
Enterprise environments run on SharePoint. Workbooks are shared across teams, linked in Teams channels, embedded in wikis, referenced by Power Automate flows. Each file has a unique SharePoint item ID that ties together:
Sharing links distributed across emails, Teams messages, and documentation
Granular permissions managed by IT or the file owner
Version history used for compliance, audit trails, and rollback
Co-authoring state that lets multiple people edit simultaneously
Comments, annotations, and threaded discussions stored in SharePoint
Power Automate flows triggered by file changes
When automation replaces the file instead of editing it through Excel, all of those connections break silently. The filename stays the same. The content looks correct. But it is a different file with a different SharePoint item ID.
Why mcp-server-excel is the right foundation
The mcp-server-excel project made an excellent architectural choice by building on Excel's native COM interface rather than on file-format libraries (openpyxl, EPPlus, xlsxwriter, etc.). File-format libraries read and write .xlsx files as ZIP archives of XML. They bypass Excel entirely, which means they cannot participate in co-authoring, cannot refresh data connections, cannot evaluate formulas with full fidelity, and cannot preserve SharePoint file identity when writing back to a synced path.
COM interop, by contrast, drives Excel as an application. Every operation goes through the same interface that the user's keyboard and mouse use. This means the full power of Excel is available: real formula calculation, native pivot table support, Power Query refresh, VBA execution, and correct handling of every file format nuance that file-format libraries get wrong.
This architectural decision is what makes the proposed enhancement possible. Because mcp-server-excel already speaks COM, extending it to attach to a running instance is a natural step. The ExcelBatch class already manages an Excel.Application COM object on a dedicated STA thread. The ExcelContext that every downstream operation receives already holds a COM reference to the workbook. The only question is how that COM reference was obtained: by creating a new process, or by connecting to one that already exists. All 165+ operations work identically either way.
A file-format library could not be extended in this direction. COM interop can, and mcp-server-excel already built the foundation for it.
The solution: session attach
session attach builds on this COM foundation by connecting to the user's already-running Excel instance instead of creating a new one. The automation operates through the same COM interface that the keyboard and mouse use. Excel handles the OneDrive sync. SharePoint sees a normal edit. Co-authors see changes appear in real time.
No files are copied, replaced, or re-created. The workbook's SharePoint item ID, sharing links, permissions, version history, and co-authoring state all remain intact because the file was never closed and reopened. From SharePoint's perspective, an AI agent editing through session attach is indistinguishable from a human user typing into cells.
How it works
The feature adds a third session mode alongside the existing open (open a file in a new Excel process) and create (create a new file).
Standard mode creates a new Excel.Application process via Activator.CreateInstance, opens the file exclusively, and owns both the process and the workbook. When the session closes, it saves the workbook, quits Excel, and force-kills the process if necessary.
Attach mode connects to an existing Excel.Application process via oleaut32.dll GetActiveObject, finds the workbook by name in the already-open workbooks collection, and borrows a COM reference. When the session closes, it releases the COM reference and walks away. It does not close the workbook. It does not quit Excel. It does not touch the process.
The P/Invoke declaration that makes this possible:
Marshal.GetActiveObject("Excel.Application") was available in .NET Framework but removed in .NET 5+. This P/Invoke to oleaut32.dll achieves the same result on .NET 10. The PreserveSig = false attribute converts COM HRESULT failures into catchable exceptions, so a missing Excel instance surfaces as a COMException with MK_E_UNAVAILABLE (0x800401E3) rather than a cryptic return code.
Architecture
All downstream operations (worksheets, ranges, tables, charts, pivots, Power Query, VBA, screenshots, conditional formatting) flow through ExcelContext, which holds three things: a workbook path string, an Excel.Application COM object, and an Excel.Workbook COM object. Every operation in the codebase receives this context. None of them care how the COM objects were obtained.
This means the change is isolated to the session creation path. The 165+ operations that already exist work identically in attach mode with zero modifications.
Ten source files were modified. Four contain the core behavioral change. Six expose it through the CLI, MCP server, and service layer.
Core: ExcelBatch.cs
This is the file that manages the STA thread, the Excel COM lifecycle, and the workbook session. Three areas changed.
1. Attach via GetActiveObject instead of Activator.CreateInstance
Before (standard mode only):
Excel.ApplicationtempExcel=(Excel.Application)Activator.CreateInstance(excelType)!;tempExcel.Visible=_showExcel;tempExcel.DisplayAlerts=false;// Capture process ID, set AutomationSecurity...
After (attach mode branch added):
Excel.ApplicationtempExcel;if(_attachToRunning){// Connect to the user's running Excel — do not create a new process,// capture PID, set Visible/DisplayAlerts, or change AutomationSecuritytry{Guidclsid=excelType.GUID;GetActiveObject(refclsid,IntPtr.Zero,outobjectppunk);tempExcel=(Excel.Application)ppunk;}catch(COMExceptionex)when(ex.HResult==unchecked((int)0x800401E3)){thrownewInvalidOperationException("No running Excel instance found. Open the workbook in Excel first, "+"then use attach mode.",ex);}}else{// Standard mode: create a new Excel processtempExcel=(Excel.Application)Activator.CreateInstance(excelType)!;tempExcel.Visible=_showExcel;tempExcel.DisplayAlerts=false;// ... PID capture, AutomationSecurity (unchanged) ...}
The attach branch deliberately skips every configuration step that standard mode performs. It does not set Visible (the user's Excel is already visible). It does not set DisplayAlerts (the user may want dialogs). It does not capture the process ID (it does not own the process). It does not set AutomationSecurity (the user's security settings should be respected).
2. Find workbook by name instead of opening by path
After (attach branch added before the existing branches):
if(_attachToRunning){stringtargetName=Path.GetFileName(path);Excel.Workbook?found=null;foreach(Excel.WorkbookopenWbintempExcel.Workbooks){if(string.Equals(openWb.Name,targetName,StringComparison.OrdinalIgnoreCase)){found=openWb;break;}}if(found==null)thrownewInvalidOperationException($"Workbook '{targetName}' is not open in the running Excel instance.");wb=found;normalizedPath=wb.FullName;// May be a SharePoint URL}elseif(_createNewFile){/* unchanged */}else{/* unchanged */}
The workbook's FullName property returns the SharePoint URL (e.g., https://company.sharepoint.com/teams/.../file.xlsx) rather than a local file path when the file is synced via OneDrive. This is stored as the session's workbook path and serves as the file's identity throughout the session.
if(_attachToRunning){// Release COM references only. Do NOT close workbook or quit Excel._logger.LogDebug("Attach mode: releasing COM references without closing workbook or quitting Excel");}else{ExcelShutdownService.CloseAndQuit(_workbook,_excel,false,_workbookPath,_logger);}
A new factory method alongside the existing BeginBatch:
publicstaticIExcelBatchBeginAttached(stringworkbookName,TimeSpan?operationTimeout=null){if(string.IsNullOrWhiteSpace(workbookName))thrownewArgumentException("Workbook name is required",nameof(workbookName));returnExcelBatch.AttachToRunning(workbookName,logger:null,operationTimeout:operationTimeout);}
Core: SessionManager.cs
A new AttachSession method alongside the existing CreateSession. The key difference: it skips File.Exists validation (the file may only exist as a SharePoint URL), skips the same-file-in-another-session check (inapplicable for attached sessions), and does not call TrackExcelProcess (the process is not owned by this session).
publicstringAttachSession(stringworkbookName,TimeSpan?operationTimeout=null,SessionOriginorigin=SessionOrigin.Unknown){stringsessionId=Guid.NewGuid().ToString("N");IExcelBatch?batch=null;try{batch=_sessionCreationPipeline.Execute(()=>ExcelSession.BeginAttached(workbookName,operationTimeout));_activeSessions.TryAdd(sessionId,batch);_sessionFilePaths[sessionId]=batch.WorkbookPath;_activeOperationCounts[sessionId]=0;_showExcelFlags[sessionId]=true;_sessionOrigins[sessionId]=origin;_sessionCreatedAt[sessionId]=DateTime.UtcNow;// Do NOT add to _activeFilePaths — path may be a SharePoint URL// Do NOT call TrackExcelProcess — we don't own this processvarresult=sessionId;batch=null;returnresult;}catch(Exceptionex){thrownewInvalidOperationException($"Failed to attach to workbook '{workbookName}': {ex.Message}",ex);}finally{batch?.Dispose();}}
A new SessionAttachCommand registered in the CLI. Takes a workbook name (not a file path) as its argument:
internalsealedclassSessionAttachCommand:AsyncCommand<SessionAttachCommand.Settings>{publicoverrideasyncTask<int>ExecuteAsync(CommandContextcontext,Settingssettings,CancellationTokencancellationToken){usingvarclient=awaitDaemonAutoStart.EnsureAndConnectAsync(cancellationToken);varresponse=awaitclient.SendAsync(newServiceRequest{Command="session.attach",Args=JsonSerializer.Serialize(new{workbookName=settings.WorkbookName,timeoutSeconds=settings.TimeoutSeconds},ServiceProtocol.JsonOptions)},cancellationToken);// ...}internalsealedclassSettings:CommandSettings{[CommandArgument(0,"<WORKBOOK_NAME>")][Description("Name of the workbook already open in Excel (e.g., budget.xlsx)")]publicstringWorkbookName{get;init;}=string.Empty;}}
Command surface: Program.cs (CLI registration)
branch.AddCommand<SessionAttachCommand>("attach").WithDescription("Attach to a workbook already open in the user's running Excel instance.");
A new "attach" case in the session command switch, a new HandleSessionAttach handler, and a new SessionAttachArgs class:
"attach"=>HandleSessionAttach(request),
privateServiceResponseHandleSessionAttach(ServiceRequestrequest){varargs=ServiceRegistry.DeserializeArgs<SessionAttachArgs>(request.Args);if(string.IsNullOrWhiteSpace(args?.WorkbookName))returnnewServiceResponse{Success=false,ErrorMessage="workbookName is required"};varsessionId=_sessionManager.AttachSession(args.WorkbookName,operationTimeout:timeout,origin:SessionOrigin.CLI);returnnewServiceResponse{Success=true,Result=JsonSerializer.Serialize(new{success=true,sessionId,workbookName=args.WorkbookName},ServiceProtocol.JsonOptions)};}
Command surface: ExcelFileTool.cs (MCP server)
A new AttachSessionAsync method and a new case in the action switch, so the MCP file tool supports action: "attach". The method sends session.attach through the service bridge, same as the CLI.
The P/Invoke approach was validated on a live SharePoint-synced workbook before any production code was written. All tests ran on .NET 10.0.201, Windows 11 Enterprise, Microsoft 365 Excel (Version 16.0), against a workbook hosted on SharePoint and synced to the local machine via OneDrive.
#
Test
Result
1
oleaut32.dllGetActiveObject P/Invoke works on .NET 10
PASS
2
Retrieved Excel.Application can access Workbooks and find open workbook
PASS
3
Can add worksheets through attached COM reference
PASS
4
Can write cell values and create Excel Tables through attached COM reference
PASS
5
workbook.Save() through attached reference saves via Excel's native path
PASS
6
FullName remains SharePoint URL after save (file identity preserved)
PASS
7
Excel remains running after test app exits (no Quit() called)
PASS
8
OneDrive sync processes the save normally
PASS
After the changes were integrated into the full codebase, the complete solution built with zero errors and zero warnings. An end-to-end test on a OneDrive-synced workbook confirmed that session attach connected to the running Excel instance, data written via range set-values appeared in the workbook immediately, and session close released the COM references without closing the workbook or quitting Excel.
Co-authoring was also tested with a SharePoint-hosted workbook where the folder was synced to the local hard drive. The CLI made changes to the locally synced file through the attached Excel instance, and those changes appeared in the Excel Online view of the same sheet in real time, in the same way they would if the user were making changes manually. From SharePoint's perspective, the CLI session was indistinguishable from a human user editing the workbook.
Skill updates
The CLI skill (skills/excel-cli/) was updated so that AI agents know about session attach and when to use it. Changes were made to the Scriban template (skills/templates/SKILL.cli.sbn) and the shared behavioral rules (skills/shared/behavioral-rules.md) so they survive the build-time regeneration process.
Specific updates:
SKILL.md description and triggers now include SharePoint, OneDrive, co-authoring, and attach
Workflow checklist updated from session create/open to session create/open/attach
Rule 1 (discovery table) added: "Is the file open in Excel?" with session attach as the action
Rule 3 (session lifecycle) expanded with full session attach documentation: when to use it, the syntax (workbook name not file path), and the behavioral differences (does not close workbook, does not quit Excel, does not create a new process)
Rule 8 (batch mode) updated to note that session.attach participates in auto-capture of session IDs
Behavioral rules reference updated with the attach workflow alongside the existing open workflow
When an agent reads the updated skill, it will choose session attach over session open when the user's workbook is already open in Excel or is hosted on SharePoint/OneDrive.
What stays the same
Every existing workflow continues to work exactly as before. The session open command still creates a new Excel process, demands exclusive file access, and closes everything on session end. The session create command still creates new workbooks. The 165+ operations (range, table, chart, pivot, Power Query, DAX, VBA, conditional formatting, screenshots, slicers, data models) all route through the same ExcelContext interface and are unaware of which session mode created it.
The change is additive. No existing behavior was modified.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Enhancement: Safe Automation of SharePoint/OneDrive Workbooks via Attach-to-Running-Instance
The problem
Excel automation tools that create a new
Excel.Applicationprocess cannot operate on files that are already open. They demand exclusive file access. For workbooks hosted on SharePoint or synced through OneDrive, this creates a serious gap: the tool either fails with a file-lock error, or it works around the lock by replacing the file on disk, which silently destroys the file's SharePoint identity.When a file is replaced rather than edited in place, SharePoint treats it as a deletion followed by a creation. The filename stays the same. The content looks correct. But from SharePoint's perspective, it is a different file. Every sharing link breaks. Every permission disappears. Every version history entry is lost. Co-authoring state is destroyed. Power Automate flows pointed at the original file's item ID stop triggering. The user gets no warning that any of this happened.
Why this matters
Enterprise environments run on SharePoint. Workbooks are shared across teams, linked in Teams channels, embedded in wikis, referenced by Power Automate flows. Each file has a unique SharePoint item ID that ties together:
When automation replaces the file instead of editing it through Excel, all of those connections break silently. The filename stays the same. The content looks correct. But it is a different file with a different SharePoint item ID.
Why mcp-server-excel is the right foundation
The mcp-server-excel project made an excellent architectural choice by building on Excel's native COM interface rather than on file-format libraries (openpyxl, EPPlus, xlsxwriter, etc.). File-format libraries read and write
.xlsxfiles as ZIP archives of XML. They bypass Excel entirely, which means they cannot participate in co-authoring, cannot refresh data connections, cannot evaluate formulas with full fidelity, and cannot preserve SharePoint file identity when writing back to a synced path.COM interop, by contrast, drives Excel as an application. Every operation goes through the same interface that the user's keyboard and mouse use. This means the full power of Excel is available: real formula calculation, native pivot table support, Power Query refresh, VBA execution, and correct handling of every file format nuance that file-format libraries get wrong.
This architectural decision is what makes the proposed enhancement possible. Because mcp-server-excel already speaks COM, extending it to attach to a running instance is a natural step. The
ExcelBatchclass already manages anExcel.ApplicationCOM object on a dedicated STA thread. TheExcelContextthat every downstream operation receives already holds a COM reference to the workbook. The only question is how that COM reference was obtained: by creating a new process, or by connecting to one that already exists. All 165+ operations work identically either way.A file-format library could not be extended in this direction. COM interop can, and mcp-server-excel already built the foundation for it.
The solution:
session attachsession attachbuilds on this COM foundation by connecting to the user's already-running Excel instance instead of creating a new one. The automation operates through the same COM interface that the keyboard and mouse use. Excel handles the OneDrive sync. SharePoint sees a normal edit. Co-authors see changes appear in real time.No files are copied, replaced, or re-created. The workbook's SharePoint item ID, sharing links, permissions, version history, and co-authoring state all remain intact because the file was never closed and reopened. From SharePoint's perspective, an AI agent editing through
session attachis indistinguishable from a human user typing into cells.How it works
The feature adds a third session mode alongside the existing
open(open a file in a new Excel process) andcreate(create a new file).Standard mode creates a new
Excel.Applicationprocess viaActivator.CreateInstance, opens the file exclusively, and owns both the process and the workbook. When the session closes, it saves the workbook, quits Excel, and force-kills the process if necessary.Attach mode connects to an existing
Excel.Applicationprocess viaoleaut32.dll GetActiveObject, finds the workbook by name in the already-open workbooks collection, and borrows a COM reference. When the session closes, it releases the COM reference and walks away. It does not close the workbook. It does not quit Excel. It does not touch the process.The P/Invoke declaration that makes this possible:
Marshal.GetActiveObject("Excel.Application")was available in .NET Framework but removed in .NET 5+. This P/Invoke tooleaut32.dllachieves the same result on .NET 10. ThePreserveSig = falseattribute converts COM HRESULT failures into catchable exceptions, so a missing Excel instance surfaces as aCOMExceptionwithMK_E_UNAVAILABLE (0x800401E3)rather than a cryptic return code.Architecture
All downstream operations (worksheets, ranges, tables, charts, pivots, Power Query, VBA, screenshots, conditional formatting) flow through
ExcelContext, which holds three things: a workbook path string, anExcel.ApplicationCOM object, and anExcel.WorkbookCOM object. Every operation in the codebase receives this context. None of them care how the COM objects were obtained.This means the change is isolated to the session creation path. The 165+ operations that already exist work identically in attach mode with zero modifications.
Code changes
Ten source files were modified. Four contain the core behavioral change. Six expose it through the CLI, MCP server, and service layer.
Core: ExcelBatch.cs
This is the file that manages the STA thread, the Excel COM lifecycle, and the workbook session. Three areas changed.
1. Attach via GetActiveObject instead of Activator.CreateInstance
Before (standard mode only):
After (attach mode branch added):
The attach branch deliberately skips every configuration step that standard mode performs. It does not set
Visible(the user's Excel is already visible). It does not setDisplayAlerts(the user may want dialogs). It does not capture the process ID (it does not own the process). It does not setAutomationSecurity(the user's security settings should be respected).2. Find workbook by name instead of opening by path
Before (standard mode only):
After (attach branch added before the existing branches):
The workbook's
FullNameproperty returns the SharePoint URL (e.g.,https://company.sharepoint.com/teams/.../file.xlsx) rather than a local file path when the file is synced via OneDrive. This is stored as the session's workbook path and serves as the file's identity throughout the session.3. Skip shutdown on dispose
Before (always closes workbook and quits Excel):
After (attach mode skips shutdown entirely):
The force-kill path in
Dispose()is also guarded:And
IsExcelProcessAlive()returnstruein attach mode since there is no captured PID to check:Core: ExcelSession.cs
A new factory method alongside the existing
BeginBatch:Core: SessionManager.cs
A new
AttachSessionmethod alongside the existingCreateSession. The key difference: it skipsFile.Existsvalidation (the file may only exist as a SharePoint URL), skips the same-file-in-another-session check (inapplicable for attached sessions), and does not callTrackExcelProcess(the process is not owned by this session).Core: ToolActions.cs
One line added to the
FileActionenum:Command surface: SessionCommands.cs (CLI)
A new
SessionAttachCommandregistered in the CLI. Takes a workbook name (not a file path) as its argument:Command surface: Program.cs (CLI registration)
Command surface: ExcelMcpService.cs (service routing)
A new
"attach"case in the session command switch, a newHandleSessionAttachhandler, and a newSessionAttachArgsclass:Command surface: ExcelFileTool.cs (MCP server)
A new
AttachSessionAsyncmethod and a new case in the action switch, so the MCPfiletool supportsaction: "attach". The method sendssession.attachthrough the service bridge, same as the CLI.Usage
CLI:
MCP:
{ "action": "attach", "path": "budget.xlsx" }Test results
The P/Invoke approach was validated on a live SharePoint-synced workbook before any production code was written. All tests ran on .NET 10.0.201, Windows 11 Enterprise, Microsoft 365 Excel (Version 16.0), against a workbook hosted on SharePoint and synced to the local machine via OneDrive.
oleaut32.dllGetActiveObjectP/Invoke works on .NET 10Excel.Applicationcan accessWorkbooksand find open workbookworkbook.Save()through attached reference saves via Excel's native pathFullNameremains SharePoint URL after save (file identity preserved)Quit()called)After the changes were integrated into the full codebase, the complete solution built with zero errors and zero warnings. An end-to-end test on a OneDrive-synced workbook confirmed that
session attachconnected to the running Excel instance, data written viarange set-valuesappeared in the workbook immediately, andsession closereleased the COM references without closing the workbook or quitting Excel.Co-authoring was also tested with a SharePoint-hosted workbook where the folder was synced to the local hard drive. The CLI made changes to the locally synced file through the attached Excel instance, and those changes appeared in the Excel Online view of the same sheet in real time, in the same way they would if the user were making changes manually. From SharePoint's perspective, the CLI session was indistinguishable from a human user editing the workbook.
Skill updates
The CLI skill (
skills/excel-cli/) was updated so that AI agents know aboutsession attachand when to use it. Changes were made to the Scriban template (skills/templates/SKILL.cli.sbn) and the shared behavioral rules (skills/shared/behavioral-rules.md) so they survive the build-time regeneration process.Specific updates:
session create/opentosession create/open/attachsession attachas the actionsession attachdocumentation: when to use it, the syntax (workbook name not file path), and the behavioral differences (does not close workbook, does not quit Excel, does not create a new process)session.attachparticipates in auto-capture of session IDsWhen an agent reads the updated skill, it will choose
session attachoversession openwhen the user's workbook is already open in Excel or is hosted on SharePoint/OneDrive.What stays the same
Every existing workflow continues to work exactly as before. The
session opencommand still creates a new Excel process, demands exclusive file access, and closes everything on session end. Thesession createcommand still creates new workbooks. The 165+ operations (range, table, chart, pivot, Power Query, DAX, VBA, conditional formatting, screenshots, slicers, data models) all route through the sameExcelContextinterface and are unaware of which session mode created it.The change is additive. No existing behavior was modified.
Beta Was this translation helpful? Give feedback.
All reactions