it-tools-mcp 5.0.4 → 5.2.3

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 CHANGED
@@ -684,7 +684,7 @@ async function getManifestContent(type) {
684
684
  function extractToolFromReadme(readmeContent, toolName) {
685
685
  // Look for the tool in the Available Tools table
686
686
  const lines = readmeContent.split('\n');
687
- const toolRegex = new RegExp(`\\|\s*\`${toolName}\`\\s*\\|`, 'i');
687
+ const toolRegex = new RegExp(`\\|\\s*\`${toolName}\`\\s*\\|`, 'i');
688
688
  for (let i = 0; i < lines.length; i++) {
689
689
  const line = lines[i];
690
690
  if (toolRegex.test(line)) {
@@ -36,7 +36,11 @@ export function registerConvertList(server) {
36
36
  result = JSON.stringify(items, null, 2);
37
37
  break;
38
38
  case 'quoted':
39
- result = items.map(item => `"${item.replace(/"/g, '\\"')}"`).join(', ');
39
+ // Proper escaping: backslashes first, then quotes
40
+ result = items.map(item => {
41
+ const escaped = item.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
42
+ return `"${escaped}"`;
43
+ }).join(', ');
40
44
  break;
41
45
  default:
42
46
  const outputSeparator = separators[outputFormat];
@@ -12,12 +12,13 @@ export function registerDecodeHtml(server) {
12
12
  readOnlyHint: false
13
13
  }
14
14
  }, async ({ text }) => {
15
+ // Proper HTML decoding order: decode &amp; LAST to prevent double-unescaping
15
16
  const decoded = text
16
- .replace(/&amp;/g, '&')
17
17
  .replace(/&lt;/g, '<')
18
18
  .replace(/&gt;/g, '>')
19
19
  .replace(/&quot;/g, '"')
20
- .replace(/&#39;/g, "'");
20
+ .replace(/&#39;/g, "'")
21
+ .replace(/&amp;/g, '&'); // Decode ampersand LAST
21
22
  return {
22
23
  content: [
23
24
  {
@@ -41,8 +41,8 @@ export function registerEncodeHtmlEntities(server) {
41
41
  };
42
42
  }
43
43
  else {
44
+ // Proper HTML decoding order: decode &amp; LAST to prevent double-unescaping
44
45
  const decoded = text
45
- .replace(/&amp;/g, '&')
46
46
  .replace(/&lt;/g, '<')
47
47
  .replace(/&gt;/g, '>')
48
48
  .replace(/&quot;/g, '"')
@@ -56,7 +56,8 @@ export function registerEncodeHtmlEntities(server) {
56
56
  .replace(/&sect;/g, '§')
57
57
  .replace(/&para;/g, '¶')
58
58
  .replace(/&dagger;/g, '†')
59
- .replace(/&Dagger;/g, '‡');
59
+ .replace(/&Dagger;/g, '‡')
60
+ .replace(/&amp;/g, '&'); // Decode ampersand LAST
60
61
  return {
61
62
  content: [
62
63
  {
@@ -14,12 +14,19 @@ export function registerDecodeSafelink(server) {
14
14
  }, async ({ safelink }) => {
15
15
  try {
16
16
  const url = new URL(safelink);
17
- // Check if it's a SafeLink URL
18
- if (!url.hostname.includes('safelinks.protection.outlook.com')) {
17
+ // Check if it's a SafeLink URL - use secure hostname validation
18
+ const allowedSafeLinkHosts = [
19
+ 'safelinks.protection.outlook.com',
20
+ 'nam11.safelinks.protection.outlook.com',
21
+ 'eur01.safelinks.protection.outlook.com',
22
+ 'apc01.safelinks.protection.outlook.com',
23
+ 'gcc02.safelinks.protection.outlook.com'
24
+ ];
25
+ if (!allowedSafeLinkHosts.includes(url.hostname.toLowerCase())) {
19
26
  return {
20
27
  content: [{
21
28
  type: "text",
22
- text: "This doesn't appear to be a SafeLink URL."
29
+ text: "This doesn't appear to be a legitimate SafeLink URL from Microsoft Outlook."
23
30
  }]
24
31
  };
25
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "it-tools-mcp",
3
- "version": "5.0.4",
3
+ "version": "5.2.3",
4
4
  "description": "Full MCP 2025-06-18 compliant server with 121+ IT tools, logging, ping, progress tracking, cancellation, and sampling utilities",
5
5
  "type": "module",
6
6
  "main": "./build/index.js",