it-tools-mcp 3.0.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.
@@ -0,0 +1,445 @@
1
+ import { createHash, createHmac } from "crypto";
2
+ import bcryptjs from "bcryptjs";
3
+ import * as bip39 from "bip39";
4
+ import speakeasy from "speakeasy";
5
+ import { z } from "zod";
6
+ export function registerCryptoTools(server) {
7
+ // Hash generation tools
8
+ const hashAlgorithms = ['md5', 'sha1', 'sha256', 'sha512'];
9
+ hashAlgorithms.forEach(algorithm => {
10
+ server.tool(`hash-${algorithm}`, `Generate ${algorithm.toUpperCase()} hash`, {
11
+ text: z.string().describe(`Text to hash with ${algorithm.toUpperCase()}`),
12
+ }, async ({ text }) => {
13
+ const hash = createHash(algorithm);
14
+ hash.update(text);
15
+ const result = hash.digest('hex');
16
+ return {
17
+ content: [
18
+ {
19
+ type: "text",
20
+ text: `${algorithm.toUpperCase()} hash: ${result}`,
21
+ },
22
+ ],
23
+ };
24
+ });
25
+ });
26
+ // HMAC generator tool
27
+ server.tool("hmac-generator", "Generate HMAC (Hash-based Message Authentication Code)", {
28
+ message: z.string().describe("Message to authenticate"),
29
+ key: z.string().describe("Secret key for HMAC"),
30
+ algorithm: z.enum(["sha1", "sha256", "sha512"]).describe("Hash algorithm").optional(),
31
+ }, async ({ message, key, algorithm = "sha256" }) => {
32
+ try {
33
+ const hmac = createHmac(algorithm, key);
34
+ hmac.update(message);
35
+ const result = hmac.digest('hex');
36
+ return {
37
+ content: [
38
+ {
39
+ type: "text",
40
+ text: `HMAC-${algorithm.toUpperCase()}: ${result}
41
+
42
+ Message: ${message}
43
+ Key: ${key}
44
+ Algorithm: ${algorithm.toUpperCase()}`,
45
+ },
46
+ ],
47
+ };
48
+ }
49
+ catch (error) {
50
+ return {
51
+ content: [
52
+ {
53
+ type: "text",
54
+ text: `Error generating HMAC: ${error instanceof Error ? error.message : 'Unknown error'}`,
55
+ },
56
+ ],
57
+ };
58
+ }
59
+ });
60
+ // JWT decode tool (header and payload only)
61
+ server.tool("jwt-decode", "Decode JWT token (header and payload only)", {
62
+ token: z.string().describe("JWT token to decode"),
63
+ }, async ({ token }) => {
64
+ try {
65
+ const parts = token.split('.');
66
+ if (parts.length !== 3) {
67
+ throw new Error("Invalid JWT format. JWT must have 3 parts separated by dots.");
68
+ }
69
+ const header = JSON.parse(Buffer.from(parts[0], 'base64url').toString());
70
+ const payload = JSON.parse(Buffer.from(parts[1], 'base64url').toString());
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: `JWT Token Decoded:
76
+
77
+ Header:
78
+ ${JSON.stringify(header, null, 2)}
79
+
80
+ Payload:
81
+ ${JSON.stringify(payload, null, 2)}
82
+
83
+ Note: Signature verification is not performed. Do not trust this token without proper verification.`,
84
+ },
85
+ ],
86
+ };
87
+ }
88
+ catch (error) {
89
+ return {
90
+ content: [
91
+ {
92
+ type: "text",
93
+ text: `Error decoding JWT: ${error instanceof Error ? error.message : 'Unknown error'}`,
94
+ },
95
+ ],
96
+ };
97
+ }
98
+ });
99
+ // Basic auth generator tool
100
+ server.tool("basic-auth-generator", "Generate HTTP Basic Authentication header", {
101
+ username: z.string().describe("Username"),
102
+ password: z.string().describe("Password"),
103
+ }, async ({ username, password }) => {
104
+ try {
105
+ const credentials = `${username}:${password}`;
106
+ const encoded = Buffer.from(credentials, 'utf-8').toString('base64');
107
+ const authHeader = `Basic ${encoded}`;
108
+ return {
109
+ content: [
110
+ {
111
+ type: "text",
112
+ text: `HTTP Basic Auth Header:
113
+ Authorization: ${authHeader}
114
+
115
+ Credentials: ${username}:${password}
116
+ Base64 Encoded: ${encoded}
117
+
118
+ Usage in curl:
119
+ curl -H "Authorization: ${authHeader}" https://api.example.com
120
+
121
+ Usage in fetch:
122
+ fetch('https://api.example.com', {
123
+ headers: {
124
+ 'Authorization': '${authHeader}'
125
+ }
126
+ })`,
127
+ },
128
+ ],
129
+ };
130
+ }
131
+ catch (error) {
132
+ return {
133
+ content: [
134
+ {
135
+ type: "text",
136
+ text: `Error generating basic auth: ${error instanceof Error ? error.message : 'Unknown error'}`,
137
+ },
138
+ ],
139
+ };
140
+ }
141
+ });
142
+ // Bcrypt hash tool
143
+ server.tool("bcrypt-hash", "Generate bcrypt hash or verify password against hash", {
144
+ password: z.string().describe("Password to hash or verify"),
145
+ rounds: z.number().describe("Number of salt rounds (4-12, default 10)").optional(),
146
+ hash: z.string().optional().describe("Existing hash to verify against (for verification)"),
147
+ }, async ({ password, rounds = 10, hash }) => {
148
+ try {
149
+ if (rounds < 4 || rounds > 12) {
150
+ return {
151
+ content: [
152
+ {
153
+ type: "text",
154
+ text: "Rounds must be between 4 and 12.",
155
+ },
156
+ ],
157
+ };
158
+ }
159
+ if (hash) {
160
+ // Verification mode
161
+ const isValid = await bcryptjs.compare(password, hash);
162
+ return {
163
+ content: [
164
+ {
165
+ type: "text",
166
+ text: `Password Verification: ${isValid ? 'VALID' : 'INVALID'}
167
+
168
+ Password: ${password}
169
+ Hash: ${hash}`,
170
+ },
171
+ ],
172
+ };
173
+ }
174
+ else {
175
+ // Hash generation mode
176
+ const salt = await bcryptjs.genSalt(rounds);
177
+ const hashedPassword = await bcryptjs.hash(password, salt);
178
+ return {
179
+ content: [
180
+ {
181
+ type: "text",
182
+ text: `Bcrypt Hash Generated:
183
+ Hash: ${hashedPassword}
184
+
185
+ Password: ${password}
186
+ Rounds: ${rounds}
187
+ Algorithm: bcrypt
188
+
189
+ This hash can be safely stored in databases and used for password verification.`,
190
+ },
191
+ ],
192
+ };
193
+ }
194
+ }
195
+ catch (error) {
196
+ return {
197
+ content: [
198
+ {
199
+ type: "text",
200
+ text: `Error with bcrypt operation: ${error instanceof Error ? error.message : 'Unknown error'}`,
201
+ },
202
+ ],
203
+ };
204
+ }
205
+ });
206
+ // BIP39 mnemonic generator
207
+ server.tool("bip39-generate", "Generate BIP39 mnemonic phrases", {
208
+ wordCount: z.enum(["12", "15", "18", "21", "24"]).describe("Number of words in the mnemonic").optional(),
209
+ }, async ({ wordCount = "12" }) => {
210
+ try {
211
+ const count = parseInt(wordCount);
212
+ // Generate entropy based on word count
213
+ // 12 words = 128 bits, 15 words = 160 bits, 18 words = 192 bits, 21 words = 224 bits, 24 words = 256 bits
214
+ const entropyBits = Math.floor((count * 11) / 33) * 32;
215
+ const entropyBytes = entropyBits / 8;
216
+ // Generate cryptographically secure random entropy
217
+ const { randomBytes } = await import('crypto');
218
+ const entropy = randomBytes(entropyBytes);
219
+ // Generate mnemonic using proper BIP39 library
220
+ const mnemonic = bip39.entropyToMnemonic(entropy);
221
+ const words = mnemonic.split(' ');
222
+ // Validate the generated mnemonic
223
+ const isValid = bip39.validateMnemonic(mnemonic);
224
+ return {
225
+ content: [
226
+ {
227
+ type: "text",
228
+ text: `BIP39 Mnemonic Phrase (${words.length} words):
229
+
230
+ ${mnemonic}
231
+
232
+ Entropy: ${entropy.toString('hex')}
233
+ Valid: ${isValid ? 'Yes ✅' : 'No ❌'}
234
+ Entropy Bits: ${entropyBits}
235
+
236
+ ⚠️ SECURITY WARNING:
237
+ - This uses cryptographically secure random generation
238
+ - Store this mnemonic securely and never share it
239
+ - This can be used to generate cryptocurrency wallet seeds
240
+ - Anyone with this mnemonic can access associated wallets`,
241
+ },
242
+ ],
243
+ };
244
+ }
245
+ catch (error) {
246
+ return {
247
+ content: [
248
+ {
249
+ type: "text",
250
+ text: `Error generating BIP39 mnemonic: ${error instanceof Error ? error.message : 'Unknown error'}`,
251
+ },
252
+ ],
253
+ };
254
+ }
255
+ });
256
+ // Password generator tool
257
+ server.tool("password-generate", "Generate a secure password", {
258
+ length: z.number().describe("Password length").optional(),
259
+ includeUppercase: z.boolean().describe("Include uppercase letters").optional(),
260
+ includeLowercase: z.boolean().describe("Include lowercase letters").optional(),
261
+ includeNumbers: z.boolean().describe("Include numbers").optional(),
262
+ includeSymbols: z.boolean().describe("Include symbols").optional(),
263
+ }, async ({ length = 16, includeUppercase = true, includeLowercase = true, includeNumbers = true, includeSymbols = true }) => {
264
+ if (length < 4 || length > 128) {
265
+ return {
266
+ content: [
267
+ {
268
+ type: "text",
269
+ text: "Length must be between 4 and 128.",
270
+ },
271
+ ],
272
+ };
273
+ }
274
+ let charset = '';
275
+ if (includeUppercase)
276
+ charset += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
277
+ if (includeLowercase)
278
+ charset += 'abcdefghijklmnopqrstuvwxyz';
279
+ if (includeNumbers)
280
+ charset += '0123456789';
281
+ if (includeSymbols)
282
+ charset += '!@#$%^&*()_+-=[]{}|;:,.<>?';
283
+ if (charset === '') {
284
+ return {
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: "Error: At least one character type must be selected",
289
+ },
290
+ ],
291
+ };
292
+ }
293
+ let password = '';
294
+ const { randomBytes } = await import('crypto');
295
+ const randomValues = randomBytes(length);
296
+ for (let i = 0; i < length; i++) {
297
+ password += charset.charAt(randomValues[i] % charset.length);
298
+ }
299
+ return {
300
+ content: [
301
+ {
302
+ type: "text",
303
+ text: `Generated password: ${password}`,
304
+ },
305
+ ],
306
+ };
307
+ });
308
+ // Token generator tool
309
+ server.tool("token-generator", "Generate secure random tokens", {
310
+ length: z.number().describe("Token length").optional(),
311
+ charset: z.enum(["alphanumeric", "hex", "base64", "custom"]).describe("Character set to use").optional(),
312
+ customChars: z.string().optional().describe("Custom characters (required if charset is 'custom')"),
313
+ }, async ({ length = 32, charset = "alphanumeric", customChars }) => {
314
+ try {
315
+ if (length < 8 || length > 256) {
316
+ return {
317
+ content: [
318
+ {
319
+ type: "text",
320
+ text: "Length must be between 8 and 256.",
321
+ },
322
+ ],
323
+ };
324
+ }
325
+ let chars = '';
326
+ switch (charset) {
327
+ case 'alphanumeric':
328
+ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
329
+ break;
330
+ case 'hex':
331
+ chars = '0123456789abcdef';
332
+ break;
333
+ case 'base64':
334
+ chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
335
+ break;
336
+ case 'custom':
337
+ if (!customChars) {
338
+ return {
339
+ content: [
340
+ {
341
+ type: "text",
342
+ text: "Error: Custom characters required when charset is 'custom'",
343
+ },
344
+ ],
345
+ };
346
+ }
347
+ chars = customChars;
348
+ break;
349
+ }
350
+ let token = '';
351
+ const { randomBytes } = await import('crypto');
352
+ const randomValues = randomBytes(length);
353
+ for (let i = 0; i < length; i++) {
354
+ token += chars.charAt(randomValues[i] % chars.length);
355
+ }
356
+ return {
357
+ content: [
358
+ {
359
+ type: "text",
360
+ text: `Generated Token:
361
+ ${token}
362
+
363
+ Length: ${length} characters
364
+ Character set: ${charset}
365
+ ${charset === 'custom' ? `Custom chars: ${customChars}` : ''}`,
366
+ },
367
+ ],
368
+ };
369
+ }
370
+ catch (error) {
371
+ return {
372
+ content: [
373
+ {
374
+ type: "text",
375
+ text: `Error generating token: ${error instanceof Error ? error.message : 'Unknown error'}`,
376
+ },
377
+ ],
378
+ };
379
+ }
380
+ });
381
+ // OTP code generator
382
+ server.tool("otp-code-generator", "Generate Time-based One-Time Password (TOTP) codes", {
383
+ secret: z.string().describe("Base32 encoded secret key"),
384
+ digits: z.number().describe("Number of digits in the code").optional(),
385
+ period: z.number().describe("Time period in seconds").optional(),
386
+ }, async ({ secret, digits = 6, period = 30 }) => {
387
+ try {
388
+ if (digits < 4 || digits > 10) {
389
+ return {
390
+ content: [
391
+ {
392
+ type: "text",
393
+ text: "Digits must be between 4 and 10.",
394
+ },
395
+ ],
396
+ };
397
+ }
398
+ // Generate TOTP code using proper speakeasy library
399
+ const token = speakeasy.totp({
400
+ secret: secret,
401
+ encoding: 'base32',
402
+ digits: digits,
403
+ step: period
404
+ });
405
+ // Calculate remaining time for this token
406
+ const now = Math.floor(Date.now() / 1000);
407
+ const timeRemaining = period - (now % period);
408
+ // Verify the token is valid (for demonstration)
409
+ const verified = speakeasy.totp.verify({
410
+ secret: secret,
411
+ encoding: 'base32',
412
+ token: token,
413
+ step: period,
414
+ window: 1
415
+ });
416
+ return {
417
+ content: [
418
+ {
419
+ type: "text",
420
+ text: `TOTP Code: ${token}
421
+
422
+ Valid for: ${timeRemaining} seconds
423
+ Digits: ${digits}
424
+ Period: ${period} seconds
425
+ Secret: ${secret}
426
+ Verified: ${verified ? 'Yes ✅' : 'No ❌'}
427
+
428
+ This code can be used for two-factor authentication.
429
+ The token changes every ${period} seconds.`,
430
+ },
431
+ ],
432
+ };
433
+ }
434
+ catch (error) {
435
+ return {
436
+ content: [
437
+ {
438
+ type: "text",
439
+ text: `Error generating OTP: ${error instanceof Error ? error.message : 'Unknown error'}`,
440
+ },
441
+ ],
442
+ };
443
+ }
444
+ });
445
+ }