Building an MCP for Excel


Introduction
These days, everyone seems to be talking about MCPs and agentic workflows in the context of AI-driven software development. Rather than add another technical deep dive to the pile, I’ll skip the detailed explanation of what an MCP is—if you’re curious or need a refresher, feel free to ask me in the comments or check out this resource from the official MCP documentation for more details.
If you’ve followed my writing, you’ll know I’m passionate about applying artificial intelligence to software development. I’ve already shared my thoughts about how AI is transforming our workflows—if you missed those, you can check them out here: Post 0: Launching My Agentic Coding & AI‑Automation Journey and LLM Agents Transforming Enterprise Efficiency.
Today, I want to focus on a recent project that took that passion in a new direction: building an MCP for Excel, integrating it with generative AI to automate and supercharge my development process.
Project Background & Motivation
The motivation behind building an MCP for Excel came directly from a real-world need in one of my recent projects. I was tasked with writing and maintaining VBA code within Excel files to automate various time-consuming and error-prone tasks. If you’ve ever developed in Excel, you know that the environment feels stuck in time—the built-in VBA editor is basic, outdated, and lacks modern development features we take for granted elsewhere.
At the same time, I wanted to leverage the power of artificial intelligence to accelerate development, automate repetitive tasks, and enhance my coding experience. However, for AI tools to be truly helpful, they need a way to “see” and understand the structure and data within Excel files—something not easily possible out of the box.
This challenge led me to develop my own MCP server for Excel: a solution that could bridge the gap between modern AI-powered coding assistants and the legacy world of VBA scripting. My goal was simple: make the AI smarter, giving it a tool to fully understand Excel and make my workflow much more efficient.
Choosing the Stack
When it came time to choose the technology stack for this project, C# was the natural choice. I’ve been programming in C# since around 2001-2002 when I was a beta-tester of Visual Studio .NET 2002, and while I’ve also used TypeScript and Python to build other small MCP servers, I was particularly excited to take advantage of Microsoft’s recently released C# SDK for MCP development. This project provided the perfect opportunity to combine my deep knowledge of C# with my ongoing passion for artificial intelligence.
A key technical challenge was how to interact with Excel files—reading their structure and contents—without requiring Excel to be installed on the server. During my research, I discovered ClosedXML, a robust open-source library for working with Excel files in .NET. ClosedXML turned out to be exactly what I needed: it offered comprehensive support for reading Excel sheets, formulas, ranges, etc., all without any dependency on the Excel application itself.
With the C# SDK and ClosedXML in hand, I was able to move forward and start building the tools I needed for the project, confident that I was using a stack that matched both my experience and the requirements of the solution.
Architecture Overview
High-Level Architecture
The Excel MCP Server is a modular, extensible C# application that exposes a set of tools for programmatic inspection and analysis of Excel workbooks via the Model Context Protocol (MCP). It is designed for use by AI agents (e.g., GitHub Copilot Chat) and other automation clients, enabling deep, structured access to Excel file content and metadata without requiring Microsoft Excel to be installed.
Key Architectural Components
Entry Point (
Program.cs
): Configures dependency injection, logging (Serilog), and registers all available tools with the MCP server. Sets up stdio-based communication for MCP.Tool Layer (
src/Tools/
): Each tool (e.g.,get_schema
,get_formulas
,get_sheet_data
) is implemented as a class with a clear interface, request/response models, and error handling. Tools are registered with the MCP server and exposed as endpoints.Service Layer (
src/Tools/<Tool>/Services/
): Each tool has dedicated services for validation and Excel file operations. Services use ClosedXML for direct file access and manipulation, ensuring cross-platform compatibility and no COM/Interop dependency.Models Layer (
src/Tools/<Tool>/Models/
): Defines request, response, and error models for each tool, ensuring consistent and structured data exchange.Core/Validation Layer (
src/Core/Validation/
): Shared validation logic for file paths, formats, and worksheet existence, used across multiple tools.Logging: All operations are logged using Serilog, with structured logging for traceability and diagnostics.
Testing (
tests/
): Comprehensive unit and integration tests for all tools and services, using xUnit and Moq.
Data Flow
Request: An MCP-compatible client sends a request (e.g.,
get_schema
) with parameters (e.g., file path).Validation: The tool validates input parameters using its validation service.
Processing: The tool delegates to its service layer to open and analyze the Excel file using ClosedXML.
Response: The tool returns a structured JSON response (or error) to the client.
Logging: All steps are logged for auditing and debugging.
Extensibility
New tools can be added by implementing a tool class, models, and services, then registering the tool in
Program.cs
.The architecture is modular, with each tool isolated in its own folder.
Mermaid Diagram
graph TD
subgraph "Client"
A["MCP Client e.g. Copilot Chat"]
end
subgraph "Server"
B["Program.cs Entry Point"]
C["MCP Server"]
D["Tool Layer"]
E["Service Layer"]
F["Models Layer"]
G["Core/Validation"]
H["Serilog Logging"]
end
subgraph "Excel"
I["Excel File .xlsx, .xlsm, .xltx, .xltm"]
end
A-->|"MCP Request"|C
C-->|"Tool Registration"|D
D-->|"Validate Input"|G
D-->|"Call Service"|E
E-->|"Read/Analyze"|I
E-->|"Return Data"|D
D-->|"Structured Response"|C
C-->|"MCP Response"|A
D-->|"Log Events"|H
E-->|"Log Events"|H
G-->|"Log Events"|H
Technology Stack
.NET 9 / C#
ClosedXML (Excel file access)
ModelContextProtocol/csharp-sdk (MCP communication)
Serilog (logging)
xUnit, Moq (testing)
Key Design Principles
Stateless per request: Each request is handled independently; Excel files are opened, processed, and closed per operation.
No Excel/COM dependency: All file operations use ClosedXML for portability and reliability.
Structured error handling: All errors are returned as structured JSON with codes and messages.
Modular and extensible: Each tool is self-contained and easily testable.
Tools Created
Here I'm showing the full description, not the final description sent to the MCP Client.
get_formulas
Extracts all formulas from an Excel workbook or a specific worksheet. Returns a list of formulas with cell address, formula string (as written in Excel, without the leading '='), evaluated value (if requested), hidden status, and worksheet name. Supports filtering by sheet and optionally includes formula results. Use this tool to audit, analyze, or document all formulas present in a workbook, including detection of hidden or error formulas.
get_schema
Extracts a complete structural overview of an Excel workbook. Returns a detailed JSON schema listing all worksheet names, their dimensions, all tables, and named ranges present in the file. Use this tool to understand the organization, available data regions, and metadata of any supported Excel file before attempting data extraction or analysis.
get_sheet_data
Retrieves tabular data from a specified worksheet in an Excel file. Returns column headers and a configurable number of data rows (with pagination support). Use this tool to access the actual cell values from a sheet, for previewing, processing, or exporting worksheet data. Requires the sheet name and supports limiting the number of rows returned.
get_range_data
Retrieves data from a specified range in an Excel workbook. Supports both explicit ranges (e.g., A1:B10
) and named ranges. Returns a 2D array of cell values, with support for formulas (returns calculated values), merged cells (returns the merged value for all covered cells), and empty cells (as empty strings). Enforces a maximum of 1000 rows x 100 columns per request, with a warning if data is truncated. Use this tool for precise extraction of rectangular or named regions, including tables, headers, or custom ranges. Also supports workbook-level named ranges that may span multiple sheets (returns sheet names in response) and provides clear error handling for ambiguous, missing, or unsupported named ranges (e.g., non-contiguous).
get_sheet_summary
Analyzes a worksheet and returns a summary of its columns, including column names, inferred data types (e.g., Text, Decimal, Date, Boolean, Unknown), and statistics such as count of non-empty cells, distinct values, and presence of formulas. Use this tool to quickly understand the structure and content of a sheet, identify data types, and detect columns with mixed or empty data.
get_table_data
Retrieves structured data from a specified Excel table (ListObject). Returns column headers, data rows with preserved data types, and table metadata including dimensions and location. Supports pagination for large tables. Use this tool to access structured tabular data that has been defined as an Excel table, with automatic type preservation for numbers, dates, and formulas.
list_named_ranges
Lists all visible named ranges in an Excel workbook, including name, absolute reference, scope, and worksheet.
Development Journey
For this project, my main source of information was the official documentation for the C# SDK for MCP servers. I also found it helpful to study examples of other MCPs available in the github.com/modelcontextprotocol/servers repository.
Throughout the early stages, a recurring challenge was describing tools and their parameters so that artificial intelligence could use them effectively. Initial attempts often led to underutilization by the AI until I began directly iterating based on AI feedback, and even created a custom GPT within ChatGPT to refine prompt and tool definitions.
Debugging was another challenge. Without the ability to set breakpoints as in traditional application development, I had to rely on detailed log files to track down issues—a workaround reminiscent of earlier coding days, but effective nonetheless.
GitHub Copilot was invaluable. Whether using it in Chat, Edit, or Agent modes, Copilot’s suggestions, custom instructions, and prompt guidance made development faster and more enjoyable.
With these tools and methods, I was able to build the entire MCP server in just two days—much faster than if I had started from scratch without modern AI-driven tools and iterative development. Keep in mind that this is a 6,175-line code project with 164 tests (Unit and Integration tests).
Excitement of AI Using My Tool
The real “wow” moment came after I finished developing the MCP server and integrated it into my project for generating VBA scripts for Excel. Seeing artificial intelligence actually leverage the tools I had built—to extract all the necessary details from Excel files, understand the columns, formulas, tables, ranges, and structure, and then generate fully functional VBA scripts—was simply amazing.
It was incredibly exciting to watch the AI use my MCP to seamlessly access and interpret the information from the files I was working on. Suddenly, tasks that used to be tedious and manual became much more efficient. The tool I had created was now empowering the AI to do things it couldn’t do before, making my workflow smoother and smarter.
Witnessing this in action was genuinely surprising. I realized that by bridging the gap between Excel and AI, I had given artificial intelligence a new capability to understand and manipulate complex Excel files in ways that made my own life as a developer much easier. It’s moments like these that remind me why I’m so passionate about combining automation, AI, and practical problem-solving.
Key Takeaways and Lessons Learned
Describe Tools with AI in Mind: One key lesson was the importance of crafting clear, unambiguous tool descriptions and parameter explanations for the AI to use them effectively. Initially, I underestimated how much small changes in wording could affect whether AI agents discovered and leveraged the right tools. Iterative testing and actually “asking the AI for advice” led to substantial improvements.
Iterate with Feedback Loops: Prompt engineering is an ongoing process. Creating a custom GPT and using AI suggestions as part of my workflow allowed for rapid experimentation and better outcomes.
Debugging Requires Creativity: Traditional debugging tools are often unavailable when working with agentic tools or headless servers. Falling back on structured, verbose logging was essential for troubleshooting issues and understanding execution flows.
AI as a Pair Programmer: Treating AI as a partner—using GitHub Copilot’s modes, reviewing suggestions, and organizing prompts—increased productivity and helped bridge the gap between idea and implementation.
Speed Gains Are Real: By combining a familiar stack (C#, .NET, ClosedXML), good open-source libraries, and generative AI tools, I built a robust and extensible MCP server in a fraction of the time a traditional approach would have required.
Learning Never Stops: There are still open questions—such as how to enable better debugging for MCP servers. If you have tips or tools for this, please share them in the comments!
Closing
If there’s one thing I hope you take away from this article, it’s that creating your own MCP tools can truly expand what artificial intelligence is capable of. By building custom tools that give AI access to data and context it otherwise couldn’t reach, you not only solve your own challenges but also push the boundaries of what’s possible with automation.
I encourage you to experiment with creating your own MCP tools or agentic workflows, whether it’s for Excel, other applications, or any scenario where AI could benefit from better access to structured information. You’ll be surprised at how much you can streamline your work—and how empowering it feels to see AI making use of the capabilities you’ve built.
If you have any questions, want to share your own experience, or need advice on getting started, feel free to reach out or leave a comment. I’m always happy to connect with others exploring the intersection of software development and artificial intelligence.
Let’s keep building and learning together!
Subscribe to my newsletter
Read articles from Jorge Castillo directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jorge Castillo
Jorge Castillo
I’m a seasoned software architect and technical leader with over 20 years’ experience designing, modernizing, and optimizing enterprise systems. Lately I’ve been harnessing large language models—integrating agents like GitHub Copilot, Cline, and Windsurf—to automate workflows, build n8n and VS Code extensions, and power custom MCP servers that bring generative AI into real-world development. A cloud-native specialist on Azure, I’ve architected scalable, resilient microservices solutions using Service Bus, Cosmos DB, Redis Cache, Functions, Cognitive Services and more, all backed by DevOps pipelines (GitHub Actions, Azure DevOps, Terraform) and strict IaC practices. Equally at home crafting UML diagrams, leading multidisciplinary teams as CTO or tech lead, and championing agile, TDD/BDD, clean-architecture and security best practices, I bridge business goals with robust, future-proof technology solutions.