@utilix-tech/mcp 0.88.0 → 0.89.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 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.89.0
6
+ - Add `check_acronym_expansion` tool: scan text for acronyms and flag any used before being expanded on first mention, recognizing both the "full term (ACRONYM)" and "ACRONYM (full term)" conventions, with acronyms never expanded anywhere reported separately.
7
+
5
8
  ## 0.88.0
6
9
  - Add `validate_mermaid_syntax` tool: check a Mermaid diagram definition for syntax errors with line numbers, including an unterminated subgraph, unbalanced node brackets, a malformed edge arrow, and a sequence-diagram participant referenced before its explicit declaration.
7
10
  - Add `calculate_annuity_payout` tool: solve the standard annuity formula in either direction, the periodic payout a lump sum funds, or the lump sum required to fund a target payout, for an ordinary or annuity-due structure.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @utilix-tech/mcp
2
2
 
3
- MCP server exposing 269 developer utility tools to Claude, Cursor, VS Code Copilot, and any [Model Context Protocol](https://modelcontextprotocol.io) compatible AI assistant.
3
+ MCP server exposing 270 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
 
@@ -134,7 +134,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
134
134
  | `generate_random_data` | Generate random mock data: names, emails, UUIDs, IPs, etc. |
135
135
  | `generate_csp_nonce` | Generate a cryptographically random CSP nonce with ready-to-paste header directive and script/style tag snippets |
136
136
 
137
- ### Text (17 tools)
137
+ ### Text (18 tools)
138
138
  | Tool | Description |
139
139
  |------|-------------|
140
140
  | `convert_case` | Convert text case: camelCase, snake_case, PascalCase, etc. |
@@ -156,6 +156,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
156
156
  | `lookup_emoji` | Search a curated table of ~280 common emoji by name, keyword, or GitHub-style shortcode, or look one up exactly by shortcode, character, or category |
157
157
  | `analyze_keyword_density` | Count keyword/phrase frequency and density (occurrences per 100 words) across a block of text, with single-word or 2/3-word phrase modes |
158
158
  | `check_dash_usage` | Scan text for likely dash misuse: a hyphen surrounded by spaces, an unconverted double hyphen, and inconsistent spacing around em dashes across the same document |
159
+ | `check_acronym_expansion` | Scan text for acronyms and flag any that are used before being expanded on first mention, or never expanded at all |
159
160
 
160
161
  ### Time (6 tools)
161
162
  | Tool | Description |
package/dist/index.js CHANGED
@@ -13944,6 +13944,76 @@ server.tool(
13944
13944
  return text(JSON.stringify(_checkDashUsageMcp(input), null, 2));
13945
13945
  }
13946
13946
  );
