it-tools-mcp 3.2.10 → 3.6.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 (119) hide show
  1. package/README.dockerhub.md +2 -2
  2. package/README.md +14 -7
  3. package/build/index.js +223 -53
  4. package/build/tools/ansible/ansible-inventory-generator/index.js +5 -2
  5. package/build/tools/ansible/ansible-playbook-validator/index.js +5 -2
  6. package/build/tools/ansible/ansible-reference/index.js +4 -1
  7. package/build/tools/ansible/ansible-vault-decrypt/index.js +6 -3
  8. package/build/tools/ansible/ansible-vault-encrypt/index.js +7 -4
  9. package/build/tools/color/color-hex-to-rgb/index.js +5 -2
  10. package/build/tools/color/color-rgb-to-hex/index.js +7 -4
  11. package/build/tools/crypto/basic-auth-generator/index.js +6 -3
  12. package/build/tools/crypto/bcrypt-hash/index.js +7 -4
  13. package/build/tools/crypto/bip39-generate/index.js +5 -2
  14. package/build/tools/crypto/hash-md5/index.js +5 -2
  15. package/build/tools/crypto/hash-sha1/index.js +5 -2
  16. package/build/tools/crypto/hash-sha256/index.js +5 -2
  17. package/build/tools/crypto/hash-sha512/index.js +5 -2
  18. package/build/tools/crypto/hmac-generator/index.js +7 -4
  19. package/build/tools/crypto/jwt-decode/index.js +5 -2
  20. package/build/tools/crypto/otp-code-generator/index.js +7 -4
  21. package/build/tools/crypto/password-generate/index.js +9 -6
  22. package/build/tools/crypto/token-generator/index.js +7 -4
  23. package/build/tools/dataFormat/html-to-markdown/index.js +5 -2
  24. package/build/tools/dataFormat/json-diff/index.js +6 -3
  25. package/build/tools/dataFormat/json-format/index.js +7 -3
  26. package/build/tools/dataFormat/json-minify/index.js +5 -2
  27. package/build/tools/dataFormat/json-to-csv/index.js +6 -3
  28. package/build/tools/dataFormat/json-to-toml/index.js +5 -2
  29. package/build/tools/dataFormat/markdown-to-html/index.js +5 -2
  30. package/build/tools/dataFormat/phone-format/index.js +6 -3
  31. package/build/tools/dataFormat/sql-format/index.js +6 -3
  32. package/build/tools/dataFormat/toml-to-json/index.js +5 -2
  33. package/build/tools/dataFormat/xml-format/index.js +6 -3
  34. package/build/tools/dataFormat/yaml-format/index.js +5 -2
  35. package/build/tools/development/crontab-generate/index.js +9 -6
  36. package/build/tools/development/html-prettifier/index.js +6 -3
  37. package/build/tools/development/javascript-prettifier/index.js +7 -4
  38. package/build/tools/development/list-converter/index.js +8 -5
  39. package/build/tools/development/markdown-toc-generator/index.js +7 -4
  40. package/build/tools/development/regex-tester/index.js +7 -4
  41. package/build/tools/docker/docker-compose-to-docker-run/index.js +5 -2
  42. package/build/tools/docker/docker-compose-validator/index.js +5 -2
  43. package/build/tools/docker/docker-reference/index.js +4 -1
  44. package/build/tools/docker/docker-run-to-docker-compose/index.js +5 -2
  45. package/build/tools/docker/traefik-compose-generator/index.js +9 -6
  46. package/build/tools/encoding/base64-decode/index.js +6 -2
  47. package/build/tools/encoding/base64-encode/index.js +27 -11
  48. package/build/tools/encoding/html-decode/index.js +5 -2
  49. package/build/tools/encoding/html-encode/index.js +5 -2
  50. package/build/tools/encoding/html-entities-extended/index.js +6 -3
  51. package/build/tools/encoding/text-to-binary/index.js +6 -3
  52. package/build/tools/encoding/url-decode/index.js +5 -2
  53. package/build/tools/encoding/url-encode/index.js +5 -2
  54. package/build/tools/forensic/file-type-identifier/index.js +6 -3
  55. package/build/tools/forensic/safelink-decoder/index.js +5 -2
  56. package/build/tools/forensic/url-fanger/index.js +6 -3
  57. package/build/tools/idGenerators/qr-generate/index.js +6 -3
  58. package/build/tools/idGenerators/svg-placeholder-generator/index.js +9 -6
  59. package/build/tools/idGenerators/ulid-generate/index.js +4 -1
  60. package/build/tools/idGenerators/uuid-generate/index.js +4 -1
  61. package/build/tools/math/math-evaluate/index.js +5 -2
  62. package/build/tools/math/number-base-converter/index.js +7 -4
  63. package/build/tools/math/percentage-calculator/index.js +7 -4
  64. package/build/tools/math/roman-numeral-converter/index.js +5 -2
  65. package/build/tools/math/temperature-converter/index.js +7 -4
  66. package/build/tools/math/unix-timestamp-converter/index.js +5 -2
  67. package/build/tools/network/cat/index.js +5 -2
  68. package/build/tools/network/cidr-to-ip-range/index.js +5 -2
  69. package/build/tools/network/curl/index.js +11 -6
  70. package/build/tools/network/dig/index.js +6 -3
  71. package/build/tools/network/grep/index.js +6 -3
  72. package/build/tools/network/head/index.js +6 -3
  73. package/build/tools/network/iban-validate/index.js +5 -2
  74. package/build/tools/network/ip-range-to-cidr/index.js +6 -3
  75. package/build/tools/network/ip-subnet-calculator/index.js +6 -3
  76. package/build/tools/network/ipv4-subnet-calc/index.js +5 -2
  77. package/build/tools/network/ipv6-subnet-calculator/index.js +6 -3
  78. package/build/tools/network/ipv6-ula-generator/index.js +5 -2
  79. package/build/tools/network/mac-address-generate/index.js +6 -3
  80. package/build/tools/network/nslookup/index.js +5 -2
  81. package/build/tools/network/ping/index.js +9 -4
  82. package/build/tools/network/ps/index.js +4 -1
  83. package/build/tools/network/random-port/index.js +8 -5
  84. package/build/tools/network/scp/index.js +10 -7
  85. package/build/tools/network/ssh/index.js +8 -5
  86. package/build/tools/network/tail/index.js +6 -3
  87. package/build/tools/network/telnet/index.js +6 -3
  88. package/build/tools/network/top/index.js +4 -1
  89. package/build/tools/network/url-parse/index.js +5 -2
  90. package/build/tools/physics/angle-converter/index.js +11 -8
  91. package/build/tools/physics/energy-converter/index.js +13 -10
  92. package/build/tools/physics/power-converter/index.js +13 -10
  93. package/build/tools/text/ascii-art-text/index.js +6 -3
  94. package/build/tools/text/distinct-words/index.js +5 -2
  95. package/build/tools/text/emoji-search/index.js +5 -2
  96. package/build/tools/text/lorem-ipsum-generator/index.js +6 -3
  97. package/build/tools/text/numeronym-generator/index.js +5 -2
  98. package/build/tools/text/slugify-string/index.js +7 -4
  99. package/build/tools/text/string-obfuscator/index.js +6 -3
  100. package/build/tools/text/text-camelcase/index.js +5 -2
  101. package/build/tools/text/text-capitalize/index.js +5 -2
  102. package/build/tools/text/text-diff/index.js +6 -3
  103. package/build/tools/text/text-kebabcase/index.js +5 -2
  104. package/build/tools/text/text-lowercase/index.js +5 -2
  105. package/build/tools/text/text-pascalcase/index.js +5 -2
  106. package/build/tools/text/text-snakecase/index.js +5 -2
  107. package/build/tools/text/text-stats/index.js +5 -2
  108. package/build/tools/text/text-to-nato-alphabet/index.js +6 -3
  109. package/build/tools/text/text-to-unicode/index.js +6 -3
  110. package/build/tools/text/text-to-unicode-names/index.js +5 -2
  111. package/build/tools/text/text-uppercase/index.js +5 -2
  112. package/build/tools/utility/css-prettifier/index.js +6 -3
  113. package/build/tools/utility/device-info/index.js +4 -1
  114. package/build/tools/utility/email-normalizer/index.js +5 -2
  115. package/build/tools/utility/http-status-codes/index.js +5 -2
  116. package/build/tools/utility/mime-types/index.js +6 -3
  117. package/build/tools/utility/port-numbers/index.js +5 -2
  118. package/build/tools/utility/rem-px-converter/index.js +8 -4
  119. package/package.json +1 -1
