FLOPPY
FPY.SH/DOCS/AGENTSTHIS PAGE AS MARKDOWN

AGENT DOCS

Floppy (https://fpy.sh) shares a file with a short link and shows who opened it: which pages they read and for how long, with bots filtered out. Agents can use it with no account. Upload with one HTTP call, or connect over MCP, and hand your human a claim link so the work becomes theirs.

The fast way: paste this into Claude Code

Also works in Codex, Cursor or any agent that can run commands. It connects Floppy, uploads a test file and hands you a link to claim it. Signed in? API keys gives you the same prompt with your own key.

Set up Floppy (https://fpy.sh) for me, so you can share files as short links and tell me who opened them.

1. Read https://fpy.sh/skill.md to learn how Floppy works.
2. Write a short hello.md and upload it with no account: curl -T hello.md https://fpy.sh/api/drop/hello.md
   The JSON reply has share_url, agent_key (shown once) and claim_url. Keep agent_key private: don't echo it back, commit it, or write it into a file inside a repo.
3. Connect the Floppy MCP server at https://fpy.sh/mcp with that key, the way your tool adds MCP servers (replace <agent_key>):
   - Claude Code: claude mcp add --transport http --scope user floppy https://fpy.sh/mcp --header "Authorization: Bearer <agent_key>"
   - Codex: add [mcp_servers.floppy] with url = "https://fpy.sh/mcp" and bearer_token_env_var = "FLOPPY_API_KEY" to ~/.codex/config.toml, and export FLOPPY_API_KEY in my shell profile
   - Cursor: add "floppy": { "url": "https://fpy.sh/mcp", "headers": { "Authorization": "Bearer <agent_key>" } } under mcpServers in ~/.cursor/mcp.json
   - Anything else, or if you can't add MCP servers: use HTTP with the same header, e.g. curl -T notes.md https://fpy.sh/api/drop/notes.md -H "Authorization: Bearer <agent_key>"
4. If you support skills or saved instructions, save https://fpy.sh/skill.md as one so you remember Floppy next time (Claude Code: ~/.claude/skills/floppy/SKILL.md).
5. Give me the share_url and the claim_url, and tell me to open the claim link and sign in with Google within 72 hours so the files stay in my account. If the MCP server only loads after a restart, tell me to restart.

Pick what you use. Two minutes, no code.

  1. 1.

    In Claude (web or desktop), open Customize → Connectors. Click + Add, then Add custom connector.

  2. 2.

    Name it Floppy, paste this URL, click Add and sign in with Google:

    https://fpy.sh/mcp
  3. 3.

    Test it. Paste this into your agent:

    Write a short Markdown note called hello.md, upload it to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? On a Team or Enterprise plan, an owner adds the connector first under Organization settings → Connectors. TROUBLESHOOTING

  1. 1.

    Open a terminal and run:

    claude mcp add --transport http floppy https://fpy.sh/mcp
  2. 2.

    Start Claude Code and type /mcp. Pick floppy and sign in with Google.

  3. 3.

    Test it. Paste this into your agent:

    Upload README.md to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Run claude mcp list to check that floppy is connected. Add --scope user to use it in every project. TROUBLESHOOTING

  1. 1.

    Open chatgpt.com/plugins, click +, then Add custom MCP server.

    Don't see it? Turn on Developer mode under Settings → Apps & Connectors → Advanced first.

  2. 2.

    Name it Floppy, paste this URL, choose OAuth, create it and sign in with Google:

    https://fpy.sh/mcp
  3. 3.

    Test it. Paste this into your agent:

    Write a short Markdown note called hello.md, upload it to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Uploading needs a plan with full MCP access (Business, Enterprise or Edu). On other plans, use an agent that can run code: see OTHER. TROUBLESHOOTING

  1. 1.

    Install in one click, or add this to ~/.cursor/mcp.json:

    ADD TO CURSOR →
    {
      "mcpServers": {
        "floppy": {
          "url": "https://fpy.sh/mcp"
        }
      }
    }
  2. 2.

    Open Cursor Settings → MCP. Next to floppy, click Connect and sign in with Google.

  3. 3.

    Test it. Paste this into your agent:

    Upload README.md to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Restart Cursor after editing mcp.json by hand. A red dot means the URL or the key is wrong. TROUBLESHOOTING

  1. 1.

    Add this to ~/.codex/config.toml:

    [mcp_servers.floppy]
    url = "https://fpy.sh/mcp"
  2. 2.

    Sign in with Google:

    codex mcp login floppy
  3. 3.

    Test it. Paste this into your agent:

    Upload README.md to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Run codex mcp list to check that floppy is there. TROUBLESHOOTING

  1. 1.

    Install in one click, or run this in a terminal:

    INSTALL IN VS CODE →
    code --add-mcp '{"name":"floppy","type":"http","url":"https://fpy.sh/mcp"}'
  2. 2.

    Open Copilot Chat in Agent mode. When VS Code asks, start the floppy server and sign in with Google.

  3. 3.

    Test it. Paste this into your agent:

    Upload README.md to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Run MCP: List Servers from the Command Palette and check that floppy is running. TROUBLESHOOTING

  1. 1.

    MCP clients: connect to this URL (Streamable HTTP). Sign in with OAuth, or send this header:

    https://fpy.sh/mcp
    Authorization: Bearer fpy_live_…

    Make a key at fpy.sh/app/keys.

  2. 2.

    No MCP? Anything that can make an HTTP call can upload:

    curl -T deck.pdf https://fpy.sh/api/drop/deck.pdf
  3. 3.

    Test it. Paste this into your agent:

    Read https://fpy.sh/llms.txt, then upload README.md to Floppy and give me the link.

✓ WORKED? YOU'LL SEE THE LINK IN YOUR CHAT AND IN FPY.SH/APP.

✕ STUCK? Every error has a next hint and a docs link. 401? Check the header: Authorization: Bearer, one space, no quotes. TROUBLESHOOTING

No account, no key. Send the file's bytes with PUT:

curl -T deck.pdf https://fpy.sh/api/drop/deck.pdf

The filename at the end of the URL is the name people see. Optional query parameters: expiry (for example 1D, 3D) and label (for example Sequoia – Jane).

To keep every upload in one account, send the agent_key from your first response on every later call:

curl -T notes.md https://fpy.sh/api/drop/notes.md -H "Authorization: Bearer fpy_live_…"

Files over 100 MB don't fit in one request. Use the multipart flow (POST /api/v1/links, then PUT each part, then POST …/complete) with your key, or upload_file over MCP, which returns a multipart plan for big files.

{
  "link": {
    "id": "q7f2m9x4k1ab",
    "name": "deck.pdf",
    "url": "https://fpy.sh/k3x9",
    "slug": "k3x9",
    "kind": "pdf",
    "size": 4404019,
    "status": "ready",
    "scan": "scanning",
    "created_at": "2026-11-06T12:03:00.000Z",
    "expires_at": "2026-11-09T12:03:00.000Z",
    "shares": 0,
    "views": 0,
    "via_agent": true
  },
  "share": null,
  "share_url": "https://fpy.sh/k3x9",
  "analytics_url": "https://fpy.sh/api/v1/links/<id>/analytics",
  "claim_url": "https://fpy.sh/claim/7f3c…",
  "agent_key": "fpy_live_…",
  "scan": "scanning",
  "limits": { "storageBytes": 1073741824, "maxFileBytes": 1073741824, "maxExpiryDays": 3, "maxLinks": 20, "expires_in_hours": 72 },
  "next": "Share the share_url. Your human can claim these files at https://fpy.sh/claim/7f3c… within 72 hours."
}
  • share_url is the link to send. It works at once; while scan is scanning, visitors see "Checking file…" and the file opens when the scan is clean.
  • agent_key is shown once. Save it and send it as Authorization: Bearer … on later calls so your uploads stay together. claim_url and agent_key only appear when Floppy created a new unclaimed account for you.
  • claim_url is for your human. Give it to them with the link.
  • scan is one of uploading, scanning, clean, blocked or unscanned-large.
  • next is one plain sentence telling you what to do or tell your human. Every response has one.

An upload without an account goes into an unclaimed account. It lasts 72 hours. Tell your human, in your own words:

I uploaded your file to Floppy: https://fpy.sh/k3x9. To keep it and see who opens it, claim it within 72 hours: https://fpy.sh/claim/7f3c…

  • Opening the claim link means signing in with Google. Everything the agent made moves to that person's account: links, files, folders and view history. It works for a new or an existing Floppy account.
  • The claim link works once and expires with the unclaimed account. Lost it? Call GET /api/v1/claim with your agent key, or the get_claim_link MCP tool.
  • After the claim, your agent key keeps working, but it stays limited to the links it created (scope own). It can't see the human's other links. The human can widen it to the whole account at https://fpy.sh/app/keys.
  • Nothing is claimed after 72 hours? The links stop working and every file is deleted.
  • Unclaimed accounts can't pay. The claim page also offers "Claim and upgrade", which goes to checkout after sign-in.

URLhttps://fpy.sh/mcp
TransportStreamable HTTP
AuthOAuth (sign in with Google; dynamic client registration), or Authorization: Bearer fpy_live_… with an agent key or API key

Every tool returns its result plus a next hint.

ToolInputWhat it does
upload_file{ name, text?, content_base64?, url?, expiry?, label? }, exactly one sourceUploads a file and returns its link. Up to 25 MB inline, or a url up to 100 MB. Bigger files get a multipart plan back.
create_share{ link_id, label, expiry? }Makes a separate link for one recipient, such as "Sequoia – Jane", so you can see what each person read.
update_link{ link_id, expiry?, password?, downloads_allowed?, note?, name? }Changes a link's settings.
revoke_share{ share_id }, or { link_id } to revoke everythingTurns off one recipient's link, or the whole link.
list_links{ query?, limit? }Lists links, newest first.
get_link_analytics{ link_id }Who opened a link, pages reached, time per page, completion, and how many bot visits were filtered.
get_viewer_timeline{ share_id }One recipient's visits, page by page.
who_viewed_since{ since } (ISO time or 24h)Everything that happened since a time, newest first.
get_usage{}Plan, storage used and limits.
get_upgrade_link{}A checkout link for your human (or the claim link, if unclaimed).
get_claim_link{}The claim link for an unclaimed account.

Base URL https://fpy.sh. Auth is Authorization: Bearer fpy_live_… (or the dashboard's session cookie). JSON in and out. The full schema is at https://fpy.sh/openapi.json.

MethodPathAccessRequestResponse
PUT/api/drop/:filenamenone or keyRaw bytes, up to 100 MB. Query: expiry, label{ link, share, share_url, analytics_url, claim_url?, agent_key?, scan, limits, next }
GET/api/v1/linksread{ links, next }
POST/api/v1/linkswrite{ files: [{ name, size, type? }], folderId? }{ link, uploads: [{ fileId, partSize, parts }], next }
PUT/api/v1/files/:id/parts/:nwriteRaw part, up to 32 MiB{ partNumber, etag }
POST/api/v1/files/:id/completewrite{ parts: [{ partNumber, etag }] }{ ok, linkReady, scan, next }
POST/api/v1/links/from-urlwrite{ url, name? }, up to 100 MBsame as drop
GET/api/v1/links/:idreadLinkDetail
PATCH/api/v1/links/:idwrite{ expiry?, password?, downloadsAllowed?, note?, name? }LinkDetail
DELETE/api/v1/links/:idwrite{ ok, next } (revokes the link)
GET/api/v1/links/:id/sharesread{ shares }
POST/api/v1/links/:id/shareswrite{ label, expiry? }Share
PATCH/api/v1/shares/:idwrite{ label?, active? }Share
DELETE/api/v1/shares/:idwrite{ ok }
GET/api/v1/links/:id/analyticsreadLinkAnalytics
GET/api/v1/shares/:id/timelineread{ share, visits }
GET/api/v1/activity?since=<ISO>read{ events }, newest first
GET/api/v1/usageread{ plan, claimed, used_bytes, limits, link_count, expires_at? }
POST/api/v1/upgraderead{ upgrade_url }, or { claim_url, next } if unclaimed
GET/api/v1/claimagent key (unclaimed){ claim_url, expires_at }
POST/api/v/:slug/reportnone{ reason, details? }{ ok }

API keys are created and revoked by a signed-in human at https://fpy.sh/app/keys (/api/v1/tokens takes a session, never a key). Keys have access read, write or both, and scope account (everything) or own (only the links the key created).

PlanStoragePer fileLongest expiryLinks
Unclaimed (agent, no account)1 GB1 GB72 hours, then deleted20
Free2 GB500 MB30 daysno limit
Pro1 TB50 GBany, or neverno limit

A single drop or inline upload is also capped at 100 MB per request; use multipart above that. Unclaimed accounts can upload safe file types only (see Safety).

Every error has the same shape. next says what to do, and docs links here:

{
  "error": {
    "code": "limit_reached",
    "message": "This unclaimed account has used its 1 GB.",
    "claim_url": "https://fpy.sh/claim/7f3c…",
    "next": "Ask your human to claim this account at https://fpy.sh/claim/7f3c…. Claiming unlocks Free limits and lets them upgrade.",
    "docs": "https://fpy.sh/docs/agents#errors"
  }
}
StatusCodeMeansWhat to do
400bad_requestThe request is malformedFix the field named in message
401unauthorizedMissing or invalid keyRead https://fpy.sh/auth.md (the WWW-Authenticate header points there)
402limit_reachedOver a plan limitUnclaimed: give your human claim_url. Claimed: give them upgrade_url
403forbiddenThe key can't touch this linkAn own key only sees links it created; ask your human to widen it
404not_foundNo such link, share or fileCheck the id. Never guess share links
409conflictThe thing changed or already existsFetch it again and retry
413limit_reachedToo big for one requestUse the multipart flow in next
——A file failed the safety checkThe upload still returns 201, but scan becomes blocked (check GET /api/v1/links/:id). Don't re-upload the same file
429slow_downToo many requestsWait retry_after seconds (also in the Retry-After header)

  • Every file is scanned before anyone but its owner can open it. Uploads start as scanning; the share page shows "Checking file…" until the verdict is in. Blocked files are never served.
  • Executables and installers are blocked on every plan. Unclaimed accounts can upload only PDF, Markdown and text, images, audio, video, CSV and JSON. No archives, HTML or SVG.
  • HTML and SVG are always downloaded, never rendered as a web page on fpy.sh.
  • Bots are filtered. Email security scanners, link previews and datacenter traffic are kept apart and never counted as views.
  • Share links are private. They belong to the people who made them. Never guess, enumerate or crawl fpy.sh links.
  • Report abuse with the Report link on any share page.

  • 401 on every call. The header must be exactly Authorization: Bearer fpy_live_…, with one space and no quotes. Keys revoked at https://fpy.sh/app/keys stop working at once.
  • The client doesn't show Floppy's tools. Restart the client after adding the server, then sign in again (/mcp in Claude Code, codex mcp login floppy in Codex, Connect in Cursor).
  • Sign-in loops or fails. Use the Google account you want the files in. Blocked pop-ups stop the OAuth window; allow them for the client.
  • ChatGPT can read but not upload. Your plan only allows read access to custom MCP servers. Use another agent, or the curl call.
  • The file is stuck on "Checking file…". Scans usually take seconds; large files take longer. Poll GET /api/v1/links/:id and look at scan.
  • 402 limit_reached. Hand your human the claim_url or upgrade_url from the error. Paying or claiming lifts the limit for the same key at once.
  • 413 on a drop. The file is over 100 MB. Use the multipart flow.
  • I lost the agent key. It can't be shown again. If the account is unclaimed, start a new drop; if it was claimed, your human can make a new key at https://fpy.sh/app/keys.
  • The claim link expired. After 72 hours unclaimed uploads are deleted. Upload again and pass the new claim link on sooner.

Setup for one tool at a time, with things to ask and an FAQ. Each page is also available as Markdown (add .md).

How Floppy compares with other ways to share files: