it-tools-mcp 3.0.23 → 3.1.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/README.dockerhub.md +30 -17
- package/README.md +81 -33
- package/build/index.js +47 -15
- package/build/tools/ansible/ansible-inventory-generator/index.js +212 -0
- package/build/tools/ansible/ansible-playbook-validator/index.js +128 -0
- package/build/tools/ansible/ansible-reference/index.js +393 -0
- package/build/tools/ansible/ansible-vault-decrypt/index.js +137 -0
- package/build/tools/ansible/ansible-vault-encrypt/index.js +79 -0
- package/build/tools/color/color-hex-to-rgb/index.js +29 -0
- package/build/tools/{color.js → color/color-rgb-to-hex/index.js} +1 -27
- package/build/tools/crypto/basic-auth-generator/index.js +45 -0
- package/build/tools/crypto/bcrypt-hash/index.js +67 -0
- package/build/tools/crypto/bip39-generate/index.js +53 -0
- package/build/tools/crypto/hash-md5/index.js +19 -0
- package/build/tools/crypto/hash-sha1/index.js +19 -0
- package/build/tools/crypto/hash-sha256/index.js +19 -0
- package/build/tools/crypto/hash-sha512/index.js +19 -0
- package/build/tools/crypto/hmac-generator/index.js +37 -0
- package/build/tools/crypto/jwt-decode/index.js +41 -0
- package/build/tools/crypto/otp-code-generator/index.js +67 -0
- package/build/tools/crypto/password-generate/index.js +54 -0
- package/build/tools/crypto/token-generator/index.js +75 -0
- package/build/tools/dataFormat/html-to-markdown/index.js +34 -0
- package/build/tools/dataFormat/json-diff/index.js +94 -0
- package/build/tools/dataFormat/json-format/index.js +100 -0
- package/build/tools/dataFormat/json-minify/index.js +29 -0
- package/build/tools/dataFormat/json-to-csv/index.js +34 -0
- package/build/tools/dataFormat/json-to-toml/index.js +30 -0
- package/build/tools/dataFormat/markdown-to-html/index.js +32 -0
- package/build/tools/dataFormat/phone-format/index.js +35 -0
- package/build/tools/dataFormat/sql-format/index.js +37 -0
- package/build/tools/dataFormat/toml-to-json/index.js +29 -0
- package/build/tools/dataFormat/xml-format/index.js +44 -0
- package/build/tools/dataFormat/yaml-format/index.js +58 -0
- package/build/tools/{development.js → development/crontab-generate/index.js} +1 -129
- package/build/tools/development/html-prettifier/index.js +47 -0
- package/build/tools/development/javascript-prettifier/index.js +74 -0
- package/build/tools/development/list-converter/index.js +62 -0
- package/build/tools/development/markdown-toc-generator/index.js +53 -0
- package/build/tools/development/regex-tester/index.js +69 -0
- package/build/tools/docker/docker-compose-to-docker-run/index.js +138 -0
- package/build/tools/docker/docker-compose-validator/index.js +125 -0
- package/build/tools/docker/docker-reference/index.js +188 -0
- package/build/tools/docker/docker-run-to-docker-compose/index.js +117 -0
- package/build/tools/docker/traefik-compose-generator/index.js +98 -0
- package/build/tools/encoding/base64-decode/index.js +28 -0
- package/build/tools/encoding/base64-encode/index.js +16 -0
- package/build/tools/encoding/html-decode/index.js +21 -0
- package/build/tools/encoding/html-encode/index.js +21 -0
- package/build/tools/encoding/html-entities-extended/index.js +72 -0
- package/build/tools/encoding/text-to-binary/index.js +51 -0
- package/build/tools/encoding/url-decode/index.js +28 -0
- package/build/tools/encoding/url-encode/index.js +16 -0
- package/build/tools/forensic/file-type-identifier/index.js +90 -0
- package/build/tools/forensic/safelink-decoder/index.js +54 -0
- package/build/tools/forensic/url-fanger/index.js +52 -0
- package/build/tools/idGenerators/qr-generate/index.js +76 -0
- package/build/tools/idGenerators/svg-placeholder-generator/index.js +59 -0
- package/build/tools/idGenerators/ulid-generate/index.js +34 -0
- package/build/tools/idGenerators/uuid-generate/index.js +14 -0
- package/build/tools/math/math-evaluate/index.js +33 -0
- package/build/tools/math/number-base-converter/index.js +46 -0
- package/build/tools/math/percentage-calculator/index.js +50 -0
- package/build/tools/math/roman-numeral-converter/index.js +76 -0
- package/build/tools/math/temperature-converter/index.js +59 -0
- package/build/tools/math/unix-timestamp-converter/index.js +55 -0
- package/build/tools/network/cat/index.js +15 -0
- package/build/tools/network/cidr-to-ip-range/index.js +108 -0
- package/build/tools/network/curl/index.js +35 -0
- package/build/tools/network/dig/index.js +19 -0
- package/build/tools/network/grep/index.js +18 -0
- package/build/tools/network/head/index.js +17 -0
- package/build/tools/network/iban-validate/index.js +83 -0
- package/build/tools/network/ip-range-to-cidr/index.js +88 -0
- package/build/tools/network/ip-subnet-calculator/index.js +102 -0
- package/build/tools/network/ipv4-subnet-calc/index.js +112 -0
- package/build/tools/network/ipv6-subnet-calculator/index.js +104 -0
- package/build/tools/network/ipv6-ula-generator/index.js +65 -0
- package/build/tools/network/mac-address-generate/index.js +68 -0
- package/build/tools/network/nslookup/index.js +18 -0
- package/build/tools/network/ping/index.js +20 -0
- package/build/tools/network/ps/index.js +22 -0
- package/build/tools/network/random-port/index.js +53 -0
- package/build/tools/network/scp/index.js +134 -0
- package/build/tools/network/ssh/index.js +83 -0
- package/build/tools/network/tail/index.js +16 -0
- package/build/tools/network/telnet/index.js +45 -0
- package/build/tools/network/top/index.js +14 -0
- package/build/tools/network/url-parse/index.js +52 -0
- package/build/tools/physics/angle-converter/index.js +73 -0
- package/build/tools/physics/energy-converter/index.js +72 -0
- package/build/tools/physics/power-converter/index.js +71 -0
- package/build/tools/text/ascii-art-text/index.js +112 -0
- package/build/tools/text/distinct-words/index.js +30 -0
- package/build/tools/text/emoji-search/index.js +76 -0
- package/build/tools/text/lorem-ipsum-generator/index.js +87 -0
- package/build/tools/text/numeronym-generator/index.js +37 -0
- package/build/tools/text/slugify-string/index.js +44 -0
- package/build/tools/text/string-obfuscator/index.js +49 -0
- package/build/tools/text/text-camelcase/index.js +20 -0
- package/build/tools/text/text-capitalize/index.js +16 -0
- package/build/tools/text/text-diff/index.js +72 -0
- package/build/tools/text/text-kebabcase/index.js +20 -0
- package/build/tools/text/text-lowercase/index.js +15 -0
- package/build/tools/text/text-pascalcase/index.js +18 -0
- package/build/tools/text/text-snakecase/index.js +20 -0
- package/build/tools/text/text-stats/index.js +29 -0
- package/build/tools/text/text-to-nato-alphabet/index.js +57 -0
- package/build/tools/text/text-to-unicode/index.js +50 -0
- package/build/tools/text/text-to-unicode-names/index.js +34 -0
- package/build/tools/text/text-uppercase/index.js +15 -0
- package/build/tools/utility/css-prettifier/index.js +70 -0
- package/build/tools/utility/device-info/index.js +44 -0
- package/build/tools/utility/email-normalizer/index.js +73 -0
- package/build/tools/utility/http-status-codes/index.js +173 -0
- package/build/tools/utility/mime-types/index.js +121 -0
- package/build/tools/utility/port-numbers/index.js +106 -0
- package/build/tools/utility/rem-px-converter/index.js +63 -0
- package/package.json +3 -3
- package/build/tools/crypto.js +0 -445
- package/build/tools/dataFormat.js +0 -535
- package/build/tools/encoding.js +0 -240
- package/build/tools/idGenerators.js +0 -180
- package/build/tools/math.js +0 -310
- package/build/tools/network.js +0 -931
- package/build/tools/text.js +0 -678
- package/build/tools/utility.js +0 -407
|
@@ -1,74 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { CronExpressionParser } from 'cron-parser';
|
|
3
|
-
export function
|
|
4
|
-
// Regex tester
|
|
5
|
-
server.tool("regex-tester", "Test regular expressions against text", {
|
|
6
|
-
pattern: z.string().describe("Regular expression pattern"),
|
|
7
|
-
text: z.string().describe("Text to test against the regex"),
|
|
8
|
-
flags: z.string().optional().describe("Regex flags (g, i, m, s, u, y)"),
|
|
9
|
-
}, async ({ pattern, text, flags }) => {
|
|
10
|
-
try {
|
|
11
|
-
const regex = new RegExp(pattern, flags);
|
|
12
|
-
const matches = text.match(regex);
|
|
13
|
-
const globalMatches = flags?.includes('g') ? [...text.matchAll(new RegExp(pattern, flags))] : null;
|
|
14
|
-
const isMatch = regex.test(text);
|
|
15
|
-
let result = `Regex Test Results:
|
|
16
|
-
|
|
17
|
-
Pattern: ${pattern}
|
|
18
|
-
Flags: ${flags || 'none'}
|
|
19
|
-
Text: ${text}
|
|
20
|
-
|
|
21
|
-
Match: ${isMatch ? '✅ Yes' : '❌ No'}`;
|
|
22
|
-
if (matches) {
|
|
23
|
-
result += `\n\nFirst Match: ${matches[0]}`;
|
|
24
|
-
if (matches.length > 1) {
|
|
25
|
-
result += `\nCapture Groups: ${matches.slice(1).join(', ')}`;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
if (globalMatches && globalMatches.length > 0) {
|
|
29
|
-
result += `\n\nAll Matches (${globalMatches.length}):`;
|
|
30
|
-
globalMatches.forEach((match, index) => {
|
|
31
|
-
result += `\n${index + 1}. "${match[0]}" at position ${match.index}`;
|
|
32
|
-
if (match.length > 1) {
|
|
33
|
-
result += ` (groups: ${match.slice(1).join(', ')})`;
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
result += `\n\nCommon Regex Patterns:
|
|
38
|
-
• Email: ^[\\w\\.-]+@[\\w\\.-]+\\.[a-zA-Z]{2,}$
|
|
39
|
-
• Phone: ^\\+?[1-9]\\d{1,14}$
|
|
40
|
-
• URL: ^https?:\\/\\/.+
|
|
41
|
-
• IPv4: ^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$
|
|
42
|
-
• Date (YYYY-MM-DD): ^\\d{4}-\\d{2}-\\d{2}$`;
|
|
43
|
-
return {
|
|
44
|
-
content: [
|
|
45
|
-
{
|
|
46
|
-
type: "text",
|
|
47
|
-
text: result,
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
catch (error) {
|
|
53
|
-
return {
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: "text",
|
|
57
|
-
text: `Error testing regex: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
58
|
-
|
|
59
|
-
Common regex flags:
|
|
60
|
-
• g - Global (find all matches)
|
|
61
|
-
• i - Case insensitive
|
|
62
|
-
• m - Multiline
|
|
63
|
-
• s - Dot matches newline
|
|
64
|
-
• u - Unicode
|
|
65
|
-
• y - Sticky`,
|
|
66
|
-
},
|
|
67
|
-
],
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
// Crontab generator
|
|
3
|
+
export function registerCrontabGenerate(server) {
|
|
72
4
|
server.tool("crontab-generate", "Generate crontab expressions", {
|
|
73
5
|
minute: z.string().describe("Minute (0-59, *, */n, n-m)").optional(),
|
|
74
6
|
hour: z.string().describe("Hour (0-23, *, */n, n-m)").optional(),
|
|
@@ -204,64 +136,4 @@ Note: Use 'crontab -e' to edit your crontab file.`,
|
|
|
204
136
|
};
|
|
205
137
|
}
|
|
206
138
|
});
|
|
207
|
-
// List converter
|
|
208
|
-
server.tool("list-converter", "Convert between different list formats (comma-separated, line-separated, etc.)", {
|
|
209
|
-
list: z.string().describe("Input list to convert"),
|
|
210
|
-
inputFormat: z.enum(["comma", "semicolon", "newline", "space", "pipe"]).describe("Input format"),
|
|
211
|
-
outputFormat: z.enum(["comma", "semicolon", "newline", "space", "pipe", "json", "quoted"]).describe("Output format"),
|
|
212
|
-
trim: z.boolean().describe("Trim whitespace from items").optional(),
|
|
213
|
-
}, async ({ list, inputFormat, outputFormat, trim = true }) => {
|
|
214
|
-
try {
|
|
215
|
-
const separators = {
|
|
216
|
-
comma: ',',
|
|
217
|
-
semicolon: ';',
|
|
218
|
-
newline: '\n',
|
|
219
|
-
space: ' ',
|
|
220
|
-
pipe: '|'
|
|
221
|
-
};
|
|
222
|
-
// Parse input list
|
|
223
|
-
const inputSeparator = separators[inputFormat];
|
|
224
|
-
let items = list.split(inputSeparator);
|
|
225
|
-
if (trim) {
|
|
226
|
-
items = items.map(item => item.trim()).filter(item => item.length > 0);
|
|
227
|
-
}
|
|
228
|
-
// Convert to output format
|
|
229
|
-
let result = '';
|
|
230
|
-
switch (outputFormat) {
|
|
231
|
-
case 'json':
|
|
232
|
-
result = JSON.stringify(items, null, 2);
|
|
233
|
-
break;
|
|
234
|
-
case 'quoted':
|
|
235
|
-
result = items.map(item => `"${item.replace(/"/g, '\\"')}"`).join(', ');
|
|
236
|
-
break;
|
|
237
|
-
default:
|
|
238
|
-
const outputSeparator = separators[outputFormat];
|
|
239
|
-
result = items.join(outputSeparator);
|
|
240
|
-
break;
|
|
241
|
-
}
|
|
242
|
-
return {
|
|
243
|
-
content: [
|
|
244
|
-
{
|
|
245
|
-
type: "text",
|
|
246
|
-
text: `Converted list:
|
|
247
|
-
${result}
|
|
248
|
-
|
|
249
|
-
Items count: ${items.length}
|
|
250
|
-
Input format: ${inputFormat}
|
|
251
|
-
Output format: ${outputFormat}`,
|
|
252
|
-
},
|
|
253
|
-
],
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
catch (error) {
|
|
257
|
-
return {
|
|
258
|
-
content: [
|
|
259
|
-
{
|
|
260
|
-
type: "text",
|
|
261
|
-
text: `Error converting list: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
262
|
-
},
|
|
263
|
-
],
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
139
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerHtmlPrettifier(server) {
|
|
3
|
+
server.tool("html-prettifier", "Format and beautify HTML code", {
|
|
4
|
+
html: z.string().describe("HTML code to prettify"),
|
|
5
|
+
indentSize: z.number().optional().default(2).describe("Number of spaces for indentation")
|
|
6
|
+
}, async ({ html, indentSize }) => {
|
|
7
|
+
try {
|
|
8
|
+
// Simple HTML prettifier
|
|
9
|
+
let formatted = html;
|
|
10
|
+
let indentLevel = 0;
|
|
11
|
+
const indent = ' '.repeat(indentSize);
|
|
12
|
+
// Remove extra whitespace
|
|
13
|
+
formatted = formatted.replace(/>\s*</g, '><');
|
|
14
|
+
// Add line breaks and indentation
|
|
15
|
+
formatted = formatted.replace(/(<\/?[^>]+>)/g, (match) => {
|
|
16
|
+
if (match.startsWith('</') && !match.includes('/>')) {
|
|
17
|
+
indentLevel--;
|
|
18
|
+
}
|
|
19
|
+
const result = '\n' + indent.repeat(indentLevel) + match;
|
|
20
|
+
if (!match.startsWith('</') && !match.includes('/>') && !match.includes('<input') && !match.includes('<img') && !match.includes('<br') && !match.includes('<hr')) {
|
|
21
|
+
indentLevel++;
|
|
22
|
+
}
|
|
23
|
+
return result;
|
|
24
|
+
});
|
|
25
|
+
// Clean up
|
|
26
|
+
formatted = formatted.trim();
|
|
27
|
+
return {
|
|
28
|
+
content: [{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: `Prettified HTML:
|
|
31
|
+
|
|
32
|
+
\`\`\`html
|
|
33
|
+
${formatted}
|
|
34
|
+
\`\`\``
|
|
35
|
+
}]
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{
|
|
41
|
+
type: "text",
|
|
42
|
+
text: `Error formatting HTML: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
43
|
+
}]
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerJavascriptPrettifier(server) {
|
|
3
|
+
server.tool("javascript-prettifier", "Format and beautify JavaScript/CSS code", {
|
|
4
|
+
code: z.string().describe("JavaScript or CSS code to prettify"),
|
|
5
|
+
type: z.enum(["javascript", "css"]).describe("Type of code to format"),
|
|
6
|
+
indentSize: z.number().optional().default(2).describe("Number of spaces for indentation")
|
|
7
|
+
}, async ({ code, type, indentSize }) => {
|
|
8
|
+
try {
|
|
9
|
+
let formatted = code;
|
|
10
|
+
const indent = ' '.repeat(indentSize);
|
|
11
|
+
if (type === "javascript") {
|
|
12
|
+
// Basic JS formatting
|
|
13
|
+
formatted = formatted
|
|
14
|
+
.replace(/\s*{\s*/g, ' {\n')
|
|
15
|
+
.replace(/\s*}\s*/g, '\n}\n')
|
|
16
|
+
.replace(/;\s*/g, ';\n')
|
|
17
|
+
.replace(/,\s*/g, ', ')
|
|
18
|
+
.split('\n')
|
|
19
|
+
.map(line => line.trim())
|
|
20
|
+
.filter(line => line.length > 0)
|
|
21
|
+
.map((line, index, lines) => {
|
|
22
|
+
let indentLevel = 0;
|
|
23
|
+
for (let i = 0; i < index; i++) {
|
|
24
|
+
if (lines[i].includes('{'))
|
|
25
|
+
indentLevel++;
|
|
26
|
+
if (lines[i].includes('}'))
|
|
27
|
+
indentLevel--;
|
|
28
|
+
}
|
|
29
|
+
if (line.includes('}'))
|
|
30
|
+
indentLevel--;
|
|
31
|
+
return indent.repeat(Math.max(0, indentLevel)) + line;
|
|
32
|
+
})
|
|
33
|
+
.join('\n');
|
|
34
|
+
}
|
|
35
|
+
else if (type === "css") {
|
|
36
|
+
// Basic CSS formatting
|
|
37
|
+
formatted = formatted
|
|
38
|
+
.replace(/\s*{\s*/g, ' {\n')
|
|
39
|
+
.replace(/\s*}\s*/g, '\n}\n')
|
|
40
|
+
.replace(/;\s*/g, ';\n')
|
|
41
|
+
.replace(/:\s*/g, ': ')
|
|
42
|
+
.split('\n')
|
|
43
|
+
.map(line => line.trim())
|
|
44
|
+
.filter(line => line.length > 0)
|
|
45
|
+
.map((line, index, lines) => {
|
|
46
|
+
if (line.includes('}'))
|
|
47
|
+
return line;
|
|
48
|
+
if (line.includes('{'))
|
|
49
|
+
return line;
|
|
50
|
+
return indent + line;
|
|
51
|
+
})
|
|
52
|
+
.join('\n');
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
content: [{
|
|
56
|
+
type: "text",
|
|
57
|
+
text: `Prettified ${type.toUpperCase()}:
|
|
58
|
+
|
|
59
|
+
\`\`\`${type}
|
|
60
|
+
${formatted}
|
|
61
|
+
\`\`\``
|
|
62
|
+
}]
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
return {
|
|
67
|
+
content: [{
|
|
68
|
+
type: "text",
|
|
69
|
+
text: `Error formatting ${type}: ${error instanceof Error ? error.message : 'Unknown error'}`
|
|
70
|
+
}]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerListConverter(server) {
|
|
3
|
+
server.tool("list-converter", "Convert between different list formats (comma-separated, line-separated, etc.)", {
|
|
4
|
+
list: z.string().describe("Input list to convert"),
|
|
5
|
+
inputFormat: z.enum(["comma", "semicolon", "newline", "space", "pipe"]).describe("Input format"),
|
|
6
|
+
outputFormat: z.enum(["comma", "semicolon", "newline", "space", "pipe", "json", "quoted"]).describe("Output format"),
|
|
7
|
+
trim: z.boolean().describe("Trim whitespace from items").optional(),
|
|
8
|
+
}, async ({ list, inputFormat, outputFormat, trim = true }) => {
|
|
9
|
+
try {
|
|
10
|
+
const separators = {
|
|
11
|
+
comma: ',',
|
|
12
|
+
semicolon: ';',
|
|
13
|
+
newline: '\n',
|
|
14
|
+
space: ' ',
|
|
15
|
+
pipe: '|'
|
|
16
|
+
};
|
|
17
|
+
// Parse input list
|
|
18
|
+
const inputSeparator = separators[inputFormat];
|
|
19
|
+
let items = list.split(inputSeparator);
|
|
20
|
+
if (trim) {
|
|
21
|
+
items = items.map(item => item.trim()).filter(item => item.length > 0);
|
|
22
|
+
}
|
|
23
|
+
// Convert to output format
|
|
24
|
+
let result = '';
|
|
25
|
+
switch (outputFormat) {
|
|
26
|
+
case 'json':
|
|
27
|
+
result = JSON.stringify(items, null, 2);
|
|
28
|
+
break;
|
|
29
|
+
case 'quoted':
|
|
30
|
+
result = items.map(item => `"${item.replace(/"/g, '\\"')}"`).join(', ');
|
|
31
|
+
break;
|
|
32
|
+
default:
|
|
33
|
+
const outputSeparator = separators[outputFormat];
|
|
34
|
+
result = items.join(outputSeparator);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
content: [
|
|
39
|
+
{
|
|
40
|
+
type: "text",
|
|
41
|
+
text: `Converted list:
|
|
42
|
+
${result}
|
|
43
|
+
|
|
44
|
+
Items count: ${items.length}
|
|
45
|
+
Input format: ${inputFormat}
|
|
46
|
+
Output format: ${outputFormat}`,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
content: [
|
|
54
|
+
{
|
|
55
|
+
type: "text",
|
|
56
|
+
text: `Error converting list: ${error instanceof Error ? error.message : 'Unknown error'}`,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerMarkdownTocGenerator(server) {
|
|
3
|
+
server.tool("markdown-toc-generator", "Generate a table of contents from Markdown headers", {
|
|
4
|
+
markdown: z.string().describe("Markdown content to generate TOC from"),
|
|
5
|
+
maxLevel: z.number().optional().default(6).describe("Maximum header level to include (1-6)"),
|
|
6
|
+
generateAnchors: z.boolean().optional().default(true).describe("Whether to generate anchor links")
|
|
7
|
+
}, async ({ markdown, maxLevel, generateAnchors }) => {
|
|
8
|
+
// Extract headers from markdown
|
|
9
|
+
const headerRegex = /^(#{1,6})\s+(.+)$/gm;
|
|
10
|
+
const headers = [];
|
|
11
|
+
let match;
|
|
12
|
+
while ((match = headerRegex.exec(markdown)) !== null) {
|
|
13
|
+
const level = match[1].length;
|
|
14
|
+
if (level <= maxLevel) {
|
|
15
|
+
const text = match[2].trim();
|
|
16
|
+
// Generate anchor from text
|
|
17
|
+
const anchor = text
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace(/[^\w\s-]/g, '')
|
|
20
|
+
.replace(/\s+/g, '-')
|
|
21
|
+
.replace(/-+/g, '-')
|
|
22
|
+
.replace(/^-|-$/g, '');
|
|
23
|
+
headers.push({ level, text, anchor });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (headers.length === 0) {
|
|
27
|
+
return {
|
|
28
|
+
content: [{
|
|
29
|
+
type: "text",
|
|
30
|
+
text: "No headers found in the markdown content."
|
|
31
|
+
}]
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
// Generate TOC
|
|
35
|
+
const tocLines = [];
|
|
36
|
+
headers.forEach(header => {
|
|
37
|
+
const indent = ' '.repeat(header.level - 1);
|
|
38
|
+
const link = generateAnchors ? `[${header.text}](#${header.anchor})` : header.text;
|
|
39
|
+
tocLines.push(`${indent}- ${link}`);
|
|
40
|
+
});
|
|
41
|
+
const toc = tocLines.join('\n');
|
|
42
|
+
return {
|
|
43
|
+
content: [{
|
|
44
|
+
type: "text",
|
|
45
|
+
text: `Table of Contents:
|
|
46
|
+
|
|
47
|
+
${toc}
|
|
48
|
+
|
|
49
|
+
${generateAnchors ? '\nAnchors have been generated based on header text.' : ''}`
|
|
50
|
+
}]
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerRegexTester(server) {
|
|
3
|
+
server.tool("regex-tester", "Test regular expressions against text", {
|
|
4
|
+
pattern: z.string().describe("Regular expression pattern"),
|
|
5
|
+
text: z.string().describe("Text to test against the regex"),
|
|
6
|
+
flags: z.string().optional().describe("Regex flags (g, i, m, s, u, y)"),
|
|
7
|
+
}, async ({ pattern, text, flags }) => {
|
|
8
|
+
try {
|
|
9
|
+
const regex = new RegExp(pattern, flags);
|
|
10
|
+
const matches = text.match(regex);
|
|
11
|
+
const globalMatches = flags?.includes('g') ? [...text.matchAll(new RegExp(pattern, flags))] : null;
|
|
12
|
+
const isMatch = regex.test(text);
|
|
13
|
+
let result = `Regex Test Results:
|
|
14
|
+
|
|
15
|
+
Pattern: ${pattern}
|
|
16
|
+
Flags: ${flags || 'none'}
|
|
17
|
+
Text: ${text}
|
|
18
|
+
|
|
19
|
+
Match: ${isMatch ? '✅ Yes' : '❌ No'}`;
|
|
20
|
+
if (matches) {
|
|
21
|
+
result += `\n\nFirst Match: ${matches[0]}`;
|
|
22
|
+
if (matches.length > 1) {
|
|
23
|
+
result += `\nCapture Groups: ${matches.slice(1).join(', ')}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (globalMatches && globalMatches.length > 0) {
|
|
27
|
+
result += `\n\nAll Matches (${globalMatches.length}):`;
|
|
28
|
+
globalMatches.forEach((match, index) => {
|
|
29
|
+
result += `\n${index + 1}. "${match[0]}" at position ${match.index}`;
|
|
30
|
+
if (match.length > 1) {
|
|
31
|
+
result += ` (groups: ${match.slice(1).join(', ')})`;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
result += `\n\nCommon Regex Patterns:
|
|
36
|
+
• Email: ^[\\w\\.-]+@[\\w\\.-]+\\.[a-zA-Z]{2,}$
|
|
37
|
+
• Phone: ^\\+?[1-9]\\d{1,14}$
|
|
38
|
+
• URL: ^https?:\\/\\/.+
|
|
39
|
+
• IPv4: ^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$
|
|
40
|
+
• Date (YYYY-MM-DD): ^\\d{4}-\\d{2}-\\d{2}$`;
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: "text",
|
|
45
|
+
text: result,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: "text",
|
|
55
|
+
text: `Error testing regex: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
56
|
+
|
|
57
|
+
Common regex flags:
|
|
58
|
+
• g - Global (find all matches)
|
|
59
|
+
• i - Case insensitive
|
|
60
|
+
• m - Multiline
|
|
61
|
+
• s - Dot matches newline
|
|
62
|
+
• u - Unicode
|
|
63
|
+
• y - Sticky`,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import yaml from "js-yaml";
|
|
3
|
+
export function registerDockerComposeToRun(server) {
|
|
4
|
+
server.tool("docker-compose-to-docker-run", "Convert Docker Compose files to docker run commands", {
|
|
5
|
+
content: z.string().describe("Docker Compose file content to convert"),
|
|
6
|
+
}, async ({ content }) => {
|
|
7
|
+
if (!content?.trim()) {
|
|
8
|
+
return {
|
|
9
|
+
content: [
|
|
10
|
+
{
|
|
11
|
+
type: "text",
|
|
12
|
+
text: "Please provide a Docker Compose file content to convert",
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const parsed = yaml.load(content);
|
|
19
|
+
if (!parsed?.services) {
|
|
20
|
+
return {
|
|
21
|
+
content: [
|
|
22
|
+
{
|
|
23
|
+
type: "text",
|
|
24
|
+
text: "Invalid Docker Compose file: missing services section",
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const commands = [];
|
|
30
|
+
for (const [serviceName, service] of Object.entries(parsed.services)) {
|
|
31
|
+
const serviceObj = service;
|
|
32
|
+
let command = 'docker run';
|
|
33
|
+
// Add detached mode by default
|
|
34
|
+
command += ' -d';
|
|
35
|
+
// Add name
|
|
36
|
+
command += ` --name ${serviceName}`;
|
|
37
|
+
// Add ports
|
|
38
|
+
if (serviceObj.ports) {
|
|
39
|
+
for (const port of serviceObj.ports) {
|
|
40
|
+
if (typeof port === 'string') {
|
|
41
|
+
command += ` -p ${port}`;
|
|
42
|
+
}
|
|
43
|
+
else if (typeof port === 'object' && port.published && port.target) {
|
|
44
|
+
command += ` -p ${port.published}:${port.target}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Add volumes
|
|
49
|
+
if (serviceObj.volumes) {
|
|
50
|
+
for (const volume of serviceObj.volumes) {
|
|
51
|
+
if (typeof volume === 'string') {
|
|
52
|
+
command += ` -v ${volume}`;
|
|
53
|
+
}
|
|
54
|
+
else if (typeof volume === 'object' && volume.source && volume.target) {
|
|
55
|
+
command += ` -v ${volume.source}:${volume.target}`;
|
|
56
|
+
if (volume.read_only) {
|
|
57
|
+
command += ':ro';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Add environment variables
|
|
63
|
+
if (serviceObj.environment) {
|
|
64
|
+
if (Array.isArray(serviceObj.environment)) {
|
|
65
|
+
for (const env of serviceObj.environment) {
|
|
66
|
+
command += ` -e "${env}"`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (typeof serviceObj.environment === 'object') {
|
|
70
|
+
for (const [key, value] of Object.entries(serviceObj.environment)) {
|
|
71
|
+
command += ` -e "${key}=${value}"`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Add restart policy
|
|
76
|
+
if (serviceObj.restart) {
|
|
77
|
+
command += ` --restart ${serviceObj.restart}`;
|
|
78
|
+
}
|
|
79
|
+
// Add networks
|
|
80
|
+
if (serviceObj.networks) {
|
|
81
|
+
if (Array.isArray(serviceObj.networks)) {
|
|
82
|
+
for (const network of serviceObj.networks) {
|
|
83
|
+
command += ` --network ${network}`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (typeof serviceObj.networks === 'object') {
|
|
87
|
+
for (const networkName of Object.keys(serviceObj.networks)) {
|
|
88
|
+
command += ` --network ${networkName}`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Add working directory
|
|
93
|
+
if (serviceObj.working_dir) {
|
|
94
|
+
command += ` -w ${serviceObj.working_dir}`;
|
|
95
|
+
}
|
|
96
|
+
// Add user
|
|
97
|
+
if (serviceObj.user) {
|
|
98
|
+
command += ` --user ${serviceObj.user}`;
|
|
99
|
+
}
|
|
100
|
+
// Add image
|
|
101
|
+
if (serviceObj.image) {
|
|
102
|
+
command += ` ${serviceObj.image}`;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
command += ` <image-name>`;
|
|
106
|
+
}
|
|
107
|
+
// Add command/entrypoint
|
|
108
|
+
if (serviceObj.command) {
|
|
109
|
+
if (Array.isArray(serviceObj.command)) {
|
|
110
|
+
command += ` ${serviceObj.command.join(' ')}`;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
command += ` ${serviceObj.command}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
commands.push(command);
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: commands.join('\n\n'),
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
return {
|
|
129
|
+
content: [
|
|
130
|
+
{
|
|
131
|
+
type: "text",
|
|
132
|
+
text: `Error converting Docker Compose to run commands: ${error.message}`,
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|