@withpica/mcp-server
Version:
MCP Server for withPICA — enables AI assistants to interact with your withPICA music catalog
125 lines (112 loc) • 3.85 kB
JavaScript
// Copyright (c) 2025-2026 Withpica Ltd. All rights reserved.
/**
* pica_download MCP App card — file delivery.
*
* Shows filename, mime_type, size, and an optional description, then a copper
* "download" button wired to app.downloadFile(). After dispatch the button
* flips to a "downloaded" state with a secondary "download again" action.
*
* DOM API only — never innerHTML.
*/
import { buildAppHtml } from "./shared.js";
const DOWNLOAD_BODY = `
<div class="stack gap-6">
<header>
<h1 class="heading heading-lg">download ready</h1>
<p class="text-secondary">your file is ready to save</p>
</header>
<div class="card-flat dl-file">
<div class="dl-icon" id="dl-icon">\u25CF</div>
<div class="dl-meta">
<div class="heading heading-sm" id="dl-filename">file</div>
<div class="text-tertiary" id="dl-sub" style="font-size: 12px; margin-top: 4px;"></div>
<div class="text-secondary" id="dl-description" style="font-size: 13px; margin-top: 8px; display: none;"></div>
<div class="text-tertiary" id="dl-expires" style="font-size: 11px; margin-top: 6px; display: none;"></div>
</div>
</div>
<div class="row" style="gap: 12px;">
<button class="btn-copper" id="dl-button">download</button>
<a class="btn-ghost" id="dl-fallback" href="#" target="_blank" rel="noopener">or open in browser</a>
</div>
</div>
<style>
.dl-file {
display: flex;
gap: 16px;
align-items: flex-start;
}
.dl-icon {
font-size: 32px;
color: var(--accent);
flex: 0 0 auto;
line-height: 1;
padding-top: 4px;
}
.dl-meta { flex: 1 1 auto; min-width: 0; }
#dl-filename { word-break: break-all; }
</style>
`;
const DOWNLOAD_JS = `
var dlState = { file: null };
function dlFormatBytes(bytes) {
if (bytes == null || isNaN(bytes)) return "";
if (bytes < 1024) return bytes + " B";
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + " KB";
if (bytes < 1024 * 1024 * 1024) return (bytes / (1024 * 1024)).toFixed(1) + " MB";
return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB";
}
function dlRender() {
var f = dlState.file;
if (!f) return;
var filenameEl = document.getElementById("dl-filename");
if (filenameEl) filenameEl.textContent = f.filename;
var subParts = [];
if (f.mime_type) subParts.push(f.mime_type);
if (f.size) subParts.push(dlFormatBytes(f.size));
var subEl = document.getElementById("dl-sub");
if (subEl) subEl.textContent = subParts.join(" \u00B7 ");
if (f.description) {
var descEl = document.getElementById("dl-description");
if (descEl) {
descEl.textContent = f.description;
descEl.style.display = "block";
}
}
if (f.expires_at) {
var expEl = document.getElementById("dl-expires");
if (expEl) {
expEl.textContent = "link expires " + f.expires_at;
expEl.style.display = "block";
}
}
var fallback = document.getElementById("dl-fallback");
if (fallback) fallback.setAttribute("href", f.url);
}
function dlTriggerDownload() {
var f = dlState.file;
if (!f) return;
var btn = document.getElementById("dl-button");
if (app && typeof app.downloadFile === "function") {
try {
app.downloadFile({ url: f.url, filename: f.filename });
if (btn) {
btn.textContent = "download again";
btn.classList.remove("btn-copper");
btn.classList.add("btn-ghost");
}
return;
} catch (err) {
console.warn("[pica_download] downloadFile failed:", err);
}
}
}
window.onPicaToolResult = function (data) {
if (!data || !data.file) return;
dlState.file = data.file;
dlRender();
var btn = document.getElementById("dl-button");
if (btn) btn.addEventListener("click", dlTriggerDownload);
};
`;
export const DOWNLOAD_HTML = buildAppHtml("pica \u2014 download", DOWNLOAD_BODY, DOWNLOAD_JS);
//# sourceMappingURL=download.js.map