it-tools-mcp 3.0.4 → 3.0.6
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/build/index.js +39 -24
- package/build/tools/dataFormat.js +51 -61
- package/build/tools/idGenerators.js +2 -7
- package/build/tools/math.js +2 -1
- package/build/tools/network.js +2 -2
- package/package.json +1 -1
package/build/index.js
CHANGED
|
@@ -2,37 +2,45 @@
|
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { getResourceUsage } from "./security.js";
|
|
5
|
-
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
import { registerColorTools } from "./tools/color.js";
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
// Helper to read version from package.json at runtime (ESM compatible)
|
|
8
|
+
function getPackageVersion() {
|
|
9
|
+
// Use import.meta.url to get the directory in ESM
|
|
10
|
+
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
11
|
+
const pkgPath = path.resolve(__dirname, '../package.json');
|
|
12
|
+
const pkgRaw = fs.readFileSync(pkgPath, 'utf-8');
|
|
13
|
+
return JSON.parse(pkgRaw).version;
|
|
14
|
+
}
|
|
16
15
|
// Create server instance
|
|
17
16
|
const server = new McpServer({
|
|
18
17
|
name: "it-tools-mcp",
|
|
19
|
-
version:
|
|
18
|
+
version: getPackageVersion(),
|
|
20
19
|
capabilities: {
|
|
21
20
|
resources: {},
|
|
22
21
|
tools: {},
|
|
23
22
|
},
|
|
24
23
|
});
|
|
25
|
-
// Register all tool modules
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
// Register all tool modules (dynamically for faster startup, with per-module timing)
|
|
25
|
+
async function registerAllTools(server) {
|
|
26
|
+
const modules = [
|
|
27
|
+
{ name: 'encoding', fn: () => import('./tools/encoding.js').then(m => m.registerEncodingTools(server)) },
|
|
28
|
+
{ name: 'crypto', fn: () => import('./tools/crypto.js').then(m => m.registerCryptoTools(server)) },
|
|
29
|
+
{ name: 'dataFormat', fn: () => import('./tools/dataFormat.js').then(m => m.registerDataFormatTools(server)) },
|
|
30
|
+
{ name: 'text', fn: () => import('./tools/text.js').then(m => m.registerTextTools(server)) },
|
|
31
|
+
{ name: 'idGenerators', fn: () => import('./tools/idGenerators.js').then(m => m.registerIdGeneratorTools(server)) },
|
|
32
|
+
{ name: 'network', fn: () => import('./tools/network.js').then(m => m.registerNetworkTools(server)) },
|
|
33
|
+
{ name: 'math', fn: () => import('./tools/math.js').then(m => m.registerMathTools(server)) },
|
|
34
|
+
{ name: 'utility', fn: () => import('./tools/utility.js').then(m => m.registerUtilityTools(server)) },
|
|
35
|
+
{ name: 'development', fn: () => import('./tools/development.js').then(m => m.registerDevelopmentTools(server)) },
|
|
36
|
+
{ name: 'color', fn: () => import('./tools/color.js').then(m => m.registerColorTools(server)) },
|
|
37
|
+
];
|
|
38
|
+
for (const mod of modules) {
|
|
39
|
+
console.time(`register:${mod.name}`);
|
|
40
|
+
await mod.fn();
|
|
41
|
+
console.timeEnd(`register:${mod.name}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
36
44
|
// Add resource monitoring tool
|
|
37
45
|
server.tool("system-info", "Get system resource usage and server information", {}, async () => {
|
|
38
46
|
const usage = getResourceUsage();
|
|
@@ -42,7 +50,7 @@ server.tool("system-info", "Get system resource usage and server information", {
|
|
|
42
50
|
type: "text",
|
|
43
51
|
text: JSON.stringify({
|
|
44
52
|
server: "IT Tools MCP Server",
|
|
45
|
-
version:
|
|
53
|
+
version: getPackageVersion(),
|
|
46
54
|
uptime: `${Math.floor(usage.uptimeSeconds)} seconds`,
|
|
47
55
|
memory: usage.memory,
|
|
48
56
|
timestamp: new Date().toISOString(),
|
|
@@ -53,8 +61,13 @@ server.tool("system-info", "Get system resource usage and server information", {
|
|
|
53
61
|
});
|
|
54
62
|
// Run the server
|
|
55
63
|
async function main() {
|
|
64
|
+
console.time("Tool registration");
|
|
65
|
+
await registerAllTools(server);
|
|
66
|
+
console.timeEnd("Tool registration");
|
|
56
67
|
const transport = new StdioServerTransport();
|
|
68
|
+
console.time("Server connect");
|
|
57
69
|
await server.connect(transport);
|
|
70
|
+
console.timeEnd("Server connect");
|
|
58
71
|
// Log startup with resource info
|
|
59
72
|
console.error("IT Tools MCP Server running on stdio");
|
|
60
73
|
console.error("Resource usage:", JSON.stringify(getResourceUsage(), null, 2));
|
|
@@ -68,7 +81,9 @@ async function main() {
|
|
|
68
81
|
}
|
|
69
82
|
}, 5 * 60 * 1000);
|
|
70
83
|
}
|
|
84
|
+
console.timeEnd("Total startup");
|
|
71
85
|
}
|
|
86
|
+
console.time("Total startup");
|
|
72
87
|
main().catch((error) => {
|
|
73
88
|
console.error("Fatal error in main():", error);
|
|
74
89
|
process.exit(1);
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import * as toml from "@iarna/toml";
|
|
2
|
-
import * as YAML from "js-yaml";
|
|
3
|
-
import Papa from "papaparse";
|
|
4
|
-
import { format as formatSQL } from "sql-formatter";
|
|
5
|
-
import formatXML from "xml-formatter";
|
|
6
|
-
import { marked } from "marked";
|
|
7
|
-
import TurndownService from "turndown";
|
|
8
1
|
import { z } from "zod";
|
|
9
2
|
export function registerDataFormatTools(server) {
|
|
10
3
|
// JSON formatting tool
|
|
@@ -132,12 +125,13 @@ Examples of supported formats:
|
|
|
132
125
|
};
|
|
133
126
|
}
|
|
134
127
|
});
|
|
135
|
-
//
|
|
128
|
+
// CSV converter (using papaparse)
|
|
136
129
|
server.tool("json-to-csv", "Convert JSON to CSV format", {
|
|
137
130
|
json: z.string().describe("JSON string to convert to CSV"),
|
|
138
131
|
delimiter: z.string().describe("CSV delimiter").optional(),
|
|
139
132
|
}, async ({ json, delimiter = "," }) => {
|
|
140
133
|
try {
|
|
134
|
+
const Papa = (await import("papaparse")).default;
|
|
141
135
|
const data = JSON.parse(json);
|
|
142
136
|
if (!Array.isArray(data)) {
|
|
143
137
|
throw new Error("JSON must be an array of objects");
|
|
@@ -163,54 +157,12 @@ Examples of supported formats:
|
|
|
163
157
|
};
|
|
164
158
|
}
|
|
165
159
|
});
|
|
166
|
-
// XML formatter tool
|
|
167
|
-
server.tool("xml-format", "Format and prettify XML", {
|
|
168
|
-
xml: z.string().describe("XML string to format"),
|
|
169
|
-
indent: z.number().describe("Number of spaces for indentation").optional(),
|
|
170
|
-
}, async ({ xml, indent = 2 }) => {
|
|
171
|
-
try {
|
|
172
|
-
const formatted = formatXML(xml, {
|
|
173
|
-
indentation: ' '.repeat(indent),
|
|
174
|
-
filter: (node) => node.type !== 'Comment',
|
|
175
|
-
collapseContent: true,
|
|
176
|
-
lineSeparator: '\n'
|
|
177
|
-
});
|
|
178
|
-
return {
|
|
179
|
-
content: [
|
|
180
|
-
{
|
|
181
|
-
type: "text",
|
|
182
|
-
text: `Formatted XML:
|
|
183
|
-
|
|
184
|
-
${formatted}
|
|
185
|
-
|
|
186
|
-
✅ XML formatted successfully
|
|
187
|
-
🎯 Features: ${indent}-space indentation, collapsed content, clean structure`,
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
catch (error) {
|
|
193
|
-
return {
|
|
194
|
-
content: [
|
|
195
|
-
{
|
|
196
|
-
type: "text",
|
|
197
|
-
text: `Error formatting XML: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
198
|
-
|
|
199
|
-
💡 Common XML issues:
|
|
200
|
-
• Check that all tags are properly closed
|
|
201
|
-
• Ensure proper nesting of elements
|
|
202
|
-
• Validate attribute syntax (key="value")
|
|
203
|
-
• Check for special character encoding`,
|
|
204
|
-
},
|
|
205
|
-
],
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
160
|
// YAML formatter tool
|
|
210
161
|
server.tool("yaml-format", "Format and prettify YAML", {
|
|
211
162
|
yaml: z.string().describe("YAML string to format"),
|
|
212
163
|
}, async ({ yaml }) => {
|
|
213
164
|
try {
|
|
165
|
+
const YAML = await import("js-yaml");
|
|
214
166
|
// Parse YAML to validate and then dump with proper formatting
|
|
215
167
|
const parsed = YAML.load(yaml);
|
|
216
168
|
// Format with proper indentation and options
|
|
@@ -261,18 +213,56 @@ ${formatted.trim()}
|
|
|
261
213
|
};
|
|
262
214
|
}
|
|
263
215
|
});
|
|
216
|
+
// XML formatter tool
|
|
217
|
+
server.tool("xml-format", "Format and prettify XML", {
|
|
218
|
+
xml: z.string().describe("XML string to format"),
|
|
219
|
+
indent: z.number().describe("Number of spaces for indentation").optional(),
|
|
220
|
+
}, async ({ xml, indent = 2 }) => {
|
|
221
|
+
try {
|
|
222
|
+
const formatXML = (await import("xml-formatter")).default;
|
|
223
|
+
const formatted = formatXML(xml, {
|
|
224
|
+
indentation: ' '.repeat(indent),
|
|
225
|
+
collapseContent: true,
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
content: [
|
|
229
|
+
{
|
|
230
|
+
type: "text",
|
|
231
|
+
text: `Formatted XML:
|
|
232
|
+
|
|
233
|
+
${formatted}
|
|
234
|
+
|
|
235
|
+
✅ XML formatted successfully
|
|
236
|
+
🎯 Features: ${indent}-space indentation, collapsed content, clean structure`,
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
return {
|
|
243
|
+
content: [
|
|
244
|
+
{
|
|
245
|
+
type: "text",
|
|
246
|
+
text: `Error formatting XML: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
247
|
+
|
|
248
|
+
💡 Common XML issues:
|
|
249
|
+
• Check that all tags are properly closed
|
|
250
|
+
• Ensure proper nesting of elements
|
|
251
|
+
• Validate attribute syntax (key="value")
|
|
252
|
+
• Check for special character encoding`,
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
});
|
|
264
258
|
// SQL formatter tool
|
|
265
259
|
server.tool("sql-format", "Format and prettify SQL queries", {
|
|
266
260
|
sql: z.string().describe("SQL query to format"),
|
|
267
261
|
}, async ({ sql }) => {
|
|
268
262
|
try {
|
|
263
|
+
const { format: formatSQL } = await import("sql-formatter");
|
|
269
264
|
const formatted = formatSQL(sql, {
|
|
270
|
-
language:
|
|
271
|
-
tabWidth: 2,
|
|
272
|
-
useTabs: false,
|
|
273
|
-
keywordCase: 'upper',
|
|
274
|
-
identifierCase: 'lower',
|
|
275
|
-
functionCase: 'upper'
|
|
265
|
+
language: "sql"
|
|
276
266
|
});
|
|
277
267
|
return {
|
|
278
268
|
content: [
|
|
@@ -310,6 +300,7 @@ ${formatted}
|
|
|
310
300
|
toml: z.string().describe("TOML string to convert"),
|
|
311
301
|
}, async ({ toml: tomlString }) => {
|
|
312
302
|
try {
|
|
303
|
+
const toml = await import("@iarna/toml");
|
|
313
304
|
const result = toml.parse(tomlString);
|
|
314
305
|
return {
|
|
315
306
|
content: [
|
|
@@ -336,6 +327,7 @@ ${formatted}
|
|
|
336
327
|
json: z.string().describe("JSON string to convert"),
|
|
337
328
|
}, async ({ json }) => {
|
|
338
329
|
try {
|
|
330
|
+
const toml = await import("@iarna/toml");
|
|
339
331
|
const data = JSON.parse(json);
|
|
340
332
|
const tomlResult = toml.stringify(data);
|
|
341
333
|
return {
|
|
@@ -363,7 +355,7 @@ ${formatted}
|
|
|
363
355
|
markdown: z.string().describe("Markdown content to convert to HTML"),
|
|
364
356
|
}, async ({ markdown }) => {
|
|
365
357
|
try {
|
|
366
|
-
|
|
358
|
+
const { marked } = await import("marked");
|
|
367
359
|
const html = marked(markdown, {
|
|
368
360
|
breaks: true,
|
|
369
361
|
gfm: true
|
|
@@ -393,13 +385,11 @@ ${formatted}
|
|
|
393
385
|
html: z.string().describe("HTML content to convert to Markdown"),
|
|
394
386
|
}, async ({ html }) => {
|
|
395
387
|
try {
|
|
396
|
-
|
|
388
|
+
const TurndownService = (await import("turndown")).default;
|
|
397
389
|
const turndownService = new TurndownService({
|
|
398
390
|
headingStyle: 'atx',
|
|
399
391
|
codeBlockStyle: 'fenced',
|
|
400
|
-
bulletListMarker: '-',
|
|
401
392
|
emDelimiter: '*',
|
|
402
|
-
strongDelimiter: '**'
|
|
403
393
|
});
|
|
404
394
|
const markdown = turndownService.turndown(html);
|
|
405
395
|
return {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
|
-
import QRCode from "qrcode";
|
|
3
2
|
import { z } from "zod";
|
|
4
3
|
export function registerIdGeneratorTools(server) {
|
|
5
4
|
// UUID generation tool
|
|
@@ -53,6 +52,7 @@ For production use, please use a proper ULID library.`,
|
|
|
53
52
|
size: z.number().describe("Size multiplier (1-3)").optional(),
|
|
54
53
|
}, async ({ text, size = 1 }) => {
|
|
55
54
|
try {
|
|
55
|
+
const QRCode = (await import("qrcode")).default;
|
|
56
56
|
if (size < 1 || size > 3) {
|
|
57
57
|
return {
|
|
58
58
|
content: [
|
|
@@ -105,12 +105,7 @@ For production use, please use a proper ULID library.`,
|
|
|
105
105
|
content: [
|
|
106
106
|
{
|
|
107
107
|
type: "text",
|
|
108
|
-
text: `Error generating QR code: ${error instanceof Error ? error.message : 'Unknown error'}
|
|
109
|
-
|
|
110
|
-
Debug info:
|
|
111
|
-
- Text: "${text}"
|
|
112
|
-
- Size: ${size}
|
|
113
|
-
- QRCode library available: ${typeof QRCode !== 'undefined' ? 'Yes' : 'No'}`,
|
|
108
|
+
text: `Error generating QR code: ${error instanceof Error ? error.message : 'Unknown error'}\n\nDebug info:\n- Text: \"${text}\"\n- Size: ${size}`,
|
|
114
109
|
},
|
|
115
110
|
],
|
|
116
111
|
};
|
package/build/tools/math.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { evaluate } from "mathjs";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
export function registerMathTools(server) {
|
|
4
3
|
// Math expression evaluator
|
|
@@ -6,6 +5,8 @@ export function registerMathTools(server) {
|
|
|
6
5
|
expression: z.string().describe("Mathematical expression to evaluate (e.g., '2 + 3 * 4')")
|
|
7
6
|
}, async ({ expression }) => {
|
|
8
7
|
try {
|
|
8
|
+
// Dynamically import mathjs only when needed
|
|
9
|
+
const { evaluate } = await import("mathjs");
|
|
9
10
|
const result = evaluate(expression);
|
|
10
11
|
return {
|
|
11
12
|
content: [
|
package/build/tools/network.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { isValidPhoneNumber, parsePhoneNumber } from "libphonenumber-js";
|
|
2
|
-
import IBAN from "iban";
|
|
3
1
|
import { z } from "zod";
|
|
4
2
|
export function registerNetworkTools(server) {
|
|
5
3
|
// IP address tools
|
|
@@ -448,6 +446,7 @@ ${prefix ? `Used prefix: ${prefix}` : 'Randomly generated'}`,
|
|
|
448
446
|
countryCode: z.string().optional().describe("Country code (e.g., 'US', 'GB', 'FR')"),
|
|
449
447
|
}, async ({ phoneNumber, countryCode }) => {
|
|
450
448
|
try {
|
|
449
|
+
const { isValidPhoneNumber, parsePhoneNumber } = await import("libphonenumber-js");
|
|
451
450
|
// First check if it's a valid phone number
|
|
452
451
|
if (!isValidPhoneNumber(phoneNumber, countryCode)) {
|
|
453
452
|
throw new Error("Invalid phone number format");
|
|
@@ -500,6 +499,7 @@ Valid: ${parsedNumber.isValid()}
|
|
|
500
499
|
iban: z.string().describe("IBAN to validate and parse"),
|
|
501
500
|
}, async ({ iban }) => {
|
|
502
501
|
try {
|
|
502
|
+
const IBAN = (await import("iban")).default;
|
|
503
503
|
// Clean the input
|
|
504
504
|
const cleanIban = iban.replace(/\s/g, '').toUpperCase();
|
|
505
505
|
// Validate using the IBAN library
|