ffl-mcp

Give AI a "send file" capability via P2P (Local-first)

Documentation

ffl-mcp (local-only)

MCP server for ffl. Let AI share anything for you.

Backed by ffl, which turns any file/folder into an HTTPS link.

This MCP server uses the ffl-python binding locally. No file contents are sent to the LLM; the model only triggers local ffl.

This demo shows collaborative debugging: Claude on the left shares a local environment (DB + logs) via P2P link, Claude on the right downloads and diagnoses the error. In this scenario, the two Claudes represent different people working on separate machines.

ffl-mcp-demo


Table of Contents


Installation

⚡ Short URLs for convenience

  • Linux/macOS: curl -fsSL https://fastfilelink.com/mcp/install.sh | bash
  • Windows (script): iwr -useb https://fastfilelink.com/mcp/install.ps1 | iex

🔒 fastfilelink.com/mcp/* is a redirect to GitHub. Use the direct GitHub URLs below if you prefer.

Windows — GUI Installer

Download and run ffl-mcp-setup.exe from the latest release.

It registers the server with Claude Desktop, Claude Code, Codex, and Grok Build.

No command line needed — the installer registers ffl-mcp with Claude Desktop and Claude Code automatically.

Linux / macOS — one-liner

curl -fsSL https://raw.githubusercontent.com/nuwainfo/ffl-mcp/refs/heads/main/scripts/Install.sh | bash

Downloads the platform binary from the latest GitHub release and runs ffl-mcp install to register with Claude, Codex, and Grok Build. Falls back to uvx automatically if no binary is available for your platform.

Windows — one-liner (PowerShell)

iwr -useb https://raw.githubusercontent.com/nuwainfo/ffl-mcp/refs/heads/main/scripts/Install.ps1 | iex

Downloads ffl-mcp.exe from the latest GitHub release and registers it with Claude, Codex, and Grok Build.

uvx (no binary, requires uv)

uvx --from git+https://github.com/nuwainfo/ffl-mcp install

Targets can be controlled with --target (default: all):

uvx --from git+https://github.com/nuwainfo/ffl-mcp install --target claude-desktop,claude-code,codex,grok-build
uvx --from git+https://github.com/nuwainfo/ffl-mcp install --print

claude-code uses the Claude Code CLI. codex writes the native ~/.codex/config.toml configuration used by Codex clients. grok-build writes ~/.grok/config.toml, which Grok Build can reload from /mcps.

Legacy target names (claude-cli, codex-cli, codex-desktop, and grok) remain accepted as aliases. The installer first creates a timestamped backup of any config it changes.

For custom config paths, pass the file:

uvx --from git+https://github.com/nuwainfo/ffl-mcp install --config /path/to/claude_desktop_config.json
uvx --from git+https://github.com/nuwainfo/ffl-mcp install --codex-config /path/to/codex/config.toml
uvx --from git+https://github.com/nuwainfo/ffl-mcp install --grok-config /path/to/grok/config.toml

Run directly (development)

Prereq: uv installed.

# optional safety: restrict file sharing to a directory
export ALLOWED_BASE_DIR="$HOME/Downloads"

# optional: use stdin for text/base64 instead of temp files
export FFL_USE_STDIN=1

uvx --from git+https://github.com/nuwainfo/ffl-mcp ffl-mcp

MCP Config (manual JSON)

{
  "mcpServers": {
    "ffl": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/nuwainfo/ffl-mcp", "ffl-mcp"],
      "env": {
        "ALLOWED_BASE_DIR": "/Users/you/Downloads",
        "FFL_USE_STDIN": "1"
      }
    }
  }
}

Tools

Sharing

ToolInput
fflShareText(text, name?, ...)Plain text
fflShareBase64(dataB64, name?, ...)Binary data (base64-encoded)
fflShareFile(path, name?, ...)Single local file or folder
fflShareFiles(paths, name?, ...)Multiple files (ffl auto-zips them into one download)

Common options for all share tools:

OptionDefaultDescription
e2eeFalseEnd-to-end encryption
qrInTerminalFalseReturn ASCII QR art (qrCode in response)
authUser / authPassword—HTTP Basic Auth to protect the link
maxDownloads1Stop serving after N downloads (P2P only)
timeoutSeconds1800Inactivity timeout in seconds (P2P only)
recipientAuth—pickup (6-digit code), pubkey (RSA), pubkey+pickup, or email (OTP)
pickupCodeautoSpecific pickup code for pickup mode
recipientPublicKey—Path to .fflpub file for pubkey mode
recipientEmail—Email(s) for email OTP mode, comma-separated
alias—Custom link alias e.g. my-release (requires Standard+ account)
receipt—Email notification when recipient downloads
receiptConfirm—Require recipient confirmation before download; pass a message or ""
forceRelayFalseDisable WebRTC, route all traffic through tunnel
port—Local HTTP server port (auto-detect by default). Useful with fixed tunnels.
inviteFalseOpen the ffl invite page in a local browser with the generated sharing link.
enableReportingFalseEnable ffl diagnostic error reporting. Disabled by default.
upload—Upload to FFL server instead of P2P — e.g. "1 day", "6 hours" (requires Standard+ account)
resumeUploadFalseResume an interrupted upload
proxy—Proxy URL e.g. socks5://127.0.0.1:9050

Additional options for fflShareFile / fflShareFiles:

OptionDefaultDescription
previewFalseAppend ?preview=true to the returned link, so ffl's download page opens straight into its full preview view instead of the normal floating card.
exclude—Glob or regex patterns to exclude, comma-separated — e.g. *.pyc,__pycache__ or re:\.env$
pause—Pause server upload at a percentage from 1 to 99. Requires upload.
vfsFalseExpose as VFS server (vfs:// URI) — fflShareFile only
preferredTunnel—Set preferred tunnel for this and future runs — cloudflare, ngrok, bore, etc.

preview only affects the returned link's query string and works for any share (single file, folder, or multi-file). The preview sidecar routes (/manifest, /file, /thumb — the manifest/thumbnail data behind that preview page) are a separate, always-on mechanism: MCP starts them automatically for folder shares and multi-file shares regardless of preview, and never for single-file shares.

Response fields: sessionId, link, pid, qrCode? (ASCII art when qrInTerminal=True), debugLogPath?

Downloading

fflDownload(url, outputPath?, resume?, authUser?, authPassword?,
            recipientAuth?, pickupCode?, recipientPrivateKey?, proxy?,
            enableReporting?)
  -> {ok, returncode, outputPath?, transferMode?, transferInfo?, message?, ...}

Downloads from FastFileLink URLs (WebRTC P2P when possible, HTTP fallback) or any HTTP(S) URL (works like wget).

transferModeMeaning
webrtc_p2pDirect peer-to-peer over WebRTC (fastest)
p2p_tcp / p2p_quicDirect peer-to-peer over raw TCP/QUIC
http_fallbackHTTP relay when P2P fails
http_directRegular HTTP download (non-FastFileLink URL)

For authenticated links: pass recipientAuth + pickupCode (pickup mode) or recipientPrivateKey (pubkey mode). Set enableReporting=True only when you want to opt into ffl diagnostic error reporting for troubleshooting.

Keygen

fflKeygen(name?) -> {ok, returncode, output}

Generates an RSA keypair for passwordless pubkey recipient auth:

  • <name>.fflpub — share with the sender (pass as recipientPublicKey)
  • <name>.fflkey — keep private (pass as recipientPrivateKey when downloading)

Session Management

  • fflListSessions() — list active share sessions
  • fflStopSession(sessionId) — terminate a session
  • fflGetSession(sessionId) — get session details
  • fflGetSessionEvents(sessionId, limit=50) — retrieve webhook events

Notes

  • FFL_USE_STDIN=1 avoids writing text/base64 payloads to disk.
  • Folder and multi-file previews start a local webhook server so FFL can register preview routes.
  • FFL_DEBUG=1 saves ffl output to a temp log file; path returned as debugLogPath. Set FFL_DEBUG=/path/to/log.txt to use a fixed path.
  • ALLOWED_BASE_DIR restricts fflShareFile/fflShareFiles to a specific directory.

Testing

# Unit + binary tests (no network needed)
python -m unittest discover -s tests -p "*Test.py" -v

# All tests including share/download round-trips (requires network)
FFL_INTEGRATION_TESTS=1 python -m unittest discover -s tests -p "*Test.py" -v