list-directory
List files and directories on an FTP server by specifying the remote path to browse server contents.
Instructions
List contents of an FTP directory
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| remotePath | Yes | Path of the directory on the FTP server |
Implementation Reference
- src/index.ts:32-62 (handler)The MCP tool handler function for 'list-directory'. It uses ftpClient.listDirectory to fetch the listing, formats it with file types, sizes, dates, adds a summary, and returns formatted text content or error.async ({ remotePath }) => { try { const listing = await ftpClient.listDirectory(remotePath); // Format the output const formatted = listing.map((item) => `${item.type === "directory" ? "[DIR]" : "[FILE]"} ${item.name} ${item.type === "file" ? `(${formatSize(item.size)})` : ""} - ${item.modifiedDate}` ).join("\n"); const summary = `Total: ${listing.length} items (${listing.filter(i => i.type === "directory").length} directories, ${listing.filter(i => i.type === "file").length} files)`; return { content: [ { type: "text", text: `Directory listing for: ${remotePath}\n\n${formatted}\n\n${summary}` } ] }; } catch (error) { return { isError: true, content: [ { type: "text", text: `Error listing directory: ${error instanceof Error ? error.message : String(error)}` } ] }; } }
- src/index.ts:29-31 (schema)Input schema for the list-directory tool using Zod, defining the 'remotePath' parameter.{ remotePath: z.string().describe("Path of the directory on the FTP server"), },
- src/index.ts:26-63 (registration)Registration of the 'list-directory' tool on the McpServer instance, including name, description, schema, and handler.server.tool( "list-directory", "List contents of an FTP directory", { remotePath: z.string().describe("Path of the directory on the FTP server"), }, async ({ remotePath }) => { try { const listing = await ftpClient.listDirectory(remotePath); // Format the output const formatted = listing.map((item) => `${item.type === "directory" ? "[DIR]" : "[FILE]"} ${item.name} ${item.type === "file" ? `(${formatSize(item.size)})` : ""} - ${item.modifiedDate}` ).join("\n"); const summary = `Total: ${listing.length} items (${listing.filter(i => i.type === "directory").length} directories, ${listing.filter(i => i.type === "file").length} files)`; return { content: [ { type: "text", text: `Directory listing for: ${remotePath}\n\n${formatted}\n\n${summary}` } ] }; } catch (error) { return { isError: true, content: [ { type: "text", text: `Error listing directory: ${error instanceof Error ? error.message : String(error)}` } ] }; } } );
- src/ftp-client.ts:54-70 (helper)FtpClient.listDirectory method: connects to FTP, lists directory using basic-ftp client, maps to structured output with name, type, size, modifiedDate.async listDirectory(remotePath: string): Promise<Array<{name: string, type: string, size: number, modifiedDate: string}>> { try { await this.connect(); const list = await this.client.list(remotePath); await this.disconnect(); return list.map(item => ({ name: item.name, type: item.type === 1 ? "file" : item.type === 2 ? "directory" : "other", size: item.size, modifiedDate: item.modifiedAt ? item.modifiedAt.toISOString() : "" })); } catch (error) { console.error("List directory error:", error); throw new Error(`Failed to list directory: ${error instanceof Error ? error.message : String(error)}`); } }
- src/index.ts:232-237 (helper)Utility function to format file sizes in human-readable form (B, KB, MB, GB), used in the tool handler output.function formatSize(bytes: number): string { if (bytes < 1024) return bytes + " B"; else if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + " KB"; else if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(2) + " MB"; else return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB"; }