@rog0x/mcp-json-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +111 -0
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +30 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/tools/csv-to-json.d.ts +3 -0
  7. package/dist/tools/csv-to-json.d.ts.map +1 -0
  8. package/dist/tools/csv-to-json.js +69 -0
  9. package/dist/tools/csv-to-json.js.map +1 -0
  10. package/dist/tools/json-diff.d.ts +3 -0
  11. package/dist/tools/json-diff.d.ts.map +1 -0
  12. package/dist/tools/json-diff.js +123 -0
  13. package/dist/tools/json-diff.js.map +1 -0
  14. package/dist/tools/json-to-csv.d.ts +3 -0
  15. package/dist/tools/json-to-csv.d.ts.map +1 -0
  16. package/dist/tools/json-to-csv.js +97 -0
  17. package/dist/tools/json-to-csv.js.map +1 -0
  18. package/dist/tools/json-transform.d.ts +3 -0
  19. package/dist/tools/json-transform.d.ts.map +1 -0
  20. package/dist/tools/json-transform.js +176 -0
  21. package/dist/tools/json-transform.js.map +1 -0
  22. package/dist/tools/json-validator.d.ts +3 -0
  23. package/dist/tools/json-validator.d.ts.map +1 -0
  24. package/dist/tools/json-validator.js +68 -0
  25. package/dist/tools/json-validator.js.map +1 -0
  26. package/dist/tools/yaml-json.d.ts +3 -0
  27. package/dist/tools/yaml-json.d.ts.map +1 -0
  28. package/dist/tools/yaml-json.js +75 -0
  29. package/dist/tools/yaml-json.js.map +1 -0
  30. package/package.json +35 -0
  31. package/src/index.ts +32 -0
  32. package/src/tools/csv-to-json.ts +74 -0
  33. package/src/tools/json-diff.ts +151 -0
  34. package/src/tools/json-to-csv.ts +116 -0
  35. package/src/tools/json-transform.ts +223 -0
  36. package/src/tools/json-validator.ts +91 -0
  37. package/src/tools/yaml-json.ts +83 -0
  38. package/tsconfig.json +19 -0
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerJsonTransform = registerJsonTransform;
4
+ const zod_1 = require("zod");
5
+ function getNestedValue(obj, path) {
6
+ const parts = path.split(".");
7
+ let current = obj;
8
+ for (const part of parts) {
9
+ if (current === null || current === undefined || typeof current !== "object") {
10
+ return undefined;
11
+ }
12
+ current = current[part];
13
+ }
14
+ return current;
15
+ }
16
+ function setNestedValue(obj, path, value) {
17
+ const parts = path.split(".");
18
+ let current = obj;
19
+ for (let i = 0; i < parts.length - 1; i++) {
20
+ const part = parts[i];
21
+ if (!(part in current) || typeof current[part] !== "object" || current[part] === null) {
22
+ current[part] = {};
23
+ }
24
+ current = current[part];
25
+ }
26
+ current[parts[parts.length - 1]] = value;
27
+ }
28
+ function pickFields(data, fields) {
29
+ const result = {};
30
+ for (const field of fields) {
31
+ const value = getNestedValue(data, field);
32
+ if (value !== undefined) {
33
+ result[field] = value;
34
+ }
35
+ }
36
+ return result;
37
+ }
38
+ function renameFields(data, mapping) {
39
+ const result = {};
40
+ for (const [key, value] of Object.entries(data)) {
41
+ const newKey = mapping[key] || key;
42
+ result[newKey] = value;
43
+ }
44
+ return result;
45
+ }
46
+ function flattenObject(obj, prefix = "", separator = ".") {
47
+ const result = {};
48
+ if (obj === null || obj === undefined || typeof obj !== "object") {
49
+ return result;
50
+ }
51
+ if (Array.isArray(obj)) {
52
+ for (let i = 0; i < obj.length; i++) {
53
+ const newKey = prefix ? `${prefix}${separator}${i}` : String(i);
54
+ const val = obj[i];
55
+ if (typeof val === "object" && val !== null) {
56
+ Object.assign(result, flattenObject(val, newKey, separator));
57
+ }
58
+ else {
59
+ result[newKey] = val;
60
+ }
61
+ }
62
+ return result;
63
+ }
64
+ for (const [key, value] of Object.entries(obj)) {
65
+ const newKey = prefix ? `${prefix}${separator}${key}` : key;
66
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
67
+ Object.assign(result, flattenObject(value, newKey, separator));
68
+ }
69
+ else if (Array.isArray(value)) {
70
+ Object.assign(result, flattenObject(value, newKey, separator));
71
+ }
72
+ else {
73
+ result[newKey] = value;
74
+ }
75
+ }
76
+ return result;
77
+ }
78
+ function unflattenObject(obj, separator = ".") {
79
+ const result = {};
80
+ for (const [key, value] of Object.entries(obj)) {
81
+ const parts = key.split(separator);
82
+ setNestedValue(result, parts.join("."), value);
83
+ }
84
+ return result;
85
+ }
86
+ function registerJsonTransform(server) {
87
+ server.tool("json_transform", "Apply transformations to a JSON object: pick specific fields, rename keys, flatten nested objects, or unflatten dot-notation keys.", {
88
+ data: zod_1.z.string().describe("The JSON data to transform (as a JSON string)"),
89
+ operation: zod_1.z
90
+ .enum(["pick", "rename", "flatten", "unflatten"])
91
+ .describe("The transformation operation to apply"),
92
+ fields: zod_1.z
93
+ .array(zod_1.z.string())
94
+ .optional()
95
+ .describe("For 'pick': array of field paths to extract (supports dot notation like 'user.name')"),
96
+ mapping: zod_1.z
97
+ .record(zod_1.z.string(), zod_1.z.string())
98
+ .optional()
99
+ .describe("For 'rename': object mapping old key names to new key names"),
100
+ separator: zod_1.z
101
+ .string()
102
+ .optional()
103
+ .describe("For 'flatten'/'unflatten': separator character (default: '.')"),
104
+ }, async ({ data, operation, fields, mapping, separator }) => {
105
+ try {
106
+ const parsed = JSON.parse(data);
107
+ let result;
108
+ const sep = separator || ".";
109
+ switch (operation) {
110
+ case "pick": {
111
+ if (!fields || fields.length === 0) {
112
+ throw new Error("The 'fields' parameter is required for the 'pick' operation");
113
+ }
114
+ if (Array.isArray(parsed)) {
115
+ result = parsed.map((item) => pickFields(item, fields));
116
+ }
117
+ else {
118
+ result = pickFields(parsed, fields);
119
+ }
120
+ break;
121
+ }
122
+ case "rename": {
123
+ if (!mapping || Object.keys(mapping).length === 0) {
124
+ throw new Error("The 'mapping' parameter is required for the 'rename' operation");
125
+ }
126
+ if (Array.isArray(parsed)) {
127
+ result = parsed.map((item) => renameFields(item, mapping));
128
+ }
129
+ else {
130
+ result = renameFields(parsed, mapping);
131
+ }
132
+ break;
133
+ }
134
+ case "flatten": {
135
+ if (Array.isArray(parsed)) {
136
+ result = parsed.map((item) => flattenObject(item, "", sep));
137
+ }
138
+ else {
139
+ result = flattenObject(parsed, "", sep);
140
+ }
141
+ break;
142
+ }
143
+ case "unflatten": {
144
+ if (Array.isArray(parsed)) {
145
+ result = parsed.map((item) => unflattenObject(item, sep));
146
+ }
147
+ else {
148
+ result = unflattenObject(parsed, sep);
149
+ }
150
+ break;
151
+ }
152
+ }
153
+ return {
154
+ content: [
155
+ {
156
+ type: "text",
157
+ text: JSON.stringify(result, null, 2),
158
+ },
159
+ ],
160
+ };
161
+ }
162
+ catch (error) {
163
+ const message = error instanceof Error ? error.message : String(error);
164
+ return {
165
+ content: [
166
+ {
167
+ type: "text",
168
+ text: `Error transforming JSON: ${message}`,
169
+ },
170
+ ],
171
+ isError: true,
172
+ };
173
+ }
174
+ });
175
+ }
176
+ //# sourceMappingURL=json-transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-transform.js","sourceRoot":"","sources":["../../src/tools/json-transform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerJsonValidator(server: McpServer): void;
3
+ //# sourceMappingURL=json-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-validator.d.ts","sourceRoot":"","sources":["../../src/tools/json-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAoCpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsD7D"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerJsonValidator = registerJsonValidator;
7
+ const zod_1 = require("zod");
8
+ const ajv_1 = __importDefault(require("ajv"));
9
+ function validateJsonAgainstSchema(data, schema) {
10
+ const ajv = new ajv_1.default({ allErrors: true, verbose: true });
11
+ const validate = ajv.compile(schema);
12
+ const valid = validate(data);
13
+ if (valid) {
14
+ return { valid: true, errors: [] };
15
+ }
16
+ const errors = (validate.errors || []).map((err) => ({
17
+ path: err.instancePath || "/",
18
+ message: err.message || "Unknown validation error",
19
+ keyword: err.keyword,
20
+ params: err.params,
21
+ }));
22
+ return { valid: false, errors };
23
+ }
24
+ function registerJsonValidator(server) {
25
+ server.tool("json_validate", "Validate a JSON object against a JSON Schema. Returns whether the data is valid and a list of errors with their paths.", {
26
+ data: zod_1.z.string().describe("The JSON data to validate (as a JSON string)"),
27
+ schema: zod_1.z
28
+ .string()
29
+ .describe("The JSON Schema to validate against (as a JSON string)"),
30
+ }, async ({ data, schema }) => {
31
+ try {
32
+ const parsedData = JSON.parse(data);
33
+ const parsedSchema = JSON.parse(schema);
34
+ const result = validateJsonAgainstSchema(parsedData, parsedSchema);
35
+ return {
36
+ content: [
37
+ {
38
+ type: "text",
39
+ text: JSON.stringify(result, null, 2),
40
+ },
41
+ ],
42
+ };
43
+ }
44
+ catch (error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: JSON.stringify({
51
+ valid: false,
52
+ errors: [
53
+ {
54
+ path: "/",
55
+ message: `Parse error: ${message}`,
56
+ keyword: "parse",
57
+ params: {},
58
+ },
59
+ ],
60
+ }, null, 2),
61
+ },
62
+ ],
63
+ isError: true,
64
+ };
65
+ }
66
+ });
67
+ }
68
+ //# sourceMappingURL=json-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-validator.js","sourceRoot":"","sources":["../../src/tools/json-validator.ts"],"names":[],"mappings":";;;;;AAoCA,sDAsDC;AAzFD,6BAAwB;AACxB,8CAAuC;AAYvC,SAAS,yBAAyB,CAChC,IAAa,EACb,MAA+B;IAE/B,MAAM,GAAG,GAAG,IAAI,aAAG,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE7B,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAgB,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,EAAE,GAAG,CAAC,YAAY,IAAI,GAAG;QAC7B,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,0BAA0B;QAClD,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,MAAM,EAAE,GAAG,CAAC,MAAiC;KAC9C,CAAC,CAAC,CAAC;IAEJ,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAClC,CAAC;AAED,SAAgB,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,eAAe,EACf,wHAAwH,EACxH;QACE,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QACzE,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,CAAC,wDAAwD,CAAC;KACtE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAExC,MAAM,MAAM,GAAG,yBAAyB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YAEnE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACtC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,KAAK,EAAE,KAAK;4BACZ,MAAM,EAAE;gCACN;oCACE,IAAI,EAAE,GAAG;oCACT,OAAO,EAAE,gBAAgB,OAAO,EAAE;oCAClC,OAAO,EAAE,OAAO;oCAChB,MAAM,EAAE,EAAE;iCACX;6BACF;yBACF,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerYamlJson(server: McpServer): void;
3
+ //# sourceMappingURL=yaml-json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-json.d.ts","sourceRoot":"","sources":["../../src/tools/yaml-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8ExD"}
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerYamlJson = registerYamlJson;
7
+ const zod_1 = require("zod");
8
+ const yaml_1 = __importDefault(require("yaml"));
9
+ function registerYamlJson(server) {
10
+ server.tool("yaml_to_json", "Convert YAML text to a JSON string.", {
11
+ yamlText: zod_1.z.string().describe("The YAML text to convert to JSON"),
12
+ indent: zod_1.z
13
+ .number()
14
+ .optional()
15
+ .describe("JSON indentation spaces (default: 2)"),
16
+ }, async ({ yamlText, indent }) => {
17
+ try {
18
+ const parsed = yaml_1.default.parse(yamlText);
19
+ const spaces = indent ?? 2;
20
+ return {
21
+ content: [
22
+ {
23
+ type: "text",
24
+ text: JSON.stringify(parsed, null, spaces),
25
+ },
26
+ ],
27
+ };
28
+ }
29
+ catch (error) {
30
+ const message = error instanceof Error ? error.message : String(error);
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: `Error converting YAML to JSON: ${message}`,
36
+ },
37
+ ],
38
+ isError: true,
39
+ };
40
+ }
41
+ });
42
+ server.tool("json_to_yaml", "Convert a JSON string to YAML text.", {
43
+ jsonText: zod_1.z.string().describe("The JSON text to convert to YAML"),
44
+ indent: zod_1.z
45
+ .number()
46
+ .optional()
47
+ .describe("YAML indentation spaces (default: 2)"),
48
+ }, async ({ jsonText, indent }) => {
49
+ try {
50
+ const parsed = JSON.parse(jsonText);
51
+ const spaces = indent ?? 2;
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: yaml_1.default.stringify(parsed, { indent: spaces }),
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ catch (error) {
62
+ const message = error instanceof Error ? error.message : String(error);
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: `Error converting JSON to YAML: ${message}`,
68
+ },
69
+ ],
70
+ isError: true,
71
+ };
72
+ }
73
+ });
74
+ }
75
+ //# sourceMappingURL=yaml-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yaml-json.js","sourceRoot":"","sources":["../../src/tools/yaml-json.ts"],"names":[],"mappings":";;;;;AAIA,4CA8EC;AAjFD,6BAAwB;AACxB,gDAAwB;AAExB,SAAgB,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,cAAc,EACd,qCAAqC,EACrC;QACE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACjE,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;KACpD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC;YAE3B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC;qBAC3C;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,kCAAkC,OAAO,EAAE;qBAClD;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,cAAc,EACd,qCAAqC,EACrC;QACE,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;QACjE,MAAM,EAAE,OAAC;aACN,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,sCAAsC,CAAC;KACpD,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,CAAC;YAE3B,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,cAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;qBACjD;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACzD,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,kCAAkC,OAAO,EAAE;qBAClD;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@rog0x/mcp-json-tools",
3
+ "version": "1.0.0",
4
+ "description": "MCP server providing JSON and data manipulation tools for AI agents",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "mcp-json-tools": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsc --watch"
14
+ },
15
+ "keywords": [
16
+ "mcp",
17
+ "json",
18
+ "tools",
19
+ "ai",
20
+ "data-manipulation"
21
+ ],
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.12.1",
25
+ "ajv": "^8.17.1",
26
+ "json-diff": "^1.0.6",
27
+ "csv-parse": "^5.6.0",
28
+ "yaml": "^2.7.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/json-diff": "^1.0.3",
32
+ "@types/node": "^22.15.2",
33
+ "typescript": "^5.8.3"
34
+ }
35
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { registerJsonValidator } from "./tools/json-validator.js";
6
+ import { registerJsonDiff } from "./tools/json-diff.js";
7
+ import { registerJsonTransform } from "./tools/json-transform.js";
8
+ import { registerCsvToJson } from "./tools/csv-to-json.js";
9
+ import { registerJsonToCsv } from "./tools/json-to-csv.js";
10
+ import { registerYamlJson } from "./tools/yaml-json.js";
11
+
12
+ async function main(): Promise<void> {
13
+ const server = new McpServer({
14
+ name: "mcp-json-tools",
15
+ version: "1.0.0",
16
+ });
17
+
18
+ registerJsonValidator(server);
19
+ registerJsonDiff(server);
20
+ registerJsonTransform(server);
21
+ registerCsvToJson(server);
22
+ registerJsonToCsv(server);
23
+ registerYamlJson(server);
24
+
25
+ const transport = new StdioServerTransport();
26
+ await server.connect(transport);
27
+ }
28
+
29
+ main().catch((error) => {
30
+ console.error("Fatal error:", error);
31
+ process.exit(1);
32
+ });
@@ -0,0 +1,74 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { parse } from "csv-parse/sync";
4
+
5
+ export function registerCsvToJson(server: McpServer): void {
6
+ server.tool(
7
+ "csv_to_json",
8
+ "Convert CSV text to a JSON array of objects. Supports custom delimiters, header row detection, and automatic type casting.",
9
+ {
10
+ csv: z.string().describe("The CSV text to convert"),
11
+ hasHeaders: z
12
+ .boolean()
13
+ .optional()
14
+ .describe(
15
+ "Whether the first row contains column headers (default: true)"
16
+ ),
17
+ delimiter: z
18
+ .string()
19
+ .optional()
20
+ .describe("Column delimiter character (default: ','"),
21
+ castTypes: z
22
+ .boolean()
23
+ .optional()
24
+ .describe(
25
+ "Automatically cast numeric and boolean values from strings (default: false)"
26
+ ),
27
+ },
28
+ async ({ csv, hasHeaders, delimiter, castTypes }) => {
29
+ try {
30
+ const useHeaders = hasHeaders !== false;
31
+ const delim = delimiter || ",";
32
+ const shouldCast = castTypes === true;
33
+
34
+ const records = parse(csv, {
35
+ columns: useHeaders ? true : undefined,
36
+ delimiter: delim,
37
+ trim: true,
38
+ skip_empty_lines: true,
39
+ cast: shouldCast
40
+ ? (value: string) => {
41
+ if (value === "") return value;
42
+ if (value.toLowerCase() === "true") return true;
43
+ if (value.toLowerCase() === "false") return false;
44
+ const num = Number(value);
45
+ if (!isNaN(num) && value.trim() !== "") return num;
46
+ return value;
47
+ }
48
+ : undefined,
49
+ }) as unknown[];
50
+
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text" as const,
55
+ text: JSON.stringify(records, null, 2),
56
+ },
57
+ ],
58
+ };
59
+ } catch (error) {
60
+ const message =
61
+ error instanceof Error ? error.message : String(error);
62
+ return {
63
+ content: [
64
+ {
65
+ type: "text" as const,
66
+ text: `Error converting CSV to JSON: ${message}`,
67
+ },
68
+ ],
69
+ isError: true,
70
+ };
71
+ }
72
+ }
73
+ );
74
+ }
@@ -0,0 +1,151 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { diff } from "json-diff";
4
+
5
+ interface DiffEntry {
6
+ path: string;
7
+ type: "added" | "removed" | "changed";
8
+ oldValue?: unknown;
9
+ newValue?: unknown;
10
+ }
11
+
12
+ function flattenDiff(
13
+ obj: unknown,
14
+ basePath: string = ""
15
+ ): DiffEntry[] {
16
+ const entries: DiffEntry[] = [];
17
+
18
+ if (obj === undefined || obj === null) {
19
+ return entries;
20
+ }
21
+
22
+ if (typeof obj !== "object") {
23
+ return entries;
24
+ }
25
+
26
+ const record = obj as Record<string, unknown>;
27
+
28
+ for (const key of Object.keys(record)) {
29
+ const value = record[key];
30
+
31
+ if (key.endsWith("__added")) {
32
+ const cleanKey = key.replace(/__added$/, "");
33
+ const path = basePath ? `${basePath}.${cleanKey}` : cleanKey;
34
+ entries.push({ path, type: "added", newValue: value });
35
+ } else if (key.endsWith("__deleted")) {
36
+ const cleanKey = key.replace(/__deleted$/, "");
37
+ const path = basePath ? `${basePath}.${cleanKey}` : cleanKey;
38
+ entries.push({ path, type: "removed", oldValue: value });
39
+ } else if (
40
+ typeof value === "object" &&
41
+ value !== null &&
42
+ "__old" in (value as Record<string, unknown>) &&
43
+ "__new" in (value as Record<string, unknown>)
44
+ ) {
45
+ const path = basePath ? `${basePath}.${key}` : key;
46
+ const typedValue = value as { __old: unknown; __new: unknown };
47
+ entries.push({
48
+ path,
49
+ type: "changed",
50
+ oldValue: typedValue.__old,
51
+ newValue: typedValue.__new,
52
+ });
53
+ } else if (Array.isArray(value)) {
54
+ const path = basePath ? `${basePath}.${key}` : key;
55
+ for (let i = 0; i < value.length; i++) {
56
+ const item = value[i] as unknown;
57
+ if (Array.isArray(item) && item.length === 2) {
58
+ const marker = item[0] as string;
59
+ if (marker === "+") {
60
+ entries.push({
61
+ path: `${path}[${i}]`,
62
+ type: "added",
63
+ newValue: item[1],
64
+ });
65
+ } else if (marker === "-") {
66
+ entries.push({
67
+ path: `${path}[${i}]`,
68
+ type: "removed",
69
+ oldValue: item[1],
70
+ });
71
+ } else if (marker === "~") {
72
+ entries.push(...flattenDiff(item[1], `${path}[${i}]`));
73
+ }
74
+ }
75
+ }
76
+ } else if (typeof value === "object" && value !== null) {
77
+ const path = basePath ? `${basePath}.${key}` : key;
78
+ entries.push(...flattenDiff(value, path));
79
+ }
80
+ }
81
+
82
+ return entries;
83
+ }
84
+
85
+ export function registerJsonDiff(server: McpServer): void {
86
+ server.tool(
87
+ "json_diff",
88
+ "Compare two JSON objects and show additions, removals, and changes with their paths.",
89
+ {
90
+ original: z
91
+ .string()
92
+ .describe("The original JSON object (as a JSON string)"),
93
+ modified: z
94
+ .string()
95
+ .describe("The modified JSON object (as a JSON string)"),
96
+ },
97
+ async ({ original, modified }) => {
98
+ try {
99
+ const obj1 = JSON.parse(original);
100
+ const obj2 = JSON.parse(modified);
101
+
102
+ const rawDiff = diff(obj1, obj2);
103
+
104
+ if (!rawDiff) {
105
+ return {
106
+ content: [
107
+ {
108
+ type: "text" as const,
109
+ text: JSON.stringify(
110
+ { identical: true, differences: [] },
111
+ null,
112
+ 2
113
+ ),
114
+ },
115
+ ],
116
+ };
117
+ }
118
+
119
+ const differences = flattenDiff(rawDiff);
120
+
121
+ return {
122
+ content: [
123
+ {
124
+ type: "text" as const,
125
+ text: JSON.stringify(
126
+ {
127
+ identical: differences.length === 0,
128
+ differences,
129
+ },
130
+ null,
131
+ 2
132
+ ),
133
+ },
134
+ ],
135
+ };
136
+ } catch (error) {
137
+ const message =
138
+ error instanceof Error ? error.message : String(error);
139
+ return {
140
+ content: [
141
+ {
142
+ type: "text" as const,
143
+ text: `Error comparing JSON: ${message}`,
144
+ },
145
+ ],
146
+ isError: true,
147
+ };
148
+ }
149
+ }
150
+ );
151
+ }