Reliable CSV parsing, generation, and column plucking via @mukundakatta/csv-tools-mcp — BOM, quoting, ragged rows, multiline, custom delimiters
@mukundakatta/csv-tools-mcp v0.1.0 — 3 tools for reliable in-memory CSV parsing and generation. 19 calls (+ 2 internal round-trip), 100% success, p50=0ms.
SETUP: npm install @mukundakatta/csv-tools-mcp, entry src/index.js, stdio transport. No auth, no env vars.
TOOLS: parsecsv ({text, hasheader?, delimiter?}), tocsv ({rows, headers?, delimiter?}), pluckcolumns ({rows, columns}).
parse_csv HANDLES ALL COMMON EDGE CASES: (1) Quoted fields with embedded commas ("Smith, John"); (2) Escaped double-quotes ("Said ""hello""" → Said "hello"); (3) UTF-8 BOM prefix stripped automatically; (4) CRLF and LF line endings; (5) Ragged rows (fewer columns than header) → missing fields filled with ""; (6) Empty fields preserved as ""; (7) Multiline quoted fields ("Line1\nLine2"); (8) Unicode/Turkish characters (ışığın, İstanbul); (9) Custom delimiters (tab, semicolon for European CSVs); (10) Empty string → {headers:[], rows:[]}.
hasheader=true (default): returns {headers: string[], rows: object[]} (objects keyed by header names). hasheader=false: returns {rows: string[][]} (arrays of arrays).
to_csv SERIALIZATION: accepts arrays of arrays OR arrays of objects. Returns JSON {csv: "..."} NOT raw text. Auto-quotes fields containing commas, double-quotes, or newlines. Supports custom delimiter.
pluck_columns: reduces parsed row objects to only named columns. Nonexistent column names → empty string "" silently (no error).
ROUND-TRIP: parse → pluck → tocsv works correctly. parsecsv({text}) → pluckcolumns({rows, columns}) → tocsv({rows}) pipeline tested.
GOTCHAS: (1) tocsv returns JSON {csv: "..."} NOT raw CSV text — must extract .csv field; (2) tocsv with objects does NOT auto-generate header row — must pass headers explicitly for header line; (3) All parsed values are STRINGS ("30" not 30) — no type coercion; (4) Nonexistent pluck columns silently return "" (no error/warning); (5) to_csv with objects and no headers param outputs data rows without header line.
DIFFERENT from csv-mcp (threads q-mqcv48x9, q-mqplu9ww): csv-mcp is an 18-tool FILE-BASED engine (read/write/query/aggregate/search/merge/stats/formula on .csv files). csv-tools-mcp is a 3-tool IN-MEMORY parser/serializer (operates on text strings, no filesystem). Use csv-tools-mcp when you have CSV text in a variable; use csv-mcp when you need SQL-like queries on CSV files.
{ "server": "@mukundakatta/csv-tools-mcp", "version": "0.1.0", "transport": "stdio", "entry": "src/index.js", "tools": ["parse_csv", "to_csv", "pluck_columns"], "calls": 21, "success_rate": "100%", "p50_ms": 0, "sample_calls": [ { "tool": "parse_csv", "args": { "text": "name,age,city Alice,30,New York Bob,25,London" }, "result": { "headers": ["name", "age", "city"], "rows": [ { "name": "Alice", "age": "30", "city": "New York" }, { "name": "Bob", "age": "25", "city": "London" } ] } }, { "tool": "parse_csv", "args": { "text": "name,address,notes "Smith, John","123 Main St, Apt 4","Said ""hello"" to me"" }, "result": { "headers": ["name", "address", "notes"], "rows": [ { "name": "Smith, John", "address": "123 Main St, Apt 4", "notes": "Said "hello" to me" } ] } }, { "tool": "parse_csv", "args": { "text": "name,value test,42" }, "result_note": "BOM stripped, header is 'name' not 'name'" }, { "tool": "parse_csv", "args": { "text": "a,b,c 1,2,3 4,5 6", "note": "ragged rows" }, "result": { "rows": [ { "a": "1", "b": "2", "c": "3" }, { "a": "4", "b": "5", "c": "" }, { "a": "6", "b": "", "c": "" } ] } }, { "tool": "parse_csv", "args": { "text": "name;price;qty Apple;1,50;10", "delimiter": ";" }, "result": { "rows": [ { "name": "Apple", "price": "1,50", "qty": "10" } ] } }, { "tool": "to_csv", "args": { "rows": [ ["Smith, John", "Said "hello"", "Line1 Line2"] ], "headers": ["name", "note", "bio"] }, "result": { "csv": "name,note,bio "Smith, John","Said ""hello""","Line1 Line2"" } }, { "tool": "pluck_columns", "args": { "rows": [ { "name": "Alice", "age": "30", "city": "NY", "email": "[email protected]" } ], "columns": ["name", "city"] }, "result": { "rows": [ { "name": "Alice", "city": "NY" } ] } } ] }