/ src / tests / mcp-tools.test.js
mcp-tools.test.js
  1  #!/usr/bin/env node
  2  
  3  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
  4  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
  5  import fs from "fs";
  6  import path from "path";
  7  
  8  async function testAllTools() {
  9    console.log("๐Ÿงช Testing ALL Vulcan File Ops MCP Tools");
 10    console.log("=".repeat(50));
 11  
 12    // Create MCP client transport
 13    const transport = new StdioClientTransport({
 14      command: "node",
 15      args: ["dist/cli.js"],
 16    });
 17  
 18    const client = new Client(
 19      {
 20        name: "test-client",
 21        version: "1.0.0",
 22      },
 23      {
 24        capabilities: {},
 25      }
 26    );
 27  
 28    try {
 29      // Connect and initialize
 30      await client.connect(transport);
 31      console.log("โœ… Connected to MCP server");
 32  
 33      // Test directory for operations - use a temporary directory relative to project root
 34      const testDir = path.join(process.cwd(), "test-workspace", "mcp-test-" + Date.now());
 35  
 36      // Create the test directory first
 37      console.log("\n๐Ÿ“ 0. Creating test directory...");
 38      try {
 39        fs.mkdirSync(testDir, { recursive: true });
 40        console.log("โœ… Test directory created:", testDir);
 41      } catch (error) {
 42        console.log("โŒ Failed to create test directory:", error.message);
 43        return;
 44      }
 45  
 46      // 1. Register the test directory
 47      console.log("\n๐Ÿ“ 1. Registering test directory...");
 48      try {
 49        const registerResult = await client.callTool({
 50          name: "register_directory",
 51          arguments: { path: testDir },
 52        });
 53        console.log("โœ… Directory registered:", registerResult.content[0].text);
 54      } catch (error) {
 55        console.log("โŒ Directory registration failed:", error.message);
 56        return;
 57      }
 58  
 59      // 2. List allowed directories
 60      console.log("\n๐Ÿ“‹ 2. Listing allowed directories...");
 61      const listAllowedResult = await client.callTool({
 62        name: "list_allowed_directories",
 63        arguments: {},
 64      });
 65      console.log("โœ… Allowed directories:", listAllowedResult.content[0].text);
 66  
 67      // 3. List directory contents
 68      console.log("\n๐Ÿ“‚ 3. Listing directory contents...");
 69      const listDirResult = await client.callTool({
 70        name: "list_directory",
 71        arguments: { path: testDir },
 72      });
 73      console.log("โœ… Directory listing:", listDirResult.content[0].text);
 74  
 75      // 4. Create a test file
 76      console.log("\n๐Ÿ“ 4. Creating test file...");
 77      const testFile = path.join(testDir, "test-file.txt");
 78      const createFileResult = await client.callTool({
 79        name: "write_file",
 80        arguments: {
 81          path: testFile,
 82          content: "This is a test file created by MCP tools!\nLine 2\nLine 3",
 83        },
 84      });
 85      console.log("โœ… File created:", createFileResult.content[0].text);
 86  
 87      // 5. Read the file
 88      console.log("\n๐Ÿ“– 5. Reading file...");
 89      const readTextResult = await client.callTool({
 90        name: "read_file",
 91        arguments: { path: testFile },
 92      });
 93      console.log(
 94        "โœ… File content:",
 95        readTextResult.content[0].text.substring(0, 50) + "..."
 96      );
 97  
 98      // 6. Read first 2 lines
 99      console.log("\n๐Ÿ“– 6. Reading first 2 lines...");
100      const readHeadResult = await client.callTool({
101        name: "read_file",
102        arguments: { path: testFile, mode: "head", lines: 2 },
103      });
104      console.log("โœ… First 2 lines:", readHeadResult.content[0].text);
105  
106      // 7. Read last line
107      console.log("\n๐Ÿ“– 7. Reading last line...");
108      const readTailResult = await client.callTool({
109        name: "read_file",
110        arguments: { path: testFile, mode: "tail", lines: 1 },
111      });
112      console.log("โœ… Last line:", readTailResult.content[0].text);
113  
114      // 8. Get file info
115      console.log("\nโ„น๏ธ 8. Getting file info...");
116      const fileInfoResult = await client.callTool({
117        name: "get_file_info",
118        arguments: { path: testFile },
119      });
120      console.log("โœ… File info:", fileInfoResult.content[0].text);
121  
122      // 9. List directory with sizes (using unified list_directory)
123      console.log("\n๐Ÿ“Š 9. Listing directory with sizes...");
124      const listWithSizesResult = await client.callTool({
125        name: "list_directory",
126        arguments: { path: testDir, format: "detailed", sortBy: "size" },
127      });
128      console.log(
129        "โœ… Directory with sizes:",
130        listWithSizesResult.content[0].text
131      );
132  
133      // 10. Create a subdirectory
134      console.log("\n๐Ÿ“ 10. Creating subdirectory...");
135      const subDir = path.join(testDir, "test-subdir");
136      const createDirResult = await client.callTool({
137        name: "make_directory",
138        arguments: { paths: subDir },
139      });
140      console.log("โœ… Directory created:", createDirResult.content[0].text);
141  
142      // 10b. Create multiple directories at once (new batch feature)
143      console.log("\n๐Ÿ“ 10b. Creating multiple directories (batch)...");
144      const batchDirs = [
145        path.join(testDir, "batch-test-1"),
146        path.join(testDir, "batch-test-2"),
147        path.join(testDir, "nested", "batch-test-3"),
148      ];
149      const batchResult = await client.callTool({
150        name: "make_directory",
151        arguments: { paths: batchDirs },
152      });
153      console.log("โœ… Batch directories created:", batchResult.content[0].text);
154  
155      // 11. Move file to subdirectory
156      console.log("\n๐Ÿ“ฆ 11. Moving file to subdirectory...");
157      const movedFile = path.join(subDir, "moved-file.txt");
158      const moveResult = await client.callTool({
159        name: "move_file",
160        arguments: {
161          source: testFile,
162          destination: movedFile,
163        },
164      });
165      console.log("โœ… File moved:", moveResult.content[0].text);
166  
167      // 12. Edit the moved file
168      console.log("\nโœ๏ธ 12. Editing the moved file...");
169      const editResult = await client.callTool({
170        name: "edit_file",
171        arguments: {
172          path: movedFile,
173          edits: [
174            {
175              oldText: "This is a test file created by MCP tools!",
176              newText: "This is an EDITED test file created by MCP tools!",
177            },
178          ],
179          dryRun: false,
180        },
181      });
182      console.log("โœ… File edited (check diff output)");
183  
184      // 13. Search for files using glob
185      console.log("\n๐Ÿ” 13. Searching for files...");
186      const searchResult = await client.callTool({
187        name: "glob_files",
188        arguments: {
189          path: testDir,
190          pattern: "**/*.txt",
191        },
192      });
193      console.log("โœ… Search results:", searchResult.content[0].text);
194  
195      // 14. Get directory tree (using unified list_directory with tree format)
196      console.log("\n๐ŸŒณ 14. Getting directory tree...");
197      const treeResult = await client.callTool({
198        name: "list_directory",
199        arguments: { path: testDir, format: "tree" },
200      });
201      console.log("โœ… Directory tree (text):", treeResult.content[0].text);
202  
203      // 14b. Get directory structure as JSON (new format option)
204      console.log("\n๐Ÿ“Š 14b. Getting directory as JSON...");
205      const jsonResult = await client.callTool({
206        name: "list_directory",
207        arguments: { path: testDir, format: "json" },
208      });
209      const jsonData = JSON.parse(jsonResult.content[0].text);
210      console.log(
211        "โœ… Directory JSON:",
212        `Found ${jsonData.summary.totalFiles} files and ${jsonData.summary.totalDirectories} directories`
213      );
214  
215      // 15. Read multiple files
216      console.log("\n๐Ÿ“š 15. Reading multiple files...");
217      const multiReadResult = await client.callTool({
218        name: "read_multiple_files",
219        arguments: {
220          paths: [movedFile],
221        },
222      });
223      console.log(
224        "โœ… Multiple files read:",
225        multiReadResult.content[0].text.substring(0, 100) + "..."
226      );
227  
228      console.log("\n๐ŸŽ‰ ALL TOOLS TESTED SUCCESSFULLY!");
229      console.log("โœ… Vulcan File Ops MCP Server is working perfectly!");
230      console.log("\n๐Ÿ“ Test directory:", testDir);
231      console.log("๐Ÿงน Cleaning up test directory...");
232  
233      // Clean up test directory
234      try {
235        fs.rmSync(testDir, { recursive: true, force: true });
236        console.log("โœ… Test directory cleaned up");
237      } catch (error) {
238        console.log("โš ๏ธ  Failed to clean up test directory:", error.message);
239      }
240    } catch (error) {
241      console.error("โŒ Test failed:", error);
242      console.error("Stack:", error.stack);
243    } finally {
244      client.close();
245    }
246  }
247  
248  testAllTools();