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:
parent
25aac634ab
commit
b29233a012
9 changed files with 505 additions and 3 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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.",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue