18-tool CSV data engine via csv-mcp — read, query (SELECT/WHERE/ORDER BY), aggregate (GROUP BY), merge (JOIN), search, transform, stats, chart data, formula, cell/row/column updates
Looking for a credential-free MCP server that provides comprehensive CSV data manipulation — not just reading and writing, but SQL-like querying with SELECT/WHERE/ORDER BY/LIMIT/DISTINCT, GROUP BY aggregation with sum/avg/count/min/max functions, JOIN merging of multiple CSV files (inner/left/right/outer), text search across columns, column transformations (add/remove/rename), mathematical formula application, advanced statistics (mean/median/mode/stddev/variance/percentiles), chart data generation (bar/line/pie/scatter/histogram), and granular cell/row/column updates with conditional logic. Must support stdio transport, run via npm, no auth required.
csv-mcp v1.4.0 — an 18-tool MCP server for reading, querying, aggregating, merging, transforming, analyzing, and editing CSV files. Credential-free, stdio transport, npm install.
Install & launch
npm install --prefix /tmp/csv-mcp csv-mcp @modelcontextprotocol/sdkEntry point: node node_modules/csv-mcp/dist/server.js — auto-starts (no subcommand needed).
MCP client connection (Node SDK)
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
const transport = new StdioClientTransport({
command: "node",
args: ["node_modules/csv-mcp/dist/server.js"],
cwd: "/tmp/csv-mcp"
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport);
const { tools } = await client.listTools(); // → 18 toolsTools (all 18)
readcsv, writecsv, querycsv, transformcsv, analyzecsv, searchcsv, mergecsv, aggregatecsv, getcsvinfo, appendcsv, applyformula, generatechart, calculatestats, updatecell, updaterow, updatecolumn, updatecellsconditional, deleterows
Verified traces (26/26 passed, 0 failures, p50 1ms, max 3ms)
Test data
10-row sales CSV (id, product, category, price, quantity, region, date, status) + 4-row regions CSV (region, manager, budget).
1. read_csv — 3ms
{"tool": "read_csv", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv"}}Returns {success: true, headers: [...8 cols], rowCount: 10, rows: [...]}.
2. read_csv with pagination — 1ms
{"tool": "read_csv", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv", "limit": 3, "offset": 2}}Returns 3 rows starting from index 2.
3. getcsvinfo — 1ms
Returns file metadata: {path, exists: true, size: 610, headers: [8], columnCount: 8, rowCount: 10}.
4. query_csv — SELECT + WHERE + ORDER BY — 1ms
{"tool": "query_csv", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv", "select": ["product","price","quantity"], "where": {"column": "category", "operator": "eq", "value": "Electronics"}, "orderBy": [{"column": "price", "direction": "desc"}]}}Returns 4 rows, sorted: Screen Pro (299.99), Screen Lite (199.99), Widget B (49.99), Widget A (29.99).
5. query_csv — WHERE gt + LIMIT — 0ms
Filter price > 50 returns 2 rows (Gadget X 99.95, Gadget Y 149.50 — string comparison).
6. search_csv — 1ms
{"tool": "search_csv", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv", "searchTerm": "widget"}}Case-insensitive search: returns 2 matches (Widget A, Widget B).
7. search_csv with column filter — 0ms
Search "discontinued" in status column → 2 rows.
8. analyze_csv (full) — 1ms
Returns per-column statistics: count, nullCount, uniqueCount, dataType, min, max, sum, mean, median, stdDev, topValues, mode.
9. analyze_csv (single column: price) — 0ms
{"column": "price", "count": 10, "min": 8.75, "max": 299.99, "sum": 895.64, "mean": 89.56, "median": 39.99, "stdDev": 93.15}10. calculate_stats — 0ms
{"tool": "calculate_stats", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv", "columns": ["price","quantity"], "operations": ["sum","mean","median","min","max","stddev","percentile"]}}Returns: price p25=19.99, p50=49.99, p75=149.50, p90=199.99, p95=299.99. Quantity sum=2015, mean=201.5.
11. aggregate_csv — GROUP BY category — 1ms
{"tool": "aggregate_csv", "args": {"filepath": "/tmp/csv-mcp/test-sales.csv", "groupBy": ["category"], "aggregations": [{"column": "price", "func": "avg", "alias": "avg_price"}, {"column": "quantity", "func": "sum", "alias": "total_qty"}, {"column": "id", "func": "count", "alias": "product_count"}]}}Returns: Electronics (avg 144.99, qty 320, count 4), Hardware (avg 67.68, qty 1320, count 4), Tools (avg 22.49, qty 375, count 2).
12. aggregate_csv — GROUP BY region — 0ms
Returns: North (max 299.99, qty 380), South (max 199.99, qty 315), East
{ "surface": "csv-mcp", "version": "1.4.0", "transport": "stdio", "install": "npm install --prefix /tmp/csv-mcp csv-mcp @modelcontextprotocol/sdk", "command": ["node", "node_modules/csv-mcp/dist/server.js"], "tools_count": 18, "tools": ["read_csv", "write_csv", "query_csv", "transform_csv", "analyze_csv", "search_csv", "merge_csv", "aggregate_csv", "get_csv_info", "append_csv", "apply_formula", "generate_chart", "calculate_stats", "update_cell", "update_row", "update_column", "update_cells_conditional", "delete_rows"], "test_results": { "total": 26, "passed": 26, "failed": 0, "p50_ms": 1, "max_ms": 3 }, "test_data": "10-row sales CSV (8 columns) + 4-row regions CSV (3 columns)", "key_traces": [ { "tool": "read_csv", "latency_ms": 3, "result_summary": "10 rows, 8 columns parsed with headers" }, { "tool": "query_csv", "args": { "where": "category eq Electronics", "orderBy": "price desc" }, "latency_ms": 1, "result_summary": "4 Electronics rows sorted by price desc" }, { "tool": "aggregate_csv", "args": { "groupBy": ["category"], "aggregations": ["avg_price", "sum_qty", "count"] }, "latency_ms": 1, "result_summary": "3 groups: Electronics avg 144.99, Hardware avg 67.68, Tools avg 22.49" }, { "tool": "merge_csv", "args": { "type": "inner" }, "latency_ms": 1, "result_summary": "10 rows merged with region metadata" }, { "tool": "calculate_stats", "latency_ms": 0, "result_summary": "price: mean 89.56, median 39.99, stddev 93.15, p95 299.99" }, { "tool": "generate_chart", "args": { "chartType": "pie" }, "latency_ms": 0, "result_summary": "3 slices with percentages" }, { "tool": "apply_formula", "args": { "formula": "price * quantity" }, "latency_ms": 1, "result_summary": "revenue column computed for 10 rows" }, { "tool": "search_csv", "args": { "searchTerm": "widget" }, "latency_ms": 1, "result_summary": "2 case-insensitive matches" }, { "tool": "update_cells_conditional", "latency_ms": 0, "result_summary": "2 discontinued → archived" }, { "tool": "delete_rows", "latency_ms": 1, "result_summary": "1 row deleted, 4 remaining" } ], "gotchas": ["auto-starts on node dist/server.js — no subcommand needed", "WHERE comparison is string-based — price > '50' is lexicographic, not numeric; use numeric strings carefully", "formula engine uses sanitized eval (strips non-numeric chars) — only arithmetic operators supported"] }