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.
- package/README.dockerhub.md +2 -2
- package/README.md +14 -7
- package/build/index.js +223 -53
- package/build/tools/ansible/ansible-inventory-generator/index.js +5 -2
- package/build/tools/ansible/ansible-playbook-validator/index.js +5 -2
- package/build/tools/ansible/ansible-reference/index.js +4 -1
- package/build/tools/ansible/ansible-vault-decrypt/index.js +6 -3
- package/build/tools/ansible/ansible-vault-encrypt/index.js +7 -4
- package/build/tools/color/color-hex-to-rgb/index.js +5 -2
- package/build/tools/color/color-rgb-to-hex/index.js +7 -4
- package/build/tools/crypto/basic-auth-generator/index.js +6 -3
- package/build/tools/crypto/bcrypt-hash/index.js +7 -4
- package/build/tools/crypto/bip39-generate/index.js +5 -2
- package/build/tools/crypto/hash-md5/index.js +5 -2
- package/build/tools/crypto/hash-sha1/index.js +5 -2
- package/build/tools/crypto/hash-sha256/index.js +5 -2
- package/build/tools/crypto/hash-sha512/index.js +5 -2
- package/build/tools/crypto/hmac-generator/index.js +7 -4
- package/build/tools/crypto/jwt-decode/index.js +5 -2
- package/build/tools/crypto/otp-code-generator/index.js +7 -4
- package/build/tools/crypto/password-generate/index.js +9 -6
- package/build/tools/crypto/token-generator/index.js +7 -4
- package/build/tools/dataFormat/html-to-markdown/index.js +5 -2
- package/build/tools/dataFormat/json-diff/index.js +6 -3
- package/build/tools/dataFormat/json-format/index.js +7 -3
- package/build/tools/dataFormat/json-minify/index.js +5 -2
- package/build/tools/dataFormat/json-to-csv/index.js +6 -3
- package/build/tools/dataFormat/json-to-toml/index.js +5 -2
- package/build/tools/dataFormat/markdown-to-html/index.js +5 -2
- package/build/tools/dataFormat/phone-format/index.js +6 -3
- package/build/tools/dataFormat/sql-format/index.js +6 -3
- package/build/tools/dataFormat/toml-to-json/index.js +5 -2
- package/build/tools/dataFormat/xml-format/index.js +6 -3
- package/build/tools/dataFormat/yaml-format/index.js +5 -2
- package/build/tools/development/crontab-generate/index.js +9 -6
- package/build/tools/development/html-prettifier/index.js +6 -3
- package/build/tools/development/javascript-prettifier/index.js +7 -4
- package/build/tools/development/list-converter/index.js +8 -5
- package/build/tools/development/markdown-toc-generator/index.js +7 -4
- package/build/tools/development/regex-tester/index.js +7 -4
- package/build/tools/docker/docker-compose-to-docker-run/index.js +5 -2
- package/build/tools/docker/docker-compose-validator/index.js +5 -2
- package/build/tools/docker/docker-reference/index.js +4 -1
- package/build/tools/docker/docker-run-to-docker-compose/index.js +5 -2
- package/build/tools/docker/traefik-compose-generator/index.js +9 -6
- package/build/tools/encoding/base64-decode/index.js +6 -2
- package/build/tools/encoding/base64-encode/index.js +27 -11
- package/build/tools/encoding/html-decode/index.js +5 -2
- package/build/tools/encoding/html-encode/index.js +5 -2
- package/build/tools/encoding/html-entities-extended/index.js +6 -3
- package/build/tools/encoding/text-to-binary/index.js +6 -3
- package/build/tools/encoding/url-decode/index.js +5 -2
- package/build/tools/encoding/url-encode/index.js +5 -2
- package/build/tools/forensic/file-type-identifier/index.js +6 -3
- package/build/tools/forensic/safelink-decoder/index.js +5 -2
- package/build/tools/forensic/url-fanger/index.js +6 -3
- package/build/tools/idGenerators/qr-generate/index.js +6 -3
- package/build/tools/idGenerators/svg-placeholder-generator/index.js +9 -6
- package/build/tools/idGenerators/ulid-generate/index.js +4 -1
- package/build/tools/idGenerators/uuid-generate/index.js +4 -1
- package/build/tools/math/math-evaluate/index.js +5 -2
- package/build/tools/math/number-base-converter/index.js +7 -4
- package/build/tools/math/percentage-calculator/index.js +7 -4
- package/build/tools/math/roman-numeral-converter/index.js +5 -2
- package/build/tools/math/temperature-converter/index.js +7 -4
- package/build/tools/math/unix-timestamp-converter/index.js +5 -2
- package/build/tools/network/cat/index.js +5 -2
- package/build/tools/network/cidr-to-ip-range/index.js +5 -2
- package/build/tools/network/curl/index.js +11 -6
- package/build/tools/network/dig/index.js +6 -3
- package/build/tools/network/grep/index.js +6 -3
- package/build/tools/network/head/index.js +6 -3
- package/build/tools/network/iban-validate/index.js +5 -2
- package/build/tools/network/ip-range-to-cidr/index.js +6 -3
- package/build/tools/network/ip-subnet-calculator/index.js +6 -3
- package/build/tools/network/ipv4-subnet-calc/index.js +5 -2
- package/build/tools/network/ipv6-subnet-calculator/index.js +6 -3
- package/build/tools/network/ipv6-ula-generator/index.js +5 -2
- package/build/tools/network/mac-address-generate/index.js +6 -3
- package/build/tools/network/nslookup/index.js +5 -2
- package/build/tools/network/ping/index.js +9 -4
- package/build/tools/network/ps/index.js +4 -1
- package/build/tools/network/random-port/index.js +8 -5
- package/build/tools/network/scp/index.js +10 -7
- package/build/tools/network/ssh/index.js +8 -5
- package/build/tools/network/tail/index.js +6 -3
- package/build/tools/network/telnet/index.js +6 -3
- package/build/tools/network/top/index.js +4 -1
- package/build/tools/network/url-parse/index.js +5 -2
- package/build/tools/physics/angle-converter/index.js +11 -8
- package/build/tools/physics/energy-converter/index.js +13 -10
- package/build/tools/physics/power-converter/index.js +13 -10
- package/build/tools/text/ascii-art-text/index.js +6 -3
- package/build/tools/text/distinct-words/index.js +5 -2
- package/build/tools/text/emoji-search/index.js +5 -2
- package/build/tools/text/lorem-ipsum-generator/index.js +6 -3
- package/build/tools/text/numeronym-generator/index.js +5 -2
- package/build/tools/text/slugify-string/index.js +7 -4
- package/build/tools/text/string-obfuscator/index.js +6 -3
- package/build/tools/text/text-camelcase/index.js +5 -2
- package/build/tools/text/text-capitalize/index.js +5 -2
- package/build/tools/text/text-diff/index.js +6 -3
- package/build/tools/text/text-kebabcase/index.js +5 -2
- package/build/tools/text/text-lowercase/index.js +5 -2
- package/build/tools/text/text-pascalcase/index.js +5 -2
- package/build/tools/text/text-snakecase/index.js +5 -2
- package/build/tools/text/text-stats/index.js +5 -2
- package/build/tools/text/text-to-nato-alphabet/index.js +6 -3
- package/build/tools/text/text-to-unicode/index.js +6 -3
- package/build/tools/text/text-to-unicode-names/index.js +5 -2
- package/build/tools/text/text-uppercase/index.js +5 -2
- package/build/tools/utility/css-prettifier/index.js +6 -3
- package/build/tools/utility/device-info/index.js +4 -1
- package/build/tools/utility/email-normalizer/index.js +5 -2
- package/build/tools/utility/http-status-codes/index.js +5 -2
- package/build/tools/utility/mime-types/index.js +6 -3
- package/build/tools/utility/port-numbers/index.js +5 -2
- package/build/tools/utility/rem-px-converter/index.js +8 -4
- package/package.json +1 -1
package/README.dockerhub.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
[](https://hub.docker.com/r/wrenchpilot/it-tools-mcp)
|
|
12
12
|
[](https://github.com/wrenchpilot/it-tools-mcp/stargazers)
|
|
13
13
|
|
|
14
|
-
A comprehensive Model Context Protocol (MCP) server that provides access to **
|
|
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
|
|
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
|
|
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
|
-
**
|
|
23
|
+
**Quick Install:**
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
[](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) [](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
|
-
|
|
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 **
|
|
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
|
|
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
|
|
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
|
-
*
|
|
202
|
+
* Input validation and security utilities
|
|
203
203
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
//
|
|
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
|
-
|
|
263
|
-
|
|
264
|
-
'
|
|
265
|
-
|
|
266
|
-
|
|
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
|
|
273
|
-
server.
|
|
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
|
-
|
|
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
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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.
|
|
4
|
-
|
|
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.
|
|
4
|
-
|
|
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.
|
|
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.
|
|
5
|
-
|
|
6
|
-
|
|
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.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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.
|
|
4
|
-
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
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.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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);
|