@utilix-tech/mcp 0.2.0 → 0.3.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/dist/index.js +116 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,6 @@ import { z } from "zod";
|
|
|
7
7
|
import {
|
|
8
8
|
parseJson,
|
|
9
9
|
minifyJson,
|
|
10
|
-
diffJson,
|
|
11
10
|
jsonToCsv,
|
|
12
11
|
csvToJson,
|
|
13
12
|
evaluateJsonPath,
|
|
@@ -74,6 +73,7 @@ import { formatSql, formatHtml, testRegex, minifyJs, formatGql, parseDockerImage
|
|
|
74
73
|
import { validateYaml, tomlToJson, xmlToJson, parseCsv } from "@utilix-tech/sdk/data";
|
|
75
74
|
import { generateGradient, minifyCss } from "@utilix-tech/sdk/css";
|
|
76
75
|
import { optimizeSvg, charToCodePoint, numberToWords } from "@utilix-tech/sdk/misc";
|
|
76
|
+
import { estimateTokens, estimateCost, detectPii, redactPii, detectSecrets, detectPromptInjection, repairJson, trimToTokens, chunkText, extractUrls, sanitizeHtml, flattenJson, unflattenJson, mergeJson, extractJson, deduplicateLines, extractKeywords, validateJsonSchema, diffJson, extractTables, extractEntities, compressHtml, compressMarkdown, compressJson, rerankChunks, scoreRelevance, expandQuery, summarizeForLlm } from "@utilix-tech/sdk/ai_agent";
|
|
77
77
|
var CRON_DAY_MAP = {
|
|
78
78
|
SUN: "0",
|
|
79
79
|
MON: "1",
|
|
@@ -1027,5 +1027,120 @@ server.tool(
|
|
|
1027
1027
|
(${original}B \u2192 ${optimized}B, saved ${saved}%)`);
|
|
1028
1028
|
}
|
|
1029
1029
|
);
|
|
1030
|
+
server.tool(
|
|
1031
|
+
"estimate_tokens",
|
|
1032
|
+
"Estimate the token count and API cost for a text string across popular LLMs (GPT-4o, Claude, Gemini, etc.).",
|
|
1033
|
+
{
|
|
1034
|
+
text: z.string().describe("Text to estimate tokens for"),
|
|
1035
|
+
model: z.string().optional().describe("Model slug (e.g. gpt-4o, claude-sonnet-4) \u2014 omit for all models"),
|
|
1036
|
+
output_tokens: z.number().int().min(0).optional().describe("Expected output tokens (defaults to same as input)")
|
|
1037
|
+
},
|
|
1038
|
+
async ({ text: text2, model, output_tokens }) => {
|
|
1039
|
+
const est = estimateTokens(text2);
|
|
1040
|
+
const result = estimateCost(est.tokens, output_tokens, model);
|
|
1041
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1042
|
+
}
|
|
1043
|
+
);
|
|
1044
|
+
server.tool(
|
|
1045
|
+
"detect_pii",
|
|
1046
|
+
"Detect personally identifiable information (emails, phones, SSNs, credit cards, IPs, IBANs, crypto wallets) in text.",
|
|
1047
|
+
{
|
|
1048
|
+
text: z.string().describe("Text to scan for PII"),
|
|
1049
|
+
redact: z.boolean().default(false).describe("If true, return redacted text instead of findings list"),
|
|
1050
|
+
replacement: z.string().default("[REDACTED]").describe("Replacement string when redacting")
|
|
1051
|
+
},
|
|
1052
|
+
async ({ text: text2, redact, replacement }) => {
|
|
1053
|
+
const result = redact ? redactPii(text2, replacement) : detectPii(text2);
|
|
1054
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1055
|
+
}
|
|
1056
|
+
);
|
|
1057
|
+
server.tool(
|
|
1058
|
+
"detect_secrets",
|
|
1059
|
+
"Scan text for leaked API keys, tokens, and credentials (OpenAI, Anthropic, AWS, GitHub, Stripe, etc.).",
|
|
1060
|
+
{ text: z.string().describe("Text or code to scan for secrets") },
|
|
1061
|
+
async ({ text: text2 }) => {
|
|
1062
|
+
const result = detectSecrets(text2);
|
|
1063
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1064
|
+
}
|
|
1065
|
+
);
|
|
1066
|
+
server.tool(
|
|
1067
|
+
"detect_prompt_injection",
|
|
1068
|
+
"Detect prompt injection and jailbreak attempts in user-provided text before passing to an LLM.",
|
|
1069
|
+
{ text: z.string().describe("User-provided text to check for injection attempts") },
|
|
1070
|
+
async ({ text: text2 }) => {
|
|
1071
|
+
const result = detectPromptInjection(text2);
|
|
1072
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1073
|
+
}
|
|
1074
|
+
);
|
|
1075
|
+
server.tool(
|
|
1076
|
+
"repair_json",
|
|
1077
|
+
"Fix malformed JSON: unquoted keys, single quotes, trailing commas, JS comments, undefined/NaN values, unclosed brackets.",
|
|
1078
|
+
{ input: z.string().describe("Malformed JSON string to repair") },
|
|
1079
|
+
async ({ input }) => {
|
|
1080
|
+
const result = repairJson(input);
|
|
1081
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1082
|
+
}
|
|
1083
|
+
);
|
|
1084
|
+
server.tool("trim_to_tokens", "Truncate text to a token budget (end/start/middle strategy).", { text: z.string(), max_tokens: z.number().int().min(1), strategy: z.enum(["end", "start", "middle"]).default("end") }, async ({ text: text2, max_tokens, strategy }) => {
|
|
1085
|
+
return { content: [{ type: "text", text: JSON.stringify(trimToTokens(text2, max_tokens, strategy), null, 2) }] };
|
|
1086
|
+
});
|
|
1087
|
+
server.tool("chunk_text", "Split text into overlapping chunks for RAG.", { text: z.string(), chunk_size: z.number().int().min(10).default(200), overlap: z.number().int().min(0).default(20), strategy: z.enum(["paragraph", "sentence", "fixed"]).default("paragraph") }, async ({ text: text2, chunk_size, overlap, strategy }) => {
|
|
1088
|
+
return { content: [{ type: "text", text: JSON.stringify(chunkText(text2, chunk_size, overlap, strategy), null, 2) }] };
|
|
1089
|
+
});
|
|
1090
|
+
server.tool("extract_urls", "Extract all URLs from text or HTML.", { text: z.string() }, async ({ text: text2 }) => {
|
|
1091
|
+
return { content: [{ type: "text", text: JSON.stringify(extractUrls(text2), null, 2) }] };
|
|
1092
|
+
});
|
|
1093
|
+
server.tool("sanitize_html", "Strip HTML tags, scripts, and event handlers for LLM ingestion.", { html: z.string(), keep_links: z.boolean().default(false) }, async ({ html, keep_links }) => {
|
|
1094
|
+
return { content: [{ type: "text", text: JSON.stringify(sanitizeHtml(html, keep_links), null, 2) }] };
|
|
1095
|
+
});
|
|
1096
|
+
server.tool("flatten_json", "Flatten nested JSON to dot-notation keys.", { json: z.unknown(), separator: z.string().default("."), unflatten: z.boolean().default(false) }, async ({ json, separator, unflatten }) => {
|
|
1097
|
+
const result = unflatten ? unflattenJson(json, separator) : flattenJson(json, separator);
|
|
1098
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1099
|
+
});
|
|
1100
|
+
server.tool("merge_json", "Deep merge two JSON objects.", { base: z.unknown(), override: z.unknown(), strategy: z.enum(["deep", "shallow", "replace-arrays"]).default("deep") }, async ({ base, override, strategy }) => {
|
|
1101
|
+
return { content: [{ type: "text", text: JSON.stringify(mergeJson(base, override, strategy), null, 2) }] };
|
|
1102
|
+
});
|
|
1103
|
+
server.tool("extract_json", "Extract JSON blocks from mixed LLM output text.", { text: z.string() }, async ({ text: text2 }) => {
|
|
1104
|
+
return { content: [{ type: "text", text: JSON.stringify(extractJson(text2), null, 2) }] };
|
|
1105
|
+
});
|
|
1106
|
+
server.tool("deduplicate_lines", "Remove duplicate lines from text.", { text: z.string(), strategy: z.enum(["exact", "case-insensitive", "trimmed", "normalized"]).default("exact") }, async ({ text: text2, strategy }) => {
|
|
1107
|
+
return { content: [{ type: "text", text: JSON.stringify(deduplicateLines(text2, strategy), null, 2) }] };
|
|
1108
|
+
});
|
|
1109
|
+
server.tool("extract_keywords", "Extract top keywords using TF-IDF scoring.", { text: z.string(), max_keywords: z.number().int().min(1).max(100).default(20), min_word_len: z.number().int().min(2).default(3) }, async ({ text: text2, max_keywords, min_word_len }) => {
|
|
1110
|
+
return { content: [{ type: "text", text: JSON.stringify(extractKeywords(text2, max_keywords, min_word_len), null, 2) }] };
|
|
1111
|
+
});
|
|
1112
|
+
server.tool("validate_json_schema", "Validate JSON data against a JSON Schema (Draft-07).", { data: z.unknown(), schema: z.record(z.unknown()) }, async ({ data, schema }) => {
|
|
1113
|
+
return { content: [{ type: "text", text: JSON.stringify(validateJsonSchema(data, schema), null, 2) }] };
|
|
1114
|
+
});
|
|
1115
|
+
server.tool("diff_json", "Diff two JSON objects \u2014 returns added, removed, changed, and unchanged paths.", { a: z.unknown(), b: z.unknown() }, async ({ a, b }) => {
|
|
1116
|
+
return { content: [{ type: "text", text: JSON.stringify(diffJson(a, b), null, 2) }] };
|
|
1117
|
+
});
|
|
1118
|
+
server.tool("extract_tables", "Extract HTML tables into JSON arrays with headers and rows.", { html: z.string() }, async ({ html }) => {
|
|
1119
|
+
return { content: [{ type: "text", text: JSON.stringify(extractTables(html), null, 2) }] };
|
|
1120
|
+
});
|
|
1121
|
+
server.tool("extract_entities", "Extract emails, phones, dates, IPs, currencies, hashtags from text.", { text: z.string() }, async ({ text: text2 }) => {
|
|
1122
|
+
return { content: [{ type: "text", text: JSON.stringify(extractEntities(text2), null, 2) }] };
|
|
1123
|
+
});
|
|
1124
|
+
server.tool("compress_html", "Strip scripts, styles, classes, and whitespace from HTML to minimize tokens.", { html: z.string(), remove_comments: z.boolean().default(true), remove_scripts: z.boolean().default(true), remove_styles: z.boolean().default(true), collapse_whitespace: z.boolean().default(true) }, async ({ html, remove_comments, remove_scripts, remove_styles, collapse_whitespace }) => {
|
|
1125
|
+
return { content: [{ type: "text", text: JSON.stringify(compressHtml(html, { removeComments: remove_comments, removeScripts: remove_scripts, removeStyles: remove_styles, collapseWhitespace: collapse_whitespace }), null, 2) }] };
|
|
1126
|
+
});
|
|
1127
|
+
server.tool("compress_markdown", "Normalize and compress markdown to reduce token count.", { markdown: z.string(), collapse_blank_lines: z.boolean().default(true), remove_comments: z.boolean().default(true), strip_frontmatter: z.boolean().default(false) }, async ({ markdown, collapse_blank_lines, remove_comments, strip_frontmatter }) => {
|
|
1128
|
+
return { content: [{ type: "text", text: JSON.stringify(compressMarkdown(markdown, { collapseBlankLines: collapse_blank_lines, removeComments: remove_comments, stripFrontmatter: strip_frontmatter }), null, 2) }] };
|
|
1129
|
+
});
|
|
1130
|
+
server.tool("compress_json", "Remove nulls, empty arrays, and empty objects from JSON to reduce tokens.", { json: z.unknown(), remove_nulls: z.boolean().default(true), remove_empty_arrays: z.boolean().default(true), remove_empty_objects: z.boolean().default(true), sort_keys: z.boolean().default(false) }, async ({ json, remove_nulls, remove_empty_arrays, remove_empty_objects, sort_keys }) => {
|
|
1131
|
+
return { content: [{ type: "text", text: JSON.stringify(compressJson(json, { removeNulls: remove_nulls, removeEmptyArrays: remove_empty_arrays, removeEmptyObjects: remove_empty_objects, sortKeys: sort_keys }), null, 2) }] };
|
|
1132
|
+
});
|
|
1133
|
+
server.tool("rerank_chunks", "Score and rerank text chunks by TF-IDF relevance to a query.", { query: z.string(), chunks: z.array(z.string()), top_k: z.number().int().min(1).optional() }, async ({ query, chunks, top_k }) => {
|
|
1134
|
+
return { content: [{ type: "text", text: JSON.stringify(rerankChunks(query, chunks, top_k), null, 2) }] };
|
|
1135
|
+
});
|
|
1136
|
+
server.tool("score_relevance", "Score a passage relevance to a query (0-1 score with grade).", { query: z.string(), passage: z.string() }, async ({ query, passage }) => {
|
|
1137
|
+
return { content: [{ type: "text", text: JSON.stringify(scoreRelevance(query, passage), null, 2) }] };
|
|
1138
|
+
});
|
|
1139
|
+
server.tool("expand_query", "Expand a search query with synonyms and stemmed variants for better retrieval.", { query: z.string(), max_synonyms: z.number().int().min(1).max(5).default(2) }, async ({ query, max_synonyms }) => {
|
|
1140
|
+
return { content: [{ type: "text", text: JSON.stringify(expandQuery(query, max_synonyms), null, 2) }] };
|
|
1141
|
+
});
|
|
1142
|
+
server.tool("summarize_for_llm", "Extractive summarization \u2014 pick key sentences to fit a token budget.", { text: z.string(), max_tokens: z.number().int().min(10).default(200), strategy: z.enum(["extractive", "first", "last"]).default("extractive") }, async ({ text: text2, max_tokens, strategy }) => {
|
|
1143
|
+
return { content: [{ type: "text", text: JSON.stringify(summarizeForLlm(text2, max_tokens, strategy), null, 2) }] };
|
|
1144
|
+
});
|
|
1030
1145
|
var transport = new StdioServerTransport();
|
|
1031
1146
|
await server.connect(transport);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utilix-tech/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MCP server exposing 70 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",
|