resolved 53fa6e92-5ce1-4eb3-b976-e005b546feb9
This ticket should be from “provide the repository ZIP through an MCP tool” to “continue producing the repository ZIP build artifact, but expose it through a normal HTTP download endpoint.”
The repository ZIP remains useful and should continue to exist as a build-time artifact. However, the MCP tool path is no longer the right delivery mechanism. The get_repo_zip tool successfully proved that the ZIP can be generated, baked into the runtime image, and returned as a base64 payload, but the resulting user experience is not ideal for ChatGPT or cross-client connector parity. The current implementation already confirms the important artifact behavior: /app/chukwa-repo.zip exists in the built image, excludes .git, represents the copied /app/repo working-tree snapshot, and decodes into a valid ZIP.
Remove the MCP tool surface for ZIP retrieval.
Keep the build-time ZIP artifact.
Add a plain HTTP endpoint for manual browser download, preferably:
GET /chukwa-repo.zip
The endpoint should serve the prebuilt artifact from:
/app/chukwa-repo.zip
with headers similar to:
Content-Type: application/zip
Content-Disposition: attachment; filename="chukwa-repo.zip"
This preserves the value of the ZIP artifact while avoiding the complexity and ambiguity of bulk binary transfer through MCP.
The MCP tool approach technically works, but it is the wrong shape for this use case. Returning a ZIP through an MCP tool requires pushing a large base64 blob through the tool response. OpenAI’s Apps SDK describes MCP tool responses in terms of structuredContent, content, and _meta; structuredContent and content are model-visible, while _meta is widget-only and does not reach the model. That makes MCP tool responses a poor fit for “give the human a downloadable ZIP” or “make this behave like a normal uploaded file.” (OpenAI Developers)
There is a separate OpenAI mechanism, GPT Actions openaiFileResponse, that can return files into a ChatGPT conversation. Those files can become part of the conversation similarly to user uploads, with documented size and count limits. But that mechanism belongs to GPT Actions, not the ChatGPT MCP app / developer-mode path we are using here. ChatGPT developer mode is documented as MCP client support for apps and tools, so pursuing openaiFileResponse would expand this ticket into a different integration surface with a larger blast radius. (OpenAI Developers)
The desired outcome is simpler: keep the ZIP artifact available for humans. A normal HTTP download endpoint gives users a familiar browser workflow, avoids base64 bloat, avoids ambiguous ChatGPT file-ingestion behavior, and does not require reworking the connector into a GPT Actions-style integration.
This also keeps expectations clearer across clients. Anthropic’s browser connectors are also remote MCP connectors; their docs describe Claude connecting to remote MCP servers from Anthropic’s cloud infrastructure, and the API MCP connector docs emphasize tool-call support. That does not establish a reliable “remote MCP returns ZIP and the browser agent treats it like an uploaded/mounted file” parity target. (Claude Help Center)
/app/chukwa-repo.zip./app/repo working tree..git.get_repo_zip.get_repo_zip.get_repo_zip is listed or callable.A normal HTTP route that serves /app/chukwa-repo.zip.
Response headers:
Content-Type: application/zipContent-Disposition: attachment; filename="chukwa-repo.zip"A simple 404 or 500 behavior if the artifact is missing or unreadable.
Minimal tests or live checks confirming the endpoint downloads a valid ZIP.
GET /chukwa-repo.zip
Expected successful response:
200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="chukwa-repo.zip"
Body:
<raw ZIP bytes>
This should be a direct file download. It should not return JSON, base64, or an MCP resource wrapper.
.git inclusion option./app/chukwa-repo.zip./app/chukwa-repo.zip still represents the copied /app/repo working-tree snapshot..git is not present inside the ZIP.GET /chukwa-repo.zip downloads the raw ZIP file through a browser or curl.repo/Cargo.toml.tools/list no longer includes get_repo_zip.The original implementation validated the useful part of the idea — the build-time ZIP artifact — but the MCP transfer mechanism should be removed. The final feature should be a human-facing browser download endpoint for the same prebuilt artifact.
Dont actually worry about the archived ticket. Leave that dead and buried, no matter what it's staus was.
Implemented in commit dd63bc3 (deployed, pushed). The MCP get_repo_zip tool is removed; a plain HTTP GET /chukwa-repo.zip download route takes its place. The build-time /app/chukwa-repo.zip artifact is unchanged.
get_repo_zip in src/mcp.rs."get_repo_zip" => handle_get_repo_zip(env).handle_get_repo_zip function (base64 + metadata JSON path).Containerfile still installs zip and runs zip -r -q chukwa-repo.zip repo -x 'repo/.git/*' 'repo/.git' to produce /app/chukwa-repo.zip./app/repo working tree, .git excluded.CHUKWA_REPO_ZIP env + AppState.repo_zip plumbing (now consumed by the HTTP route instead of MCP).src/server.rs: GET /chukwa-repo.zip → reads the artifact and responds with:HTTP/1.1 200 OK
content-type: application/zip
content-disposition: attachment; filename="chukwa-repo.zip"
content-length: <n>
<raw ZIP bytes>
AppState.repo_zip is None (file missing); 500 on read error.get_repo_zip_not_in_tool_manifest — asserts the MCP tool stays removed so it can't silently creep back in.$ curl -sI http://192.168.29.10:30196/chukwa-repo.zip
HTTP/1.1 200 OK
content-type: application/zip
content-disposition: attachment; filename="chukwa-repo.zip"
content-length: 170264
$ curl -s http://192.168.29.10:30196/chukwa-repo.zip -o /tmp/chukwa-repo.zip
$ file /tmp/chukwa-repo.zip
/tmp/chukwa-repo.zip: Zip archive data, at least v1.0 to extract, compression method=store
$ unzip -l /tmp/chukwa-repo.zip | head -8
Archive: /tmp/chukwa-repo.zip
Length Date Time Name
--------- ---------- ----- ----
0 2026-04-21 12:48 repo/
1439 2026-04-21 12:33 repo/Cargo.toml
0 2026-04-21 12:34 repo/k8s/
3652 2026-04-21 12:34 repo/k8s/chukwa.yaml
$ unzip -p /tmp/chukwa-repo.zip repo/Cargo.toml | head -3
[package]
name = "chukwa"
version = "0.0.0"
$ unzip -l /tmp/chukwa-repo.zip | grep -c '\.git'
0
And via MCP to confirm removal:
tools/list count: 36
get_repo_zip present: False
/app/chukwa-repo.zip./app/repo working-tree snapshot..git is not present inside the ZIP.GET /chukwa-repo.zip downloads the raw ZIP through curl (and by extension a browser).file identifies it; unzip lists it).repo/Cargo.toml.tools/list no longer includes get_repo_zip.Tests: full suite 236/236 passing (221 lib + 15 phase0, net -3 from removing 4 MCP tests and adding 1 guard).
Picked up. Plan: remove the get_repo_zip MCP tool (manifest + dispatch + handler + tests). Keep /app/chukwa-repo.zip build artifact intact. Add GET /chukwa-repo.zip HTTP route with Content-Type: application/zip and Content-Disposition: attachment. Deploy and verify via curl that the file downloads, opens as a valid ZIP, contains repo/Cargo.toml, and no longer shows in MCP tools/list.
Implemented in dd63bc3 and deployed. MCP get_repo_zip tool removed (manifest, dispatch, handler, tests). New GET /chukwa-repo.zip HTTP route serves the prebuilt /app/chukwa-repo.zip with Content-Type: application/zip and Content-Disposition: attachment. Verified live: 200 OK, 170264 bytes, valid zip, 0 .git entries, repo/Cargo.toml extracts cleanly, and MCP tools/list no longer shows get_repo_zip.
add a link to the zip download to https://chukwa.benac.dev/
Added the link in commit b04d566 (deployed). Landing page at https://chukwa.benac.dev/ now has a "Download repo snapshot (zip)" link under the Source section pointing at /chukwa-repo.zip. Verified live: the anchor is served on the home page.
Caller accepted: looks great!
Sign in as a human to drive this ticket from the page, or use the MCP tools.
Ticket created: Swap zip MCP tool for url endpoint