Skip to main content
Glama
cablate

Simple Document Processing MCP Server

excel_read

Convert Excel files to structured JSON format to extract and process spreadsheet data programmatically.

Instructions

Read Excel file and convert to JSON format while preserving structure

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
inputPathYesPath to the input Excel file
includeHeadersNoWhether to include headers in the output

Implementation Reference

  • The async handler function that implements the core logic for reading Excel files, parsing sheets into JSON structure, handling headers, and returning success/error responses.
    export async function readExcelFile(inputPath: string, includeHeaders: boolean = true) {
      try {
        // 驗證檔案存在
        if (!fs.existsSync(inputPath)) {
          return {
            success: false,
            error: `File not found: ${inputPath}`,
          };
        }
    
        // 驗證檔案副檔名
        const ext = path.extname(inputPath).toLowerCase();
        if (ext !== ".xlsx" && ext !== ".xls") {
          return {
            success: false,
            error: `Unsupported file format: ${ext}`,
          };
        }
    
        console.log(`Reading Excel file: ${inputPath}`);
        const workbook = new ExcelJS.Workbook();
        await workbook.xlsx.readFile(inputPath);
    
        const result: Record<string, any[]> = {};
    
        workbook.worksheets.forEach((worksheet) => {
          const sheetName = worksheet.name;
          const rows: any[] = [];
    
          worksheet.eachRow((row, rowNumber) => {
            const rowData: Record<number, any> = {};
            row.eachCell((cell, colNumber) => {
              if (includeHeaders && rowNumber === 1) {
                rows.push(cell.value);
              } else {
                rowData[colNumber] = cell.value;
              }
            });
            if (rowNumber > 1 || !includeHeaders) {
              rows.push(rowData);
            }
          });
    
          result[sheetName] = rows;
        });
    
        console.log(`Successfully parsed Excel file: ${inputPath}`);
        return {
          success: true,
          data: result,
        };
      } catch (error: unknown) {
        const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
        console.error(`Error processing Excel file: ${errorMessage}`);
        return {
          success: false,
          error: errorMessage,
        };
      }
    }
  • Tool definition with inputSchema, TypeScript interface for args, and runtime validator function isExcelReadArgs.
    export const EXCEL_READ_TOOL: Tool = {
      name: "excel_read",
      description: "Read Excel file and convert to JSON format while preserving structure",
      inputSchema: {
        type: "object",
        properties: {
          inputPath: {
            type: "string",
            description: "Path to the input Excel file",
          },
          includeHeaders: {
            type: "boolean",
            description: "Whether to include headers in the output",
            default: true,
          },
        },
        required: ["inputPath"],
      },
    };
    
    export interface ExcelReadArgs {
      inputPath: string;
      includeHeaders?: boolean;
    }
    
    // 類型檢查函數
    export function isExcelReadArgs(args: unknown): args is ExcelReadArgs {
      return typeof args === "object" && args !== null && "inputPath" in args && typeof (args as ExcelReadArgs).inputPath === "string" && (typeof (args as ExcelReadArgs).includeHeaders === "undefined" || typeof (args as ExcelReadArgs).includeHeaders === "boolean");
    }
  • Imports EXCEL_READ_TOOL and includes it in the exported tools array used for MCP ListTools response.
    import { EXCEL_READ_TOOL } from "./excelTools.js";
    import { FORMAT_CONVERTER_TOOL } from "./formatConverterPlus.js";
    import { HTML_CLEAN_TOOL, HTML_EXTRACT_RESOURCES_TOOL, HTML_FORMAT_TOOL, HTML_TO_MARKDOWN_TOOL, HTML_TO_TEXT_TOOL } from "./htmlTools.js";
    import { PDF_MERGE_TOOL, PDF_SPLIT_TOOL } from "./pdfTools.js";
    import { TEXT_DIFF_TOOL, TEXT_ENCODING_CONVERT_TOOL, TEXT_FORMAT_TOOL, TEXT_SPLIT_TOOL } from "./txtTools.js";
    
    export const tools = [DOCUMENT_READER_TOOL, PDF_MERGE_TOOL, PDF_SPLIT_TOOL, DOCX_TO_PDF_TOOL, DOCX_TO_HTML_TOOL, HTML_CLEAN_TOOL, HTML_TO_TEXT_TOOL, HTML_TO_MARKDOWN_TOOL, HTML_EXTRACT_RESOURCES_TOOL, HTML_FORMAT_TOOL, TEXT_DIFF_TOOL, TEXT_SPLIT_TOOL, TEXT_FORMAT_TOOL, TEXT_ENCODING_CONVERT_TOOL, EXCEL_READ_TOOL, FORMAT_CONVERTER_TOOL];
  • Exports the partial Tool object for excel_read which is included in the tools list.
    export const EXCEL_READ_TOOL: Tool = {
      name: "excel_read",
      description: "Read Excel file and convert to JSON format while preserving structure",
      inputSchema: {
        type: "object",
        properties: {
          inputPath: {
            type: "string",
            description: "Path to the input Excel file",
          },
          includeHeaders: {
            type: "boolean",
            description: "Whether to include headers in the output",
            default: true,
          },
        },
        required: ["inputPath"],
      },
    };
  • Supporting static class method for reading Excel files, similar to the main handler but without the success/error wrapper and with additional options.
    export class ExcelTools {
      /**
       * Reads an Excel file and returns its content as JSON
       * @param filePath Path to the Excel file
       * @param options Processing options
       * @returns Promise resolving to the parsed Excel data
       */
      public static async readExcelFile(filePath: string, options: ExcelProcessOptions = { includeHeaders: true }): Promise<any> {
        try {
          // Verify file exists
          if (!fs.existsSync(filePath)) {
            throw new Error(`File not found: ${filePath}`);
          }
    
          // Verify file extension
          const ext = path.extname(filePath).toLowerCase();
          if (ext !== ".xlsx" && ext !== ".xls") {
            throw new Error(`Unsupported file format: ${ext}`);
          }
    
          console.log(`Reading Excel file: ${filePath}`);
          const workbook = new ExcelJS.Workbook();
          await workbook.xlsx.readFile(filePath);
    
          const result: any = {};
    
          workbook.worksheets.forEach((worksheet) => {
            const sheetName = worksheet.name;
            const rows: any[] = [];
    
            worksheet.eachRow((row, rowNumber) => {
              const rowData: any = {};
              row.eachCell((cell, colNumber) => {
                if (options.includeHeaders && rowNumber === 1) {
                  // Handle headers
                  rows.push(cell.value);
                } else {
                  // Handle data rows
                  rowData[colNumber] = cell.value;
                }
              });
              if (rowNumber > 1 || !options.includeHeaders) {
                rows.push(rowData);
              }
            });
    
            result[sheetName] = rows;
          });
    
          console.log(`Successfully parsed Excel file: ${filePath}`);
          return result;
        } catch (error: any) {
          console.error(`Error processing Excel file: ${error.message}`);
          throw error;
        }
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions reading and converting to JSON while preserving structure, but fails to address critical aspects like error handling (e.g., invalid file paths, unsupported Excel versions), performance implications (e.g., large file handling), or output specifics (e.g., JSON schema, nesting). This leaves significant gaps for a tool that performs file I/O and data transformation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's function without unnecessary words. It is front-loaded with the core action and outcome, making it easy to parse quickly. Every part of the sentence contributes essential information, earning its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of reading and converting Excel files to JSON, the description is insufficient. With no annotations and no output schema, it lacks details on behavioral traits (e.g., error handling, performance), output format (e.g., JSON structure), and usage context. This leaves the agent under-informed for a tool that involves file processing and data transformation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with clear documentation for both parameters ('inputPath' and 'includeHeaders'). The description adds no additional parameter semantics beyond what the schema provides, such as explaining what 'preserving structure' entails or how headers affect the JSON output. Thus, it meets the baseline for adequate but unenriched parameter context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Read Excel file and convert to JSON format') and the resource ('Excel file'), making the purpose immediately understandable. However, it doesn't explicitly differentiate this tool from sibling tools like 'format_convert' or 'document_reader', which might also handle file format conversions, leaving some ambiguity about when to choose this specific tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, such as sibling tools like 'format_convert' or 'document_reader'. It lacks context about prerequisites, file formats supported, or scenarios where this tool is preferred, leaving the agent to infer usage based on the tool name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/cablate/mcp-doc-forge'

If you have feedback or need assistance with the MCP directory API, please join our Discord server