Add .mcpb Claude Desktop bundle with zero-config token handling

New scripts/build-mcpb.mjs packs a Claude Desktop extension bundle
(scripts/mcpb-wrapper.mjs + manifest + icon) into dist-mcpb/tiletopia.mcpb.
The wrapper reads the bearer token from %APPDATA% at launch and execs
`npx -y mcp-remote`, so no secrets are baked in and Regenerate keeps
working transparently. Run via `pnpm run build:mcpb`.

McpPanel gets a "Download .mcpb" button linking to the releases page; the
help-overlay tip and README MCP section both lead with the bundle install
path and keep the .mcp.json shim recipe as the Claude Code fallback.

Session-log entry in memory.md covers the design choices, especially why
the wrapper-script approach beat the alternatives (user_config prompt
would defeat one-click; baked-in token would be wrong for everyone else).
This commit is contained in:
megaproxy 2026-05-26 17:31:34 +01:00
parent 25aac634ab
commit b29233a012
9 changed files with 505 additions and 3 deletions

View file

@ -187,6 +187,55 @@
color: #ccd;
}
/* Inline small-print under inputs small, muted, tight line-height. Used by
* the token hint and the .mcpb install hint. */
.mcp-hint {
margin: 4px 0 0;
color: #888;
font-size: 11px;
line-height: 1.4;
}
.mcp-hint code {
background: #0c0c0c;
padding: 1px 4px;
border-radius: 2px;
font-family: inherit;
color: #aac;
}
/* ---- Claude Desktop .mcpb install row ----------------------------------- */
.mcp-mcpb-row {
display: flex;
align-items: flex-start;
gap: 12px;
}
.mcp-mcpb-btn {
font: inherit;
font-family: inherit;
font-size: 11px;
font-weight: 600;
background: #1a2a3a;
color: #cce6ff;
border: 1px solid #2a4a6a;
border-radius: 3px;
padding: 6px 14px;
cursor: pointer;
flex-shrink: 0;
white-space: nowrap;
}
.mcp-mcpb-btn:hover {
background: #2a4a6a;
color: #e0f0ff;
border-color: #4488cc;
}
.mcp-mcpb-hint {
flex: 1 1 auto;
margin: 0;
}
.mcp-snippet {
font: inherit;
font-family: inherit;

View file

@ -2,12 +2,18 @@ import { useEffect, useState, useCallback } from "react";
import {
writeText as clipboardWriteText,
} from "@tauri-apps/plugin-clipboard-manager";
import { openUrl } from "@tauri-apps/plugin-opener";
import type { McpStatus, McpAuditEntry } from "../ipc";
import AuditTab from "./AuditTab";
import PolicyTab from "./PolicyTab";
import ErrorBoundary from "./ErrorBoundary";
import "./McpPanel.css";
// URL of the GitHub-style releases page where each tagged build attaches the
// prebuilt `.mcpb` bundle (sibling to the NSIS installer). Source bundle is
// regeneratable via `pnpm run build:mcpb`.
const MCPB_RELEASES_URL = "https://git.rdx4.com/megaproxy/tiletopia/releases";
interface McpPanelProps {
status: McpStatus;
onStart: () => Promise<void>;
@ -196,6 +202,31 @@ export default function McpPanel({
</p>
</div>
<div className="mcp-field">
<label>Claude Desktop (one-click install)</label>
<div className="mcp-mcpb-row">
<button
className="mcp-mcpb-btn"
onClick={() => {
void openUrl(MCPB_RELEASES_URL).catch((e) =>
console.warn("open releases page failed:", e),
);
}}
>
Download .mcpb
</button>
<p className="mcp-hint mcp-mcpb-hint">
Grab <code>tiletopia.mcpb</code> from the releases
page, then drag it into Claude Desktop's{" "}
<em>Settings Extensions</em>. The bundle reads your
bearer token from <code>%APPDATA%</code> at launch
zero copy-paste, and token regeneration above keeps
working transparently. (Bundle is regeneratable from
source via <code>pnpm run build:mcpb</code>.)
</p>
</div>
</div>
<div className="mcp-field">
<label>Claude Code config snippet (.mcp.json)</label>
<pre className="mcp-snippet">

View file

@ -110,6 +110,6 @@ export const TIPS: TipSpec[] = [
},
{
title: "MCP server (let Claude drive the workspace)",
body: "Titlebar 🤖 opens the MCP control panel — start the server and paste the snippet into your Claude Code .mcp.json. The snippet uses npx mcp-remote as a stdio shim because Claude Code's HTTP-MCP client ignores static bearer auth and tries OAuth instead; the shim proxies the HTTP endpoint with the bearer baked in. URL + token persist across restarts; Regenerate the token in the panel if it leaks. Default-deny per pane: toggle 🤖 on each pane's toolbar to expose it to MCP. Read-only in v1 (no spawn or write yet).",
body: "Titlebar 🤖 opens the MCP control panel. Start the server, then for Claude Desktop click 'Download .mcpb' and drag the file into Settings → Extensions — zero-config because the bundle reads your bearer token from %APPDATA% at launch (no copy-paste, survives token rotation). For Claude Code (terminal CLI) use the fallback snippet in the panel: it wires npx mcp-remote as a stdio shim because Claude Code's HTTP-MCP client ignores static bearer auth and tries OAuth instead. URL + token persist across restarts; Regenerate the token in the panel if it leaks. Default-deny per pane: toggle 🤖 on each pane's toolbar to expose it to MCP.",
},
];