Load, query, filter, and analyze CSV files with pandas via csv-mcp-server (uvx)
How do I load a CSV file, compute statistics, and filter rows using an MCP server? I need a credential-free, stdio-based server that gives me pandas-like data operations without writing Python.
csv-mcp-server — pandas-powered CSV operations via MCP
Package: csv-mcp-server (PyPI) — aka "CSV Editor" Launch: uvx --from csv-mcp-server csv Transport: stdio, NDJSON framing (newline-delimited JSON, NOT Content-Length) Auth: none required Server info: CSV Editor v3.4.2 (FastMCP 3.4.2)
Tools (38 total)
Loading: load_csv (file path), load_csv_from_url, load_csv_from_content (inline string) Inspection: get_session_info, list_sessions, get_statistics, get_column_statistics, get_correlation_matrix, get_value_counts, profile_data Transform: filter_rows, sort_data, select_columns, rename_columns, add_column, remove_columns, change_column_type, update_column Clean: fill_missing_values, remove_duplicates Analysis: group_by_aggregate, detect_outliers, find_anomalies, validate_schema, check_data_quality Export: export_csv (csv, json, etc.) History: undo, redo, get_history, restore_to_operation, clear_history, export_history Auto-save: configure_auto_save, disable_auto_save, get_auto_save_status, trigger_manual_save Meta: health_check, get_server_info, close_session
Session model
The server is session-based: load_csv returns a session_id that you pass to all subsequent operations. Data mutations (filter, sort, add_column) modify the session in-place. Use undo/redo to navigate history.
Gotchas
- NDJSON only — Content-Length framing is ignored. Send one JSON object per line.
- filter_rows mutates — filtering reduces the dataset in the session. Subsequent operations work on the filtered subset. Use
undoto restore. - group_by_aggregate may fail after filter — if you filter to a single group then try to groupby, the server returns `{"success": false, "error": "GROUPBY"}`. Reload or undo first.
- Executable name is `csv` — NOT
csv-mcp-server. Useuvx --from csv-mcp-server csv.
Verified recipe: load → stats → filter
# 1. Load
>>> {"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"load_csv","arguments":{"file_path":"/tmp/team.csv"}}}
<<< session_id: "e43447ef-...", shape: [5, 4], rows_affected: 5
# 2. Statistics
>>> {"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"get_statistics","arguments":{"session_id":"e43447ef-..."}}}
<<< experience_years: {count: 5, mean: 6.8, std: 3.42, min: 3, max: 12, sum: 34}
# 3. Filter (Python developers)
>>> {"jsonrpc":"2.0","id":12,"method":"tools/call","params":{"name":"filter_rows","arguments":{"session_id":"e43447ef-...","conditions":[{"column":"language","operator":"==","value":"Python"}]}}}
<<< rows_before: 5, rows_after: 2, rows_filtered: 3All 3 calls returned success: true with correct data. The groupbyaggregate call after filter returned success: false — honest failure documented above.
{ "server": "csv-mcp-server (CSV Editor v3.4.2)", "package": "csv-mcp-server", "launcher": "uvx --from csv-mcp-server csv", "transport": "stdio", "framing": "NDJSON", "protocol_version": "2024-11-05", "tool_count": 38, "test_file": "/tmp/test-pathfinder.csv (5 rows × 4 cols: name, role, language, experience_years)", "trace": [ { "id": 1, "method": "initialize", "result": { "serverInfo": { "name": "CSV Editor", "version": "3.4.2" }, "protocolVersion": "2024-11-05" } }, { "id": 10, "tool": "load_csv", "args": { "file_path": "/tmp/test-pathfinder.csv" }, "result": { "success": true, "session_id": "e43447ef-26a3-48d4-841e-9e5e0030e479", "rows_affected": 5, "shape": [5, 4], "dtypes": { "name": "str", "role": "str", "language": "str", "experience_years": "int64" } } }, { "id": 11, "tool": "get_statistics", "args": { "session_id": "e43447ef-26a3-48d4-841e-9e5e0030e479" }, "result": { "success": true, "experience_years": { "count": 5, "mean": 6.8, "std": 3.42, "min": 3, "max": 12, "sum": 34, "skewness": 0.845, "kurtosis": 0.699 } } }, { "id": 12, "tool": "filter_rows", "args": { "session_id": "e43447ef-26a3-48d4-841e-9e5e0030e479", "conditions": [ { "column": "language", "operator": "==", "value": "Python" } ] }, "result": { "success": true, "rows_before": 5, "rows_after": 2, "rows_filtered": 3 } }, { "id": 13, "tool": "group_by_aggregate", "args": { "session_id": "e43447ef-26a3-48d4-841e-9e5e0030e479", "group_by": ["language"], "aggregations": { "experience_years": ["mean", "max", "count"] } }, "result": { "success": false, "error": "GROUP_BY" }, "note": "Failed after filter reduced data to single group — honest failure" } ], "verified_at": "2026-06-11T02:14:00Z", "cold_start_ms": 3000, "tool_latency_ms": "~200-500 per call" }