@utilix-tech/mcp 0.36.0 → 0.38.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 +7 -0
- package/README.md +6 -3
- package/dist/index.js +257 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
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.38.0
|
|
6
|
+
- Add `check_set_cookie_header` tool: parse a Set-Cookie header value and validate its attribute combination, flagging SameSite=None missing Secure, __Host-/__Secure- prefix violations, a missing Secure attribute, and a Max-Age past 400 days.
|
|
7
|
+
- Add `test_gitignore_patterns` tool: test a list of paths against a .gitignore file's patterns, following git's last-match-wins and negation rules, and report which pattern and line number decided each path's outcome.
|
|
8
|
+
|
|
9
|
+
## 0.37.0
|
|
10
|
+
- Add `build_link_header` tool: build an HTTP Link response header from URL/rel pairs (preload, preconnect, prefetch, canonical, pagination, etc.), including the as/type/crossorigin attributes preload needs, plus a plain-English explanation of each entry and warnings for common mistakes like a preload missing `as`.
|
|
11
|
+
|
|
5
12
|
## 0.36.0
|
|
6
13
|
- Add `calculate_roi` tool: return on investment percent from an initial and final value, plus the annualized (CAGR) return given an optional holding period in years.
|
|
7
14
|
- Add `lookup_emoji` tool: 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.
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @utilix-tech/mcp
|
|
2
2
|
|
|
3
|
-
MCP server exposing
|
|
3
|
+
MCP server exposing 161 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
|
|
|
@@ -184,7 +184,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
|
|
|
184
184
|
| `calculate_savings_goal` | Solve for months to reach a savings goal at a fixed monthly contribution, or the monthly contribution required to hit a goal by a target month count |
|
|
185
185
|
| `calculate_roi` | Compute return on investment percent from an initial and final value, plus the annualized (CAGR) return given an optional holding period in years |
|
|
186
186
|
|
|
187
|
-
### API / Network (
|
|
187
|
+
### API / Network (15 tools)
|
|
188
188
|
| Tool | Description |
|
|
189
189
|
|------|-------------|
|
|
190
190
|
| `decode_jwt` | Decode a JWT: header, payload, and expiry |
|
|
@@ -200,6 +200,8 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
|
|
|
200
200
|
| `build_cache_control` | Build and explain an HTTP Cache-Control response header from directives (max-age, no-store, immutable, etc.) |
|
|
201
201
|
| `build_referrer_policy` | Build and explain an HTTP Referrer-Policy header from one or more fallback-chain policy tokens |
|
|
202
202
|
| `parse_ipv6_address` | Expand an IPv6 address to its full 8-group form or compress it to its RFC 5952 canonical shortest form, classify its address type, and handle an embedded IPv4 suffix or zone ID |
|
|
203
|
+
| `build_link_header` | Build and explain an HTTP Link response header from URL/rel pairs (preload, preconnect, prefetch, canonical, pagination, etc.) |
|
|
204
|
+
| `check_set_cookie_header` | Parse a Set-Cookie header and validate its attribute combination: SameSite=None requires Secure, __Host-/__Secure- prefix rules, missing Secure, overly long Max-Age |
|
|
203
205
|
|
|
204
206
|
### Color (4 tools)
|
|
205
207
|
| Tool | Description |
|
|
@@ -209,7 +211,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
|
|
|
209
211
|
| `color_palette` | Generate a color palette from a base color |
|
|
210
212
|
| `color_shades` | Generate shades or tints from a base color |
|
|
211
213
|
|
|
212
|
-
### Code (
|
|
214
|
+
### Code (12 tools)
|
|
213
215
|
| Tool | Description |
|
|
214
216
|
|------|-------------|
|
|
215
217
|
| `format_sql` | Format a SQL query with proper indentation |
|
|
@@ -223,6 +225,7 @@ claude mcp add utilix -- npx -y @utilix-tech/mcp
|
|
|
223
225
|
| `parse_github_url` | Parse a github.com URL (repo, pull request, issue, commit, file, or release) into structured components |
|
|
224
226
|
| `detect_redos` | Statically flag catastrophic-backtracking (ReDoS) risk in a regex: nested quantifiers, overlapping alternation, adjacent overlapping quantifiers |
|
|
225
227
|
| `lint_conventional_commit` | Lint a commit message against the Conventional Commits v1.0.0 spec: header format, blank-line separation, footer tokens, and BREAKING CHANGE casing |
|
|
228
|
+
| `test_gitignore_patterns` | Test a list of paths against a .gitignore file's patterns, following git's last-match-wins and negation rules |
|
|
226
229
|
|
|
227
230
|
### Data (8 tools)
|
|
228
231
|
| Tool | Description |
|
package/dist/index.js
CHANGED
|
@@ -4217,6 +4217,88 @@ server.tool(
|
|
|
4217
4217
|
return text(JSON.stringify(result, null, 2));
|
|
4218
4218
|
}
|
|
4219
4219
|
);
|
|
4220
|
+
var _LINK_REL_VALUES_MCP = [
|
|
4221
|
+
"preload",
|
|
4222
|
+
"preconnect",
|
|
4223
|
+
"prefetch",
|
|
4224
|
+
"prerender",
|
|
4225
|
+
"dns-prefetch",
|
|
4226
|
+
"canonical",
|
|
4227
|
+
"next",
|
|
4228
|
+
"prev",
|
|
4229
|
+
"alternate",
|
|
4230
|
+
"stylesheet",
|
|
4231
|
+
"icon",
|
|
4232
|
+
"modulepreload"
|
|
4233
|
+
];
|
|
4234
|
+
var _LINK_REL_INFO_MCP = {
|
|
4235
|
+
preload: "Tells the browser to fetch this resource early, before the parser would otherwise discover it, without blocking rendering. Requires an `as` attribute so the browser applies the right request priority and Content-Security-Policy check; omitting it commonly causes the resource to be fetched twice.",
|
|
4236
|
+
preconnect: "Tells the browser to start the connection handshake (DNS, TCP, TLS) to this origin early, before any real request to it is made, so the first actual request lands faster.",
|
|
4237
|
+
prefetch: "Tells the browser to fetch this resource at low priority for a likely future navigation and cache it. Unlike preload, it does not affect the current page load.",
|
|
4238
|
+
prerender: "Tells the browser to fetch and render this page in the background so navigating to it feels instant, at a real bandwidth and CPU cost if the user never navigates there.",
|
|
4239
|
+
"dns-prefetch": "Tells the browser to resolve this origin's DNS early, a lighter-weight version of preconnect that skips the TCP/TLS handshake.",
|
|
4240
|
+
canonical: "Tells search engines which URL is the authoritative version of this page, used to consolidate duplicate-content signals across query-string or protocol variants.",
|
|
4241
|
+
next: "Marks the next page in a paginated sequence, a hint search engines and some browsers use for pagination.",
|
|
4242
|
+
prev: "Marks the previous page in a paginated sequence.",
|
|
4243
|
+
alternate: "Points to an alternate version of this resource, such as a different language or an RSS feed.",
|
|
4244
|
+
stylesheet: 'Loads an external stylesheet, the same effect as a `<link rel="stylesheet">` tag but delivered as a response header instead.',
|
|
4245
|
+
icon: 'Points to this resource\'s favicon, the same effect as a `<link rel="icon">` tag but delivered as a response header instead.',
|
|
4246
|
+
modulepreload: "Tells the browser to fetch and parse this JavaScript module early, ahead of when the module graph would otherwise discover it."
|
|
4247
|
+
};
|
|
4248
|
+
function _buildLinkHeaderMcp(links) {
|
|
4249
|
+
if (links.length === 0) return { error: "At least one link entry is required" };
|
|
4250
|
+
const entries = [];
|
|
4251
|
+
for (const link of links) {
|
|
4252
|
+
const url = link.url.trim();
|
|
4253
|
+
const rel = link.rel.trim();
|
|
4254
|
+
if (!url) return { error: "Each link entry requires a non-empty url" };
|
|
4255
|
+
if (!rel) return { error: "Each link entry requires a non-empty rel" };
|
|
4256
|
+
if (!_LINK_REL_VALUES_MCP.includes(rel)) {
|
|
4257
|
+
return { error: `'${rel}' is not a supported rel value. Supported values: ${_LINK_REL_VALUES_MCP.join(", ")}` };
|
|
4258
|
+
}
|
|
4259
|
+
const as = link.as?.trim() || void 0;
|
|
4260
|
+
const type = link.type?.trim() || void 0;
|
|
4261
|
+
const crossorigin = link.crossorigin === true;
|
|
4262
|
+
let value = `<${url}>; rel="${rel}"`;
|
|
4263
|
+
if (as) value += `; as="${as}"`;
|
|
4264
|
+
if (type) value += `; type="${type}"`;
|
|
4265
|
+
if (crossorigin) value += "; crossorigin";
|
|
4266
|
+
entries.push({ url, rel, as, type, crossorigin: crossorigin || void 0, value, explanation: _LINK_REL_INFO_MCP[rel] });
|
|
4267
|
+
}
|
|
4268
|
+
const warnings = [];
|
|
4269
|
+
for (const entry of entries) {
|
|
4270
|
+
if (entry.rel === "preload" && !entry.as) {
|
|
4271
|
+
warnings.push(`preload link for "${entry.url}" is missing an \`as\` attribute \u2014 the browser may fetch it twice or apply the wrong request priority.`);
|
|
4272
|
+
}
|
|
4273
|
+
if ((entry.rel === "preconnect" || entry.rel === "dns-prefetch") && (entry.as || entry.type)) {
|
|
4274
|
+
warnings.push(`${entry.rel} link for "${entry.url}" sets \`as\`/\`type\`, which it ignores since no specific resource is being fetched yet.`);
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
const canonicalCount = entries.filter((e) => e.rel === "canonical").length;
|
|
4278
|
+
if (canonicalCount > 1) {
|
|
4279
|
+
warnings.push(`${canonicalCount} canonical links present \u2014 only one canonical URL should be declared per page.`);
|
|
4280
|
+
}
|
|
4281
|
+
const header = entries.map((e) => e.value).join(", ");
|
|
4282
|
+
return { header, headerName: "Link", snippet: `Link: ${header}`, links: entries, warnings };
|
|
4283
|
+
}
|
|
4284
|
+
server.tool(
|
|
4285
|
+
"build_link_header",
|
|
4286
|
+
"Build an HTTP Link response-header value from one or more URL/rel pairs (preload, preconnect, prefetch, canonical, pagination, etc.), including the as/type/crossorigin attributes preload needs, with a plain-English explanation of each entry and warnings for common mistakes like a preload missing `as`. Pure string assembly and lookup; it never fetches or validates that a URL exists.",
|
|
4287
|
+
{
|
|
4288
|
+
links: z.array(z.object({
|
|
4289
|
+
url: z.string().describe("The linked resource URL"),
|
|
4290
|
+
rel: z.enum(_LINK_REL_VALUES_MCP),
|
|
4291
|
+
as: z.string().optional().describe("Resource type hint, mainly used with preload/modulepreload"),
|
|
4292
|
+
type: z.string().optional().describe("MIME type of the linked resource"),
|
|
4293
|
+
crossorigin: z.boolean().optional()
|
|
4294
|
+
})).min(1).describe("One or more link entries")
|
|
4295
|
+
},
|
|
4296
|
+
async ({ links }) => {
|
|
4297
|
+
const result = _buildLinkHeaderMcp(links);
|
|
4298
|
+
if ("error" in result) return errText(result);
|
|
4299
|
+
return text(JSON.stringify(result, null, 2));
|
|
4300
|
+
}
|
|
4301
|
+
);
|
|
4220
4302
|
function _isValidIpv6HexGroup(g) {
|
|
4221
4303
|
return /^[0-9a-fA-F]{1,4}$/.test(g);
|
|
4222
4304
|
}
|
|
@@ -6339,5 +6421,180 @@ server.tool(
|
|
|
6339
6421
|
return text(JSON.stringify(result, null, 2));
|
|
6340
6422
|
}
|
|
6341
6423
|
);
|
|
6424
|
+
var _MAX_COOKIE_AGE_SECONDS_MCP = 400 * 24 * 60 * 60;
|
|
6425
|
+
function _checkSetCookieHeaderMcp(header) {
|
|
6426
|
+
if (!header.trim()) return { error: "A Set-Cookie header value is required" };
|
|
6427
|
+
const parts = header.split(";").map((p) => p.trim()).filter(Boolean);
|
|
6428
|
+
const [nameValue, ...attrParts] = parts;
|
|
6429
|
+
const eqIdx = nameValue.indexOf("=");
|
|
6430
|
+
if (eqIdx === -1) return { error: "Missing name=value pair" };
|
|
6431
|
+
const name = nameValue.slice(0, eqIdx).trim();
|
|
6432
|
+
const value = nameValue.slice(eqIdx + 1).trim();
|
|
6433
|
+
if (!name) return { error: "Cookie name cannot be empty" };
|
|
6434
|
+
const cookie = {
|
|
6435
|
+
name,
|
|
6436
|
+
value,
|
|
6437
|
+
domain: null,
|
|
6438
|
+
path: null,
|
|
6439
|
+
expires: null,
|
|
6440
|
+
maxAge: null,
|
|
6441
|
+
secure: false,
|
|
6442
|
+
httpOnly: false,
|
|
6443
|
+
sameSite: null
|
|
6444
|
+
};
|
|
6445
|
+
for (const attr of attrParts) {
|
|
6446
|
+
const idx = attr.indexOf("=");
|
|
6447
|
+
const key = (idx === -1 ? attr : attr.slice(0, idx)).trim().toLowerCase();
|
|
6448
|
+
const val = idx === -1 ? "" : attr.slice(idx + 1).trim();
|
|
6449
|
+
switch (key) {
|
|
6450
|
+
case "domain":
|
|
6451
|
+
cookie.domain = val || null;
|
|
6452
|
+
break;
|
|
6453
|
+
case "path":
|
|
6454
|
+
cookie.path = val || null;
|
|
6455
|
+
break;
|
|
6456
|
+
case "expires":
|
|
6457
|
+
cookie.expires = val || null;
|
|
6458
|
+
break;
|
|
6459
|
+
case "max-age": {
|
|
6460
|
+
const n = Number(val);
|
|
6461
|
+
cookie.maxAge = Number.isFinite(n) ? n : null;
|
|
6462
|
+
break;
|
|
6463
|
+
}
|
|
6464
|
+
case "secure":
|
|
6465
|
+
cookie.secure = true;
|
|
6466
|
+
break;
|
|
6467
|
+
case "httponly":
|
|
6468
|
+
cookie.httpOnly = true;
|
|
6469
|
+
break;
|
|
6470
|
+
case "samesite": {
|
|
6471
|
+
const normalized = val.toLowerCase();
|
|
6472
|
+
if (normalized === "strict") cookie.sameSite = "Strict";
|
|
6473
|
+
else if (normalized === "lax") cookie.sameSite = "Lax";
|
|
6474
|
+
else if (normalized === "none") cookie.sameSite = "None";
|
|
6475
|
+
break;
|
|
6476
|
+
}
|
|
6477
|
+
}
|
|
6478
|
+
}
|
|
6479
|
+
const issues = [];
|
|
6480
|
+
const warnings = [];
|
|
6481
|
+
if (cookie.sameSite === "None" && !cookie.secure) {
|
|
6482
|
+
issues.push("SameSite=None requires the Secure attribute \u2014 modern browsers reject this cookie without it.");
|
|
6483
|
+
}
|
|
6484
|
+
if (name.startsWith("__Host-")) {
|
|
6485
|
+
if (!cookie.secure) issues.push("__Host- prefixed cookies require the Secure attribute.");
|
|
6486
|
+
if (cookie.domain) issues.push("__Host- prefixed cookies must not set a Domain attribute.");
|
|
6487
|
+
if (cookie.path !== "/") issues.push("__Host- prefixed cookies must set Path=/.");
|
|
6488
|
+
} else if (name.startsWith("__Secure-")) {
|
|
6489
|
+
if (!cookie.secure) issues.push("__Secure- prefixed cookies require the Secure attribute.");
|
|
6490
|
+
}
|
|
6491
|
+
if (!cookie.secure) {
|
|
6492
|
+
warnings.push("Missing Secure attribute \u2014 the cookie can be sent over a plain HTTP connection.");
|
|
6493
|
+
}
|
|
6494
|
+
if (cookie.maxAge !== null && cookie.maxAge > _MAX_COOKIE_AGE_SECONDS_MCP) {
|
|
6495
|
+
warnings.push(`Max-Age (${cookie.maxAge}s) exceeds 400 days \u2014 Chromium-based browsers clamp cookie expiry to 400 days from when it's set, so this will be shortened.`);
|
|
6496
|
+
}
|
|
6497
|
+
return { cookie, issues, warnings, valid: issues.length === 0 };
|
|
6498
|
+
}
|
|
6499
|
+
server.tool(
|
|
6500
|
+
"check_set_cookie_header",
|
|
6501
|
+
"Parse a Set-Cookie header value and validate its attribute combination: SameSite=None requires Secure, the __Host-/__Secure- name prefixes each require their own attributes (__Host- additionally forbids Domain and requires Path=/), a missing Secure attribute is flagged, and a Max-Age beyond 400 days is flagged since Chromium-based browsers clamp it to that cap.",
|
|
6502
|
+
{
|
|
6503
|
+
header: z.string().describe('The Set-Cookie header value to parse and validate, e.g. "session=abc123; Secure; SameSite=None"')
|
|
6504
|
+
},
|
|
6505
|
+
async ({ header }) => {
|
|
6506
|
+
const result = _checkSetCookieHeaderMcp(header);
|
|
6507
|
+
if ("error" in result) return errText(result);
|
|
6508
|
+
return text(JSON.stringify(result, null, 2));
|
|
6509
|
+
}
|
|
6510
|
+
);
|
|
6511
|
+
function _globSegmentToRegexSourceMcp(segment) {
|
|
6512
|
+
let out = "";
|
|
6513
|
+
for (let i = 0; i < segment.length; i++) {
|
|
6514
|
+
const c = segment[i];
|
|
6515
|
+
if (c === "*") {
|
|
6516
|
+
out += "[^/]*";
|
|
6517
|
+
} else if (c === "?") {
|
|
6518
|
+
out += "[^/]";
|
|
6519
|
+
} else if (c === "[") {
|
|
6520
|
+
const close = segment.indexOf("]", i + 1);
|
|
6521
|
+
if (close === -1) {
|
|
6522
|
+
out += "\\[";
|
|
6523
|
+
} else {
|
|
6524
|
+
let cls = segment.slice(i + 1, close);
|
|
6525
|
+
if (cls.startsWith("!")) cls = "^" + cls.slice(1);
|
|
6526
|
+
out += `[${cls}]`;
|
|
6527
|
+
i = close;
|
|
6528
|
+
}
|
|
6529
|
+
} else {
|
|
6530
|
+
out += c.replace(/[.+^${}()|\\]/g, "\\$&");
|
|
6531
|
+
}
|
|
6532
|
+
}
|
|
6533
|
+
return out;
|
|
6534
|
+
}
|
|
6535
|
+
function _compileGitignorePatternMcp(raw, line) {
|
|
6536
|
+
let pattern = raw.replace(/\s+$/, "");
|
|
6537
|
+
if (!pattern || pattern.startsWith("#")) return null;
|
|
6538
|
+
let negate = false;
|
|
6539
|
+
if (pattern.startsWith("!")) {
|
|
6540
|
+
negate = true;
|
|
6541
|
+
pattern = pattern.slice(1);
|
|
6542
|
+
}
|
|
6543
|
+
pattern = pattern.replace(/\\(.)/g, "$1");
|
|
6544
|
+
if (!pattern) return null;
|
|
6545
|
+
const dirOnly = pattern.endsWith("/") && !pattern.endsWith("\\/");
|
|
6546
|
+
if (dirOnly) pattern = pattern.slice(0, -1);
|
|
6547
|
+
const hasLeadingSlash = pattern.startsWith("/");
|
|
6548
|
+
if (hasLeadingSlash) pattern = pattern.slice(1);
|
|
6549
|
+
const anchored = hasLeadingSlash || pattern.includes("/");
|
|
6550
|
+
const segments = pattern.split("/");
|
|
6551
|
+
const regexParts = segments.map((seg) => {
|
|
6552
|
+
if (seg === "**") return "(?:.*)";
|
|
6553
|
+
return _globSegmentToRegexSourceMcp(seg);
|
|
6554
|
+
});
|
|
6555
|
+
let body = regexParts.join("/");
|
|
6556
|
+
body = body.replace(/\(\?:\.\*\)\//g, "(?:.*/)?").replace(/\/\(\?:\.\*\)/g, "(?:/.*)?");
|
|
6557
|
+
const prefix = anchored ? "^" : "^(?:.*/)?";
|
|
6558
|
+
const suffix = "(?:/.*)?$";
|
|
6559
|
+
const regex = new RegExp(prefix + body + suffix);
|
|
6560
|
+
return { raw, line, negate, regex };
|
|
6561
|
+
}
|
|
6562
|
+
function _testGitignorePatternsMcp(gitignoreContent, paths) {
|
|
6563
|
+
if (!gitignoreContent.trim()) return { error: "gitignore content is required" };
|
|
6564
|
+
if (paths.length === 0) return { error: "At least one path is required" };
|
|
6565
|
+
const lines = gitignoreContent.split("\n");
|
|
6566
|
+
const patterns = [];
|
|
6567
|
+
lines.forEach((line, idx) => {
|
|
6568
|
+
const compiled = _compileGitignorePatternMcp(line, idx + 1);
|
|
6569
|
+
if (compiled) patterns.push(compiled);
|
|
6570
|
+
});
|
|
6571
|
+
return paths.map((rawPath) => {
|
|
6572
|
+
const path = rawPath.trim().replace(/^\.\//, "");
|
|
6573
|
+
let ignored = false;
|
|
6574
|
+
let matchedPattern = null;
|
|
6575
|
+
let matchedLine = null;
|
|
6576
|
+
for (const p of patterns) {
|
|
6577
|
+
if (p.regex.test(path)) {
|
|
6578
|
+
ignored = !p.negate;
|
|
6579
|
+
matchedPattern = p.raw.trim();
|
|
6580
|
+
matchedLine = p.line;
|
|
6581
|
+
}
|
|
6582
|
+
}
|
|
6583
|
+
return { path, ignored, matchedPattern, matchedLine };
|
|
6584
|
+
});
|
|
6585
|
+
}
|
|
6586
|
+
server.tool(
|
|
6587
|
+
"test_gitignore_patterns",
|
|
6588
|
+
"Test a list of paths against a .gitignore file's contents, following git's matching rules: a leading `!` negates a pattern, a trailing `/` restricts a pattern to directories, and a pattern with no interior `/` can match at any depth. The last matching pattern wins. Does not replicate git's rule that a negation cannot re-include a file whose parent directory was already excluded.",
|
|
6589
|
+
{
|
|
6590
|
+
gitignore: z.string().describe("The .gitignore file contents"),
|
|
6591
|
+
paths: z.array(z.string()).min(1).describe('Relative, forward-slash separated paths to test; use a trailing "/" to mark a directory')
|
|
6592
|
+
},
|
|
6593
|
+
async ({ gitignore, paths }) => {
|
|
6594
|
+
const result = _testGitignorePatternsMcp(gitignore, paths);
|
|
6595
|
+
if (!Array.isArray(result) && "error" in result) return errText(result);
|
|
6596
|
+
return text(JSON.stringify(result, null, 2));
|
|
6597
|
+
}
|
|
6598
|
+
);
|
|
6342
6599
|
var transport = new StdioServerTransport();
|
|
6343
6600
|
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.38.0",
|
|
4
4
|
"description": "MCP server exposing 152 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",
|