local-mcp 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.js +17 -11
  2. package/package.json +1 -1
  3. package/setup.js +13 -6
package/index.js CHANGED
@@ -11,7 +11,7 @@
11
11
  * npx local-mcp status → muestra estado del servidor local
12
12
  */
13
13
 
14
- const { spawn } = require('child_process')
14
+ const { spawn, execFileSync } = require('child_process')
15
15
  const path = require('path')
16
16
  const os = require('os')
17
17
  const fs = require('fs')
@@ -88,17 +88,23 @@ async function main() {
88
88
 
89
89
  const { binPath } = runtime
90
90
 
91
- // ── Symlink estable + migración de config de Claude Desktop ──────────────────
92
- // El binario corre como hijo de node TCC muestra "node" en los diálogos de
93
- // permisos (Messages, Mail, etc.) en lugar de "local-mcp-server".
94
- // Solución: crear un symlink estable y apuntar Claude Desktop directamente
95
- // al binario. En la próxima sesión, Claude Desktop llama al binario sin node
96
- // como padre → TCC ve "com.local-mcp.server" directamente.
91
+ // ── Stable binary copy + Claude Desktop migration ──────────────────────────
92
+ // Copy binary to a stable path so auto-updates (which clean versioned dirs)
93
+ // never break the binary that Claude Desktop points to.
97
94
  const { CACHE_DIR } = require('./download')
98
- const stableLink = path.join(CACHE_DIR, 'local-mcp-server')
95
+ const stablePath = path.join(CACHE_DIR, 'local-mcp-server')
99
96
  try {
100
- if (fs.existsSync(stableLink)) fs.unlinkSync(stableLink)
101
- fs.symlinkSync(binPath, stableLink)
97
+ const tmpPath = stablePath + '.tmp'
98
+ fs.copyFileSync(binPath, tmpPath)
99
+ fs.chmodSync(tmpPath, 0o755)
100
+ // Re-sign with stable identity
101
+ try { execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.server', tmpPath], { stdio: 'pipe' }) } catch {}
102
+ // Atomic replace
103
+ fs.renameSync(tmpPath, stablePath)
104
+ // Also copy settings.html
105
+ const settingsSrc = path.join(path.dirname(binPath), 'settings.html')
106
+ const settingsDst = path.join(CACHE_DIR, 'settings.html')
107
+ if (fs.existsSync(settingsSrc)) fs.copyFileSync(settingsSrc, settingsDst)
102
108
 
103
109
  // Migrar claude_desktop_config.json si todavía usa npx
104
110
  const claudeConfig = path.join(
@@ -108,7 +114,7 @@ async function main() {
108
114
  const cfg = JSON.parse(fs.readFileSync(claudeConfig, 'utf8'))
109
115
  const srv = cfg.mcpServers?.['local-mcp']
110
116
  if (srv && srv.command === 'npx') {
111
- cfg.mcpServers['local-mcp'] = { command: stableLink }
117
+ cfg.mcpServers['local-mcp'] = { command: stablePath }
112
118
  fs.writeFileSync(claudeConfig, JSON.stringify(cfg, null, 2))
113
119
  process.stderr.write(`\n✓ Config de Claude Desktop actualizado.\n`)
114
120
  process.stderr.write(` Reiniciá Claude Desktop para que Pilot MCP corra sin node como padre.\n`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "Pilot MCP — connect Claude Desktop, Cursor, Windsurf to Mail, Calendar, Contacts, Teams, OneDrive on macOS. Privacy-first: all data stays on your Mac.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/setup.js CHANGED
@@ -120,14 +120,21 @@ async function runSetup(opts = {}) {
120
120
  const { ensureBinary, CACHE_DIR } = require('./download')
121
121
  process.stderr.write('Downloading Pilot MCP runtime...\n')
122
122
  const { binPath } = await ensureBinary()
123
- // Crear stable symlink
124
- const stableLink = path.join(CACHE_DIR, 'local-mcp-server')
123
+ // Copy binary to stable path (not symlink — survives version cleanup)
124
+ const stablePath = path.join(CACHE_DIR, 'local-mcp-server')
125
125
  try {
126
- if (fs.existsSync(stableLink)) fs.unlinkSync(stableLink)
127
- fs.symlinkSync(binPath, stableLink)
126
+ const tmpPath = stablePath + '.tmp'
127
+ fs.copyFileSync(binPath, tmpPath)
128
+ fs.chmodSync(tmpPath, 0o755)
129
+ try { require('child_process').execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.server', tmpPath], { stdio: 'pipe' }) } catch {}
130
+ fs.renameSync(tmpPath, stablePath)
131
+ // Also copy settings.html
132
+ const settingsSrc = path.join(path.dirname(binPath), 'settings.html')
133
+ const settingsDst = path.join(CACHE_DIR, 'settings.html')
134
+ if (fs.existsSync(settingsSrc)) fs.copyFileSync(settingsSrc, settingsDst)
128
135
  } catch { /* no crítico — fallback a npx */ }
129
- if (fs.existsSync(stableLink)) {
130
- stableCommand = stableLink
136
+ if (fs.existsSync(stablePath)) {
137
+ stableCommand = stablePath
131
138
  stableArgs = undefined
132
139
  process.stderr.write('✓ Runtime ready\n\n')
133
140
  }