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.
Files changed (127) hide show
  1. package/README.dockerhub.md +30 -17
  2. package/README.md +81 -33
  3. package/build/index.js +47 -15
  4. package/build/tools/ansible/ansible-inventory-generator/index.js +212 -0
  5. package/build/tools/ansible/ansible-playbook-validator/index.js +128 -0
  6. package/build/tools/ansible/ansible-reference/index.js +393 -0
  7. package/build/tools/ansible/ansible-vault-decrypt/index.js +137 -0
  8. package/build/tools/ansible/ansible-vault-encrypt/index.js +79 -0
  9. package/build/tools/color/color-hex-to-rgb/index.js +29 -0
  10. package/build/tools/{color.js → color/color-rgb-to-hex/index.js} +1 -27
  11. package/build/tools/crypto/basic-auth-generator/index.js +45 -0
  12. package/build/tools/crypto/bcrypt-hash/index.js +67 -0
  13. package/build/tools/crypto/bip39-generate/index.js +53 -0
  14. package/build/tools/crypto/hash-md5/index.js +19 -0
  15. package/build/tools/crypto/hash-sha1/index.js +19 -0
  16. package/build/tools/crypto/hash-sha256/index.js +19 -0
  17. package/build/tools/crypto/hash-sha512/index.js +19 -0
  18. package/build/tools/crypto/hmac-generator/index.js +37 -0
  19. package/build/tools/crypto/jwt-decode/index.js +41 -0
  20. package/build/tools/crypto/otp-code-generator/index.js +67 -0
  21. package/build/tools/crypto/password-generate/index.js +54 -0
  22. package/build/tools/crypto/token-generator/index.js +75 -0
  23. package/build/tools/dataFormat/html-to-markdown/index.js +34 -0
  24. package/build/tools/dataFormat/json-diff/index.js +94 -0
  25. package/build/tools/dataFormat/json-format/index.js +100 -0
  26. package/build/tools/dataFormat/json-minify/index.js +29 -0
  27. package/build/tools/dataFormat/json-to-csv/index.js +34 -0
  28. package/build/tools/dataFormat/json-to-toml/index.js +30 -0
  29. package/build/tools/dataFormat/markdown-to-html/index.js +32 -0
  30. package/build/tools/dataFormat/phone-format/index.js +35 -0
  31. package/build/tools/dataFormat/sql-format/index.js +37 -0
  32. package/build/tools/dataFormat/toml-to-json/index.js +29 -0
  33. package/build/tools/dataFormat/xml-format/index.js +44 -0
  34. package/build/tools/dataFormat/yaml-format/index.js +58 -0
  35. package/build/tools/{development.js → development/crontab-generate/index.js} +1 -129
  36. package/build/tools/development/html-prettifier/index.js +47 -0
  37. package/build/tools/development/javascript-prettifier/index.js +74 -0
  38. package/build/tools/development/list-converter/index.js +62 -0
  39. package/build/tools/development/markdown-toc-generator/index.js +53 -0
  40. package/build/tools/development/regex-tester/index.js +69 -0
  41. package/build/tools/docker/docker-compose-to-docker-run/index.js +138 -0
  42. package/build/tools/docker/docker-compose-validator/index.js +125 -0
  43. package/build/tools/docker/docker-reference/index.js +188 -0
  44. package/build/tools/docker/docker-run-to-docker-compose/index.js +117 -0
  45. package/build/tools/docker/traefik-compose-generator/index.js +98 -0
  46. package/build/tools/encoding/base64-decode/index.js +28 -0
  47. package/build/tools/encoding/base64-encode/index.js +16 -0
  48. package/build/tools/encoding/html-decode/index.js +21 -0
  49. package/build/tools/encoding/html-encode/index.js +21 -0
  50. package/build/tools/encoding/html-entities-extended/index.js +72 -0
  51. package/build/tools/encoding/text-to-binary/index.js +51 -0
  52. package/build/tools/encoding/url-decode/index.js +28 -0
  53. package/build/tools/encoding/url-encode/index.js +16 -0
  54. package/build/tools/forensic/file-type-identifier/index.js +90 -0
  55. package/build/tools/forensic/safelink-decoder/index.js +54 -0
  56. package/build/tools/forensic/url-fanger/index.js +52 -0
  57. package/build/tools/idGenerators/qr-generate/index.js +76 -0
  58. package/build/tools/idGenerators/svg-placeholder-generator/index.js +59 -0
  59. package/build/tools/idGenerators/ulid-generate/index.js +34 -0
  60. package/build/tools/idGenerators/uuid-generate/index.js +14 -0
  61. package/build/tools/math/math-evaluate/index.js +33 -0
  62. package/build/tools/math/number-base-converter/index.js +46 -0
  63. package/build/tools/math/percentage-calculator/index.js +50 -0
  64. package/build/tools/math/roman-numeral-converter/index.js +76 -0
  65. package/build/tools/math/temperature-converter/index.js +59 -0
  66. package/build/tools/math/unix-timestamp-converter/index.js +55 -0
  67. package/build/tools/network/cat/index.js +15 -0
  68. package/build/tools/network/cidr-to-ip-range/index.js +108 -0
  69. package/build/tools/network/curl/index.js +35 -0
  70. package/build/tools/network/dig/index.js +19 -0
  71. package/build/tools/network/grep/index.js +18 -0
  72. package/build/tools/network/head/index.js +17 -0
  73. package/build/tools/network/iban-validate/index.js +83 -0
  74. package/build/tools/network/ip-range-to-cidr/index.js +88 -0
  75. package/build/tools/network/ip-subnet-calculator/index.js +102 -0
  76. package/build/tools/network/ipv4-subnet-calc/index.js +112 -0
  77. package/build/tools/network/ipv6-subnet-calculator/index.js +104 -0
  78. package/build/tools/network/ipv6-ula-generator/index.js +65 -0
  79. package/build/tools/network/mac-address-generate/index.js +68 -0
  80. package/build/tools/network/nslookup/index.js +18 -0
  81. package/build/tools/network/ping/index.js +20 -0
  82. package/build/tools/network/ps/index.js +22 -0
  83. package/build/tools/network/random-port/index.js +53 -0
  84. package/build/tools/network/scp/index.js +134 -0
  85. package/build/tools/network/ssh/index.js +83 -0
  86. package/build/tools/network/tail/index.js +16 -0
  87. package/build/tools/network/telnet/index.js +45 -0
  88. package/build/tools/network/top/index.js +14 -0
  89. package/build/tools/network/url-parse/index.js +52 -0
  90. package/build/tools/physics/angle-converter/index.js +73 -0
  91. package/build/tools/physics/energy-converter/index.js +72 -0
  92. package/build/tools/physics/power-converter/index.js +71 -0
  93. package/build/tools/text/ascii-art-text/index.js +112 -0
  94. package/build/tools/text/distinct-words/index.js +30 -0
  95. package/build/tools/text/emoji-search/index.js +76 -0
  96. package/build/tools/text/lorem-ipsum-generator/index.js +87 -0
  97. package/build/tools/text/numeronym-generator/index.js +37 -0
  98. package/build/tools/text/slugify-string/index.js +44 -0
  99. package/build/tools/text/string-obfuscator/index.js +49 -0
  100. package/build/tools/text/text-camelcase/index.js +20 -0
  101. package/build/tools/text/text-capitalize/index.js +16 -0
  102. package/build/tools/text/text-diff/index.js +72 -0
  103. package/build/tools/text/text-kebabcase/index.js +20 -0
  104. package/build/tools/text/text-lowercase/index.js +15 -0
  105. package/build/tools/text/text-pascalcase/index.js +18 -0
  106. package/build/tools/text/text-snakecase/index.js +20 -0
  107. package/build/tools/text/text-stats/index.js +29 -0
  108. package/build/tools/text/text-to-nato-alphabet/index.js +57 -0
  109. package/build/tools/text/text-to-unicode/index.js +50 -0
  110. package/build/tools/text/text-to-unicode-names/index.js +34 -0
  111. package/build/tools/text/text-uppercase/index.js +15 -0
  112. package/build/tools/utility/css-prettifier/index.js +70 -0
  113. package/build/tools/utility/device-info/index.js +44 -0
  114. package/build/tools/utility/email-normalizer/index.js +73 -0
  115. package/build/tools/utility/http-status-codes/index.js +173 -0
  116. package/build/tools/utility/mime-types/index.js +121 -0
  117. package/build/tools/utility/port-numbers/index.js +106 -0
  118. package/build/tools/utility/rem-px-converter/index.js +63 -0
  119. package/package.json +3 -3
  120. package/build/tools/crypto.js +0 -445
  121. package/build/tools/dataFormat.js +0 -535
  122. package/build/tools/encoding.js +0 -240
  123. package/build/tools/idGenerators.js +0 -180
  124. package/build/tools/math.js +0 -310
  125. package/build/tools/network.js +0 -931
  126. package/build/tools/text.js +0 -678
  127. 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 registerDevelopmentTools(server) {
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
+ }