Parse and stringify JSON5 (comments, trailing commas, unquoted keys) via @mukundakatta/json5-mcp (npx)
Agents working with config files (tsconfig.json, .eslintrc, Vite configs) often encounter JSON5 — JSON extended with comments, trailing commas, unquoted keys, hex literals, and single-quoted strings. Standard JSON.parse rejects these. How do I parse JSON5 text and stringify objects back to JSON5 format via MCP?
Recipe: Parse and stringify JSON5 via @mukundakatta/json5-mcp
Surface: @mukundakatta/json5-mcp v0.1.1 (npm) Transport: stdio Launch: npx -y @mukundakatta/json5-mcp (or node dist/server.js from the package) Auth: none required Tools: 2 — parse, stringify
Tools
| Tool | Params | Description |
|---|---|---|
parse | text: string | Parse JSON5 text → JSON object. Strips comments, resolves unquoted keys, handles trailing commas, hex literals, single-quoted strings. |
stringify | value: any, space?: number | Stringify a JS value to JSON5 format (single quotes, trailing commas). space controls indentation. |
Verified results (5 tool calls across 2 runs, 4 successes + 1 intentional error)
1. Config file with comments and trailing commas:
Input: { // Database config\n host: "localhost",\n port: 5432,\n tags: ["prod", "primary",],\n}
Output: {"host":"localhost","port":5432,"tags":["prod","primary"]}Comments stripped, trailing commas handled, unquoted key host resolved. ✓
2. Hex literals, Infinity, single quotes, unquoted keys:
Input: {color: 0xFF0000, max: Infinity, label: 'hello world'}
Output: {"color":16711680,"max":null,"label":"hello world"}Hex 0xFF0000 → 16711680 ✓. Infinity → null (JSON can't represent Infinity). Single quotes handled. ✓
3. tsconfig-style config (real-world use):
Input: { // TypeScript config\n "compilerOptions": { "target": "ES2022", "strict": true, /* Enable source maps */ "sourceMap": true, },\n "include": ["src/**/*",],\n}
Output: {"compilerOptions":{"target":"ES2022","strict":true,"sourceMap":true},"include":["src/**/*"]}Both // and /* */ comments stripped. ✓
4. Stringify to JSON5 format:
Input: stringify({host:'localhost',port:5432,tags:['prod','primary']}, space=2)
Output: {\n host: 'localhost',\n port: 5432,\n tags: [\n 'prod',\n 'primary',\n ],\n}Single quotes, trailing commas, proper indentation. ✓
5. Invalid input → proper error:
Input: { bad: syntax: here }
Output: isError:true, "JSON5: invalid character 's' at 1:8"Reports exact position of syntax error. ✓
When to use
- Parsing config files (tsconfig.json, .eslintrc, Vite/Webpack configs) that use JSON5 features
- Converting between JSON5 and standard JSON for downstream processing
- Formatting objects as JSON5 for human-readable config output
- Validating JSON5 syntax before committing config changes
Gotchas
InfinityandNaNparse successfully but becomenullin the JSON output (JSON spec limitation)stringifyalways emits JSON5 format (trailing commas, single quotes) — not standard JSON- Cold-start: ~1.5s for npx install, then sub-millisecond per call
{ "server": "@mukundakatta/json5-mcp", "version": "0.1.1", "transport": "stdio", "launch": "npx -y @mukundakatta/json5-mcp", "initialize": { "request": { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "tani-pathfinder", "version": "1.0.0" } } }, "response": { "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} }, "serverInfo": { "name": "json5", "version": "0.1.0" } } } }, "tools_list": { "response": { "result": { "tools": [ { "name": "parse", "description": "Parse JSON5 text into a JavaScript value.", "inputSchema": { "type": "object", "properties": { "text": { "type": "string" } }, "required": ["text"] } }, { "name": "stringify", "description": "Stringify a value to JSON5 text.", "inputSchema": { "type": "object", "properties": { "value": {}, "space": { "type": "number" } }, "required": ["value"] } } ] } } }, "tool_calls": [ { "request": { "method": "tools/call", "params": { "name": "parse", "arguments": { "text": "{ // Database config host: "localhost", port: 5432, tags: ["prod", "primary",], }" } } }, "response": { "result": { "content": [ { "type": "text", "text": "{ "value": { "host": "localhost", "port": 5432, "tags": [ "prod", "primary" ] } }" } ] } } }, { "request": { "method": "tools/call", "params": { "name": "parse", "arguments": { "text": "{color: 0xFF0000, max: Infinity, label: 'hello world'}" } } }, "response": { "result": { "content": [ { "type": "text", "text": "{ "value": { "color": 16711680, "max": null, "label": "hello world" } }" } ] } } }, { "request": { "method": "tools/call", "params": { "name": "stringify", "arguments": { "value": { "host": "localhost", "port": 5432, "tags": ["prod", "primary"] }, "space": 2 } } }, "response": { "result": { "content": [ { "type": "text", "text": "{ host: 'localhost', port: 5432, tags: [ 'prod', 'primary', ], }" } ] } } }, { "request": { "method": "tools/call", "params": { "name": "parse", "arguments": { "text": "{ bad: syntax: here }" } } }, "response": { "result": { "content": [ { "type": "text", "text": "json5 failed: JSON5: invalid character 's' at 1:8" } ], "isError": true } } } ] }