@utilix-tech/mcp 0.77.0 → 0.78.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.
- package/CHANGELOG.md +3 -0
- package/README.md +2 -1
- package/dist/index.js +55 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Full release notes for all Utilix surfaces (browser tools, REST API, SDKs, MCP server) live at [utilix.tech/changelog](https://utilix.tech/changelog). This file tracks just this package.
|
|
4
4
|
|
|
5
|
+
## 0.78.0
|
|
6
|
+
- Add `ndjson_to_csv` tool: convert newline-delimited JSON (one flat object per line) into CSV, inferring the header row from the union of keys across all lines.
|
|
7
|
+
|
|
5
8
|
## 0.77.0
|
|
6
9
|
- Add `read_pdf_outline` tool: walk a PDF's /Outlines bookmark tree (the Root -> Outlines -> First/Next/First chain) and list every bookmark's title, nesting level, and link target, in document order.
|
|
7
10
|
- Add `score_security_headers` tool: score a pasted block of raw HTTP response headers against commonly recommended security headers (CSP, HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, Cross-Origin-*), with an overall 0-100 score and A-F letter grade.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/mcp
|
|
2
2
|
|
|
3
|
-
MCP server exposing
|
|
3
|
+
MCP server exposing 250 developer utility tools to Claude, Cursor, VS Code Copilot, and any [Model Context Protocol](https://modelcontextprotocol.io) compatible AI assistant.
|
|
4
4
|
|
|
5
5
|
No API key required. All tools run locally. Requires Node.js 18 or later.
|
|
6
6
|
|
|
@@ -313,6 +313,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
|
|
|
313
313
|
| `parse_csv` | Parse a CSV string and return the data as JSON |
|
|
314
314
|
| `format_ndjson` | Validate and pretty-print newline-delimited JSON (NDJSON) |
|
|
315
315
|
| `dedupe_ndjson` | Remove duplicate records from NDJSON, by exact match or by a key field |
|
|
316
|
+
| `ndjson_to_csv` | Convert NDJSON into CSV, inferring the header row from the union of keys |
|
|
316
317
|
| `diff_env_example` | Diff a .env file against its .env.example template: flags keys missing from either side, plus empty placeholder values |
|
|
317
318
|
| `parse_markdown_front_matter` | Split a Markdown document into its YAML front matter fields and body content |
|
|
318
319
|
| `generate_markdown_toc` | Scan a Markdown document's ATX headings and build a nested table of contents with GitHub-style anchor slugs |
|
package/dist/index.js
CHANGED
|
@@ -2702,6 +2702,61 @@ server.tool(
|
|
|
2702
2702
|
return text(JSON.stringify(result, null, 2));
|
|
2703
2703
|
}
|
|
2704
2704
|
);
|
|
2705
|
+
function _toCsvStringMcp(headers, rows) {
|
|
2706
|
+
const escapeField = (field) => {
|
|
2707
|
+
if (field.includes(",") || field.includes('"') || field.includes("\n") || field.includes("\r")) {
|
|
2708
|
+
return `"${field.replace(/"/g, '""')}"`;
|
|
2709
|
+
}
|
|
2710
|
+
return field;
|
|
2711
|
+
};
|
|
2712
|
+
const lines = [headers.map(escapeField).join(",")];
|
|
2713
|
+
for (const row of rows) lines.push(row.map(escapeField).join(","));
|
|
2714
|
+
return lines.join("\n");
|
|
2715
|
+
}
|
|
2716
|
+
function _stringifyCsvValueMcp(value) {
|
|
2717
|
+
if (value === void 0 || value === null) return "";
|
|
2718
|
+
if (typeof value === "string") return value;
|
|
2719
|
+
if (typeof value === "object") return JSON.stringify(value);
|
|
2720
|
+
return String(value);
|
|
2721
|
+
}
|
|
2722
|
+
function _ndjsonToCsvMcp(input) {
|
|
2723
|
+
const validated = _validateNdjson(input);
|
|
2724
|
+
if (!validated.valid) {
|
|
2725
|
+
const firstError = validated.lines.find((l) => !l.valid);
|
|
2726
|
+
return { error: firstError ? `Line ${firstError.line}: ${firstError.error}` : "Invalid NDJSON" };
|
|
2727
|
+
}
|
|
2728
|
+
if (validated.lines.length === 0) return { error: "No records found" };
|
|
2729
|
+
const records = validated.lines.map((l) => JSON.parse(l.raw));
|
|
2730
|
+
for (const record of records) {
|
|
2731
|
+
if (typeof record !== "object" || record === null || Array.isArray(record)) {
|
|
2732
|
+
return { error: "Every line must be a flat JSON object to convert to CSV" };
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
const headers = [];
|
|
2736
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2737
|
+
for (const record of records) {
|
|
2738
|
+
for (const key of Object.keys(record)) {
|
|
2739
|
+
if (!seen.has(key)) {
|
|
2740
|
+
seen.add(key);
|
|
2741
|
+
headers.push(key);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
const rows = records.map((record) => headers.map((h) => _stringifyCsvValueMcp(record[h])));
|
|
2746
|
+
return { output: _toCsvStringMcp(headers, rows) };
|
|
2747
|
+
}
|
|
2748
|
+
server.tool(
|
|
2749
|
+
"ndjson_to_csv",
|
|
2750
|
+
"Convert NDJSON (newline-delimited JSON, one flat object per line) into CSV, inferring the header row from the union of keys across every line.",
|
|
2751
|
+
{
|
|
2752
|
+
input: z.string().describe("NDJSON content: one flat JSON object per line")
|
|
2753
|
+
},
|
|
2754
|
+
async ({ input }) => {
|
|
2755
|
+
const result = _ndjsonToCsvMcp(input);
|
|
2756
|
+
if ("error" in result) return errText(result);
|
|
2757
|
+
return text(result.output);
|
|
2758
|
+
}
|
|
2759
|
+
);
|
|
2705
2760
|
function _decodePdfString(raw, isHex) {
|
|
2706
2761
|
const bytes = [];
|
|
2707
2762
|
if (isHex) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilix-tech/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.78.0",
|
|
4
4
|
"description": "MCP server exposing 198 Utilix developer tools to Claude, Cursor, VS Code Copilot, and any MCP-compatible AI assistant.",
|
|
5
5
|
"author": "Utilix <hello@utilix.tech>",
|
|
6
6
|
"license": "MIT",
|