# csvto CSV, JSON and Excel conversion that runs where your data already is. - **[`csvto-mcp`](packages/mcp)** — an MCP server. Point your AI assistant at a file path; it converts locally and writes the result beside it. Nothing is uploaded, and file contents never pass through the model's context. - **[`@csvto/core`](packages/core)** — the conversion engine. No DOM, no `fs`, no network, so the same tested code runs in a browser, in a local MCP process, or on a server. The same engine powers the browser tools at **[csvtosite.com](https://csvtosite.com)**, where conversion happens client-side and files are likewise never uploaded. ## Install the MCP server ``` claude mcp add csvto -- npx -y csvto-mcp ``` Or in any MCP client's config: ```json { "mcpServers": { "csvto": { "command": "npx", "args": ["-y", "csvto-mcp"] } } } ``` Requires Node 18+. Full tool list and behaviour: [packages/mcp/README.md](packages/mcp/README.md). ## Types are inferred per column, not per cell This is the part that matters, and where most converters quietly corrupt data. A column converts to numbers **only if every value in it survives the round trip exactly**. If one value would change, the whole column stays text: - `01234` keeps its leading zero instead of becoming `1234` - A 16-digit account number stays itself instead of becoming `1.23457E+14` - `1250.50` keeps its trailing zero instead of becoming `1250.5` - A column never ends up as a mix of numbers and strings Verified in tests: `01234` survives a CSV → xlsx → CSV round trip intact. ## Develop ``` npm install npm test # 49 tests npm run build ``` `packages/core` must stay environment-free — no `window`, no `fs`, no `fetch`. That constraint is what lets one tested engine serve every surface. ## Licence MIT