Skip to content
devtoolbox.cc

json_convert MCP tool: JSON, YAML and CSV for AI agents

· 6 min read

Get the devtoolbox.cc MCP serverOpen the JSON / YAML / CSV tool

Converting a file between JSON, YAML and CSV looks like an easy job to hand an assistant, and the result usually looks right. The problems are in the details a model doesn’t check. In YAML 1.1 the bare word no is the boolean false, so a country code for Norway turns into false. In CSV a ZIP code like 01234 loses its leading zero once anyone treats it as a number. And a spreadsheet will run a cell starting with = as a formula.

The devtoolbox.cc MCP server includes json_convert, which does these conversions with real parsers and writers that know about those traps. It’s the converter behind the JSON / YAML / CSV tool on this site, packaged for assistants. Installation is on the MCP page.

What the converter handles

  • YAML output quotes every string that a YAML 1.1 reader would misread: no, yes, on, off, y, n, numbers with leading zeros, and anything else that looks like a number or a date.
  • YAML input supports anchors, aliases, merge keys (<<) and multiple documents. Alias expansion is limited, so a “billion laughs” file can’t blow up memory.
  • CSV follows RFC 4180: quotes, embedded commas and line breaks are handled properly, and the reading delimiter is detected automatically.
  • Nested JSON is flattened into a.b columns when writing CSV, and unflattened when reading it back. Alternatively, nested values can be kept as JSON text in one column.
  • Types are detected when reading CSV: unquoted 30, true and empty cells become numbers, booleans and null. Quoted cells always stay strings.
  • escape_formulas prefixes cells that start with =, +, - or @ with an apostrophe, so a spreadsheet shows them as text.

Numbers are carried over exactly, including integers beyond 2^53 and decimals like 1.10.

Arguments

Argument Type Meaning
input / path string The text to convert, or a local file.
from "json", "yaml", "csv" Input format. Taken from the file extension if omitted.
to "json", "yaml", "csv" Output format. Required.
csv_delimiter ",", ";", "tab", "|" Delimiter when writing CSV. Default ",".
csv_header boolean The CSV has a header row. Default true.
detect_types boolean Read unquoted CSV numbers and booleans as such. Default true.
nested "flatten" or "json" How nested values become CSV cells. Default "flatten".
escape_formulas boolean Protect cells that look like spreadsheet formulas. Default false.
json_indent "0", "2", "4" JSON indentation; "0" minifies. Default "2".
output_path string Write the result to a file instead of returning it.

Examples

These examples were run against the real tool. A small CSV export:

id,name,country,zip,active
1,Anna,no,01234,true
2,Boris,se,"04711",false

Converted to JSON, the format is taken from the .csv extension. Unquoted numbers and booleans get their types, and both ZIP codes stay strings:

{ "path": "/home/dev/data/customers.csv", "to": "json" }
[
  {
    "id": 1,
    "name": "Anna",
    "country": "no",
    "zip": "01234",
    "active": true
  },
  {
    "id": 2,
    "name": "Boris",
    "country": "se",
    "zip": "04711",
    "active": false
  }
]

Anna’s ZIP code was not quoted in the file, and it still came through as "01234". A value with a leading zero is never read as a number, because the zero would be lost. If you’d rather not have any type detection at all, for example because IDs must stay text, turn off detect_types and every cell stays a string:

{ "path": "/home/dev/data/customers.csv", "to": "json", "detect_types": false, "json_indent": "0" }
[{"id":"1","name":"Anna","country":"no","zip":"01234","active":"true"},{"id":"2","name":"Boris","country":"se","zip":"04711","active":"false"}]

Going the other way, JSON to YAML, the country code no gets quotes. Without them a YAML 1.1 reader would load Norway as false:

{
  "input": "[{\"id\": 1, \"country\": \"no\", \"zip\": \"01234\", \"tags\": {\"plan\": \"pro\"}}]",
  "from": "json",
  "to": "yaml"
}
- id: 1
  country: "no"
  zip: "01234"
  tags:
    plan: pro

Writing CSV from user-supplied data is where formula injection happens. With escape_formulas, a name that starts with = is written as text:

{
  "input": "[{\"name\": \"=HYPERLINK(\\\"http://evil.example\\\")\", \"plan\": {\"tier\": \"pro\", \"seats\": 5}}]",
  "from": "json",
  "to": "csv",
  "escape_formulas": true
}
name,plan.tier,plan.seats
"'=HYPERLINK(""http://evil.example"")",pro,5

The nested plan object was flattened into plan.tier and plan.seats columns.

Round trips with nested data

When CSV columns are named with dots, reading the CSV rebuilds the nested objects, so JSON that went to CSV for a spreadsheet can come back in its original shape:

id,plan.tier,plan.seats,plan.renews
1,pro,5,true
2,team,25,false
{ "path": "/home/dev/data/plans.csv", "to": "json" }
[
  {
    "id": 1,
    "plan": {
      "tier": "pro",
      "seats": 5,
      "renews": true
    }
  },
  {
    "id": 2,
    "plan": {
      "tier": "team",
      "seats": 25,
      "renews": false
    }
  }
]

Set nested to "json" when writing, and nested values go into a single column as JSON text instead. That’s the safer choice when keys themselves contain dots.

Things to ask your assistant

  • “Convert docker-compose.yml to JSON so I can query it.”
  • “Turn orders.json into a CSV for the finance team. Escape formulas and use semicolons, they open it in Excel.”
  • “Convert translations.csv to YAML, and keep every value as a string.”
  • “Read values.yaml (it uses anchors) and give me the resolved JSON.”

For a single file, the JSON / YAML / CSV converter on this site shows the same conversions with the warnings next to the output. The JSON formatter is useful to inspect the result.

Why the model shouldn’t convert by hand

Converting by rewriting the text works on the examples a model has seen most often, and fails on the edge cases. Quoting rules for YAML 1.1 versus 1.2, CSV escaping of embedded quotes and newlines, and which numbers survive a round trip are all things a parser gets right every time and a model gets right most of the time. A dataset with ten thousand rows only needs one wrong row. Real conversion code also keeps the file out of the conversation: the agent sees “Wrote 2.3 MB” instead of the whole export.

json_convert runs in the devtoolbox.cc MCP server on your computer and never sends data anywhere. Setup steps for Claude Desktop, Claude Code, Cursor and VS Code are on the MCP install page.

← All posts