# FTP, FTPS & SFTP MCP Server (`theprogrammer/mcp-server-ftp`) Actor

Connect AI assistants to FTP, FTPS, and SFTP servers through MCP. List directories, read and upload files, edit text, and manage remote files using your own server credentials.

- **URL**: https://apify.com/theprogrammer/mcp-server-ftp.md
- **Developed by:** [Alx Spiker](https://apify.com/theprogrammer) (community)
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 read files

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## FTP, FTPS & SFTP server

This Actor talks to an FTP, FTPS, or SFTP server in two ways.

**Standby MCP.** Save a task with your server connection and leave Operation empty. In the task's settings, enable **Validate and pass Actor input**. Open the Server tab, copy the MCP URL, and add `/mcp` if it is not already in the path. Connect an MCP client with `Authorization: Bearer <Apify token>`. Use a private, scoped token.

**Scheduled or manual job.** Set Operation to backup, sync, or compare, then run the task from Console, the API, or an Apify Schedule. The run does the job and exits. A schedule must target the task, not the Standby URL. Console → Schedules → create a schedule → choose the task and how often it should run.

Create a separate task for each server. Standby runs must stay on Apify's single-tenant configuration. Passwords, private keys, and passphrases are secret inputs. For SFTP, enter the server's SHA256 host-key fingerprint from your server administrator. FTPS checks the certificate. Plain FTP sends credentials and file contents without encryption.

### Jobs

- **Backup** copies a remote directory into a snapshot in a persistent named key-value store (or the store ID you set). Include and exclude use glob patterns. The snapshot is replaced. Files on the server are not deleted. Pick another snapshot name to keep an older copy.
- **Sync** mirrors that directory and a snapshot. Direction is remote-to-store or store-to-remote. Dry run only lists what would change. Delete extraneous files is off unless you turn it on.
- **Compare** diffs the directory against a snapshot or a second server. Added, changed, and removed paths are written to the dataset. Neither side is modified.

Files are copied one at a time. Anything over the maximum file size (100 MiB unless you set a lower limit) fails the job with an error that names the file.

By default, the store is selected from the server, username, and remote directory, so scheduled runs reuse the same snapshot. Find the store name in the job's summary output (`storeId`). To restore to a different server or directory, enter that name in Key-value store. Named stores persist until deleted and may incur storage charges. Snapshots from older runs that used an unnamed default store remain there; supply that store's ID to access them.

The same jobs are available inside Standby as the MCP tools `backup-directory`, `sync-directory`, and `compare-directories`. They use the task's saved connection.

### Pricing

Successful directory listings cost $0.002 each. File reads cost $0.005. Uploads, edits, and appends cost $0.01. File or directory management costs $0.01. Failed operations are not charged. Standby platform usage, including idle time, is billed separately. Prices are USD.

Backup, sync, and compare are charged only after the work succeeds: one `automation-run` event per finished job, and one `automation-file-transferred` event per file that was actually copied. Dry-runs, compares, skips, and deletes do not charge the per-file event.

Automation costs $0.02 per finished job and $0.005 per copied file. See the [setup notes](https://github.com/alxspiker/mcp-server-ftp/blob/main/APIFY.md).

### File handling

Use `upload-file` and `download-file` for text or base64 content. The desktop package's local-path tools are not available here. Incoming MCP requests are capped at 12 MiB. One-file MCP downloads still buffer the file; automation transfers stream instead and stop at the file-size cap.

Operations in one run happen one after another. Different runs do not coordinate, so avoid overlapping writes to the same server. If billing fails after a successful operation, the response says so and the run stops accepting more work. The transfer is not repeated.

The [open-source package](https://github.com/alxspiker/mcp-server-ftp) is still the one to run on your own computer.

# Changelog

This Actor's version history is a separate document: https://apify.com/theprogrammer/mcp-server-ftp/changelog.md

# Actor input Schema

## `protocol` (type: `string`):

Select the connection protocol.

## `host` (type: `string`):

Hostname or IP address, without a URL or path.

## `port` (type: `integer`):

Leave empty for port 21 (FTP/FTPS) or 22 (SFTP).

## `username` (type: `string`):

Username for the remote file server.

## `password` (type: `string`):

Password for the remote file server, if used.

## `privateKey` (type: `string`):

Optional SFTP private key in PEM or OpenSSH format.

## `passphrase` (type: `string`):

Passphrase for the SSH private key, if encrypted.

## `hostKeySha256` (type: `string`):

Required for SFTP. The server's trusted SHA256 fingerprint, for example SHA256:... Obtain it from your server administrator.

## `operation` (type: `string`):

Leave empty for a Standby MCP task. Set this to run one job from the Console, the API, or a Schedule.

## `remotePath` (type: `string`):

Directory to back up, sync, or compare. Defaults to /.

## `include` (type: `array`):

Only consider files matching at least one pattern. Empty includes every file. A pattern without a slash matches the file name in any directory. \*\* crosses directories.

## `exclude` (type: `array`):

Skip files matching any of these patterns. Exclude is applied before include.

## `direction` (type: `string`):

Sync only. remote-to-store copies the server into the snapshot. store-to-remote copies a snapshot onto the server.

## `dryRun` (type: `boolean`):

Sync only. Report what would change and do not copy or delete anything.

## `deleteExtraneous` (type: `boolean`):

Sync only. Delete destination files that are not in the source. Off by default. A backup always replaces its named snapshot and does not delete remote files.

## `snapshotName` (type: `string`):

Name of the snapshot in the key-value store. 1-40 characters: letters, numbers, and !-\_.'(). Use a new name to keep an older backup.

## `keyValueStoreId` (type: `string`):

Store ID or name for the snapshot. Leave empty to use a persistent named store unique to this server, username, and directory. Use the same store when restoring to a different server or directory.

## `maxFileBytes` (type: `integer`):

Files larger than this fail the job with an error before they are stored. Default and hard cap: 100 MiB (104857600). Files are streamed one at a time.

## `baseline` (type: `string`):

Compare only. A snapshot is a backup already stored under Snapshot name.

## `compareRemotePath` (type: `string`):

Remote directory for the second server. Leave empty to use the same directory as Remote directory.

## `compareProtocol` (type: `string`):

Required when Compare against is a second server.

## `compareHost` (type: `string`):

Hostname or IP address of the second server.

## `comparePort` (type: `integer`):

Leave empty for port 21 (FTP/FTPS) or 22 (SFTP).

## `compareUsername` (type: `string`):

Username for the second server.

## `comparePassword` (type: `string`):

Password for the second server, if used.

## `comparePrivateKey` (type: `string`):

Optional SFTP private key for the second server.

## `comparePassphrase` (type: `string`):

Passphrase for the second server's private key, if encrypted.

## `compareHostKeySha256` (type: `string`):

Required when the second server uses SFTP. SHA256 host key fingerprint.

## Actor input object example

```json
{
  "protocol": "sftp",
  "remotePath": "/",
  "direction": "remote-to-store",
  "dryRun": false,
  "deleteExtraneous": false,
  "snapshotName": "backup",
  "baseline": "snapshot"
}
```

# Actor output Schema

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("theprogrammer/mcp-server-ftp").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("theprogrammer/mcp-server-ftp").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call theprogrammer/mcp-server-ftp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,theprogrammer/mcp-server-ftp"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/JYzy3QuB7k6peaYwt/builds/pT9tsN07CXwCm4X1M/openapi.json
