Reference
import_screenshot
Turn attachments, URLs or local paths into account-scoped refs the render tools accept.
What it does
- Writes
- No account needed
How screenshots that exist only in this conversation get into ShotOps. One call takes several sources in screenshots — PNG/JPEG URLs, or local file paths on the stdio server — and hands each back as a private ref. The bytes move server to server, so they never enter model context. Results come back one per entry in input order, and a failed entry reports its own error without cancelling the rest. A ChatGPT attachment is the exception: it arrives as the top-level file parameter, which carries one attachment, so N attached screenshots are N calls.
You can ask: “Import these two Tidebook screenshot URLs for later rendering.”
The published schema accepts any shape inside screenshots so a two-source entry comes back as a sentence instead of three stacked union errors. The real element shapes are below.
Input
screenshotsarrayoptionalat least 1 itemat most 10 itemsThe screenshots to import, 1–10, in the order you want them back. Each entry names EXACTLY ONE source: { "url": "https://…" } (this server fetches a PNG or JPEG, converts JPEG to PNG, and stores it under your account), { "file": { "download_url": "…", "file_id": "…" } } (a ChatGPT attachment descriptor), or (local stdio server only) { "path": "/abs/shot.png" }. Add "name" to any entry to keep its original filename. One result per entry, in this exact order — a failed entry reports its own error and never cancels the others. In ChatGPT, an attachment arrives as the top-level
fileparameter instead, one attachment per call — batch URL sources here and import each attachment in its own call; one call may carry both.each item
any
The published schema does not constrain this element, on purpose — a malformed entry comes back as a sentence instead of a stacked union error. What the server re-validates against is below.
fileobjectoptionalA PNG or JPEG attached by the user in ChatGPT — the top-level ChatGPT file parameter. It holds exactly ONE attachment, so N attached screenshots are N import_screenshot calls; collect a ref from each before rendering. JPEGs are converted to PNG before storage. Other clients put their sources in
screenshotsinstead.download_urlstringrequiredShort-lived HTTPS download URL supplied by ChatGPT.
file_idstringrequiredChatGPT file identifier.
mime_typestringoptionalFile MIME type supplied by ChatGPT.
file_namestringoptionalat most 200 charactersOriginal attachment filename, when available.
namestringoptionalat most 200 charactersOverride the filename stored in the returned ref for the top-level
file. Defaults to file.file_name. Entries inscreenshotscarry their own "name".localestringoptionalOptional bookkeeping tag for the App Store locale these screenshots belong to.
What the server actually accepts
The published schema above deliberately accepts a wider shape for screenshots, file, so a malformed entry comes back as a sentence rather than a stack of union errors. The server re-validates against these shapes and refuses anything else.
screenshotsarrayoptionalat least 1 itemat most 10 itemsThe screenshots to import, 1–10, in the order you want them back. Each entry names EXACTLY ONE source: { "url": "https://…" } (this server fetches a PNG or JPEG, converts JPEG to PNG, and stores it under your account), { "file": { "download_url": "…", "file_id": "…" } } (a ChatGPT attachment descriptor), or (local stdio server only) { "path": "/abs/shot.png" }. Add "name" to any entry to keep its original filename. One result per entry, in this exact order — a failed entry reports its own error and never cancels the others. In ChatGPT, an attachment arrives as the top-level
fileparameter instead, one attachment per call — batch URL sources here and import each attachment in its own call; one call may carry both.each item
one of 3 shapes
1
urlurlstringrequiredat least 1 characterAn https URL to a PNG or JPEG. This server fetches it and converts JPEG to PNG — https only, no redirects, 20MB cap.
namestringoptionalat most 200 charactersThe screenshot's original filename, stored in the returned ref (e.g. "03_stats.png").
2
fileA ChatGPT attachment descriptor: { "file": { "download_url": "…", "file_id": "…" } }.
fileobjectrequireddownload_urlstringrequiredformat uriShort-lived HTTPS download URL supplied by ChatGPT.
file_idstringrequiredat least 1 characterChatGPT file identifier.
mime_typestringoptionalFile MIME type supplied by ChatGPT.
file_namestringoptionalat most 200 charactersOriginal attachment filename, when available.
namestringoptionalat most 200 charactersThe screenshot's original filename, stored in the returned ref (e.g. "03_stats.png").
3
pathpathstringrequiredat least 1 characterA local filesystem path to a PNG, read straight off disk — ONLY on the local stdio server (npx shotops-mcp); the hosted server rejects it.
namestringoptionalat most 200 charactersThe screenshot's original filename, stored in the returned ref (e.g. "03_stats.png").
fileobjectoptionaldownload_urlstringrequiredformat uriShort-lived HTTPS download URL supplied by ChatGPT.
file_idstringrequiredat least 1 characterChatGPT file identifier.
mime_typestringoptionalFile MIME type supplied by ChatGPT.
file_namestringoptionalat most 200 charactersOriginal attachment filename, when available.
Result
okbooleanoptionalcountintegeroptionalmin 0screenshotsarrayoptionaleach item
object
okbooleanrequiredsourcestringrequiredone of
urlfilepathnamestringoptionalrefstringoptionalurlstringoptionalpathstringoptionalsizeintegeroptionalmin 0errorstringoptional
instructionsstringoptionaldisclosureobjectoptionalStated because this call moved caller bytes into ShotOps storage. Relay it before or with the result; do not paraphrase the retention window.
movesstringrequiredThe bytes that left the caller’s control, in plain words.
whystringrequiredWhat the move buys — never a restatement of the mechanism.
retentionDaysintegerrequiredgreater than 0How long ShotOps keeps it without an explicit retaining action. Read from the retention policy, never typed.
retainedBystringrequiredThe explicit action that keeps it past that window.
statementstringrequiredThe same four facts as one sentence, safe to relay verbatim.
Example
That request maps to this call:
{
"name": "import_screenshot",
"arguments": {
"screenshots": [
{
"url": "https://example.com/tidebook/01-today.png",
"name": "01-today.png"
},
{
"url": "https://example.com/tidebook/02-forecast.png",
"name": "02-forecast.png"
}
]
}
}One result per entry, in the order you sent them, each with a ref or its own error.
Access and cost
- One of the few tools a hosted caller may use with no account at all — getting your own screenshots in is part of the free taste.
- Free. Importing spends no cloud credits.
- A local filesystem path only works on the local stdio server; the hosted server refuses it, and there is no URL to hand it for a file on your own disk. Use request_screenshot_upload there instead.
- An import that produced refs put the bytes in ShotOps storage, and the reply discloses what moved, why, how long it is kept and what retains it. A local path import moves nothing and discloses nothing.
When it refuses
- One entry failed and the rest succeeded.
- That is by design. Re-import just the failed entry; the refs you already got stay valid.
- An entry names two sources at once.
- Every entry names exactly one of url, file or path. The reply says which entry and what to drop.
- A path was refused on the hosted server.
- Hosted has no access to your filesystem. Either give a URL it can fetch, or mint a signed upload.
Where this fits
What the agent is told
The title and description the server publishes on tools/list — this is the copy a model chooses between, reproduced verbatim.
Import screenshots
How screenshots that exist only in THIS conversation get into ShotOps so they can be rendered: one call takes several — an attached PNG or JPEG, or a PNG/JPEG URL — and hands each back as a private, account-scoped `ref` the render tools accept, with the image bytes moving server-to-server so they never enter model context. Every entry of `screenshots` names EXACTLY ONE source: { "url": "https://…" } (this server fetches PNG or JPEG and converts JPEG to PNG — works on any client), { "file": … } (a ChatGPT attachment descriptor; in ChatGPT it arrives as the top-level `file` parameter instead), or (local stdio server only) { "path": "/abs/shot.png" }. Results come back one per entry in input order, and a failed entry reports its own error without cancelling the rest — re-import just that one. Then call render_strip with the preferred flat input { "screenshots": [{ "ref": "THE_REF" }] }; the same refs work in emit_bundle, and with their filenames in render_project. If the screenshots are only on the user's machine and this is the hosted server, there is no URL to give — use request_screenshot_upload instead. An import that produced refs puts the bytes in ShotOps storage and says so in a `disclosure` block: what moved, why, how long it is kept and the explicit action that retains it. A local { "path" } import moves nothing and discloses nothing.