sharepoint-excel-mcp
sharepoint-excel-mcp
MCP server that gives an AI agent read access to Excel files stored in SharePoint and OneDrive for Business, turning a permission-matrix spreadsheet into structured JSON.
Built for a QA automation flow: a test-case-writing agent reads Jira stories, each story references a permission matrix as a SharePoint link, and this server is what turns that link into data the agent can reason over — unattended, with no user sign-in.
Contents
Permissions ← read this one
Related MCP server: Excel Search MCP
Quick start
npm install
cp .env.example .env # then fill in TENANT_ID / CLIENT_ID / CLIENT_SECRET
npm run build
npm run doctor -- "<your sharepoint link>" # verify the whole chainNo Azure tenant yet? Everything below runs offline:
npm run mock # full tool flow against fixtures
npm run mock -- --wac # same, forcing the download fallback
npm run doctor -- --mock "https://contoso.sharepoint.com/:x:/s/QA/T?e=1"
npm testAzure app registration
Entra admin centre → App registrations → New registration. Name it, choose Accounts in this organizational directory only, leave the redirect URI blank — this is an app-only flow with no sign-in.
Copy the Directory (tenant) ID and Application (client) ID from the Overview page into
.env.Certificates & secrets → New client secret. Copy the secret Value immediately — not the Secret ID. It is shown once and cannot be retrieved later.
API permissions → Add a permission → Microsoft Graph → Application permissions. Add one of the permissions described below.
Grant admin consent for the directory. Without this, every Graph call fails with 403 no matter how correct the code is.
Admin consent is an external dependency. If you are not a Global Admin or Privileged Role Admin you cannot grant it yourself, and no amount of retrying will work around it. A 403 almost always means this step is outstanding.
Permissions
This is the part that decides how the server behaves, so it is worth understanding rather than copying.
The situation
Microsoft's own documentation for the Excel endpoints (worksheets, usedRange) states "Application: Not supported", and the Excel overview documents only delegated scopes.
In practice app-only access does work with tenant-wide Sites.Read.All. Under
Sites.Selected it commonly fails with:
403 — Could not obtain a WAC access tokenSo the server has two read paths and picks automatically.
Option A — Sites.Selected (default, least privilege)
Graph permission |
|
Access scope | Only sites you explicitly grant |
Excel Workbook API | Usually unavailable (WAC 403) |
Read path used | Download |
After granting admin consent, grant the app access to each site:
# Find the site ID
GET https://graph.microsoft.com/v1.0/sites/{tenant}.sharepoint.com:/sites/{siteName}
# Grant this app read access to that site
POST https://graph.microsoft.com/v1.0/sites/{siteId}/permissions
{
"roles": ["read"],
"grantedToIdentities": [
{ "application": { "id": "<CLIENT_ID>", "displayName": "sharepoint-excel-mcp" } }
]
}A WAC 403 under this option is expected and is not a misconfiguration. It means
the download fallback engaged and everything is working. npm run doctor reports it
as an informational branch, not a failure.
Option B — Sites.Read.All (workbook API available)
Graph permission |
|
Access scope | Every SharePoint site in the tenant |
Excel Workbook API | Available |
Read path used |
|
More capable and avoids downloading files, but it is a tenant-wide read grant. Your security team may reasonably refuse it.
Which to choose
Start with A. Both paths produce byte-identical output — there is a test asserting exactly that — so the only differences are latency and breadth of access. Move to B only if the download fallback proves too slow for your file sizes.
OneDrive / personal sites
Files under https://{tenant}-my.sharepoint.com/personal/... are not supported.
Sites.Selected does not reach personal OneDrive, and it resolves through a
different Graph path. Put the matrix in a SharePoint site document library.
Registering with Claude
claude mcp add sharepoint-excel \
--env TENANT_ID=<tenant-id> \
--env CLIENT_ID=<client-id> \
--env CLIENT_SECRET=<client-secret> \
-- node /absolute/path/to/share-point-mcp/dist/index.jsRun npm run build first. For development you can point at tsx src/index.ts
instead of the built output.
Tools
resolve_link(link)
Converts a link into stable driveId / itemId.
{ "driveId": "b!…", "itemId": "01…", "name": "matrix.xlsx", "webUrl": "https://…" }Call this once and reuse the IDs. Sharing links expire and get revoked; resolving one costs an extra Graph round trip on every call.
Three link shapes are accepted:
Shape | Example |
Sharing link |
|
Direct path |
|
Library view |
|
list_excel_sheets(link | driveId+itemId)
Worksheet names. Uncapped.
describe_sheet(ref, sheet?, headerRow?)
Headers, total row count, and up to 3 sample rows — no full data dump. This is the intended first call against an unfamiliar matrix: see the shape, then build a targeted filter.
get_permission_matrix(ref, sheet?, headerRow?, maxRows?, offset?, columns?, filter?)
The main tool. Uses the header row as keys.
{
"file": "matrix.xlsx", "sheet": "Permission Matrix",
"headers": ["Role", "Module", "Delete"],
"rowCount": 8, "returnedCount": 3, "offset": 0, "truncated": true,
"hint": "Showing 3 of 8 matching rows. Narrow with `filter` or `columns` first…",
"records": [ { "Role": "Admin", "Module": "Billing", "Delete": true } ]
}maxRows— default 500offset— for pagingcolumns— project to a subset; large saving on wide matricesfilter—{ column, equals? , contains? }, case-insensitive
rowCount is the number of rows matching the filter, not the sheet size.
get_cell_range(ref, sheet, range)
Raw values for an explicit A1 range like "A1:D20", for sheets whose layout does
not fit the header-row model.
Behaviour worth knowing
maxRows / offset / filter / columns are applied client-side
They bound what the agent receives, not what crosses the network. usedRange
returns the entire grid regardless, so maxRows: 10 on a 50,000-row sheet still
transfers all 50,000 rows.
This matters because the parameter names strongly imply server-side paging, and the
gap only shows up as unexplained latency on a large sheet. If you need to genuinely
bound the transfer, use get_cell_range with an explicit address — that is the
tool that actually does it.
Dates come back as Excel serial numbers
A date cell reads as 45292, not "2024-01-01". That is what Graph's usedRange
returns, and the download fallback normalizes to match so the two paths cannot be
told apart. Convert on the consuming side:
new Date(Date.UTC(1899, 11, 30) + serial * 86400000).
Dates before 1900-03-01 are off by one, because Excel reproduces a Lotus 1-2-3 bug that treats 1900 as a leap year. Not corrected — see the test that pins it.
Blank cells are empty strings
"", not null — again matching Graph. Fully blank rows are dropped entirely.
Header normalization
Real matrices have messy header rows, and both failure modes are silent:
Input | Becomes | Why |
|
| trimmed |
|
| named by its real sheet column |
|
| duplicates would otherwise overwrite |
The 25 MB download ceiling
Under the fallback path, files above MAX_DOWNLOAD_BYTES (default 25 MB) are
refused before the transfer starts. exceljs loads the whole workbook into
memory; an OOM would kill the stdio transport and surface to the agent as a
connection drop rather than a readable error.
Timeouts
30 s on Graph calls, 60 s on the download. A timeout is reported as its own error type naming the request, and is not retried — 429 and 5xx are retried up to 3 times, 403 never is.
Troubleshooting
Run the doctor first. It walks every leg and tells you which one broke:
npm run doctor -- "<your link>"1. Configuration 2. Link 3. Access token
4. Resolve to driveItem 5. Workbook API 6. usedRange
7. Download fallback → VerdictIt exits non-zero only when neither read path works.
Symptom | Meaning |
|
|
401 at step 3 | Wrong tenant/client ID, or the secret's ID was copied instead of its Value, or it expired |
403 at step 4 | Admin consent not granted, or the site not granted under |
404 at step 4 | Link revoked or expired. Confirm it opens in a browser — a revoked link and a bad share-ID encoding are indistinguishable from the response |
Yellow | Expected under |
403 at step 5 that is not yellow | A genuine consent problem, not a WAC issue |
npm run encode -- "<link>" prints the share ID and the exact Graph request to
paste into Graph Explorer —
useful for isolating an encoding problem from a permissions one.
Limitations
.xlsxonly..xlsand.csvare not supported by the Excel REST APIs.No consumer OneDrive. Business platform only.
No personal OneDrive sites (
/personal/…). Use a SharePoint site library.Read-only. No write tools, by design.
Dates are Excel serials; pre-1900-03-01 dates are off by one.
Development
npm test # 181 tests, no network
npm run typecheck # strict, includes tests and scripts
npm run lint
npm run dev # run the server from source
npm run fixtures # regenerate the .xlsx test fixtureLayout
src/
index.ts MCP server + tool registration, nothing else
config.ts env parsing, fail-fast validation
logger.ts stderr-only logger
auth.ts token acquisition, caching, single-flight
graph.ts authed fetch, retry, error mapping, redaction
links.ts pure: link classification + share-ID encoding
sharepoint.ts resolution + the two-path read
xlsx-fallback.ts download + exceljs parse + cell normalization
transform.ts pure: grid → recordsTesting approach
Pure logic (share-ID encoding, link parsing, the transform pipeline, cell
normalization) is unit tested with no network. Graph interactions run against a
routing stub and recorded fixtures. server.test.ts drives the real server through
an in-memory MCP client, which catches registration mistakes unit tests cannot see.
The most important test is cross-path equivalence: the same fixture is read via the workbook API and via the download fallback, and the results must be deeply equal. Testing each path alone cannot catch a divergence between them — and it caught a real one during development.
Nothing in npm test touches the network. Only npm run doctor talks to Azure.
Stdout is the protocol
Under StdioServerTransport, stdout carries JSON-RPC frames. A stray console.log
in src/ corrupts the stream and breaks the server with an opaque parse error on
the client. All logging goes to stderr via logger.ts, enforced by an eslint
no-console rule on src/**. Scripts under scripts/ are exempt — they are CLIs.
Available Tools
5 toolsdescribe_sheetDescribe a worksheetA
Inspect a sheet without pulling its data: returns the column headers, the total row count, and up to 3 sample rows. Call this FIRST against an unfamiliar matrix so you can build a targeted filter for get_permission_matrix instead of pulling everything.
| Name | Required | Description | Default |
|---|---|---|---|
| link | No | SharePoint sharing link (…/:x:/s/Site/TOKEN?e=code) or a direct document URL. Omit if supplying driveId and itemId. | |
| sheet | No | Worksheet name. Defaults to the first sheet. | |
| itemId | No | Item ID from resolve_link. Use with driveId. | |
| driveId | No | Drive ID from resolve_link. Use with itemId. | |
| headerRow | No | 1-indexed header row. Default 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It transparently states the tool does not pull the full dataset, returns only headers, row count, and up to 3 sample rows, and is safe to call first. It could add nuance about whether sample rows are the first rows or random, but overall it gives enough context for a read-only inspection tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: the first front-loads the purpose and return values; the second gives direct usage guidance. Every word is purposeful, with no fluff or repetition. Highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema and no annotations, the description covers the essential context: what callers receive (headers, row count, sample rows), when to invoke it (first on unfamiliar sheets), and why (to avoid pulling everything). For a simple inspection tool with fully documented parameters, this is complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for all 5 parameters, so the schema already fully documents their meaning. The description adds limited parameter-level detail beyond what the schema provides (e.g., 'headerRow' is self-explanatory). This meets the baseline but does not go further.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource ('Inspect a sheet') and clearly defines its scope: returns column headers, total row count, and up to 3 sample rows. It also differentiates from sibling tools by emphasizing it's a lightweight inspection ('without pulling its data') and explicitly mentions the targeted use case for get_permission_matrix.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: 'Call this FIRST against an unfamiliar matrix'. It also states why (to build a targeted filter) and contrasts with the alternative 'pulling everything' via get_permission_matrix, effectively giving a when-not scenario. This is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_cell_rangeRead an explicit cell rangeA
Read raw values for an explicit A1 range, e.g. "A1:D20". Use when the sheet has a non-standard layout that the header-row model does not fit. Unlike get_permission_matrix, the range genuinely bounds what Graph transfers.
| Name | Required | Description | Default |
|---|---|---|---|
| link | No | SharePoint sharing link (…/:x:/s/Site/TOKEN?e=code) or a direct document URL. Omit if supplying driveId and itemId. | |
| range | Yes | A1-style range, e.g. "A1:D20". | |
| sheet | Yes | Worksheet name. | |
| itemId | No | Item ID from resolve_link. Use with driveId. | |
| driveId | No | Drive ID from resolve_link. Use with itemId. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It adds meaningful behavioral details: 'raw values' (not formatted), and 'the range genuinely bounds what Graph transfers' (performance/scope). However, it doesn't mention potential errors, authentication requirements, or response structure, so it's not a perfect disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, each earning its place: purpose, use case, and a distinguishing comparison. No redundancy, and front-loaded with the primary action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool with no output schema, the description does not mention the return format, but the phrase 'raw values' gives a hint. It could be clearer about what the agent gets back, yet it covers selection and invocation well. Slight gap, but overall complete for the core use case.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds value by providing an explicit range example ('A1:D20') and explaining why the range is important in the context of non-standard layouts, going slightly beyond the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Read') and resource ('raw values for an explicit A1 range'), with a concrete example. It clearly distinguishes itself from siblings, especially get_permission_matrix, by stating the range bounds what Graph transfers.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool: 'when the sheet has a non-standard layout that the header-row model does not fit.' It also names an alternative (get_permission_matrix) and explains the key difference, providing clear selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_permission_matrixRead a permission matrixA
Read a worksheet as structured records, using the header row as keys. Note that maxRows/offset/filter/columns are applied AFTER the full sheet is fetched: they bound what you receive, not what is transferred. If the result is truncated, narrow it with filter or columns first, and only page with offset as a fallback.
| Name | Required | Description | Default |
|---|---|---|---|
| link | No | SharePoint sharing link (…/:x:/s/Site/TOKEN?e=code) or a direct document URL. Omit if supplying driveId and itemId. | |
| sheet | No | Worksheet name. Defaults to the first sheet. | |
| filter | No | Server-side row filter, applied before maxRows. | |
| itemId | No | Item ID from resolve_link. Use with driveId. | |
| offset | No | Records to skip. Default 0. | |
| columns | No | Return only these columns. Greatly reduces payload on wide matrices. | |
| driveId | No | Drive ID from resolve_link. Use with itemId. | |
| maxRows | No | Maximum records to return. Default 500. | |
| headerRow | No | 1-indexed header row. Default 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavioral disclosure. It explicitly discloses a non-obvious performance behavior: 'maxRows/offset/filter/columns are applied AFTER the full sheet is fetched.' This adds significant context beyond the schema and helps the agent anticipate resource usage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, both essential. The first states the core purpose; the second provides crucial behavioral guidance. No filler or redundancy. The most important caveat is front-loaded in the second sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 9 parameters and no output schema, the description covers the core purpose, return shape (structured records with header row keys), and the most impactful performance caveat. It could mention explicit return field structure or error cases, but the essential context for correct invocation is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value by explaining how the key parameters interact: 'maxRows/offset/filter/columns are applied AFTER the full sheet is fetched.' This synthesizes the individual parameter descriptions and reveals the ordering semantics, which is not immediately obvious from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource: 'Read a worksheet as structured records, using the header row as keys.' This distinguishes it from siblings like get_cell_range (raw cells) and describe_sheet (structure) by emphasizing structured row/record output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage guidance on handling truncation: 'If the result is truncated, narrow it with `filter` or `columns` first, and only page with `offset` as a fallback.' This tells the agent how to use the tool effectively in a common scenario, though it does not explicitly mention when to use this tool over siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_excel_sheetsList worksheetsA
List the worksheet names in a SharePoint-hosted Excel workbook.
| Name | Required | Description | Default |
|---|---|---|---|
| link | No | SharePoint sharing link (…/:x:/s/Site/TOKEN?e=code) or a direct document URL. Omit if supplying driveId and itemId. | |
| itemId | No | Item ID from resolve_link. Use with driveId. | |
| driveId | No | Drive ID from resolve_link. Use with itemId. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, and the description does not disclose any behavioral details beyond the primary read operation. It does not mention authentication requirements, side effects, or error conditions. However, for a simple list operation, the behavior is self-evident, so this is adequate but not comprehensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is one sentence, front-loaded with the verb and resource, and contains no unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple with three optional parameters and no output schema. The description explains the primary function and implies the return of worksheet names. It does not explicitly describe the output format or the requirement to supply either link or driveId/itemId, but these are covered in the schema. Overall, it is sufficient for a basic list operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides 100% coverage of the three parameters with clear descriptions. The tool description adds no additional parameter semantics beyond the schema, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the action (list) and the resource (worksheet names in a SharePoint-hosted Excel workbook), distinguishing it from sibling tools like describe_sheet or get_cell_range.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a caller needs worksheet names, but it does not explicitly state when to prefer this over resolve_link or describe_sheet, nor any exclusions. The usage context is clear from the purpose, so an agent can infer when to call it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resolve_linkResolve a SharePoint linkA
Convert a SharePoint sharing link or document URL into stable driveId/itemId values. Call this once and reuse the IDs: sharing links can expire or be revoked, and resolving them costs an extra Graph round trip on every call.
| Name | Required | Description | Default |
|---|---|---|---|
| link | Yes | SharePoint sharing link or direct document URL. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It adds valuable context: links can expire/be revoked, resolving costs a round trip, and the returned IDs are stable. It doesn't cover failure modes or auth requirements, but the key behavioral traits are disclosed, exceeding a bare description.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, then a succinct rationale for reuse. No fluff or redundancy; every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter tool with no output schema, the description is quite complete: it explains the input, output, and usage context. It could mention error handling (e.g., invalid link) but is otherwise coherent and sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description for 'link' is 100% covered ('SharePoint sharing link or direct document URL'). The description reinforces this and adds the purpose of stable IDs, but it doesn't provide format examples or constraints beyond the schema. Baseline of 3 is appropriate as the schema already documents the parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Convert' and the resource 'SharePoint sharing link or document URL' into 'driveId/itemId values'. This is specific and distinguishes it from sibling tools like list_excel_sheets or get_cell_range, which focus on sheet operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says 'Call this once and reuse the IDs' and explains why (links can expire, extra Graph round trip). This is clear usage guidance, though it doesn't mention explicit exclusions or alternatives. However, given the unique purpose, this is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
describe_sheet - First observed
get_cell_range - First observed
get_permission_matrix - First observed
list_excel_sheets - First observed
resolve_link
TDQS
Scored across 5 tools
Each tool addresses a distinct step in the workflow: resolve_link handles link-to-ID conversion, list_excel_sheets discovers sheets, describe_sheet inspects structure, get_permission_matrix reads structured data, and get_cell_range reads raw ranges. No two tools perform the same function.
All tool names follow the verb_noun snake_case pattern (resolve_link, list_excel_sheets, describe_sheet, get_permission_matrix, get_cell_range). The verbs clearly indicate the action, and naming is uniformly consistent.
Five tools is a well-scoped count for a focused Excel-reading server. Each tool covers a necessary operation without unnecessary bloat, and the set feels neither too thin nor too heavy.
The core read workflow is well-covered: resolving a link, listing sheets, inspecting structure, and reading data either as structured records or raw ranges. Minor gaps exist such as no write/update tools or a way to enumerate workbooks without a URL, but these appear outside the intended scope.
Maintenance
Related MCP Connectors
AI access to Quadratic spreadsheets: open files, run Python/SQL, query connected databases.
Connect AI assistants to Google Sheets through controlled tools for reading and updating rows.
Open, inspect, filter, edit and convert xlsx and csv files from your AI chat. Processing is local.
Permissioned access to Outlook, OneDrive and Teams via the user's own Microsoft account
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create, read, and manipulate Excel files without requiring Microsoft Excel installation. Supports comprehensive spreadsheet operations including formulas, formatting, charts, pivot tables, and data validation.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI models to search, read, and analyze Excel files from your local file system with support for multiple worksheets, text search, and JSON data conversion.4MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to create, read, and modify Excel workbooks without requiring Microsoft Excel, supporting operations like formulas, charts, pivot tables, formatting, and data validation.MIT
- AlicenseBqualityCmaintenanceEnables AI assistants to perform Excel file operations (create, read, write, format) without requiring Microsoft Excel installation.175MIT