EasyDrop

Sending video through MCP: why the file becomes a URL

Build anything on the Model Context Protocol that touches media and you hit the same wall within an hour. Tool arguments are JSON. Video is not. Everything after that is a choice about where the bytes go instead.

The obvious answer, and why it fails

Base64 the file into a string argument. It works in a demo with a two-second clip and stops working almost immediately after.

Encoding adds roughly a third to the size, so a 100 MB video becomes about 133 MB of text. That text has to be assembled by the client, held in memory, parsed as JSON by the server, and held again. Both sides now carry the whole file at once, in the least efficient representation available, inside a message the protocol never intended to be that large. Model context windows are not the binding limit here — the transport and the memory are.

The URL is not a workaround

Passing a link and letting the server fetch it looks like a compromise until you notice it matches what the caller already has. An agent that just rendered a video has it in object storage. One that pulled it from a library has a link. One that received it from a user has an upload URL. The bytes are almost never in the agent’s own memory, so asking for them there forces a download it did not need to do.

The tool call stays small and describable — a URL, a caption, a list of accounts — which is also what makes it legible to the model deciding whether to call it.

What a URL argument obliges you to do

You have accepted an instruction to fetch an arbitrary address, so the guards are not optional.

Cap the size as it streams. A declared content length is a claim, not a fact. Count the bytes as they arrive and abort past the limit.

Cap every ingest path, not just the new one. If the REST endpoint that predates the MCP server has no limit, adding one here does not close the hole — it just moves the traffic.

Stream, do not buffer. Bytes passing through a runtime cost almost nothing in memory; the same bytes accumulated in a variable cost all of it. This is why a server with a small memory ceiling can still move large files — and why one careless await that reads the whole body turns that into an outage.

The call returns a job, not a post

The other thing media forces on the design is time. Fetching, uploading and waiting for a platform to finish processing takes far longer than a tool call should block for, and platforms publish per-account rate limits that a loop of tool calls walks straight into.

So the tool returns a job id immediately and a second tool reports on it. The agent gets an answer it can act on, the queue does the pacing, and a burst of enthusiasm from the caller turns into a slower queue rather than a wall of rejections.

How EasyDrop does it

Video arrives as a URL, is streamed rather than buffered, is capped on every path that can ingest it, and turns into a queued job the moment it lands. Publishing goes through TikTok’s official Content Posting API, paced per account, with each video-and-account pair tracked separately so one failure does not take the rest with it.

Common questions

Can you send a file through an MCP tool call?

A small one, yes. A video, in practice no. Tool arguments are JSON, so bytes have to be base64-encoded, which inflates them by about a third and puts the whole file in memory on both sides at once. For anything the size of a video the sane transport is a URL the server fetches.

Why not accept a multipart upload alongside the tool call?

Because it stops being one protocol. The client would need a second code path that MCP does not describe, and the agent would have to sequence an upload and a tool call by hand — exactly the coordination that using MCP was supposed to remove.

What does the server need to guard when it fetches a URL?

A size cap enforced as the bytes arrive rather than from the declared length, since a header can lie. Every ingest path needs the same cap — capping only the new one moves the abuse to the old one instead of closing it.

Does streaming the file need a lot of memory?

No, and this is the part that surprises people. Bytes can pass through the runtime rather than accumulate in it, so a server with a modest memory limit can move a file far larger than that limit, provided nothing in the path buffers the whole body.

Sending video through MCP: why the file becomes a URL — EasyDrop