[3.5.4] - 2026-04-17
MCP Hardening & Study-Driven Bug Fixes
A second independent audit (Claude Opus 4.7, 250 live tool calls across MCP and CLI on 32 provider profiles) surfaced a cluster of issues at the MCP boundary and a handful of CLI/provider edge cases. All findings have been fixed and re-validated against real endpoints.
Added
- CLI
aeroftp mcptop-level subcommand: equivalent toaeroftp agent --mcp. The VS Code Marketplace extension (axpdev-lab.aeroftp-mcpv1.0.2+) registersaeroftp-cli mcpas the server command, so the extension now works out of the box after upgrading AeroFTP - Shared
profile_loadermodule: newsrc-tauri/src/profile_loader.rscentralizes profile option normalization (insert_profile_option,apply_profile_options) and S3 preset defaults (apply_s3_profile_defaults). Both the CLI and the MCP server consume this single source of truth, eliminating the drift that caused the "bucket required" MCP regression - MCP JSON-RPC schema validation: tools/call arguments are now validated against each tool's
inputSchema.requiredbefore the call is dispatched. Missing fields return-32602 Invalid params for '<tool>': missing required field '<name>'instead of the previous opaque provider-level "bucket required" / "path is required" errors
Fixed
- MCP S3 bucket not extracted from vault (P0): the connection pool's
create_provider_from_vaultpreviously read only the credential blob and ignored the profile'soptionsfield, wherebucket,region,endpoint, andpath_stylelive. S3 profiles (Storj, AWS, Cloudflare R2, Backblaze, Mega S3, Wasabi, iDrive E2, Alibaba OSS, Tencent COS, Google Cloud Storage, and FileLu S3) now work end-to-end via MCP. Azure container mapping and Mega mode default also restored - MCP server did not initialize the credential vault (P0): a freshly-spawned
aeroftp-cli mcpsubprocess hit an emptyVAULT_CACHEand returned "Vault not open" for every authenticated tool call. The server now callsCredentialStore::init()at startup (auto-unlock in keyring mode) and falls back toAEROFTP_MASTER_PASSWORDwhen a master password is configured. A descriptivevault_erroris surfaced to the client otherwise - MCP tool calls raced on the same server (P1): rapid-fire
mkdir+upload_fileagainst the same profile could run in parallel, and on slow NAS targets the upload reached the server before the mkdir returned, producing spurious "parent not found" errors. A per-profiletokio::sync::Mutexnow serializes calls to the same server while keeping cross-server parallelism intact (via theserverargument in tool args) - MCP shutdown dropped in-flight responses (P2): stdin EOF immediately returned 0, cancelling every
tokio::spawned tool-call task. The server now tracks dispatched tasks in aJoinSetand drains them with a 10s timeout on EOF, so pending responses are written before the process exits - CLI
treepanicked with clap TypeId mismatch (P1): the global--max-depth: Option<u32>collided with themax_depth: usizefield on theTreeandNcdusubcommands because clap derives the long form from the field name. The subcommand fields have been renamed todepth(CLI surface is still-d/--depth), resolving the panic.aeroftp tree / --depth 2works in v3.5.4 on every provider - Drime race on mkdir → put with cryptic error (P1): freshly created folders were not yet indexed when the subsequent
putarrived, and the error message degraded to"Find file failed: {"becausesanitize_api_errortruncated the JSON body to a single opening brace.find_file_in_foldernow retries transient 4xx/5xx responses with exponential backoff (200 ms / 500 ms / 2 s) and includes the HTTP status and folder ID in the final error message for diagnosis - Filen passwordless share links failed with "Invalid salt" (P3): the v3 API rejects an empty salt field even when no password is set.
create_share_linknow generates a fresh 128-byte random salt on every call, regardless of whether the link is password-protected - FileLu native
mkdirreturned JSON parse error (P3): thefolder/createresponse sometimes returnsfld_idas a JSON string (not a number). TheFolderCreateResultstruct now uses the tolerantdeserialize_opt_u64deserializer already used for other FileLu API shapes - WebDAV
MKCOLrejected 204 No Content (P3): FileLu's WebDAV frontend returns 204 on success instead of the RFC 4918 standard 201. Some Nextcloud variants return 200 OK. All three are now accepted as idempotent success, matching real-world server behavior - Immich rejected non-media uploads with opaque error (P3): uploading a text, archive, or office document returned "HTTP 400: {" with no explanation. The provider now detects the 400 shape and returns
Immich accepts only media files (JPG, PNG, HEIC, MP4, MOV). Non-media files (text, archive, office documents) are rejected.
Changed
- CLI
hashsumaccepts--algorithm/-awith defaultsha256: the algorithm was positional only, contradicting the documented agent syntax and the MCP tool schema.hashsum path(default sha256),hashsum -a md5 path, andhashsum --algorithm sha512 pathall work. The MCP tool already matched the new CLI surface - CLI
speedaccepts--size/-sas a visible alias for--test-size. Aligns with rclone, aws s3, and iperf3 conventions; canonical--test-sizestill works for scripts
Validation
- 46 / 48 automated live checks passed on real endpoints (S3 Storj, Cloudflare R2, AWS, Mega S3, Backblaze, iDrive E2, SFTP Lumo Cloud, WebDAV FileLu/Koofr/InfiniCloud/jianguoyun, Filen, Drime, FileLu native, MCP tools/call for aeroftp_list_files / aeroftp_read_file / aeroftp_create_directory / aeroftp_upload_file / aeroftp_delete). Two skips were authentication/network issues unrelated to the fixes
- Clippy clean with
-D warnings; release build completes in ~4 min
Downloads:
- Windows:
.msiinstaller,.exe, or.zipportable (no installation required) - macOS:
.dmgdisk image - Linux:
.deb,.rpm,.snap, or.AppImage