Guide · AWS Transfer Family · File Transfer
AWS Transfer Family for MCP Servers — SFTP, FTPS, FTP, and AS2 Managed File Transfer
AWS Transfer Family is a fully managed SFTP, FTPS, FTP, and AS2 service that exposes your S3 buckets and EFS file systems as standard file-transfer endpoints — no server infrastructure to manage. For MCP server developers, Transfer Family solves the "automate legacy file-exchange workflows" problem: expose an SFTP endpoint that business partners can drop files into, then trigger your MCP tool to process new arrivals via S3 event notifications. The service handles SSH key management, user authentication, bandwidth throttling, and CloudWatch logging. The critical Transfer Family decisions at server creation time: endpoint type (PUBLIC, VPC, or VPC_ENDPOINT), which protocols to enable (SFTP, FTPS, FTP — AS2 is configured separately), and identity provider type (SERVICE_MANAGED for console-managed users, AWS_DIRECTORY_SERVICE for Active Directory, or API_GATEWAY for a custom Lambda-backed provider). These settings are partially immutable — you cannot change endpoint type or identity provider on an existing server without recreating it.
TL;DR
Create a Transfer Family server with identity-provider-type SERVICE_MANAGED and endpoint-type PUBLIC for internet-accessible SFTP. Add users with IAM roles that restrict access to specific S3 bucket prefixes using session policies. Map home directories using HomeDirectoryType LOGICAL with HomeDirectoryMappings so each user sees only their prefix as /. Enable CloudWatch logging with a server IAM role that has logs:CreateLogStream and logs:PutLogEvents. For private SFTP within a VPC (no public internet exposure), use endpoint-type VPC — this provisions an NLB and Elastic IPs but blocks public access entirely.
Creating a Transfer Family server
A Transfer Family server is the top-level resource that defines the endpoint, protocols, and authentication method. You create one server per use-case cluster — for example, one server for partner file drops (SFTP, public endpoint) and another for internal batch jobs (SFTP, VPC endpoint). Server creation choices that are immutable after the fact: EndpointType (PUBLIC vs VPC) and IdentityProviderType. Protocols can be changed after creation.
# Create a managed SFTP server with service-managed users
aws transfer create-server \
--protocols SFTP \
--endpoint-type PUBLIC \
--identity-provider-type SERVICE_MANAGED \
--logging-role arn:aws:iam::123456789012:role/TransferLoggingRole \
--tags Key=Project,Value=mcp-file-intake
# The response includes the server ID:
# { "ServerId": "s-0123456789abcdef0" }
# Get the server endpoint (SFTP hostname):
aws transfer describe-server \
--server-id s-0123456789abcdef0 \
--query 'Server.EndpointDetails.{Hostname:AddressAllocationIds}'
# For PUBLIC endpoint, the hostname is:
# s-0123456789abcdef0.server.transfer.us-east-1.amazonaws.com
# Wait for the server to become ONLINE:
aws transfer describe-server \
--server-id s-0123456789abcdef0 \
--query 'Server.State'
The server is identified by the ServerId in all subsequent API calls. The SFTP hostname for a PUBLIC endpoint follows the pattern <server-id>.server.transfer.<region>.amazonaws.com. For VPC endpoints, the hostname is the DNS name of the Network Load Balancer that Transfer Family provisions — you can also use Elastic IPs or custom DNS.
Endpoint types: PUBLIC vs VPC
Transfer Family supports three endpoint types that determine network accessibility. PUBLIC servers are reachable over the internet at an AWS-managed hostname. VPC servers are reachable only within a VPC via an NLB — you can optionally assign Elastic IPs to make them internet-accessible from specific CIDR ranges. VPC_ENDPOINT (legacy) uses a PrivateLink VPC interface endpoint without an NLB.
# PUBLIC endpoint — internet-accessible, no custom IP filtering
aws transfer create-server \
--protocols SFTP \
--endpoint-type PUBLIC \
--identity-provider-type SERVICE_MANAGED
# VPC endpoint — private NLB inside your VPC
# Elastic IPs allow internet access from specific IPs
aws transfer create-server \
--protocols SFTP \
--endpoint-type VPC \
--endpoint-details '{
"VpcId": "vpc-0abc123",
"SubnetIds": ["subnet-0aaa", "subnet-0bbb"],
"SecurityGroupIds": ["sg-0transfer"],
"AddressAllocationIds": ["eipalloc-01234", "eipalloc-05678"]
}' \
--identity-provider-type SERVICE_MANAGED
# For VPC endpoint without internet access, omit AddressAllocationIds:
aws transfer create-server \
--protocols SFTP \
--endpoint-type VPC \
--endpoint-details '{
"VpcId": "vpc-0abc123",
"SubnetIds": ["subnet-0aaa"],
"SecurityGroupIds": ["sg-0transfer-internal"]
}'
For VPC endpoints, the security group attached to the Transfer Family server controls which source IPs can connect to SFTP (port 22). The security group must allow inbound port 22 from your client IP ranges. If you assign AddressAllocationIds (Elastic IPs), those IPs are the public-facing IPs of the NLB — you can whitelist them in your partner's firewall and Transfer Family will always appear to come from those IPs for passive FTP data connections.
IAM roles for Transfer Family users
Every Transfer Family user needs two IAM roles: a User Role that grants access to S3 or EFS, and a Logging Role on the server that allows Transfer Family to write CloudWatch logs. These are separate concerns — the user role is assumed per-transfer and scoped to that user's home directory, while the logging role is assumed by the Transfer Family service itself.
# User role trust policy — Transfer Family service assumes this role
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "transfer.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}
# User role permission policy — grant S3 access
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::mcp-file-intake"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:GetObjectAcl",
"s3:PutObjectAcl"
],
"Resource": "arn:aws:s3:::mcp-file-intake/*"
}
]
}
# Logging role trust policy — Transfer Family service assumes this
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "transfer.amazonaws.com" },
"Action": "sts:AssumeRole"
}]
}
# Logging role permission policy
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}]
}
The user role is scoped further at runtime using a session policy — a JSON policy passed at user-creation time that restricts the role's effective permissions to the user's home directory prefix. Without a session policy, a user with the above role could access every key in the bucket. The session policy is what provides multi-tenant isolation. See the SFTP-to-S3 integration guide for the session policy pattern.
Creating users and mapping home directories
Transfer Family users are created on a specific server. Each user has a username, SSH public key, IAM role, and home directory mapping. The HomeDirectoryType is critical: ABSOLUTE maps the user's root to a specific S3 path like /bucket/prefix — the user sees the raw S3 key hierarchy. LOGICAL maps virtual paths to S3 targets using HomeDirectoryMappings — the user sees / as their root regardless of where files actually live in S3.
# Create a user with LOGICAL home directory mapping
aws transfer create-user \
--server-id s-0123456789abcdef0 \
--user-name alice \
--role arn:aws:iam::123456789012:role/TransferUserRole \
--home-directory-type LOGICAL \
--home-directory-mappings '[
{
"Entry": "/",
"Target": "/mcp-file-intake/alice"
},
{
"Entry": "/shared",
"Target": "/mcp-file-intake/shared"
}
]' \
--policy '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:*"],
"Resource": [
"arn:aws:s3:::mcp-file-intake",
"arn:aws:s3:::mcp-file-intake/alice/*",
"arn:aws:s3:::mcp-file-intake/shared/*"
]
}]
}'
# Upload an SSH public key for the user
aws transfer import-ssh-public-key \
--server-id s-0123456789abcdef0 \
--user-name alice \
--ssh-public-key-body "ssh-rsa AAAA... alice@example.com"
With LOGICAL mapping, when Alice uploads a file to /reports/q1.csv via SFTP, it lands in S3 at mcp-file-intake/alice/reports/q1.csv. She cannot see or traverse the mcp-file-intake/ prefix — her world starts at /. The /shared mapping gives her read/write access to the shared prefix without exposing other users' directories. This is the recommended pattern for multi-tenant SFTP drops.
Protocol options: SFTP, FTPS, FTP, and AS2
Transfer Family supports four protocols, each suited to different integration scenarios. SFTP (SSH File Transfer Protocol, port 22) is the most common and uses SSH keys or passwords for authentication. FTPS (FTP over TLS, port 21 + ephemeral data ports) is required by partners using legacy FTP clients that support TLS. Plain FTP is unencrypted and should only be used inside a VPC for internal batch jobs. AS2 (Applicability Statement 2) is an EDI standard for B2B document exchange — it uses HTTPS and requires certificates for signing and encryption.
# Create a server with multiple protocols (SFTP + FTPS, no FTP)
aws transfer create-server \
--protocols SFTP FTPS \
--certificate arn:aws:acm::123456789012:certificate/abc-def \
--endpoint-type PUBLIC \
--identity-provider-type SERVICE_MANAGED
# Note: FTPS requires a TLS certificate ARN (ACM or IAM)
# FTP is only allowed with VPC endpoint type (not PUBLIC)
# AS2 connector — send files to a trading partner's AS2 endpoint
aws transfer create-connector \
--url https://partner.example.com/as2 \
--as2-config '{
"LocalProfileId": "p-local123",
"PartnerProfileId": "p-partner456",
"MessageSubject": "EDI-order",
"Compression": "ZLIB",
"EncryptionAlgorithm": "AES256_CBC",
"SigningAlgorithm": "SHA256",
"MdnSigningAlgorithm": "SHA256",
"MdnResponse": "SYNC"
}' \
--access-role arn:aws:iam::123456789012:role/TransferConnectorRole
FTPS requires a TLS server certificate — use ACM to provision one and pass the ARN via --certificate. Passive FTPS data connections use a range of ephemeral ports (49152–65535) — your firewall must allow these inbound in addition to port 21. For AS2, you create a Connector (outbound — you push files to partners) and a Server Agreement (inbound — partners push files to you). Each trading partner requires a Profile with their AS2 ID and public certificate.
Triggering MCP tools on file arrival
Transfer Family writes files directly to S3 when users upload. To trigger an MCP tool when a new file arrives, use S3 event notifications or EventBridge. S3 event notifications are lower-latency (milliseconds) and support Lambda, SQS, and SNS targets. EventBridge rules offer richer filtering — you can route events from specific Transfer Family servers by matching on the server ID in the event source.
# S3 bucket notification — trigger Lambda on new file in alice's prefix
aws s3api put-bucket-notification-configuration \
--bucket mcp-file-intake \
--notification-configuration '{
"LambdaFunctionConfigurations": [{
"Id": "mcp-file-processor",
"LambdaFunctionArn": "arn:aws:lambda:us-east-1:123:function:mcp-process-upload",
"Events": ["s3:ObjectCreated:*"],
"Filter": {
"Key": {
"FilterRules": [{
"Name": "prefix",
"Value": "alice/"
}]
}
}
}]
}'
# EventBridge rule — Transfer Family server-level file upload events
# Transfer Family emits events to EventBridge when file transfer completes
aws events put-rule \
--name transfer-file-complete \
--event-pattern '{
"source": ["aws.transfer"],
"detail-type": ["File Transfer Complete"],
"detail": {
"ServerId": ["s-0123456789abcdef0"]
}
}'
Transfer Family emits File Transfer Complete and File Transfer Failed events to EventBridge automatically — no configuration needed on the server. The event detail includes ServerId, Username, SessionId, FileLocation (the S3 URI), and BytesTransferred. This lets your MCP tool subscribe to transfer completions without polling S3 — use an EventBridge rule to trigger a Lambda or SQS queue when a transfer from a specific user or server finishes.
Failure modes reference
| Failure | Symptom | Fix |
|---|---|---|
| Server stuck in STARTING state | Server never reaches ONLINE after creation | Check IAM role trust policy — logging role must trust transfer.amazonaws.com; missing trust = server stalls during startup |
| User authentication fails (key rejected) | SFTP client reports "Permission denied (publickey)" | Verify the public key was imported with exact format (including key type prefix and comment); Transfer Family requires OpenSSH format — convert PuTTY PPK keys with puttygen key.ppk -O public-openssh |
| User can list bucket root | SFTP ls shows other users' directories | Add a session policy to the user that restricts S3 access to their prefix — the user role alone grants bucket-wide access unless scoped by session policy |
| FTPS connection fails on data transfer | LIST and RETR commands time out after control connection succeeds | Open ephemeral ports 49152–65535 inbound in the security group — FTPS passive mode uses these for data channels; missing rule causes control connection success but data transfer timeout |
| Immutable setting error | UpdateServer API call returns InvalidRequestException for EndpointType or IdentityProviderType changes | Endpoint type and identity provider type are immutable — create a new server with correct settings, migrate users, then delete the old server |
| File not appearing in S3 | SFTP upload succeeds but S3 object does not exist | Check user role has s3:PutObject on the correct bucket ARN; also verify session policy is not more restrictive than the role — if both are present, the effective permission is the intersection |