From c248080541b25dc10edc92a1d5f6efd0d27c4818 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Apr 2026 10:29:39 +0000 Subject: [PATCH 1/2] feat: automate .mcpb Desktop Extension build in release pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add esbuild + zip step to release.yml that produces clashcontrol-mcp.mcpb - Upload .mcpb alongside platform binaries in GitHub Releases - Fix manifest.json entry_point to server/index.js (matches .mcpb internal layout) Now every merged PR automatically produces the .mcpb file — BIM managers download it from Releases and double-click to install. Zero manual steps for ClashControl, zero terminal for end users. Verified locally: esbuild bundles to 1.4MB, zips to 214KB .mcpb containing manifest.json + server/index.js. https://claude.ai/code/session_01XEvUykWcLc452uxGWPb1mb --- .github/workflows/release.yml | 10 ++++++++++ manifest.json | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6ff1f0..f639037 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,6 +41,15 @@ jobs: if: steps.tag_check.outputs.exists == 'false' run: npx pkg smart-bridge.js --targets node18-win-x64,node18-macos-x64,node18-linux-x64 --output dist/clashcontrol-smart-bridge + - name: Build .mcpb Desktop Extension + if: steps.tag_check.outputs.exists == 'false' + run: | + npx esbuild index.js --bundle --platform=node --target=node18 --format=cjs --outfile=dist/mcp-bundle.cjs + mkdir -p staging/server + cp manifest.json staging/ + cp dist/mcp-bundle.cjs staging/server/index.js + cd staging && zip -r ../dist/clashcontrol-mcp.mcpb . && cd .. + - name: Create tag and release if: steps.tag_check.outputs.exists == 'false' uses: softprops/action-gh-release@v2 @@ -50,5 +59,6 @@ jobs: dist/clashcontrol-smart-bridge-win.exe dist/clashcontrol-smart-bridge-macos dist/clashcontrol-smart-bridge-linux + dist/clashcontrol-mcp.mcpb generate_release_notes: true # Build timestamp: Fri Apr 10 22:08:43 UTC 2026 diff --git a/manifest.json b/manifest.json index a86ddc1..d73249e 100644 --- a/manifest.json +++ b/manifest.json @@ -12,7 +12,7 @@ "repository": "https://github.com/clashcontrol-io/ClashControlSmartBridge", "server": { "type": "node", - "entry_point": "dist/mcp-bundle.cjs" + "entry_point": "server/index.js" }, "compatibility": { "platforms": ["darwin", "win32"], From 29a9a1eaa7db8bbea5fb77b6b9ea8843217ce805 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Apr 2026 11:01:09 +0000 Subject: [PATCH 2/2] feat: auto-configure Claude Desktop on first Smart Bridge run MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the Smart Bridge binary starts, it now automatically adds itself to Claude Desktop's claude_desktop_config.json if not already present. Points to the installed binary path with --mcp flag. This means the full setup flow is now: 1. User downloads and runs the Smart Bridge binary 2. Binary self-installs to a permanent location (existing) 3. Binary configures Claude Desktop automatically (NEW) 4. User restarts Claude Desktop — ClashControl tools appear No manual JSON editing, no terminal, no .mcpb download needed. Preserves any existing mcpServers entries in the config. https://claude.ai/code/session_01XEvUykWcLc452uxGWPb1mb --- smart-bridge.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/smart-bridge.js b/smart-bridge.js index 3ea7909..e2816d1 100644 --- a/smart-bridge.js +++ b/smart-bridge.js @@ -73,6 +73,53 @@ function selfInstall() { } } +// ── Auto-configure Claude Desktop ──────────────────────────────── +// On first run, add ClashControl to Claude Desktop's MCP config +// so the user never needs to edit JSON manually. + +function getClaudeConfigPath() { + if (process.platform === 'win32') + return path.join(process.env.APPDATA || os.homedir(), 'Claude', 'claude_desktop_config.json'); + if (process.platform === 'darwin') + return path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'); + return path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json'); +} + +function configureClaude() { + const configPath = getClaudeConfigPath(); + const binaryPath = process.pkg ? getInstallPath() : process.execPath; + + let config = {}; + try { + config = JSON.parse(fs.readFileSync(configPath, 'utf8')); + } catch (e) { + // File doesn't exist or isn't valid JSON — we'll create it + } + + if (!config.mcpServers) config.mcpServers = {}; + + // Already configured — check if path still matches + if (config.mcpServers.clashcontrol) { + const existing = config.mcpServers.clashcontrol; + if (existing.command === binaryPath) return; // already correct + } + + // Add or update the clashcontrol entry + config.mcpServers.clashcontrol = { + command: binaryPath, + args: ['--mcp'] + }; + + try { + fs.mkdirSync(path.dirname(configPath), { recursive: true }); + fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n'); + log('Claude Desktop configured: ' + configPath); + log('Restart Claude Desktop to activate ClashControl tools.'); + } catch (e) { + log('Could not configure Claude Desktop: ' + e.message); + } +} + // ── Auto-updater ────────────────────────────────────────────────── // Only active when running as a compiled pkg binary. @@ -392,6 +439,7 @@ async function startMcpServer() { async function main() { selfInstall(); + configureClaude(); checkAndUpdate(); startWsBridge();