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"], 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();