41. MCP clients download files under /mcp#
Date: 2026-10-31 (#479)
Status#
Accepted
Context#
read, search and current_page give image and file URLs under /api/blobs/{sha}. Behind
Cloudflare Access only /mcp takes the service token, so an MCP client sent there gets the
email login page, not the file. A client could not save an attachment, publish a page with its
pictures, or get a drawing past the drawing tool’s 200 kB cut.
The PWA fetches /api/blobs/... from the browser with no bearer token, so /api cannot need
one. Telling a machine request from a browser one (by the Access JWT’s claims, or the
CF-Access-Client-Id header) would tie scrap to one proxy and add moving parts.
Decision#
The read-only GETs a client needs are served under
/mcptoo, by the/apiroutes’ own handlers (mcp_files.pyregisters each one on a second path; a missing one stops startup):/mcp/blobs/{sha},/previewand/uses;/mcp/pages/{key}/download;/mcp/captures/{cid}/photos/{sha}/drawingand/versions. One more is/mcponly:.../drawing.excalidraw, the whole current drawing as an.excalidrawfile (as a page’s download has it).BearerAuthalready guards/mcpand everything under it, and the Access application on path/mcpcovers its subpaths, so they need the same headers as/mcp: no new auth code and no Cloudflare change. With no token set they are open, as/mcpis.They are GETs, so
hostguardchecks theirHost(as for every route) and noOriginis needed: curl works.Results keep
url(the browser’s link) and adddownload_url(images, files,page),drawing_download_url,image_download_url(search rows) and thedrawingtool’sdownload_url.
Consequences#
The
/apipaths and the PWA are unchanged; nothing is written through/mcp/....A client with the MCP headers can read every stored file by hash, as anyone past the email login can.
A new download for MCP clients is a line in
mcp_files.MIRRORED.