13947
+ var _ACRONYM_TOKEN_RE_MCP = /\b[A-Z][A-Z0-9]{1,9}\b/g;
13948
+ var _ACRONYM_IN_PARENS_RE_MCP = /\(([A-Z][A-Z0-9]{1,9})\)/g;
13949
+ var _ACRONYM_THEN_EXPANSION_RE_MCP = /\b([A-Z][A-Z0-9]{1,9})\b\s*\(([a-zA-Z][^()]{1,100})\)/g;
13950
+ function _acronymContextSnippetMcp(input, index, matchLen) {
13951
+ const start = Math.max(0, index - 25);
13952
+ const end = Math.min(input.length, index + matchLen + 25);
13953
+ const body = input.slice(start, end).replace(/\s+/g, " ").trim();
13954
+ return (start > 0 ? "\u2026" : "") + body + (end < input.length ? "\u2026" : "");
13955
+ }
13956
+ function _checkAcronymExpansionMcp(input) {
13957
+ const definedAt = /* @__PURE__ */ new Map();
13958
+ for (const m of input.matchAll(_ACRONYM_IN_PARENS_RE_MCP)) {
13959
+ const acronym = m[1];
13960
+ const idx = (m.index ?? 0) + 1;
13961
+ const existing = definedAt.get(acronym);
13962
+ if (existing === void 0 || idx < existing) definedAt.set(acronym, idx);
13963
+ }
13964
+ for (const m of input.matchAll(_ACRONYM_THEN_EXPANSION_RE_MCP)) {
13965
+ const acronym = m[1];
13966
+ const idx = m.index ?? 0;
13967
+ const existing = definedAt.get(acronym);
13968
+ if (existing === void 0 || idx < existing) definedAt.set(acronym, idx);
13969
+ }
13970
+ const occurrencesByAcronym = /* @__PURE__ */ new Map();
13971
+ for (const m of input.matchAll(_ACRONYM_TOKEN_RE_MCP)) {
13972
+ const acronym = m[0];
13973
+ const idx = m.index ?? 0;
13974
+ const list = occurrencesByAcronym.get(acronym);
13975
+ if (list) list.push(idx);
13976
+ else occurrencesByAcronym.set(acronym, [idx]);
13977
+ }
13978
+ const acronyms = [];
13979
+ const issues = [];
13980
+ for (const [acronym, indicesUnsorted] of occurrencesByAcronym) {
13981
+ const indices = [...indicesUnsorted].sort((a, b) => a - b);
13982
+ const firstUsedAt = indices[0];
13983
+ const expandedAt = definedAt.has(acronym) ? definedAt.get(acronym) : null;
13984
+ const earlyUse = expandedAt !== null ? indices.find((i) => i < expandedAt) : void 0;
13985
+ const usedBeforeExpansion = earlyUse !== void 0;
13986
+ acronyms.push({ acronym, occurrences: indices.length, firstUsedAt, expandedAt, usedBeforeExpansion });
13987
+ if (usedBeforeExpansion) {
13988
+ issues.push({
13989
+ type: "used-before-expansion",
13990
+ acronym,
13991
+ index: earlyUse,
13992
+ context: _acronymContextSnippetMcp(input, earlyUse, acronym.length),
13993
+ message: `"${acronym}" is used here before it's expanded later in the document (at character ${expandedAt}).`
13994
+ });
13995
+ } else if (expandedAt === null) {
13996
+ issues.push({
13997
+ type: "never-expanded",
13998
+ acronym,
13999
+ index: firstUsedAt,
14000
+ context: _acronymContextSnippetMcp(input, firstUsedAt, acronym.length),
14001
+ message: `"${acronym}" is never expanded anywhere in this document.`
14002
+ });
14003
+ }
14004
+ }
14005
+ acronyms.sort((a, b) => a.firstUsedAt - b.firstUsedAt);
14006
+ issues.sort((a, b) => a.index - b.index);
14007
+ return { acronyms, issues };
14008
+ }
14009
+ server.tool(
14010
+ "check_acronym_expansion",
14011
+ "Scan text for acronyms (2-10 character all-caps tokens) and flag any that are used before being expanded on first mention, per standard technical writing style guides. Recognizes both expansion conventions: the full term followed by the acronym in parentheses, and the acronym followed by its expansion in parentheses. Pure regex heuristic, not a dictionary of real acronyms.",
14012
+ { text: z.string().describe("The text to scan for acronym expansion order") },
14013
+ async ({ text: input }) => {
14014
+ return text(JSON.stringify(_checkAcronymExpansionMcp(input), null, 2));
14015
+ }
14016
+ );
13947
14017
  var _CommissionTierSchema = z.object({
13948
14018
  upTo: z.number().nullable().describe("Upper bound of this tier (exclusive). null means unbounded and is only valid on the last tier."),
13949
14019
  ratePercent: z.number().min(0).describe("Commission rate as a percent applied to the slice of salesAmount within this tier")
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@utilix-tech/mcp",
3
- "version": "0.88.0",
4
- "description": "MCP server exposing 198 Utilix developer tools to Claude, Cursor, VS Code Copilot, and any MCP-compatible AI assistant.",
3
+ "version": "0.89.0",
4
+ "description": "MCP server exposing 270 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",
7
7
  "homepage": "https://utilix.tech/mcp",