Skip to main content
Glama
marekrost

mcp-server-spreadsheet

sql_query

Execute SQL SELECT queries on spreadsheet data to analyze, filter, and join information across sheets using a database-like interface.

Instructions

Execute a read-only SQL SELECT query against the spreadsheet data.

Every sheet in the workbook is loaded as a database table, with the header row defining column names and data rows below it. Returns results as a list of {column: value} objects.

Only SELECT (and WITH ... SELECT) statements are accepted. Use sql_execute for INSERT, UPDATE, or DELETE.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
fileYesPath to the spreadsheet file
sqlYesSQL SELECT statement to execute. Each sheet is a table (quote names with double quotes if they contain spaces). Supports WHERE, ORDER BY, LIMIT, GROUP BY, HAVING, JOINs across sheets, DISTINCT, UNION, subqueries, and aggregates (COUNT, SUM, AVG, MIN, MAX). Example: SELECT name, revenue FROM Sales WHERE status = 'Active' ORDER BY revenue DESC LIMIT 20
header_rowNo1-based row number containing column headers. Defaults to 1.

Implementation Reference

  • The `sql_query` tool is implemented here. It takes a spreadsheet file path and a SQL SELECT statement, loads the sheets into DuckDB, executes the query, and returns the results.
    def sql_query(
        file: Annotated[str, Field(description="Path to the spreadsheet file")],
        sql: Annotated[str, Field(description=(
            "SQL SELECT statement to execute. Each sheet is a table (quote names "
            "with double quotes if they contain spaces). "
            "Supports WHERE, ORDER BY, LIMIT, GROUP BY, HAVING, JOINs across "
            "sheets, DISTINCT, UNION, subqueries, and aggregates (COUNT, SUM, "
            "AVG, MIN, MAX). "
            "Example: SELECT name, revenue FROM Sales WHERE status = 'Active' "
            "ORDER BY revenue DESC LIMIT 20"
        ))],
        header_row: Annotated[int, Field(description="1-based row number containing column headers. Defaults to 1.")] = 1,
    ) -> list[dict]:
        """Execute a read-only SQL SELECT query against the spreadsheet data.
    
        Every sheet in the workbook is loaded as a database table, with the
        header row defining column names and data rows below it. Returns
        results as a list of {column: value} objects.
    
        Only SELECT (and WITH ... SELECT) statements are accepted. Use
        sql_execute for INSERT, UPDATE, or DELETE.
        """
        sql_stripped = sql.strip().rstrip(";")
        first_keyword = sql_stripped.split()[0].upper() if sql_stripped else ""
        if first_keyword not in ("SELECT", "WITH"):
            raise ValueError(
                "sql_query only accepts SELECT statements (or WITH ... SELECT). "
                "Use sql_execute for INSERT/UPDATE/DELETE."
            )
    
        wb = load_workbook(file)
        conn = _load_sheets_to_duckdb(wb, header_row)
    
        result = conn.execute(sql_stripped)
        columns = [desc[0] for desc in result.description]
        return [dict(zip(columns, row)) for row in result.fetchall()]
  • The `sql_query` function is registered as an MCP tool using the `@mcp.tool()` decorator.
    @mcp.tool()

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/marekrost/mcp-server-spreadsheet'

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