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
@@ -0,0 +1,128 @@
1
+ import { z } from "zod";
2
+ export function registerAnsiblePlaybookValidator(server) {
3
+ server.tool("ansible-playbook-validator", "Validate Ansible playbook syntax and structure", {
4
+ playbook: z.string().describe("Ansible playbook YAML content"),
5
+ }, async ({ playbook }) => {
6
+ if (!playbook?.trim()) {
7
+ return {
8
+ content: [
9
+ {
10
+ type: "text",
11
+ text: "Please provide playbook content to validate",
12
+ },
13
+ ],
14
+ };
15
+ }
16
+ try {
17
+ const yaml = await import('js-yaml');
18
+ let parsed;
19
+ try {
20
+ parsed = yaml.load(playbook);
21
+ }
22
+ catch (yamlError) {
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: `YAML syntax error: ${yamlError.message}`,
28
+ },
29
+ ],
30
+ };
31
+ }
32
+ const errors = [];
33
+ const warnings = [];
34
+ // Basic playbook structure validation
35
+ if (!Array.isArray(parsed)) {
36
+ errors.push('Playbook must be a YAML array of plays');
37
+ }
38
+ else {
39
+ // Validate each play
40
+ parsed.forEach((play, index) => {
41
+ const playNum = index + 1;
42
+ if (typeof play !== 'object' || play === null) {
43
+ errors.push(`Play ${playNum}: must be an object`);
44
+ return;
45
+ }
46
+ // Check required fields
47
+ if (!play.name && !play.hosts) {
48
+ warnings.push(`Play ${playNum}: should have either 'name' or 'hosts' field`);
49
+ }
50
+ if (!play.hosts) {
51
+ errors.push(`Play ${playNum}: missing required 'hosts' field`);
52
+ }
53
+ // Validate tasks
54
+ if (play.tasks) {
55
+ if (!Array.isArray(play.tasks)) {
56
+ errors.push(`Play ${playNum}: 'tasks' must be an array`);
57
+ }
58
+ else {
59
+ play.tasks.forEach((task, taskIndex) => {
60
+ const taskNum = taskIndex + 1;
61
+ if (typeof task !== 'object' || task === null) {
62
+ errors.push(`Play ${playNum}, Task ${taskNum}: must be an object`);
63
+ return;
64
+ }
65
+ // Check for task action
66
+ const taskActions = Object.keys(task).filter(key => !['name', 'when', 'tags', 'become', 'become_user', 'vars', 'register', 'failed_when', 'changed_when', 'ignore_errors', 'notify'].includes(key));
67
+ if (taskActions.length === 0) {
68
+ errors.push(`Play ${playNum}, Task ${taskNum}: no action module specified`);
69
+ }
70
+ else if (taskActions.length > 1) {
71
+ warnings.push(`Play ${playNum}, Task ${taskNum}: multiple action modules found: ${taskActions.join(', ')}`);
72
+ }
73
+ if (!task.name) {
74
+ warnings.push(`Play ${playNum}, Task ${taskNum}: should have a 'name' field for better readability`);
75
+ }
76
+ });
77
+ }
78
+ }
79
+ // Validate handlers
80
+ if (play.handlers) {
81
+ if (!Array.isArray(play.handlers)) {
82
+ errors.push(`Play ${playNum}: 'handlers' must be an array`);
83
+ }
84
+ }
85
+ // Check for common variables sections
86
+ if (play.vars && typeof play.vars !== 'object') {
87
+ errors.push(`Play ${playNum}: 'vars' must be an object`);
88
+ }
89
+ if (play.vars_files && !Array.isArray(play.vars_files)) {
90
+ errors.push(`Play ${playNum}: 'vars_files' must be an array`);
91
+ }
92
+ });
93
+ }
94
+ let result = '';
95
+ if (errors.length === 0 && warnings.length === 0) {
96
+ result = '✅ Playbook validation passed! No errors or warnings found.';
97
+ }
98
+ else {
99
+ if (errors.length > 0) {
100
+ result += `❌ Errors found:\n${errors.map(error => ` • ${error}`).join('\n')}`;
101
+ }
102
+ if (warnings.length > 0) {
103
+ if (result)
104
+ result += '\n\n';
105
+ result += `⚠️ Warnings:\n${warnings.map(warning => ` • ${warning}`).join('\n')}`;
106
+ }
107
+ }
108
+ return {
109
+ content: [
110
+ {
111
+ type: "text",
112
+ text: result,
113
+ },
114
+ ],
115
+ };
116
+ }
117
+ catch (error) {
118
+ return {
119
+ content: [
120
+ {
121
+ type: "text",
122
+ text: `Error validating playbook: ${error.message}`,
123
+ },
124
+ ],
125
+ };
126
+ }
127
+ });
128
+ }
@@ -0,0 +1,393 @@
1
+ export function registerAnsibleReference(server) {
2
+ server.tool("ansible-reference", "Get Ansible commands reference and cheatsheet", {}, async () => {
3
+ const reference = `# Ansible Quick Reference
4
+
5
+ ## Installation
6
+ \`\`\`bash
7
+ # Install via pip
8
+ pip install ansible
9
+
10
+ # Install via apt (Ubuntu/Debian)
11
+ sudo apt update
12
+ sudo apt install ansible
13
+
14
+ # Install via yum (CentOS/RHEL)
15
+ sudo yum install ansible
16
+
17
+ # Verify installation
18
+ ansible --version
19
+ \`\`\`
20
+
21
+ ## Configuration Files
22
+ - \`/etc/ansible/ansible.cfg\` - Global configuration
23
+ - \`~/.ansible.cfg\` - User configuration
24
+ - \`./ansible.cfg\` - Project configuration
25
+ - \`/etc/ansible/hosts\` - Default inventory file
26
+
27
+ ## Basic Commands
28
+ \`\`\`bash
29
+ # Run ad-hoc command
30
+ ansible <hosts> -m <module> -a "<arguments>"
31
+
32
+ # Run playbook
33
+ ansible-playbook playbook.yml
34
+
35
+ # Check playbook syntax
36
+ ansible-playbook --syntax-check playbook.yml
37
+
38
+ # Dry run (check mode)
39
+ ansible-playbook --check playbook.yml
40
+
41
+ # Limit to specific hosts
42
+ ansible-playbook -l <host_pattern> playbook.yml
43
+
44
+ # Use specific inventory
45
+ ansible-playbook -i inventory.ini playbook.yml
46
+
47
+ # Ask for sudo password
48
+ ansible-playbook --ask-become-pass playbook.yml
49
+ \`\`\`
50
+
51
+ ## Inventory Examples
52
+
53
+ ### INI Format
54
+ \`\`\`ini
55
+ [webservers]
56
+ web1.example.com
57
+ web2.example.com
58
+
59
+ [databases]
60
+ db1.example.com
61
+ db2.example.com
62
+
63
+ [production:children]
64
+ webservers
65
+ databases
66
+
67
+ [webservers:vars]
68
+ http_port=80
69
+ max_clients=200
70
+ \`\`\`
71
+
72
+ ### YAML Format
73
+ \`\`\`yaml
74
+ all:
75
+ children:
76
+ webservers:
77
+ hosts:
78
+ web1.example.com:
79
+ web2.example.com:
80
+ vars:
81
+ http_port: 80
82
+ max_clients: 200
83
+ databases:
84
+ hosts:
85
+ db1.example.com:
86
+ db2.example.com:
87
+ \`\`\`
88
+
89
+ ## Playbook Structure
90
+ \`\`\`yaml
91
+ ---
92
+ - name: Configure web servers
93
+ hosts: webservers
94
+ become: yes
95
+ vars:
96
+ http_port: 80
97
+
98
+ tasks:
99
+ - name: Install Apache
100
+ package:
101
+ name: apache2
102
+ state: present
103
+
104
+ - name: Start Apache service
105
+ service:
106
+ name: apache2
107
+ state: started
108
+ enabled: yes
109
+
110
+ handlers:
111
+ - name: restart apache
112
+ service:
113
+ name: apache2
114
+ state: restarted
115
+ \`\`\`
116
+
117
+ ## Common Modules
118
+
119
+ ### Package Management
120
+ \`\`\`yaml
121
+ # Install package
122
+ - package:
123
+ name: nginx
124
+ state: present
125
+
126
+ # Install specific version
127
+ - package:
128
+ name: nginx=1.18.0
129
+ state: present
130
+
131
+ # Remove package
132
+ - package:
133
+ name: nginx
134
+ state: absent
135
+ \`\`\`
136
+
137
+ ### Service Management
138
+ \`\`\`yaml
139
+ # Start and enable service
140
+ - service:
141
+ name: nginx
142
+ state: started
143
+ enabled: yes
144
+
145
+ # Stop service
146
+ - service:
147
+ name: nginx
148
+ state: stopped
149
+ \`\`\`
150
+
151
+ ### File Operations
152
+ \`\`\`yaml
153
+ # Copy file
154
+ - copy:
155
+ src: /local/file.txt
156
+ dest: /remote/file.txt
157
+ owner: root
158
+ group: root
159
+ mode: '0644'
160
+
161
+ # Create directory
162
+ - file:
163
+ path: /path/to/directory
164
+ state: directory
165
+ mode: '0755'
166
+
167
+ # Create symlink
168
+ - file:
169
+ src: /path/to/source
170
+ dest: /path/to/link
171
+ state: link
172
+ \`\`\`
173
+
174
+ ### Template
175
+ \`\`\`yaml
176
+ - template:
177
+ src: nginx.conf.j2
178
+ dest: /etc/nginx/nginx.conf
179
+ owner: root
180
+ group: root
181
+ mode: '0644'
182
+ notify: restart nginx
183
+ \`\`\`
184
+
185
+ ### Command Execution
186
+ \`\`\`yaml
187
+ # Run command
188
+ - command: /bin/ls -la /tmp
189
+
190
+ # Run shell command
191
+ - shell: echo "Hello" > /tmp/hello.txt
192
+
193
+ # Raw command (no processing)
194
+ - raw: /bin/ls
195
+ \`\`\`
196
+
197
+ ## Variables and Facts
198
+
199
+ ### Variable Files
200
+ \`\`\`yaml
201
+ # vars.yml
202
+ database_name: myapp
203
+ database_user: myuser
204
+ database_password: mypass
205
+ \`\`\`
206
+
207
+ ### Using Variables
208
+ \`\`\`yaml
209
+ - name: Create database
210
+ mysql_db:
211
+ name: "{{ database_name }}"
212
+ state: present
213
+ \`\`\`
214
+
215
+ ### Gathering Facts
216
+ \`\`\`yaml
217
+ # Disable fact gathering
218
+ - hosts: all
219
+ gather_facts: no
220
+
221
+ # Use facts
222
+ - debug:
223
+ msg: "OS is {{ ansible_distribution }}"
224
+ \`\`\`
225
+
226
+ ## Conditionals and Loops
227
+
228
+ ### Conditionals
229
+ \`\`\`yaml
230
+ - name: Install package on Ubuntu
231
+ package:
232
+ name: apache2
233
+ state: present
234
+ when: ansible_distribution == "Ubuntu"
235
+ \`\`\`
236
+
237
+ ### Loops
238
+ \`\`\`yaml
239
+ # Simple loop
240
+ - name: Install packages
241
+ package:
242
+ name: "{{ item }}"
243
+ state: present
244
+ loop:
245
+ - nginx
246
+ - git
247
+ - curl
248
+
249
+ # Loop with dictionaries
250
+ - name: Create users
251
+ user:
252
+ name: "{{ item.name }}"
253
+ group: "{{ item.group }}"
254
+ loop:
255
+ - { name: 'alice', group: 'admins' }
256
+ - { name: 'bob', group: 'users' }
257
+ \`\`\`
258
+
259
+ ## Handlers
260
+ \`\`\`yaml
261
+ tasks:
262
+ - name: Copy config file
263
+ copy:
264
+ src: nginx.conf
265
+ dest: /etc/nginx/nginx.conf
266
+ notify:
267
+ - restart nginx
268
+ - reload nginx
269
+
270
+ handlers:
271
+ - name: restart nginx
272
+ service:
273
+ name: nginx
274
+ state: restarted
275
+
276
+ - name: reload nginx
277
+ service:
278
+ name: nginx
279
+ state: reloaded
280
+ \`\`\`
281
+
282
+ ## Vault (Encryption)
283
+ \`\`\`bash
284
+ # Create encrypted file
285
+ ansible-vault create secret.yml
286
+
287
+ # Edit encrypted file
288
+ ansible-vault edit secret.yml
289
+
290
+ # Encrypt existing file
291
+ ansible-vault encrypt file.yml
292
+
293
+ # Decrypt file
294
+ ansible-vault decrypt file.yml
295
+
296
+ # View encrypted file
297
+ ansible-vault view secret.yml
298
+
299
+ # Run playbook with vault
300
+ ansible-playbook --ask-vault-pass playbook.yml
301
+ ansible-playbook --vault-password-file vault_pass.txt playbook.yml
302
+ \`\`\`
303
+
304
+ ## Roles Structure
305
+ \`\`\`
306
+ roles/
307
+ webserver/
308
+ tasks/
309
+ main.yml
310
+ handlers/
311
+ main.yml
312
+ templates/
313
+ nginx.conf.j2
314
+ files/
315
+ index.html
316
+ vars/
317
+ main.yml
318
+ defaults/
319
+ main.yml
320
+ meta/
321
+ main.yml
322
+ \`\`\`
323
+
324
+ ## Best Practices
325
+ - Use descriptive task names
326
+ - Organize with roles and includes
327
+ - Use variables for configuration
328
+ - Always use version control
329
+ - Test with \`--check\` mode first
330
+ - Use handlers for service restarts
331
+ - Make playbooks idempotent
332
+ - Use tags for selective execution
333
+ - Keep secrets in vault files
334
+
335
+ ## Common Patterns
336
+
337
+ ### Rolling Updates
338
+ \`\`\`yaml
339
+ - hosts: webservers
340
+ serial: 1
341
+ max_fail_percentage: 25
342
+ \`\`\`
343
+
344
+ ### Tags
345
+ \`\`\`yaml
346
+ - name: Install packages
347
+ package:
348
+ name: nginx
349
+ tags:
350
+ - install
351
+ - packages
352
+ \`\`\`
353
+
354
+ ### Error Handling
355
+ \`\`\`yaml
356
+ - name: Risky task
357
+ command: /bin/risky-command
358
+ ignore_errors: yes
359
+ register: result
360
+ failed_when: result.rc != 0 and "expected error" not in result.stderr
361
+ \`\`\`
362
+
363
+ ## Useful Commands
364
+ \`\`\`bash
365
+ # List hosts
366
+ ansible-inventory --list
367
+
368
+ # Check connectivity
369
+ ansible all -m ping
370
+
371
+ # Gather facts
372
+ ansible hostname -m setup
373
+
374
+ # Run with tags
375
+ ansible-playbook --tags "install,config" playbook.yml
376
+
377
+ # Skip tags
378
+ ansible-playbook --skip-tags "slow" playbook.yml
379
+
380
+ # Limit hosts
381
+ ansible-playbook -l "webservers:!web3" playbook.yml
382
+ \`\`\`
383
+ `;
384
+ return {
385
+ content: [
386
+ {
387
+ type: "text",
388
+ text: reference,
389
+ },
390
+ ],
391
+ };
392
+ });
393
+ }
@@ -0,0 +1,137 @@
1
+ import { z } from "zod";
2
+ import { pbkdf2Sync } from "crypto";
3
+ export function registerAnsibleVaultDecrypt(server) {
4
+ server.tool("ansible-vault-decrypt", "Decrypt Ansible Vault encrypted text", {
5
+ encryptedText: z.string().describe("Ansible Vault encrypted text to decrypt"),
6
+ password: z.string().describe("Password for decryption"),
7
+ }, async ({ encryptedText, password }) => {
8
+ if (!encryptedText?.trim()) {
9
+ return {
10
+ content: [
11
+ {
12
+ type: "text",
13
+ text: "Please provide encrypted text to decrypt",
14
+ },
15
+ ],
16
+ };
17
+ }
18
+ if (!password?.trim()) {
19
+ return {
20
+ content: [
21
+ {
22
+ type: "text",
23
+ text: "Please provide a password for decryption",
24
+ },
25
+ ],
26
+ };
27
+ }
28
+ try {
29
+ // Parse Ansible Vault format
30
+ const lines = encryptedText.trim().split('\n');
31
+ if (!lines[0].startsWith('$ANSIBLE_VAULT;')) {
32
+ return {
33
+ content: [
34
+ {
35
+ type: "text",
36
+ text: "Invalid Ansible Vault format: missing header",
37
+ },
38
+ ],
39
+ };
40
+ }
41
+ // Extract vault header info
42
+ const headerParts = lines[0].split(';');
43
+ if (headerParts.length < 3) {
44
+ return {
45
+ content: [
46
+ {
47
+ type: "text",
48
+ text: "Invalid Ansible Vault format: malformed header",
49
+ },
50
+ ],
51
+ };
52
+ }
53
+ const version = headerParts[1];
54
+ const cipher = headerParts[2];
55
+ const vaultId = headerParts.length > 3 ? headerParts[3] : null;
56
+ if (version !== '1.1' && version !== '1.2') {
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: `Unsupported Ansible Vault version: ${version}`,
62
+ },
63
+ ],
64
+ };
65
+ }
66
+ if (cipher !== 'AES256') {
67
+ return {
68
+ content: [
69
+ {
70
+ type: "text",
71
+ text: `Unsupported cipher: ${cipher}`,
72
+ },
73
+ ],
74
+ };
75
+ }
76
+ // Combine data lines and decode base64
77
+ const dataLines = lines.slice(1).join('');
78
+ const combined = Buffer.from(dataLines, 'base64');
79
+ if (combined.length < 80) { // 32 (salt) + 16 (iv) + 32 (mac) = 80 minimum
80
+ return {
81
+ content: [
82
+ {
83
+ type: "text",
84
+ text: "Invalid Ansible Vault format: insufficient data",
85
+ },
86
+ ],
87
+ };
88
+ }
89
+ // Extract components
90
+ const salt = combined.subarray(0, 32);
91
+ const iv = combined.subarray(32, 48);
92
+ const encryptedData = combined.subarray(48, -32);
93
+ const mac = combined.subarray(-32);
94
+ // Derive key using PBKDF2
95
+ const key = pbkdf2Sync(password, salt, 10000, 32, 'sha256');
96
+ // Verify HMAC
97
+ const crypto = await import('crypto');
98
+ const hmac = crypto.createHmac('sha256', key);
99
+ hmac.update(salt);
100
+ hmac.update(iv);
101
+ hmac.update(encryptedData);
102
+ const calculatedMac = hmac.digest();
103
+ if (!calculatedMac.equals(mac)) {
104
+ return {
105
+ content: [
106
+ {
107
+ type: "text",
108
+ text: "Decryption failed: invalid password or corrupted data",
109
+ },
110
+ ],
111
+ };
112
+ }
113
+ // Decrypt using AES-256-CTR
114
+ const decipher = crypto.createDecipheriv('aes-256-ctr', key, iv);
115
+ let decrypted = decipher.update(encryptedData, undefined, 'utf8');
116
+ decrypted += decipher.final('utf8');
117
+ return {
118
+ content: [
119
+ {
120
+ type: "text",
121
+ text: decrypted,
122
+ },
123
+ ],
124
+ };
125
+ }
126
+ catch (error) {
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text",
131
+ text: `Error decrypting text: ${error.message}`,
132
+ },
133
+ ],
134
+ };
135
+ }
136
+ });
137
+ }