@mrfentmen/excel-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Excel MCP
2
+
3
+ Create and read Excel workbooks on the local machine. No network, no key. Real xlsx files written to and read from disk.
4
+
5
+ This file is self contained. It reads public data only and never writes to the machine. All output is bounded and honest about what could not be fetched.
6
+
7
+ ## Tools
8
+
9
+
10
+ * `create_workbook` Create an xlsx workbook from rows.
11
+ * `read_workbook` Read the first rows of an existing workbook.
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ npm install
17
+ npm run build
18
+ node dist/index.js
19
+ ```
20
+
21
+ Output files are written to the system temp directory and the path is returned.
package/dist/api.js ADDED
@@ -0,0 +1,44 @@
1
+ import ExcelJS from "exceljs";
2
+ import { mkdtempSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ export class ExcelError extends Error {
6
+ }
7
+ function outPath(name) {
8
+ const safe = /^[\w.\- ]+$/.test(name) && name.endsWith(".xlsx") ? name : `workbook-${Date.now()}.xlsx`;
9
+ return join(mkdtempSync(join(tmpdir(), "xlsx-")), safe);
10
+ }
11
+ export async function createWorkbook(args) {
12
+ const wb = new ExcelJS.Workbook();
13
+ const ws = wb.addWorksheet(args.sheet_name ?? "Sheet1");
14
+ const lines = (args.rows ?? "").split("\n").map((l) => l.trim()).filter(Boolean);
15
+ if (lines.length === 0)
16
+ throw new ExcelError("Provide at least one row of comma separated values");
17
+ for (const line of lines.slice(0, 500)) {
18
+ const cells = line.split(",").map((c) => c.trim());
19
+ const nums = cells.map((c) => (/^-?\d+(\.\d+)?$/.test(c) ? Number(c) : c));
20
+ ws.addRow(nums);
21
+ }
22
+ const path = outPath(args.filename ?? `workbook-${Date.now()}.xlsx`);
23
+ await wb.xlsx.writeFile(path);
24
+ return `Created ${path} (${lines.length} rows)`;
25
+ }
26
+ export async function readWorkbook(args) {
27
+ const path = args.path ?? "";
28
+ if (!path)
29
+ throw new ExcelError("Provide a path to an xlsx file");
30
+ const wb = new ExcelJS.Workbook();
31
+ await wb.xlsx.readFile(path);
32
+ const ws = wb.worksheets[0];
33
+ if (!ws)
34
+ throw new ExcelError("The workbook has no sheets");
35
+ const max = Math.min(args.max_rows ?? 20, 100);
36
+ const out = [];
37
+ ws.eachRow({ includeEmpty: false }, (row, n) => {
38
+ if (n > max)
39
+ return;
40
+ const vals = row.values;
41
+ out.push(`${n}. ${vals.slice(1).map((v) => String(v)).join(" | ")}`);
42
+ });
43
+ return `${ws.name} (${ws.rowCount} rows)\n${out.join("\n")}`;
44
+ }
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { createServer } from "./server.js";
3
+ const main = async () => { const server = createServer(); await server.connect(new StdioServerTransport()); };
4
+ main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });
package/dist/server.js ADDED
@@ -0,0 +1,39 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { createWorkbook } from "./api.js";
4
+ import { readWorkbook } from "./api.js";
5
+ const text = (value) => ({ content: [{ type: "text", text: value }] });
6
+ const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
7
+ const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
8
+ const WRITE = { readOnlyHint: false, openWorldHint: true };
9
+ const error = (e) => `Error: ${e instanceof Error ? e.message : String(e)}`;
10
+ export function createServer() {
11
+ const server = new McpServer({ name: "excel-mcp", version: "1.0.0" });
12
+ server.registerTool("create_workbook", {
13
+ title: "Create workbook",
14
+ description: "Create an xlsx workbook from rows of comma separated values.",
15
+ inputSchema: z.object({ sheet_name: z.string().describe("Sheet name.").optional(), rows: z.string().describe("Newline separated rows, each comma separated."), filename: z.string().describe("Output file name.").optional() }),
16
+ annotations: WRITE,
17
+ }, async (args) => {
18
+ try {
19
+ return text(await createWorkbook(args));
20
+ }
21
+ catch (e) {
22
+ return textError(error(e));
23
+ }
24
+ });
25
+ server.registerTool("read_workbook", {
26
+ title: "Read workbook",
27
+ description: "Read the first rows of an xlsx workbook from a path.",
28
+ inputSchema: z.object({ path: z.string().describe("Path to the xlsx file."), max_rows: z.number().describe("Max rows to read.").optional() }),
29
+ annotations: READ_ONLY,
30
+ }, async (args) => {
31
+ try {
32
+ return text(await readWorkbook(args));
33
+ }
34
+ catch (e) {
35
+ return textError(error(e));
36
+ }
37
+ });
38
+ return server;
39
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "type": "module",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/mrfentmen/excel-mcp.git"
7
+ },
8
+ "bin": {
9
+ "excel-mcp": "./dist/index.js"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "files": [
13
+ "dist",
14
+ "server.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.json",
19
+ "start": "node dist/index.js",
20
+ "dev": "npm run build && node dist/index.js"
21
+ },
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.0.4",
25
+ "zod": "^3.23.8",
26
+ "pdf-lib": "^1.17.1",
27
+ "exceljs": "^4.4.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "typescript": "^5.6.0"
32
+ },
33
+ "name": "@mrfentmen/excel-mcp",
34
+ "description": "Create and edit Excel workbooks locally with rows and sheets. No network and no key.",
35
+ "mcpName": "io.github.mrfentmen/excel-mcp",
36
+ "keywords": [
37
+ "mcp",
38
+ "excel",
39
+ "spreadsheet",
40
+ "xlsx",
41
+ "sheet"
42
+ ],
43
+ "engines": {
44
+ "node": ">=20"
45
+ }
46
+ }
package/server.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.mrfentmen/excel-mcp",
4
+ "description": "Create and edit Excel workbooks locally with rows and sheets. No network and no key.",
5
+ "repository": {
6
+ "url": "https://github.com/mrfentmen/excel-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "1.0.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "@mrfentmen/excel-mcp",
14
+ "version": "1.0.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }