Make your excel as a database to query with SQL.
[δΈζ]
A Model Context Protocol (MCP) server that enables SQL querying of Excel files. Transform your Excel spreadsheets into queryable databases using familiar SQL syntax.
- SQL Query Support: Execute SELECT queries on Excel worksheets using standard SQL syntax
- Multiple Worksheet Support: Query different worksheets within the same Excel file
- Advanced SQL Operations: Support for WHERE clauses, ORDER BY, GROUP BY, aggregation functions, and more
- Field Validation: Clear error messages when SQL queries reference non-existent fields
- MCP Protocol: Seamlessly integrates with MCP-compatible clients
- Easy Installation: Install and run with a single npx command
npx @zhangzichao2008/mcp-excel-db@latest
npm install -g @zhangzichao2008/mcp-excel-db
mcp-excel-db
npm install @zhangzichao2008/mcp-excel-db
- TRAE/CURSOR/ClaudeCode MCP configuration
{
"mcpServers": {
"excel-db": {
"command": "npx",
"args": [
"-y",
"@zhangzichao2008/mcp-excel-db@latest"
]
}
}
}
The server runs on stdio and communicates using the Model Context Protocol:
npx @zhangzichao2008/mcp-excel-db@latest
The MCP server provides the following tools:
Execute SQL queries on Excel files. Each query requires specifying the file path.
Parameters:
sql
(string): SQL SELECT statementfilePath
(string): Path to the Excel file (.xlsx or .xls)
Example:
{
"sql": "SELECT * FROM Sheet1 WHERE age > 25 ORDER BY name",
"filePath": "/path/to/your/spreadsheet.xlsx"
}
Special SQL Commands:
- Use
DESCRIBE tablename
to get column information for a worksheet - Example:
DESCRIBE Sheet1
returns column names and data types
Get basic information about all worksheets in an Excel file (lightweight operation).
Parameters:
filePath
(string): Path to the Excel file (.xlsx or .xls)
Returns:
- List of worksheet names
Example:
{
"filePath": "/path/to/your/spreadsheet.xlsx"
}
Note: For performance reasons, this method does not return row count information. To get the specific row count, use SQL query: SELECT COUNT(*) FROM SheetName
Get column information for worksheets in an Excel file (lightweight operation).
Parameters:
filePath
(string): Path to the Excel file (.xlsx or .xls)worksheetName
(string, optional): Specific worksheet name to get columns for
Returns:
- Worksheet names and their column lists
Example:
{
"filePath": "/path/to/your/spreadsheet.xlsx",
"worksheetName": "Sheet1"
}
SELECT * FROM Sheet1;
SELECT name, age, salary FROM employees WHERE age > 30;
SELECT * FROM products ORDER BY price DESC;
SELECT department, COUNT(*) as employee_count, AVG(salary) as avg_salary
FROM employees
GROUP BY department;
SELECT category, SUM(quantity) as total_quantity
FROM inventory
WHERE status = 'active'
GROUP BY category
ORDER BY total_quantity DESC;
-- Filter by multiple values
SELECT * FROM products WHERE category IN ('Electronics', 'Books', 'Clothing');
-- Exclude multiple values
SELECT * FROM employees WHERE department NOT IN ('HR', 'Finance');
-- Complex conditions with IN
SELECT name, price FROM products
WHERE category IN ('A', 'B') AND price > 100;
SELECT a.name, a.price FROM Sheet1 AS a WHERE a.price > 10;
-- LEFT JOIN between worksheets
SELECT a.name, a.price, b.supplier
FROM Sheet1 AS a
LEFT JOIN Sheet2 AS b ON a.id = b.sheet1_id;
-- INNER JOIN between worksheets
SELECT a.*, b.rating
FROM products AS a
INNER JOIN suppliers AS b ON a.supplier_id = b.id;
-- CROSS JOIN between worksheets (Cartesian product)
SELECT a.name, b.category
FROM Sheet1 AS a
CROSS JOIN Sheet2 AS b;
-- UNION: Combine results and remove duplicates
SELECT name FROM employees_2023
UNION
SELECT name FROM employees_2024;
-- UNION ALL: Combine results keeping duplicates
SELECT product_name FROM orders_q1
UNION ALL
SELECT product_name FROM orders_q2;
-- Multiple UNION operations
SELECT customer_id, amount FROM orders_2023
UNION
SELECT customer_id, amount FROM orders_2024
UNION ALL
SELECT customer_id, amount FROM orders_2025;
-- String manipulation functions
SELECT
LENGTH(name) as name_length,
UPPER(category) as upper_category,
LOWER(description) as lower_desc,
TRIM(notes) as clean_notes,
SUBSTR(name, 1, 3) as name_prefix,
REPLACE(description, 'old', 'new') as updated_desc
FROM products;
-- The system now validates field existence and returns clear error messages
SELECT non_existent_field FROM Sheet1;
-- Error: Field "non_existent_field" does not exist in table "Sheet1"
SELECT name, typo_field FROM Sheet1 WHERE non_existent_column = 'value';
-- Error: Field "typo_field" does not exist in table "Sheet1"
SELECT * FROM Sheet1 ORDER BY wrong_column_name;
-- Error: Field "wrong_column_name" does not exist in table "Sheet1"
-- Mathematical operations
SELECT
ABS(profit) as absolute_profit,
ROUND(price, 2) as rounded_price,
CEIL(rating) as ceiling_rating,
FLOOR(discount) as floor_discount,
RANDOM() as random_number
FROM products;
DESCRIBE Sheet1;
Note: All SQL queries now require specifying the filePath
parameter when using the MCP tools. The Excel file is loaded and processed for each query, ensuring you always work with the latest data.
- Column selection (
SELECT col1, col2
) - Wildcard selection (
SELECT *
) - Column aliases (
SELECT col1 AS alias
)
- Comparison operators (
=
,>
,<
,>=
,<=
,!=
,<>
) - Pattern matching (
LIKE
with%
wildcards) - Logical operators (
AND
,OR
,NOT
) - NULL checks (
IS NULL
,IS NOT NULL
) - List membership (
IN
,NOT IN
) - Check if value exists in a list of values
- Table aliases (
FROM Sheet1 AS a
) - Column references with aliases (
a.column_name
)
LEFT JOIN
- Left outer join between worksheetsINNER JOIN
- Inner join between worksheetsRIGHT JOIN
- Right outer join between worksheetsFULL OUTER JOIN
- Full outer join between worksheetsCROSS JOIN
- Cartesian product between worksheets- Join conditions with
ON
clause
LENGTH(str)
- Get string lengthUPPER(str)
- Convert to uppercaseLOWER(str)
- Convert to lowercaseTRIM(str)
- Remove leading and trailing spacesLTRIM(str)
- Remove leading spacesRTRIM(str)
- Remove trailing spacesSUBSTR(str, start, length)
- Extract substring (1-based indexing)INSTR(str, substr)
- Find substring position (1-based, returns 0 if not found)REPLACE(str, from_str, to_str)
- Replace substring
ABS(x)
- Absolute valueROUND(x, d)
- Round to d decimal placesCEIL(x)
/CEILING(x)
- Round up to nearest integerFLOOR(x)
- Round down to nearest integerRANDOM()
- Generate random integer
COUNT(*)
- Count all rowsCOUNT(column)
- Count non-null valuesSUM(column)
- Sum numeric valuesMAX(column)
- Find maximum valueMIN(column)
- Find minimum valueAVG(column)
- Calculate average value
ORDER BY
withASC
/DESC
GROUP BY
for aggregationDISTINCT
for unique valuesLIMIT
for result limitingUNION
andUNION ALL
for combining query results
- Only SELECT queries are supported (no INSERT, UPDATE, DELETE)
- No subqueries
- No HAVING clauses
- No UNION operations
- Limited comparison operators (supports
=
,!=
,<
,<=
, but not>
,>=
,IS NOT
) - Each query requires specifying the file path (no persistent file loading)
- For large files (>5MB), row counts are estimated using sampling for performance
git clone https://github.com/steven0lisa/mcp-excel-db.git
cd mcp-excel-db
npm install
npm run build
This project has two types of tests:
Run Jest unit tests for core functionality:
npm test
Run comprehensive feature tests for all SQL functionality:
npm run test:features
The feature tests validate all implemented SQL features including WHERE conditions, JOIN operations, string functions, math functions, and more. Each feature has its own test suite in the test/test-case/
directory.
npm run dev
mcp-excel-db/
βββ src/ # Source code
β βββ excel-sql-query.ts # Excel SQL query engine
β βββ mcp-server.ts # MCP server implementation
βββ test/ # Test files
βββ doc/ # Documentation
β βββ zh-cn/ # Chinese documentation
βββ dist/ # Compiled output
βββ package.json
βββ tsconfig.json
βββ README.md
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
If you encounter any issues or have questions, please open an issue on GitHub.
Made with β€οΈ by Zhang Zichao