Skip to content
How to install

Files (Web FTP)

A site’s files, relative to its WordPress folder (path='' is the folder itself). Everything runs inside the site’s own container as www-data, so it can do what the site’s own PHP can, no more.

Reading needs Read only and changes need Manage, unless an endpoint says otherwise. How to read this page.

List a folder: names, sizes, dates, permissions, owners, link targets.

  • Level: Read only
  • Input: ?path=wp-content
  • Returns: {path, writable, entries[], truncated} (409 when stopped)

Read a file of up to 8 MiB, with its ETag for a later save.

Raw bytes - fetch them with curl rather than the console.

  • Level: Manage. Reads any file - wp-config.php and its database password included
  • Notes: MCP file tools only
  • Input: ?path=wp-config.php
  • Returns: the bytes, ETag: "<sha256>"

Save a whole file (up to 8 MiB); If-Match makes it conditional, If-None-Match: * create-only.

Raw body - send it with curl –data-binary rather than the console.

  • Level: Manage
  • Notes: Destructive · MCP file tools only
  • Input: ?path=…&lint=php, body: the bytes (application/octet-stream)
  • Returns: {path, entry, etag}; 412 when the file changed, 422 when lint finds a PHP parse error

Download a file, or a folder as .tar.gz.

Binary stream - fetch it with curl rather than the console.

  • Level: Manage. Downloads any file or folder, secrets included
  • Notes: Not over MCP
  • Input: ?path=wp-content/themes/mytheme
  • Returns: an attachment (3 at a time per server)

Find files by name, or search their contents (plain text or a regex).

  • Level: Manage. A content search returns the matching lines of any file
  • Input: ?path=&q=eval(base64_decode&mode=name|content&case=&regex=&include=*.php
  • Returns: {mode, path, matches[], truncated, timedOut} (30/min)

Upload one chunk (up to 8 MiB) of a file; the chunk that completes it puts the file in place.

Raw body - see docs/web-ftp.md for the upload protocol.

  • Level: Manage
  • Notes: Destructive · Not over MCP
  • Input: ?path=…&offset=0&size=<total>&overwrite=false, body: the chunk
  • Returns: {received, written}; 409 {details.received} to resume from; the last chunk sent again gets the same answer

Abandon an upload and remove what arrived of it.

  • Level: Manage
  • Notes: Not over MCP
  • Input: ?path=…

Create a folder.

  • Level: Manage
  • Input: {path}
  • Returns: {entry}

Rename or move a file or folder.

  • Level: Manage
  • Notes: Destructive
  • Input: {from, to, overwrite?: false}
  • Returns: {entry}

Copy a file or folder (never over an existing entry).

  • Level: Manage
  • Input: {from, to}
  • Returns: {entry}

Delete files and folders; checks them all first, so one bad path deletes nothing.

  • Level: Manage
  • Notes: Destructive
  • Input: {paths: [...]} (up to 200)
  • Returns: {deleted}

Change the permissions of a file or folder.

  • Level: Manage
  • Input: {path, mode: "644"}
  • Returns: {entry}

Give everything under a path back to the site user (www-data), e.g. files root created.

  • Level: Manage
  • Input: {path?: ''}
  • Returns: {ok}

Extract a .zip into a folder; refuses unsafe archives, and anything in the way unless overwrite.

  • Level: Manage
  • Notes: Job · Destructive
  • Input: {path, to?: '', overwrite?: false}

Compress entries of one folder into a .zip beside them.

  • Level: Manage
  • Notes: Job · Destructive
  • Input: {paths: [...], to: "folder/archive.zip", overwrite?: false}