Guide

Tiny configs, no curl — `upload.write`

When the agent already has the bytes in hand, skip the pre-signed dance. `upload.write` PUTs inline content up to 1 MiB directly.

5/18/2026 · connect0 · 3 min

When the agent already holds the bytes, upload.write connects them straight into the core — no pre-signed dance.

upload.create_link is the right tool when the user has the file. But sometimes the agent has it — it just generated a Dockerfile, drafted a package.json, tweaked your .eslintrc. Asking the user to copy the agent's output and PUT it via curl is friction. Use upload.write instead.

When to reach for it

  • The agent generated content during the conversation.
  • The user pasted text into chat and you want to land it on disk.
  • A small templated file (config, scaffolding, README.md).

For anything > 1 MiB or genuine binary the user has, use upload.create_link — bytes don't tunnel efficiently through the MCP wire.

Plain text

upload.write {
  "account_slug": "acme",
  "project_slug": "demo",
  "target_path": "config/eslint.config.mjs",
  "content_text": "export default [{ rules: { 'no-console': 'warn' } }];"
}

Returns:

{ "workspace_path": "/workspace/config/eslint.config.mjs", "bytes_written": 48 }

The file is on disk immediately — sh "cat /workspace/config/eslint.config.mjs" will print what you sent.

Binary

For small images, generated PDFs, anything non-textual the agent has produced, base64-encode it:

upload.write {
  "account_slug": "acme",
  "project_slug": "demo",
  "target_path": "assets/logo.png",
  "content_base64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "content_type": "image/png"
}

Limits

  • 1 MiB total after decoding base64. Exceed it and you get payload_too_large with a hint to switch to upload.create_link.
  • Either text or base64, never both — the tool rejects ambiguous payloads.
  • Refuses zero-byte writes — there's never a good reason to create an empty file via this path, and silent zero-byte writes hide bugs.

Path rules

Same as everywhere else in the upload surface:

  • Relative, no leading /.
  • No .. segments.
  • No hidden segments (anything starting with .).
  • Characters in [A-Za-z0-9._-/] only, ≤ 256 chars.

Audit trail

Every upload.write call creates an upload_link row with source = 'mcp-write', marked claimed immediately (we already saw the bytes land). You can see them in info's recent_uploads and on the dashboard project page.

Next steps

Where this fits

This is the Connect everything pillar of connect0 — the core that connects everything your company runs on. upload.write is the shortest path for landing agent-generated files into the core your agents keep running on. Start building → · All guides →