Skip to content

File downloads (MCP resources)

Wire containers expose every uploaded file as an MCP resource. Connected agents can fetch the original bytes of a file, not just the chunks or canonical entries that come out of analysis. This is how your agent pulls a raw PDF, reads a CSV start to finish, or grabs an image that lives alongside your structured context.

Every file in a container is addressable under:

wire://container/{containerId}/file/{fileId}

This is not a fetchable URL on its own. It’s an opaque identifier that only has meaning inside an authenticated MCP session with your container. Clients resolve it by calling the MCP resources/read method — Wire mints a short-lived signed download URL and returns it.

┌──────────┐ resources/read ┌──────────────────┐
│ Agent │────────────────────────→ │ Wire MCP server │
│ client │ { uri: "wire://..." } │ │
└──────────┘ └─────────┬────────┘
▲ │
│ │ validate session,
│ │ mint signed URL,
│ { contents: [{ │ record activity event
│ uri, mimeType: │
│ "text/uri-list", │
│ text: "https://…?token=…" }] } │
└───────────────────────────────────────────┘
│ HTTPS GET (out of band)
┌─────────────────────────────┐
│ Wire download route │
│ • verifies the token │
│ • streams the file bytes │
│ • returns with correct │
│ Content-Type / Filename │
└─────────────────────────────┘
  1. The agent’s MCP client calls resources/read on a wire:// URI.
  2. Wire validates the session, checks that the URI’s container matches the session’s container (blocks swap attacks), mints a JWT (HS256, 5 minute TTL), and returns a text/uri-list resource with a single entry — the signed HTTPS download URL.
  3. The client follows the URL over ordinary HTTPS. Wire validates the token, streams the file bytes, charges 2 credits, records an activity event, and returns the response with the correct Content-Type and Content-Disposition.

The signed URL is never placed into your model’s context — only the opaque wire:// URI is.

Two tool surfaces embed resource_link content entries in their responses so agents find downloadable files in the normal flow of retrieval, not through a separate catalog.

When an agent lands on a chunk via wire_search and calls wire_navigate in source mode, the response includes the chunks from that file plus a resource_link pointing at the underlying file’s wire:// URI.

{
"content": [
{ "type": "text", "text": "{ \"mode\": \"source\", \"results\": [...] }" },
{
"type": "resource_link",
"uri": "wire://container/abc/file/xyz",
"name": "customers.csv",
"mimeType": "text/csv",
"description": "Source file (12.4 KB). Call resources/read on this URI for a short-lived signed download URL."
}
]
}

Every uploaded file has a _document canonical entry. When an agent calls wire_explore with mode: "get" on a _document, the response includes a resource_link for the file the entry represents.

resources/list is implemented but returns an empty list. The wire:// URI scheme is resolvable on demand — any valid URI the agent encounters (via resource_link in a tool response) can be passed to resources/read without pre-enumeration. We intentionally avoid emitting a flat catalog of every file on every connection, which would bloat context with entries the session isn’t actually working with.

  • 2 credits per successful download.
  • Charge happens at the download step, not when the wire:// reference is emitted or listed. If an agent surfaces 50 files and downloads 3, you pay for 3.
  • Every successful download writes a file_downloaded container event (visible in the activity feed) and a usage_event row (visible in the credits ledger). Both carry user / API key attribution.
  • 5 minutes. After that the JWT is rejected and a new resources/read call is required.
  • The token is bound to a specific (containerId, fileId) pair. A leaked URL cannot be reused against a different file even during its valid window.
  • Claude Desktop, Claude web, MCP Inspector, Continue, Zed — surface resource_link as a first-class attachment; follow text/uri-list responses natively.
  • Claude Code (today) — reads the tool responses as text, so agents see the wire:// URI and can call resources/read explicitly, but resource_link content entries are not yet rendered as attachments.

Behavior upstream of Wire will catch up. Wire itself stays spec-compliant — agents on any conforming client will be able to resolve resources as soon as the client supports it.