Zurück zum Blog
Updates

Download All, lightbox navigation, and an MCP that finally sees attachments

Every attachment in one ZIP, an image preview with thumbnail rail and swipe on mobile, plus: the MCP actually finds files now. A build-in-public devlog.

Spedy Team4 min readAuf Deutsch lesen
Download All, lightbox navigation, and an MCP that finally sees attachments
#attachments#mcp#download#lightbox#mobile#build-in-public#dx

Four changes around attachments in one session: Download All, a compact upload area, a rebuilt image preview with thumbnail rail and mobile swipe -- plus a fix so the MCP actually notices attachments exist. Classic build-in-public moment: one feature, three tangible side effects.


Download All: one ZIP for every attachment

When a ticket has several files -- screenshots, a PDF, an export log, a CSV -- the only option used to be clicking each one. From now on, there's a Download all button at the top of the attachments list.

What happens under the hood

  • The API streams every non-deleted attachment from storage and packs them into a ZIP.
  • Filenames are deduplicated: two logs.txt on the same ticket become logs.txt and logs (1).txt.
  • Legacy attachments without an S3 key are skipped -- you see how many files ended up in the ZIP and how many were left out.
  • Limit: 500 MB aggregate per ZIP. Above that the API politely refuses instead of OOMing.
  • The endpoint is rate-limited (20 bulk downloads per hour) so nobody accidentally DoSes storage.

When the button appears

As soon as a ticket has two or more attachments. For a single attachment the ZIP detour isn't worth it.


Upload that gets out of the way

The old upload area always showed a big dashed zone at the top of the tab -- even if twenty files were already attached. The tab now behaves more adaptively:

  • Empty ticket: full drop zone with icon, text and click target like before.
  • Already has attachments: the zone shrinks to a slim one-liner above the list.
  • The list itself is the drop target: drag a file anywhere over the attachment list and an overlay hint appears -- release and the upload starts.

Image preview: a lightbox that doesn't jump

The image preview used to have a problem: images brought their own natural size, the lightbox grew with them, and switching between portrait and landscape made the entire UI bounce around.

What's different now

  • The lightbox window is fixed at 90vw × 90vh -- no matter how large the image, the frame stays put.
  • The image itself scales via object-contain inside the available area.
  • Arrow buttons on either side, plus ← / → on the keyboard and Escape to close.
  • Thumbnail rail on the right (below on mobile): a click on a thumbnail jumps directly there. The active preview is marked with a coloured border.

Mobile: swipe instead of arrow-hunt

Hitting arrows with your thumb was painful on small screens. On mobile:

  • Thumbnails move below the image and scroll horizontally.
  • Swipe left/right on the image to page to the next/previous screenshot.
  • The image uses the full width because the thumbnail rail isn't eating sidebar space.

MCP: attachments are visible now

While building the download-all path, something came up during debugging: the MCP could load attachments (attachment://{attachmentId}), but didn't know they exist.

Specifically: neither the tickets_get tool nor the ticket://{id}/timeline resource returned attachment IDs. The timeline only had comments and PR events. Agents working via MCP -- Claude Desktop, a custom bot, a Spedy routine -- had a blind spot for files.

What changed

  • tickets_get now returns attachmentCount plus an attachments array with id, uri, originalName, mimeType, size, uploadedBy and uploadedAt. An agent can hand the uri (attachment://...) straight to the resource handler.
  • ticket://{id}/timeline now includes an attachment_uploaded event per file, sorted inline with comments and user events. If you ask "what happened on this ticket lately?", uploads show up at the right point in time.
  • Permissions are unchanged: the board-level access check still runs, soft-deleted records are still hidden.

Turning an agent loose on Spedy ("summarise this ticket and look at the attached logs") no longer needs an extra call to discover attachments.


Build in public: why all of this together?

Traditional release notes cleanly separate "Feature X" and "Bugfix Y". In practice they're often entangled: while building a feature you notice the preview has a layout bug. In the feedback round a mobile issue joins in. While debugging you discover that the MCP has the same problem on a different layer.

We decided to surface that -- a feature plus what we picked up along the way. Instead of "Download All shipped" followed three weeks later by "MCP fix shipped", you get the how. Build in public for us means: no polished staging, just the work as it happens.


Next up

  • Download progress for single files: bulk download has a clear start/end state; large single-file downloads are still missing a progress bar.
  • Preview for more file types: images already open in a lightbox. PDF and Office previews are on the list.
  • Pinch-zoom in the lightbox: swipe and thumbnails are in; zooming further into high-resolution screenshots is still open.

Frequently asked questions

Quick answers to the most common questions about this topic.

Where do I find the Download-All button?
On the Attachments tab of any ticket, right above the list -- as soon as there are two or more attachments. The button is labelled Download all, bundles every file into a ZIP and downloads it.
Is there a size limit on the ZIP?
Yes. The aggregate size of all attachments on a ticket is capped at 500 MB so the API doesn't page into swap. Individual files can still be up to 50 MB.
How do I navigate between images in the preview?
Left/right arrow buttons, keyboard arrows, a click on the thumbnail rail on the right -- or on mobile, a left/right swipe on the image. The lightbox layout stays stable even when images have very different dimensions.
What was the MCP attachment bug?
The MCP could already load a file via attachment://{id}, but neither tickets_get nor the timeline resource returned attachment IDs. Agents literally didn't know files existed. Both endpoints now include them.
What does 'build in public' mean for Spedy?
We publish a short devlog entry for every tangible release -- not curated marketing drops, but what actually shipped this week and why. You're reading one.
Download All, lightbox navigation, and an MCP that finally sees attachments – Spedy Blog | Spedy