local-mcp 1.88.0 → 1.89.1

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.
package/download.js CHANGED
@@ -144,13 +144,10 @@ async function ensureRuntime() {
144
144
  }
145
145
 
146
146
  /**
147
- * Descarga e instala el tray SwiftUI (menu bar app) para arm64.
148
- * En x64 retorna null silenciosamente no hay build de tray para Intel.
149
- * @returns {Promise<string|null>} Ruta al .app instalado, o null si no aplica
147
+ * Descarga e instala el tray SwiftUI (menu bar app) universal binary (arm64 + Intel).
148
+ * @returns {Promise<string|null>} Ruta al .app instalado, o null si falla
150
149
  */
151
150
  async function ensureTray() {
152
- // Solo arm64 — no hay build x64 del tray
153
- if (process.arch !== 'arm64') return null
154
151
 
155
152
  const info = await getLatestBinary()
156
153
  const version = info.version
@@ -162,7 +159,7 @@ async function ensureTray() {
162
159
  if (fs.readFileSync(verFile, 'utf8').trim() === version) return trayApp
163
160
  }
164
161
 
165
- const url = `https://download.local-mcp.com/local-mcp-tray-${version}-darwin-arm64.tar.gz`
162
+ const url = `https://download.local-mcp.com/local-mcp-tray-${version}-darwin-universal.tar.gz`
166
163
  process.stderr.write(`\nDescargando tray v${version}...\n`)
167
164
 
168
165
  fs.mkdirSync(TRAY_DIR, { recursive: true })
@@ -188,8 +185,45 @@ async function ensureTray() {
188
185
  try { execFileSync('codesign', ['--force', '--sign', '-', trayBin], { stdio: 'pipe' }) } catch { /* no crítico */ }
189
186
 
190
187
  fs.writeFileSync(verFile, version, 'utf8')
188
+
189
+ // LaunchAgent — auto-start en cada reboot de sesión
190
+ _writeTrayLaunchAgent(trayApp)
191
+
191
192
  process.stderr.write(` Tray instalado en ${trayApp}\n`)
192
193
  return trayApp
193
194
  }
194
195
 
196
+ function _writeTrayLaunchAgent(trayApp) {
197
+ const trayBin = path.join(trayApp, 'Contents', 'MacOS', 'LocalMCPTray')
198
+ const plistDir = path.join(os.homedir(), 'Library', 'LaunchAgents')
199
+ const plistPath = path.join(plistDir, 'com.local-mcp.tray.plist')
200
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
201
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
202
+ <plist version="1.0">
203
+ <dict>
204
+ <key>Label</key>
205
+ <string>com.local-mcp.tray</string>
206
+ <key>ProgramArguments</key>
207
+ <array>
208
+ <string>${trayBin}</string>
209
+ </array>
210
+ <key>RunAtLoad</key>
211
+ <true/>
212
+ <key>KeepAlive</key>
213
+ <false/>
214
+ </dict>
215
+ </plist>
216
+ `
217
+ try {
218
+ fs.mkdirSync(plistDir, { recursive: true })
219
+ fs.writeFileSync(plistPath, plist, 'utf8')
220
+ // Matar proceso viejo (si estaba corriendo por cualquier medio)
221
+ try { execFileSync('pkill', ['-x', 'LocalMCPTray'], { stdio: 'pipe' }) } catch { /* no estaba corriendo */ }
222
+ // Recargar LaunchAgent
223
+ try { execFileSync('launchctl', ['unload', plistPath], { stdio: 'pipe' }) } catch {}
224
+ execFileSync('launchctl', ['load', plistPath], { stdio: 'pipe' })
225
+ // launchctl load con RunAtLoad=true arranca el proceso — no necesitamos open()
226
+ } catch { /* no crítico */ }
227
+ }
228
+
195
229
  module.exports = { ensureBinary, ensureRuntime, ensureTray, CACHE_DIR, TRAY_DIR }
package/index.js CHANGED
@@ -71,7 +71,10 @@ async function main() {
71
71
  }
72
72
 
73
73
  // Modo default: stdio MCP server
74
- const { ensureRuntime } = require('./download')
74
+ const { ensureRuntime, ensureTray } = require('./download')
75
+
76
+ // Actualizar tray en background en cada startup (sin bloquear el arranque del servidor)
77
+ ensureTray().catch(() => { /* no crítico */ })
75
78
 
76
79
  let runtime
77
80
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "1.88.0",
3
+ "version": "1.89.1",
4
4
  "description": "MCP server for macOS \u2014 connect Claude Desktop, Cursor, Windsurf to Mail, Calendar, Contacts, Teams, OneDrive. Privacy-first: all data stays on your Mac.",
5
5
  "main": "index.js",
6
6
  "bin": {
package/setup.js CHANGED
@@ -184,12 +184,10 @@ async function _installTray() {
184
184
  try {
185
185
  const { ensureTray } = require('./download')
186
186
  const trayApp = await ensureTray()
187
- if (!trayApp) return // x64 o error silencioso
188
- console.log('\n✓ Tray installed (menu bar icon)')
189
- // Lanzar en background no bloquea, el proceso se detacha
190
- const { spawn } = require('child_process')
191
- spawn('open', [trayApp], { detached: true, stdio: 'ignore' }).unref()
192
- console.log('✓ Tray launched — look for the Local MCP icon in your menu bar\n')
187
+ if (!trayApp) return // x64 skip silencioso
188
+ console.log('\n✓ Tray installed — look for the Local MCP icon in your menu bar\n')
189
+ // ensureTray() ya escribió el LaunchAgent y lo cargó con RunAtLoad=true
190
+ // No hace falta llamar open() por separado
193
191
  } catch (err) {
194
192
  // No fatal — el servidor MCP funciona igual sin el tray
195
193
  process.stderr.write(` (Tray not available: ${err.message})\n\n`)