From Claude Desktop to AgileWatch — How Live Artifacts Get Shared Across the Organization
A live artifact is an interactive web page that displays up-to-date data each time you open it — no static files to re-send, no manual refresh gymnastics. Think of it as a live dashboard wired directly to your data sources.
Typical use cases:
- Network operations — current alarm counts, OLT/ONU status, provision order distribution
- CRM dashboards — open tickets grouped by department or region
- Team trackers — project progress, token usage, agent activity
The Two Worlds: Claude Desktop vs. AgileWatch Portal
When you build a live artifact inside Claude Code (or Claude Desktop), it runs as two separate pieces:
| Claude Desktop Session | AgileWatch Portal | |
|---|---|---|
| Architecture | index.html (browser UI) + server.ts (Express data handler). A local Node server bridges the two. | A single HTML file with an embedded <script type="text/handler"> block. AgileWatch runs the handler server-side. |
| Sharing | Not shareable — the local server must stay running. | One link. Anyone with portal access can open it. |
| Data freshness | Refreshes when you reload the browser. | Refreshes on open, or via a manual refresh button — each click calls MCP live. |
| Setup | Express + MCP server running locally. | Zero. AgileWatch handles handler execution and MCP connections. |
| Best for | Iterating and testing. | Published team dashboards. |
The workflow: iterate fast in Claude Desktop, then compile and publish to AgileWatch for the team.
How Publishing Works
The bridge between these two worlds is the /agilewatch-artifact-cd skill. It acts as a transpiler: it reads the original index.html and server.ts, then emits a single self-contained HTML file that AgileWatch can serve directly.
Here's what the skill does step by step:
Step 1 — Map the endpoints
Every fetch("/api/...") call in the browser UI gets mapped to the MCP tool calls in server.ts:
fetch("/api/data") → getData() → callMcpTool("ftth-mcp", "get_headends")
Step 2 — Transpile the handler
The Express route handlers in server.ts become a single async function getData({ callMcpTool }) embedded in a <script type="text/handler"> block:
async function getData({ callMcpTool }) {
const headends = await callMcpTool("ftth-mcp", "get_headends");
const olts = [];
for (const he of headends) {
const chassis = await callMcpTool("ftth-mcp", "get_olt_chassis", { name: he.name });
olts.push(...chassis.map(o => ({ name: o.name, site: he.name, ... })));
}
return {
timestamp: new Date().toISOString(),
headends: headends.map(h => h.name),
olts,
summary: { totalOlt: olts.length, totalOnline: ..., totalOnu: ... }
};
}
The handler runs in a sandboxed node:vm context on the portal — no require, no fs, no npm. Just pure JavaScript and callMcpTool.
Step 3 — Rewrite the frontend
All those separate fetch("/api/data"), fetch("/api/stats") calls collapse into one:
fetch("/api/artifacts/onu-dashboard/data"
+ (window.ALPM_SESSION_TOKEN ? "?token=" + window.ALPM_SESSION_TOKEN : ""))
.then(r => r.json())
.then(data => {
renderChart(data.olts);
showSummary(data.summary);
});
The frontend destructures one response object instead of making multiple round-trips.
Step 4 — Deploy
The compiled HTML is uploaded to AgileWatch via aw-mcp.deploy_artifact. The artifact gets a URL slug — e.g., onu-dashboard → http://localhost:9001/artifacts/onu-dashboard — and is immediately available to anyone in the organization.
Per-User Authentication
A critical detail: the sandboxed iframe that hosts the artifact has an opaque origin and cannot send auth headers. So how does AgileWatch know who is making the MCP call?
When the portal serves the artifact HTML, it injects a session token derived from the current user's Bearer token:
<script>window.ALPM_SESSION_TOKEN = "eyJ...";</script>
The artifact's JS passes this token as a query parameter on the /data request. The backend verifies the HMAC signature, extracts the original user token, and uses it when connecting to the MCP server. Each user gets their own MCP connection — audit logs correctly attribute every tool call to the right person.
For artifacts deployed before this auth layer existed, the ?token= parameter is gracefully absent and the system falls back to a shared service token. The ternary in the fetch call above preserves that backward compatibility.
Real Examples in Production
Several artifacts are already running on this pipeline:
| Artifact | What It Shows | MCP Backend |
|---|---|---|
| ONU Dashboard | OLT chassis ONU online/offline stats, pie charts by site | ftth-mcp |
| OLT Inspection | Per-OLT port utilization and alarm summary | ftth-mcp |
| EPON Provision | Provision order distribution by status and region | aepon-mcp |
| Provision Order | Detailed order list with filtering and search | aepon-mcp |
Each of these started as a Claude Desktop artifact, was compiled by /agilewatch-artifact-cd, and now serves live data to the team through AgileWatch.
How to Request One
You don't need to understand the compilation pipeline to get a live artifact. Just describe:
- What data — tickets, network alarms, performance metrics, project status
- How it should be organized — by time, team, region, status
- Who the audience is — just you, your team, the whole company
The agent handles building, compiling, and publishing. You get back a link.
Summary
- Live artifacts are interactive dashboards that pull fresh data on every open
- Claude Desktop is the iteration sandbox — fast, local, single-user
- AgileWatch is the publishing target — zero-setup, shareable, team-wide
/agilewatch-artifact-cdbridges the two by compilingindex.html+server.tsinto one portable HTML file- Per-user auth ensures MCP calls are correctly attributed, with backward compatibility for older artifacts
- No more stale spreadsheets or "let me re-run the script and email you a screenshot"
