it-tools-mcp 3.0.15 → 3.0.16
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 +3 -3
- package/README.md +1 -0
- package/build/tools/network.js +96 -1
- package/package.json +1 -1
package/README.dockerhub.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://hub.docker.com/r/wrenchpilot/it-tools-mcp)
|
|
5
5
|
[](https://github.com/wrenchpilot/it-tools-mcp/actions)
|
|
6
6
|
|
|
7
|
-
A comprehensive Model Context Protocol (MCP) server that provides access to **
|
|
7
|
+
A comprehensive Model Context Protocol (MCP) server that provides access to **87 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.
|
|
8
8
|
|
|
9
9
|
## Using with VS Code
|
|
10
10
|
|
|
@@ -56,7 +56,7 @@ Add to your VS Code `settings.json`:
|
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
See the complete list of all
|
|
59
|
+
See the complete list of all 87 tools with detailed parameters on [GitHub](https://github.com/wrenchpilot/it-tools-mcp#available-tools)
|
|
60
60
|
|
|
61
61
|
## 📸 Examples in Action
|
|
62
62
|
|
|
@@ -78,7 +78,7 @@ Built with **TypeScript**, **Zod** validation, and **MCP SDK** for robust, type-
|
|
|
78
78
|
|
|
79
79
|
This project was developed using **VS Code**, **Copilot Chat Agent**, **Playwright MCP**, and the **Claude Sonnet 4 Model**, showcasing modern AI-assisted software development:
|
|
80
80
|
|
|
81
|
-
- 🔧 **All
|
|
81
|
+
- 🔧 **All 87 tools** designed and implemented with AI assistance
|
|
82
82
|
- 📦 **Complete Docker setup** with GitHub Actions CI/CD pipeline
|
|
83
83
|
- 🔍 **Schema optimization** with systematic validation cleanup
|
|
84
84
|
- 📚 **Comprehensive documentation** and tool catalogs
|
package/README.md
CHANGED
|
@@ -171,6 +171,7 @@ Examples of using the IT Tools MCP server with VS Code Copilot Chat for secure p
|
|
|
171
171
|
| `telnet` | Test TCP connectivity | `target: string`, `port: number` |
|
|
172
172
|
| `dig` | DNS query (custom type) | `target: string`, `type?: string` |
|
|
173
173
|
| `ssh` | SSH command execution | `target: string`, `user: string`, `command: string` |
|
|
174
|
+
| `scp` | Copy files to/from remote host (SFTP) | `target: string`, `user: string`, `direction: 'upload'\|'download'`, `localPath: string`, `remotePath: string`, `privateKey?: string` |
|
|
174
175
|
| `ip-subnet-calculator` | Calculate IPv4 subnet | `ip: string`, `cidr: number` |
|
|
175
176
|
| `ipv4-subnet-calc` | Enhanced IPv4 subnet calc | `cidr: string` |
|
|
176
177
|
| `ipv6-ula-generator` | Generate IPv6 ULA | `globalId?: string` |
|
package/build/tools/network.js
CHANGED
|
@@ -433,7 +433,7 @@ ${exclude.length > 0 ? `Custom excluded: ${exclude.join(', ')}` : ''}`,
|
|
|
433
433
|
throw new Error("Prefix cannot have more than 6 parts");
|
|
434
434
|
}
|
|
435
435
|
for (const part of prefixParts) {
|
|
436
|
-
if (!/^[0-
|
|
436
|
+
if (!/^[0-9-A-Fa-f]{2}$/.test(part)) {
|
|
437
437
|
throw new Error(`Invalid MAC address part: ${part}`);
|
|
438
438
|
}
|
|
439
439
|
macParts.push(part.toUpperCase());
|
|
@@ -787,4 +787,99 @@ Common issues:
|
|
|
787
787
|
return { content: [{ type: "text", text: `tail failed: ${error instanceof Error ? error.message : error}` }] };
|
|
788
788
|
}
|
|
789
789
|
});
|
|
790
|
+
// SCP Tool (using ssh2 SFTP)
|
|
791
|
+
server.tool("scp", "Copy files to or from a remote host using SFTP (SCP-like)", {
|
|
792
|
+
target: z.string().describe("Target host"),
|
|
793
|
+
user: z.string().describe("Username"),
|
|
794
|
+
direction: z.enum(["upload", "download"]).describe("Direction: upload (local to remote) or download (remote to local)"),
|
|
795
|
+
localPath: z.string().describe("Local file path (source for upload, destination for download)"),
|
|
796
|
+
remotePath: z.string().describe("Remote file path (destination for upload, source for download)"),
|
|
797
|
+
privateKey: z.string().optional().describe("Private key for authentication (PEM format, optional, or path to key file)")
|
|
798
|
+
}, async ({ target, user, direction, localPath, remotePath, privateKey }) => {
|
|
799
|
+
try {
|
|
800
|
+
const { Client } = await import("ssh2");
|
|
801
|
+
const fs = await import("fs");
|
|
802
|
+
let resolvedKey;
|
|
803
|
+
try {
|
|
804
|
+
resolvedKey = resolvePrivateKey(privateKey);
|
|
805
|
+
}
|
|
806
|
+
catch (err) {
|
|
807
|
+
return { content: [{ type: "text", text: `SCP key error: ${err.message}` }] };
|
|
808
|
+
}
|
|
809
|
+
return await new Promise((resolve) => {
|
|
810
|
+
const conn = new Client();
|
|
811
|
+
let finished = false;
|
|
812
|
+
const finish = (msg) => {
|
|
813
|
+
if (!finished) {
|
|
814
|
+
finished = true;
|
|
815
|
+
try {
|
|
816
|
+
conn.end();
|
|
817
|
+
}
|
|
818
|
+
catch { }
|
|
819
|
+
resolve({ content: [{ type: "text", text: msg }] });
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
// Connection timeout (20s)
|
|
823
|
+
const timeout = setTimeout(() => {
|
|
824
|
+
finish(`SCP connection timed out after 20 seconds`);
|
|
825
|
+
}, 20000);
|
|
826
|
+
conn.on("ready", () => {
|
|
827
|
+
clearTimeout(timeout);
|
|
828
|
+
conn.sftp((err, sftp) => {
|
|
829
|
+
if (err) {
|
|
830
|
+
finish(`SFTP error: ${err.message}`);
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
if (direction === "upload") {
|
|
834
|
+
let readStream, writeStream;
|
|
835
|
+
try {
|
|
836
|
+
readStream = fs.createReadStream(localPath);
|
|
837
|
+
writeStream = sftp.createWriteStream(remotePath);
|
|
838
|
+
}
|
|
839
|
+
catch (streamErr) {
|
|
840
|
+
finish(`Upload failed: ${streamErr.message}`);
|
|
841
|
+
return;
|
|
842
|
+
}
|
|
843
|
+
writeStream.on("close", () => finish(`Upload complete: ${localPath} → ${user}@${target}:${remotePath}`));
|
|
844
|
+
writeStream.on("error", (err) => finish(`Upload failed: ${err.message}`));
|
|
845
|
+
readStream.on("error", (err) => finish(`Upload failed: ${err.message}`));
|
|
846
|
+
readStream.pipe(writeStream);
|
|
847
|
+
}
|
|
848
|
+
else {
|
|
849
|
+
let readStream, writeStream;
|
|
850
|
+
try {
|
|
851
|
+
readStream = sftp.createReadStream(remotePath);
|
|
852
|
+
writeStream = fs.createWriteStream(localPath);
|
|
853
|
+
}
|
|
854
|
+
catch (streamErr) {
|
|
855
|
+
finish(`Download failed: ${streamErr.message}`);
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
writeStream.on("close", () => finish(`Download complete: ${user}@${target}:${remotePath} → ${localPath}`));
|
|
859
|
+
writeStream.on("error", (err) => finish(`Download failed: ${err.message}`));
|
|
860
|
+
readStream.on("error", (err) => finish(`Download failed: ${err.message}`));
|
|
861
|
+
readStream.pipe(writeStream);
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
}).on("error", (err) => {
|
|
865
|
+
clearTimeout(timeout);
|
|
866
|
+
finish(`SCP connection error: ${err.message}`);
|
|
867
|
+
});
|
|
868
|
+
try {
|
|
869
|
+
conn.connect({
|
|
870
|
+
host: target,
|
|
871
|
+
username: user,
|
|
872
|
+
...(resolvedKey ? { privateKey: resolvedKey } : {})
|
|
873
|
+
});
|
|
874
|
+
}
|
|
875
|
+
catch (err) {
|
|
876
|
+
clearTimeout(timeout);
|
|
877
|
+
finish(`SCP connect threw: ${err.message}`);
|
|
878
|
+
}
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
catch (fatalErr) {
|
|
882
|
+
return { content: [{ type: "text", text: `SCP fatal error: ${fatalErr.message || fatalErr}` }] };
|
|
883
|
+
}
|
|
884
|
+
});
|
|
790
885
|
}
|