@@ -11,7 +11,7 @@
11
11
  [![Docker Platform](https://img.shields.io/badge/platform-linux%2Famd64%20%7C%20linux%2Farm64-blue)](https://hub.docker.com/r/wrenchpilot/it-tools-mcp)
12
12
  [![GitHub Stars](https://img.shields.io/github/stars/wrenchpilot/it-tools-mcp?style=social)](https://github.com/wrenchpilot/it-tools-mcp/stargazers)
13
13
 
14
- A comprehensive Model Context Protocol (MCP) server that provides access to **112 IT tools and utilities** commonly used by developers, system administrators, and IT professionals. This server exposes a complete set of tools for encoding/decoding, text manipulation, hashing, network utilities, and many other common development and IT tasks.
14
+ A comprehensive Model Context Protocol (MCP) server that provides access to over **100 IT tools and utilities** commonly used by developers, system administrators, and IT professionals. This server exposes a complete set of tools for encoding/decoding, text manipulation, hashing, network utilities, and many other common development and IT tasks.
15
15
 
16
16
  ## Using with VS Code
17
17
 
@@ -62,7 +62,7 @@ Add to your VS Code `settings.json`:
62
62
  }
63
63
  ```
64
64
 
65
- See the complete list of all 112 tools with detailed parameters on [GitHub](https://github.com/wrenchpilot/it-tools-mcp#available-tools)
65
+ See the complete list of tools with detailed parameters on [GitHub](https://github.com/wrenchpilot/it-tools-mcp#available-tools)
66
66
 
67
67
  ## 📸 Examples in Action
68
68
 
package/README.md CHANGED
@@ -14,17 +14,24 @@
14
14
 
15
15
  > **📝 Note**: A condensed version of this README is automatically synced to [Docker Hub](https://hub.docker.com/r/wrenchpilot/it-tools-mcp) due to character limits.
16
16
 
17
- A comprehensive Model Context Protocol (MCP) server that provides access to 112 IT tools and utilities commonly used by developers, system administrators, and IT professionals. This server exposes a complete set of tools for encoding/decoding, text manipulation, hashing, network utilities, and many other common development and IT tasks.
17
+ A comprehensive Model Context Protocol (MCP) server that provides access to over 100 IT tools and utilities commonly used by developers, system administrators, and IT professionals. This server exposes a complete set of tools for encoding/decoding, text manipulation, hashing, network utilities, and many other common development and IT tasks.
18
18
 
19
19
  ## 📦 Installation & Setup
20
20
 
21
21
  ### Using with VS Code
22
22
 
23
- **[Install IT Tools MCP in VS Code](vscode:mcp/install?%7B%22name%22%3A%22it-tools-mcp%22%2C%22gallery%22%3Atrue%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22it-tools-mcp%22%5D%7D)**
23
+ **Quick Install:**
24
24
 
25
- *Click the link above in VS Code to install the IT Tools MCP server.*
25
+ [![Install in VS Code](https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=it-tools&config=%7B%22command%22%3A%20%22npx%22%2C%22args%22%3A%20%5B%22it-tools-mcp%22%5D%7D) [![Install in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=it-tools&config=%7B%22command%22%3A%20%22npx%22%2C%22args%22%3A%20%5B%22it-tools-mcp%22%5D%7D&quality=insiders)
26
26
 
27
- Add to your VS Code `settings.json`:
27
+ **Install:**
28
+
29
+ 1. Open VS Code
30
+ 2. Press `Ctrl+Shift+P` (or `Cmd+Shift+P` on Mac)
31
+ 3. Type "MCP" and select "MCP: Add Server"
32
+ 4. Choose "NPM Package" and enter: `it-tools-mcp`
33
+
34
+ **Or manually add to your VS Code `settings.json`:**
28
35
 
29
36
  #### Node
30
37
 
@@ -89,7 +96,7 @@ echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"base64-enc
89
96
 
90
97
  ## 🛠️ Tool Categories
91
98
 
92
- This MCP server provides **112 tools** across **14 categories**:
99
+ This MCP server provides over **100 tools** across **14 categories**:
93
100
 
94
101
  - **� Ansible Tools** (5 tools): Vault encryption/decryption, inventory parser, playbook validator, reference
95
102
  - **🎨 Color Tools** (2 tools): Hex ↔ RGB conversion
@@ -258,14 +265,14 @@ Built with **TypeScript**, **Zod** validation, and **MCP SDK** for robust, type-
258
265
  This project was developed using **VS Code**, **Copilot Chat Agent**, **Playwright MCP**, and the **Claude Sonnet 4 Model**, demonstrating the power of AI-assisted software development:
259
266
 
260
267
  - **Intelligent Code Generation**: Claude Sonnet analyzed requirements and generated comprehensive tool implementations
261
- - **Schema Validation**: Automatically identified and resolved JSON schema validation issues across 112 tools
268
+ - **Schema Validation**: Automatically identified and resolved JSON schema validation issues across tools
262
269
  - **Docker Optimization**: Created production-ready Docker workflows and multi-stage builds
263
270
  - **Documentation**: Generated comprehensive README with examples and tool reference tables
264
271
  - **Testing**: Implemented robust error handling and validation throughout the codebase
265
272
 
266
273
  **Key AI Contributions:**
267
274
 
268
- - 🔧 **Tool Implementation**: All 112 tools designed and implemented with AI assistance
275
+ - 🔧 **Tool Implementation**: All tools designed and implemented with AI assistance
269
276
  - 📦 **Docker Setup**: Complete containerization with GitHub Actions CI/CD pipeline
270
277
  - 🔍 **Schema Cleanup**: Systematic removal of unsupported Zod keywords from all tool definitions
271
278
  - 📚 **Documentation**: Comprehensive README with usage examples and tool catalogs
package/build/index.js CHANGED
@@ -199,29 +199,34 @@ export function getResourceUsage() {
199
199
  };
200
200
  }
201
201
  /**
202
- * Security headers for responses (if applicable)
202
+ * Input validation and security utilities
203
203
  */
204
- export const SECURITY_HEADERS = {
205
- 'X-Content-Type-Options': 'nosniff',
206
- 'X-Frame-Options': 'DENY',
207
- 'X-XSS-Protection': '1; mode=block',
208
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
209
- };
210
- // Helper to read version from package.json at runtime (ESM compatible)
211
- function getPackageVersion() {
212
- // Use import.meta.url to get the directory in ESM
204
+ // Get package metadata for enhanced server info
205
+ function getPackageMetadata() {
213
206
  const __dirname = path.dirname(new URL(import.meta.url).pathname);
214
207
  const pkgPath = path.resolve(__dirname, '../package.json');
215
208
  const pkgRaw = fs.readFileSync(pkgPath, 'utf-8');
216
- return JSON.parse(pkgRaw).version;
209
+ const pkg = JSON.parse(pkgRaw);
210
+ return {
211
+ name: pkg.name,
212
+ version: pkg.version,
213
+ description: pkg.description,
214
+ keywords: pkg.keywords,
215
+ author: pkg.author,
216
+ repository: pkg.repository,
217
+ homepage: pkg.homepage
218
+ };
217
219
  }
218
- // Create server instance
220
+ // Create server instance with enhanced metadata
221
+ const packageInfo = getPackageMetadata();
219
222
  const server = new McpServer({
220
223
  name: "it-tools-mcp",
221
- version: getPackageVersion(),
224
+ version: packageInfo.version,
222
225
  capabilities: {
223
226
  resources: {},
224
227
  tools: {},
228
+ prompts: {},
229
+ logging: {}
225
230
  },
226
231
  });
227
232
  // Helper function to dynamically load modular tools from a category directory
@@ -243,13 +248,14 @@ async function loadModularTools(server, category) {
243
248
  const registerFunction = Object.values(toolModule).find((fn) => typeof fn === 'function' && fn.name.startsWith('register'));
244
249
  if (registerFunction) {
245
250
  registerFunction(server);
251
+ console.error(`Loaded tool: ${category}/${toolDir}`);
246
252
  }
247
253
  else {
248
254
  console.warn(`No register function found in ${toolPath}`);
249
255
  }
250
256
  }
251
257
  catch (error) {
252
- console.error(`Failed to load tool ${category}/${toolDir}:`, error);
258
+ console.error(`Failed to load tool ${category}/${toolDir}:`, error instanceof Error ? error.message : 'Unknown error');
253
259
  }
254
260
  }
255
261
  else {
@@ -257,58 +263,222 @@ async function loadModularTools(server, category) {
257
263
  }
258
264
  }
259
265
  }
260
- // Register all tool modules (dynamically for faster startup, with per-module timing)
266
+ // Dynamic tool discovery and metadata generation
267
+ async function discoverTools() {
268
+ const toolsBaseDir = path.join(__dirname, 'tools');
269
+ if (!fs.existsSync(toolsBaseDir)) {
270
+ return { toolCategories: {}, totalToolCount: 0 };
271
+ }
272
+ // Discover categories dynamically from the filesystem
273
+ const categories = fs.readdirSync(toolsBaseDir, { withFileTypes: true })
274
+ .filter(dirent => dirent.isDirectory())
275
+ .map(dirent => dirent.name)
276
+ .sort(); // Sort for consistent ordering
277
+ const toolCategories = {};
278
+ let totalToolCount = 0;
279
+ for (const category of categories) {
280
+ const toolsDir = path.join(toolsBaseDir, category);
281
+ const toolDirs = fs.readdirSync(toolsDir, { withFileTypes: true })
282
+ .filter(dirent => dirent.isDirectory())
283
+ .map(dirent => dirent.name)
284
+ .sort(); // Sort tools within category
285
+ if (toolDirs.length > 0) {
286
+ toolCategories[category] = {
287
+ description: await getCategoryDescription(category, toolDirs),
288
+ tools: toolDirs
289
+ };
290
+ totalToolCount += toolDirs.length;
291
+ }
292
+ }
293
+ return { toolCategories, totalToolCount };
294
+ }
295
+ // Generate category description by examining actual tool metadata
296
+ async function getCategoryDescription(category, toolNames) {
297
+ const toolsDir = path.join(__dirname, 'tools', category);
298
+ const toolDescriptions = [];
299
+ // Try to extract descriptions from a few sample tools in the category
300
+ const samplesToCheck = Math.min(3, toolNames.length); // Check up to 3 tools for description
301
+ for (let i = 0; i < samplesToCheck; i++) {
302
+ const toolDir = toolNames[i];
303
+ const toolPath = path.join(toolsDir, toolDir, 'index.js');
304
+ if (fs.existsSync(toolPath)) {
305
+ try {
306
+ const toolModule = await import(`./${path.relative(__dirname, toolPath).replace(/\\/g, '/')}`);
307
+ // Look for description in the tool registration
308
+ const registerFunction = Object.values(toolModule).find((fn) => typeof fn === 'function' && fn.name.startsWith('register'));
309
+ if (registerFunction) {
310
+ // Create a mock server to capture the tool registration
311
+ const mockServer = {
312
+ registerTool: (name, config) => {
313
+ if (config.description && typeof config.description === 'string') {
314
+ toolDescriptions.push(config.description);
315
+ }
316
+ }
317
+ };
318
+ try {
319
+ registerFunction(mockServer);
320
+ }
321
+ catch (error) {
322
+ // Ignore errors in mock registration
323
+ }
324
+ }
325
+ }
326
+ catch (error) {
327
+ // Continue if we can't load a tool
328
+ }
329
+ }
330
+ }
331
+ // Generate category description based on collected tool descriptions
332
+ if (toolDescriptions.length > 0) {
333
+ // Create a summary from the actual tool descriptions
334
+ const uniqueDescriptions = [...new Set(toolDescriptions)];
335
+ if (uniqueDescriptions.length === 1) {
336
+ // If all tools have the same description, use it directly
337
+ return uniqueDescriptions[0];
338
+ }
339
+ else if (uniqueDescriptions.length <= 3) {
340
+ // If we have 2-3 unique descriptions, combine them
341
+ return `${category.charAt(0).toUpperCase() + category.slice(1)} tools: ${uniqueDescriptions.join(', ')}`;
342
+ }
343
+ else {
344
+ // If we have many descriptions, provide a generic summary
345
+ return `${category.charAt(0).toUpperCase() + category.slice(1)} category with ${toolNames.length} tools including: ${uniqueDescriptions.slice(0, 2).join(', ')} and more`;
346
+ }
347
+ }
348
+ // Fallback: generate description from category name and tool count
349
+ const categoryTitle = category.charAt(0).toUpperCase() + category.slice(1);
350
+ return `${categoryTitle} tools and utilities (${toolNames.length} tools available)`;
351
+ }
352
+ // Register all tools dynamically by discovering categories from filesystem
261
353
  async function registerAllTools(server) {
262
- // All categories to load modularly
263
- const categories = [
264
- 'docker', 'ansible', 'color', 'encoding', 'idGenerators',
265
- 'crypto', 'dataFormat', 'text', 'network', 'math',
266
- 'utility', 'development', 'forensic', 'physics'
267
- ];
354
+ const toolsBaseDir = path.join(__dirname, 'tools');
355
+ if (!fs.existsSync(toolsBaseDir)) {
356
+ console.warn('Tools directory does not exist:', toolsBaseDir);
357
+ return;
358
+ }
359
+ // Discover categories dynamically from the filesystem
360
+ const categories = fs.readdirSync(toolsBaseDir, { withFileTypes: true })
361
+ .filter(dirent => dirent.isDirectory())
362
+ .map(dirent => dirent.name)
363
+ .sort(); // Sort for consistent ordering
268
364
  for (const category of categories) {
269
365
  await loadModularTools(server, category);
270
366
  }
271
367
  }
272
- // Add resource monitoring tool
273
- server.tool("system-info", "Get system resource usage and server information", {}, async () => {
368
+ // Add comprehensive system and server information tool
369
+ server.registerTool("system-info", {
370
+ description: "Get comprehensive system information, server details, available tool categories, and resource usage",
371
+ inputSchema: {
372
+ include_tools: z.boolean().optional().describe("Include detailed information about all available tools"),
373
+ category: z.string().optional().describe("Get information about a specific category (dynamically discovered)")
374
+ }
375
+ }, async (args) => {
376
+ const { include_tools = false, category } = args;
377
+ // Discover tools dynamically
378
+ const { toolCategories, totalToolCount } = await discoverTools();
379
+ // Get comprehensive system info
274
380
  const usage = getResourceUsage();
381
+ const systemInfo = {
382
+ timestamp: new Date().toISOString(),
383
+ platform: process.platform,
384
+ nodeVersion: process.version,
385
+ memoryUsage: process.memoryUsage(),
386
+ uptime: process.uptime(),
387
+ resourceUsage: usage
388
+ };
389
+ // Server metadata from package.json
390
+ const serverMetadata = {
391
+ name: "IT Tools MCP Server",
392
+ version: packageInfo.version,
393
+ description: packageInfo.description,
394
+ author: packageInfo.author,
395
+ repository: packageInfo.repository?.url,
396
+ homepage: packageInfo.homepage,
397
+ keywords: packageInfo.keywords,
398
+ protocol: "Model Context Protocol (MCP)",
399
+ transport: "stdio"
400
+ };
401
+ const baseResult = {
402
+ server: serverMetadata,
403
+ system: systemInfo,
404
+ categories: Object.keys(toolCategories).length,
405
+ totalTools: totalToolCount,
406
+ installation: {
407
+ vscode: "Use VS Code install button in README or manual configuration",
408
+ claude: "Add to claude_desktop_config.json",
409
+ npm: `npm install -g ${packageInfo.name}`
410
+ }
411
+ };
412
+ let result = baseResult;
413
+ // Add category-specific information
414
+ if (category && toolCategories[category]) {
415
+ result = {
416
+ ...result,
417
+ categoryDetails: {
418
+ name: category,
419
+ ...toolCategories[category]
420
+ }
421
+ };
422
+ }
423
+ else if (!category) {
424
+ result = {
425
+ ...result,
426
+ availableCategories: toolCategories
427
+ };
428
+ }
429
+ // Include detailed tool information if requested
430
+ if (include_tools) {
431
+ result = {
432
+ ...result,
433
+ toolsBreakdown: Object.entries(toolCategories).map(([cat, info]) => ({
434
+ category: cat,
435
+ count: info.tools.length,
436
+ tools: info.tools
437
+ }))
438
+ };
439
+ }
275
440
  return {
276
- content: [
277
- {
441
+ content: [{
278
442
  type: "text",
279
- text: JSON.stringify({
280
- server: "IT Tools MCP Server",
281
- version: getPackageVersion(),
282
- uptime: `${Math.floor(usage.uptimeSeconds)} seconds`,
283
- memory: usage.memory,
284
- timestamp: new Date().toISOString(),
285
- }, null, 2),
286
- },
287
- ],
443
+ text: JSON.stringify(result, null, 2)
444
+ }]
288
445
  };
289
446
  });
290
447
  // Run the server
291
448
  async function main() {
292
- await registerAllTools(server);
293
- const transport = new StdioServerTransport();
294
- await server.connect(transport);
295
- // Log startup (stderr only, no resource usage)
296
- if (process.env.NODE_ENV === 'test' && process.env.MCP_TEST_MODE === 'true') {
297
- console.error("IT Tools MCP Server running on stdio");
298
- // Exit after stdin closes (for test automation)
299
- process.stdin.on('end', () => {
300
- setTimeout(() => process.exit(0), 100);
301
- });
449
+ try {
450
+ await registerAllTools(server);
451
+ const transport = new StdioServerTransport();
452
+ await server.connect(transport);
453
+ // Log startup (stderr only, no resource usage)
454
+ if (process.env.NODE_ENV === 'test' && process.env.MCP_TEST_MODE === 'true') {
455
+ console.error("IT Tools MCP Server running on stdio");
456
+ // Exit after stdin closes (for test automation)
457
+ process.stdin.on('end', () => {
458
+ setTimeout(() => process.exit(0), 100);
459
+ });
460
+ }
461
+ // Only start periodic monitoring in production, not in tests
462
+ if (process.env.NODE_ENV !== 'test') {
463
+ // Periodic resource monitoring (every 5 minutes)
464
+ setInterval(() => {
465
+ const usage = getResourceUsage();
466
+ if (usage.memory.heapUsedBytes > 200 * 1024 * 1024) { // Alert if using more than 200MB
467
+ console.error("High memory usage detected:", usage.memory);
468
+ }
469
+ }, 5 * 60 * 1000);
470
+ }
471
+ // Handle graceful shutdown
472
+ const shutdown = () => {
473
+ console.error("Shutting down IT Tools MCP Server...");
474
+ process.exit(0);
475
+ };
476
+ process.on('SIGINT', shutdown);
477
+ process.on('SIGTERM', shutdown);
302
478
  }
303
- // Only start periodic monitoring in production, not in tests
304
- if (process.env.NODE_ENV !== 'test') {
305
- // Periodic resource monitoring (every 5 minutes)
306
- setInterval(() => {
307
- const usage = getResourceUsage();
308
- if (usage.memory.heapUsedBytes > 200 * 1024 * 1024) { // Alert if using more than 200MB
309
- console.error("High memory usage detected:", usage.memory);
310
- }
311
- }, 5 * 60 * 1000);
479
+ catch (error) {
480
+ console.error("Failed to start MCP server:", error);
481
+ process.exit(1);
312
482
  }
313
483
  }
314
484
  main().catch((error) => {
@@ -1,7 +1,10 @@
1
1
  import { z } from "zod";
2
2
  export function registerAnsibleInventoryParser(server) {
3
- server.tool("ansible-inventory-parser", "Parse and validate Ansible inventory files", {
4
- inventory: z.string().describe("Ansible inventory content (INI or YAML format)"),
3
+ server.registerTool("ansible-inventory-parser", {
4
+ description: "Parse and validate Ansible inventory files",
5
+ inputSchema: {
6
+ inventory: z.string().describe("Ansible inventory content (INI or YAML format)"),
7
+ }
5
8
  }, async ({ inventory }) => {
6
9
  if (!inventory?.trim()) {
7
10
  return {
@@ -1,7 +1,10 @@
1
1
  import { z } from "zod";
2
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"),
3
+ server.registerTool("ansible-playbook-validator", {
4
+ description: "Validate Ansible playbook syntax and structure",
5
+ inputSchema: {
6
+ playbook: z.string().describe("Ansible playbook YAML content"),
7
+ }
5
8
  }, async ({ playbook }) => {
6
9
  if (!playbook?.trim()) {
7
10
  return {
@@ -1,5 +1,8 @@
1
1
  export function registerAnsibleReference(server) {
2
- server.tool("ansible-reference", "Get Ansible commands reference and cheatsheet", {}, async () => {
2
+ server.registerTool("ansible-reference", {
3
+ description: "Get Ansible commands reference and cheatsheet",
4
+ inputSchema: {}
5
+ }, async () => {
3
6
  const reference = `# Ansible Quick Reference
4
7
 
5
8
  ## Installation
@@ -1,9 +1,12 @@
1
1
  import { z } from "zod";
2
2
  import { pbkdf2Sync } from "crypto";
3
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"),
4
+ server.registerTool("ansible-vault-decrypt", {
5
+ description: "Decrypt Ansible Vault encrypted text",
6
+ inputSchema: {
7
+ encryptedText: z.string().describe("Ansible Vault encrypted text to decrypt"),
8
+ password: z.string().describe("Password for decryption"),
9
+ }
7
10
  }, async ({ encryptedText, password }) => {
8
11
  if (!encryptedText?.trim()) {
9
12
  return {
@@ -1,10 +1,13 @@
1
1
  import { z } from "zod";
2
2
  import { pbkdf2Sync, randomBytes } from "crypto";
3
3
  export function registerAnsibleVaultEncrypt(server) {
4
- server.tool("ansible-vault-encrypt", "Encrypt text using Ansible Vault format", {
5
- text: z.string().describe("Text to encrypt"),
6
- password: z.string().describe("Password for encryption"),
7
- vaultId: z.string().optional().describe("Vault ID for the encrypted content (optional)"),
4
+ server.registerTool("ansible-vault-encrypt", {
5
+ description: "Encrypt text using Ansible Vault format",
6
+ inputSchema: {
7
+ text: z.string().describe("Text to encrypt"),
8
+ password: z.string().describe("Password for encryption"),
9
+ vaultId: z.string().optional().describe("Vault ID for the encrypted content (optional)"),
10
+ }
8
11
  }, async ({ text, password, vaultId }) => {
9
12
  if (!text?.trim()) {
10
13
  return {
@@ -1,8 +1,11 @@
1
1
  import Color from "color";
2
2
  import { z } from "zod";
3
3
  export function registerColorHexToRgb(server) {
4
- server.tool("color-hex-to-rgb", "Convert HEX color to RGB", {
5
- hex: z.string().describe("HEX color code (e.g., #FF5733 or FF5733)"),
4
+ server.registerTool("color-hex-to-rgb", {
5
+ description: "Convert HEX color to RGB",
6
+ inputSchema: {
7
+ hex: z.string().describe("HEX color code (e.g., #FF5733 or FF5733)"),
8
+ }
6
9
  }, async ({ hex }) => {
7
10
  try {
8
11
  const rgb = Color(hex).rgb().array();
@@ -1,10 +1,13 @@
1
1
  import Color from "color";
2
2
  import { z } from "zod";
3
3
  export function registerColorRgbToHex(server) {
4
- server.tool("color-rgb-to-hex", "Convert RGB color to HEX", {
5
- r: z.number().describe("Red value (0-255)"),
6
- g: z.number().describe("Green value (0-255)"),
7
- b: z.number().describe("Blue value (0-255)"),
4
+ server.registerTool("color-rgb-to-hex", {
5
+ description: "Convert RGB color to HEX",
6
+ inputSchema: {
7
+ r: z.number().describe("Red value (0-255)"),
8
+ g: z.number().describe("Green value (0-255)"),
9
+ b: z.number().describe("Blue value (0-255)"),
10
+ }
8
11
  }, async ({ r, g, b }) => {
9
12
  try {
10
13
  if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {
@@ -1,8 +1,11 @@
1
1
  import { z } from "zod";
2
2
  export function registerBasicAuthGenerator(server) {
3
- server.tool("basic-auth-generator", "Generate HTTP Basic Authentication header", {
4
- username: z.string().describe("Username"),
5
- password: z.string().describe("Password"),
3
+ server.registerTool("basic-auth-generator", {
4
+ description: "Generate HTTP Basic Authentication header",
5
+ inputSchema: {
6
+ username: z.string().describe("Username"),
7
+ password: z.string().describe("Password"),
8
+ }
6
9
  }, async ({ username, password }) => {
7
10
  try {
8
11
  const credentials = `${username}:${password}`;
@@ -1,10 +1,13 @@
1
1
  import bcryptjs from "bcryptjs";
2
2
  import { z } from "zod";
3
3
  export function registerBcryptHash(server) {
4
- server.tool("bcrypt-hash", "Generate bcrypt hash or verify password against hash", {
5
- password: z.string().describe("Password to hash or verify"),
6
- rounds: z.number().describe("Number of salt rounds (4-12, default 10)").optional(),
7
- hash: z.string().optional().describe("Existing hash to verify against (for verification)"),
4
+ server.registerTool("bcrypt-hash", {
5
+ description: "Generate bcrypt hash or verify password against hash",
6
+ inputSchema: {
7
+ password: z.string().describe("Password to hash or verify"),
8
+ rounds: z.number().describe("Number of salt rounds (4-12, default 10)").optional(),
9
+ hash: z.string().optional().describe("Existing hash to verify against (for verification)"),
10
+ }
8
11
  }, async ({ password, rounds = 10, hash }) => {
9
12
  try {
10
13
  if (rounds < 4 || rounds > 12) {
@@ -1,8 +1,11 @@
1
1
  import * as bip39 from "bip39";
2
2
  import { z } from "zod";
3
3
  export function registerBip39Generate(server) {
4
- server.tool("bip39-generate", "Generate BIP39 mnemonic phrases", {
5
- wordCount: z.enum(["12", "15", "18", "21", "24"]).describe("Number of words in the mnemonic").optional(),
4
+ server.registerTool("bip39-generate", {
5
+ description: "Generate BIP39 mnemonic phrases",
6
+ inputSchema: {
7
+ wordCount: z.enum(["12", "15", "18", "21", "24"]).describe("Number of words in the mnemonic").optional(),
8
+ }
6
9
  }, async ({ wordCount = "12" }) => {
7
10
  try {
8
11
  const count = parseInt(wordCount);
@@ -1,8 +1,11 @@
1
1
  import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
3
  export function registerHashMd5(server) {
4
- server.tool("hash-md5", "Generate MD5 hash", {
5
- text: z.string().describe("Text to hash with MD5"),
4
+ server.registerTool("hash-md5", {
5
+ description: "Generate MD5 hash",
6
+ inputSchema: {
7
+ text: z.string().describe("Text to hash with MD5"),
8
+ }
6
9
  }, async ({ text }) => {
7
10
  const hash = createHash('md5');
8
11
  hash.update(text);
@@ -1,8 +1,11 @@
1
1
  import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
3
  export function registerHashSha1(server) {
4
- server.tool("hash-sha1", "Generate SHA1 hash", {
5
- text: z.string().describe("Text to hash with SHA1"),
4
+ server.registerTool("hash-sha1", {
5
+ description: "Generate SHA1 hash",
6
+ inputSchema: {
7
+ text: z.string().describe("Text to hash with SHA1"),
8
+ }
6
9
  }, async ({ text }) => {
7
10
  const hash = createHash('sha1');
8
11
  hash.update(text);
@@ -1,8 +1,11 @@
1
1
  import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
3
  export function registerHashSha256(server) {
4
- server.tool("hash-sha256", "Generate SHA256 hash", {
5
- text: z.string().describe("Text to hash with SHA256"),
4
+ server.registerTool("hash-sha256", {
5
+ description: 'Generate SHA256 hash of input text. Example: "hello" → "2cf24dba4f21d..."',
6
+ inputSchema: {
7
+ text: z.string().describe("Text to hash with SHA256"),
8
+ }
6
9
  }, async ({ text }) => {
7
10
  const hash = createHash('sha256');
8
11
  hash.update(text);
@@ -1,8 +1,11 @@
1
1
  import { createHash } from "crypto";
2
2
  import { z } from "zod";
3
3
  export function registerHashSha512(server) {
4
- server.tool("hash-sha512", "Generate SHA512 hash", {
5
- text: z.string().describe("Text to hash with SHA512"),
4
+ server.registerTool("hash-sha512", {
5
+ description: "Generate SHA512 hash",
6
+ inputSchema: {
7
+ text: z.string().describe("Text to hash with SHA512"),
8
+ }
6
9
  }, async ({ text }) => {
7
10
  const hash = createHash('sha512');
8
11
  hash.update(text);
@@ -1,10 +1,13 @@
1
1
  import { createHmac } from "crypto";
2
2
  import { z } from "zod";
3
3
  export function registerHmacGenerator(server) {
4
- server.tool("hmac-generator", "Generate HMAC (Hash-based Message Authentication Code)", {
5
- message: z.string().describe("Message to authenticate"),
6
- key: z.string().describe("Secret key for HMAC"),
7
- algorithm: z.enum(["sha1", "sha256", "sha512"]).describe("Hash algorithm").optional(),
4
+ server.registerTool("hmac-generator", {
5
+ description: "Generate HMAC (Hash-based Message Authentication Code)",
6
+ inputSchema: {
7
+ message: z.string().describe("Message to authenticate"),
8
+ key: z.string().describe("Secret key for HMAC"),
9
+ algorithm: z.enum(["sha1", "sha256", "sha512"]).describe("Hash algorithm").optional(),
10
+ }
8
11
  }, async ({ message, key, algorithm = "sha256" }) => {
9
12
  try {
10
13
  const hmac = createHmac(algorithm, key);