---
title: File Transfer Tools
description: Send and receive files using X/Y/ZMODEM protocols
sidebar:
  order: 4
---

import { Aside } from '@astrojs/starlight/components';

Transfer files over serial connections using classic X/Y/ZMODEM protocols. These tools work in both RS-232 and RS-485 modes.

<Aside type="note">
Examples use tool-call notation: `tool_name(param=value)`. These are MCP tool calls made by the assistant, not code you write directly. Boolean values use JSON convention (`true`/`false`).
</Aside>

## Protocol Comparison

| Protocol | Block Size | Batch | Resume | Error Correction | Recommended |
|----------|-----------|-------|--------|------------------|-------------|
| XMODEM   | 128B      | No    | No     | Checksum/CRC     | Legacy only |
| XMODEM-1K| 1024B     | No    | No     | CRC-16           | -           |
| YMODEM   | 1024B     | Yes   | No     | CRC-16           | Batch needs |
| ZMODEM   | Streaming | Yes   | Yes    | CRC-32           | Yes         |

<Aside type="tip">
Use ZMODEM unless you have a specific reason not to. It is the fastest protocol, supports streaming (no stop-and-wait per block), handles batch transfers, and can resume interrupted transfers.
</Aside>

---

## file_transfer_send

Send a single file over serial using a selected protocol. The receiver must be waiting in receive mode before calling this tool. ZMODEM receivers typically auto-start when they detect the init sequence.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `port` | `str` | required | Device path of the open serial port. |
| `file_path` | `str` | required | Path to the file to send. |
| `protocol` | `Literal["xmodem", "xmodem1k", "ymodem", "zmodem"]` | `"zmodem"` | Transfer protocol to use. |

**Returns:** Transfer statistics dict with protocol-specific details including bytes sent and any errors. The dict also includes `protocol` and `file` fields.

```
# Send a firmware file using ZMODEM (default)
file_transfer_send(port="/dev/ttyUSB0", file_path="/home/user/firmware.bin")

# Send using XMODEM for legacy compatibility
file_transfer_send(
    port="/dev/ttyUSB0",
    file_path="/home/user/config.txt",
    protocol="xmodem",
)

# XMODEM-1K for faster transfers on legacy systems
file_transfer_send(
    port="/dev/ttyUSB0",
    file_path="/home/user/data.bin",
    protocol="xmodem1k",
)

# YMODEM preserves filename and size metadata
file_transfer_send(
    port="/dev/ttyUSB0",
    file_path="/home/user/update.bin",
    protocol="ymodem",
)
```

<Aside type="caution">
The file must exist on the local filesystem. The tool validates the path before starting the transfer and returns an error if the file is not found.
</Aside>

---

## file_transfer_receive

Receive a file over serial using a selected protocol. The behavior of `save_path` depends on the protocol.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `port` | `str` | required | Device path of the open serial port. |
| `save_path` | `str` | required | For XMODEM: full file path. For YMODEM/ZMODEM: directory where received files are saved. |
| `protocol` | `Literal["xmodem", "ymodem", "zmodem"]` | `"zmodem"` | Transfer protocol to use. |
| `overwrite` | `bool` | `False` | Whether to overwrite existing files. |

**Returns:** Transfer statistics dict with protocol-specific details including bytes received and file paths. Includes the `protocol` field.

<Aside type="note">
XMODEM does not transmit the filename -- the sender and receiver must agree on it beforehand. Pass the full destination file path as `save_path`. YMODEM and ZMODEM carry the filename in the protocol, so `save_path` should be a directory.
</Aside>

```
# Receive via ZMODEM into a directory
file_transfer_receive(
    port="/dev/ttyUSB0",
    save_path="/home/user/downloads/",
)

# Receive a single file via XMODEM
file_transfer_receive(
    port="/dev/ttyUSB0",
    save_path="/home/user/received_file.bin",
    protocol="xmodem",
)

# Receive via YMODEM, allowing overwrite
file_transfer_receive(
    port="/dev/ttyUSB0",
    save_path="/home/user/downloads/",
    protocol="ymodem",
    overwrite=true,
)
```

<Aside type="caution">
When `overwrite` is `False` (the default), the tool returns an error if the destination file already exists. For XMODEM this is checked before the transfer starts. For YMODEM/ZMODEM, the check happens as each file is received.
</Aside>

---

## file_transfer_send_batch

Send multiple files in a single batch transfer. Only YMODEM and ZMODEM support batch mode.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `port` | `str` | required | Device path of the open serial port. |
| `file_paths` | `list[str]` | required | List of file paths to send. |
| `protocol` | `Literal["ymodem", "zmodem"]` | `"zmodem"` | Transfer protocol. Must be `ymodem` or `zmodem`. |

**Returns:** Transfer statistics dict covering all files, including the `protocol` field.

<Aside type="note">
All files are validated before the transfer begins. If any file in the list does not exist, the entire batch is rejected with an error identifying the missing file.
</Aside>

```
# Batch send with ZMODEM (default)
file_transfer_send_batch(
    port="/dev/ttyUSB0",
    file_paths=[
        "/home/user/config.json",
        "/home/user/firmware.bin",
        "/home/user/README.txt",
    ],
)

# Batch send with YMODEM
file_transfer_send_batch(
    port="/dev/ttyUSB0",
    file_paths=["/home/user/file1.txt", "/home/user/file2.txt"],
    protocol="ymodem",
)
```

---

## Typical Workflow

A complete file transfer session looks like this:

```
# 1. Open the port at a suitable baud rate
open_serial_port(port="/dev/ttyUSB0", baudrate=115200)

# 2. Send a file
file_transfer_send(port="/dev/ttyUSB0", file_path="/home/user/firmware.bin")

# 3. Or receive a file
file_transfer_receive(port="/dev/ttyUSB0", save_path="/home/user/downloads/")

# 4. Close when done
close_serial_port(port="/dev/ttyUSB0")
```

<Aside type="tip">
Higher baud rates significantly improve transfer speed. For file transfers, use the highest baud rate both endpoints support -- 115200 is a common safe choice, but many adapters support 921600 or higher.
</Aside>
