local-mcp 3.0.14 → 3.0.15

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
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
  /**
3
- * download.js — descarga y cachea el binario standalone de Pilot MCP desde R2.
3
+ * download.js — descarga y cachea el binario standalone de LMCP desde R2.
4
4
  * El binario fue compilado con PyInstaller — no requiere Python instalado.
5
5
  * Cache: ~/.local/share/local-mcp/bin/{version}/
6
6
  */
@@ -37,7 +37,7 @@ function getArch() {
37
37
  const arch = process.arch
38
38
  if (arch === 'arm64') return 'darwin-arm64'
39
39
  if (arch === 'x64') return 'darwin-x64'
40
- throw new Error(`Arquitectura no soportada: ${arch}. Pilot MCP requiere macOS arm64 o x64.`)
40
+ throw new Error(`Arquitectura no soportada: ${arch}. LMCP requiere macOS arm64 o x64.`)
41
41
  }
42
42
 
43
43
  /**
@@ -129,7 +129,7 @@ async function ensureBinary() {
129
129
  return { binPath, versionDir }
130
130
  }
131
131
 
132
- process.stderr.write(`\nPilot MCP v${version} no encontrado en cache.\n`)
132
+ process.stderr.write(`\nLMCP v${version} no encontrado en cache.\n`)
133
133
  process.stderr.write(`Descargando desde ${url}\n`)
134
134
 
135
135
  fs.mkdirSync(versionDir, { recursive: true })
package/index.js CHANGED
@@ -18,7 +18,7 @@ const fs = require('fs')
18
18
 
19
19
  // Solo macOS
20
20
  if (process.platform !== 'darwin') {
21
- console.error('Pilot MCP solo está disponible para macOS.')
21
+ console.error('LMCP solo está disponible para macOS.')
22
22
  process.exit(1)
23
23
  }
24
24
 
@@ -63,7 +63,7 @@ async function main() {
63
63
  res.on('end', () => {
64
64
  try {
65
65
  const s = JSON.parse(data)
66
- console.log(`Pilot MCP v${s.version} — ${s.server}`)
66
+ console.log(`LMCP v${s.version} — ${s.server}`)
67
67
  console.log(`Licencia: ${s.license?.status} (${s.license?.days_left}d)`)
68
68
  } catch { console.log(data) }
69
69
  })
@@ -74,23 +74,30 @@ async function main() {
74
74
  // ── Modo default: stdio MCP server ──────────────────────────────────────────
75
75
  const { CACHE_DIR } = require('./download')
76
76
  const stableBin = path.join(CACHE_DIR, 'local-mcp-server')
77
+ const versionFile = path.join(CACHE_DIR, '.server-version')
78
+ const pkg = require('./package.json')
77
79
 
78
- // Fast path: if stable binary exists and is a real file (not a broken symlink), exec it directly.
79
- // This makes npx startup near-instant when everything is healthy.
80
+ // Fast path: if stable binary exists, version matches, exec directly.
80
81
  try {
81
82
  const stat = fs.lstatSync(stableBin)
82
- // Only use fast path if it's a real file (not a symlink — symlinks can break)
83
83
  if (stat.isFile() && (stat.mode & 0o111)) {
84
- // Download tray + teams-proxy in background (non-blocking)
85
- const { ensureTray, ensureTeamsProxy } = require('./download')
86
- ensureTray().catch(() => {})
87
- ensureTeamsProxy().catch(() => {})
88
- const child = spawn(stableBin, [], { stdio: 'inherit', env: process.env })
89
- child.on('error', () => process.exit(1))
90
- child.on('exit', (code) => process.exit(code ?? 0))
91
- return
84
+ // Check if cached binary matches current npm version
85
+ const cachedVersion = fs.existsSync(versionFile)
86
+ ? fs.readFileSync(versionFile, 'utf8').trim()
87
+ : ''
88
+ if (cachedVersion === pkg.version) {
89
+ // Version matches — use fast path
90
+ const { ensureTray, ensureTeamsProxy } = require('./download')
91
+ ensureTray().catch(() => {})
92
+ ensureTeamsProxy().catch(() => {})
93
+ const child = spawn(stableBin, [], { stdio: 'inherit', env: process.env })
94
+ child.on('error', () => process.exit(1))
95
+ child.on('exit', (code) => process.exit(code ?? 0))
96
+ return
97
+ }
98
+ // Version mismatch — fall through to download new binary
99
+ process.stderr.write(`Updating LMCP server (${cachedVersion || '?'} → ${pkg.version})...\n`)
92
100
  }
93
- // If it's a symlink (legacy), remove it and fall through to download
94
101
  if (stat.isSymbolicLink()) fs.unlinkSync(stableBin)
95
102
  } catch {
96
103
  // stat failed — binary missing, fall through to download
@@ -107,7 +114,7 @@ async function main() {
107
114
  try {
108
115
  runtime = await ensureRuntime()
109
116
  } catch (err) {
110
- process.stderr.write(`\nError al preparar el runtime de Pilot MCP:\n${err.message}\n`)
117
+ process.stderr.write(`\nError al preparar el runtime de LMCP:\n${err.message}\n`)
111
118
  process.stderr.write(`Intentá reinstalar: npx local-mcp update\n\n`)
112
119
  process.exit(1)
113
120
  }
@@ -121,6 +128,8 @@ async function main() {
121
128
  fs.chmodSync(tmpPath, 0o755)
122
129
  try { execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.server', tmpPath], { stdio: 'pipe' }) } catch {}
123
130
  fs.renameSync(tmpPath, stableBin)
131
+ // Write version file so fast path knows when to update
132
+ fs.writeFileSync(versionFile, pkg.version)
124
133
  // Also copy settings.html
125
134
  const settingsSrc = path.join(path.dirname(binPath), 'settings.html')
126
135
  const settingsDst = path.join(CACHE_DIR, 'settings.html')
@@ -130,7 +139,7 @@ async function main() {
130
139
  // Run the binary
131
140
  const child = spawn(binPath, [], { stdio: 'inherit', env: process.env })
132
141
  child.on('error', (err) => {
133
- process.stderr.write(`Error ejecutando Pilot MCP: ${err.message}\n`)
142
+ process.stderr.write(`Error ejecutando LMCP: ${err.message}\n`)
134
143
  process.exit(1)
135
144
  })
136
145
  child.on('exit', (code) => process.exit(code ?? 0))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "3.0.14",
3
+ "version": "3.0.15",
4
4
  "description": "LMCP — 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
@@ -117,7 +117,7 @@ async function runSetup(opts = {}) {
117
117
  if (refArg) process.env.LMCP_REF = refArg.split('=')[1]
118
118
 
119
119
  console.log('\n╔══════════════════════════════════════╗')
120
- console.log('║ Pilot MCP — Setup Wizard ║')
120
+ console.log('║ LMCP — Setup Wizard ║')
121
121
  console.log('╚══════════════════════════════════════╝\n')
122
122
 
123
123
  // Pre-download binary so first launch is instant
@@ -126,7 +126,7 @@ async function runSetup(opts = {}) {
126
126
  let stableArgs = NPX_ARGS
127
127
  try {
128
128
  const { ensureBinary, CACHE_DIR } = require('./download')
129
- process.stderr.write('Downloading Pilot MCP runtime...\n')
129
+ process.stderr.write('Downloading LMCP runtime...\n')
130
130
  const { binPath } = await ensureBinary()
131
131
  // Copy binary to stable path (npx fast-path will exec it directly)
132
132
  const stablePath = path.join(CACHE_DIR, 'local-mcp-server')
@@ -136,6 +136,9 @@ async function runSetup(opts = {}) {
136
136
  fs.chmodSync(tmpPath, 0o755)
137
137
  try { execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.server', tmpPath], { stdio: 'pipe' }) } catch {}
138
138
  fs.renameSync(tmpPath, stablePath)
139
+ // Write version file so fast path knows when to update
140
+ const pkg = require('./package.json')
141
+ fs.writeFileSync(path.join(CACHE_DIR, '.server-version'), pkg.version)
139
142
  const settingsSrc = path.join(path.dirname(binPath), 'settings.html')
140
143
  const settingsDst = path.join(CACHE_DIR, 'settings.html')
141
144
  if (fs.existsSync(settingsSrc)) fs.copyFileSync(settingsSrc, settingsDst)
@@ -198,17 +201,17 @@ async function runSetup(opts = {}) {
198
201
  console.log('\n──────────────────────────────────────')
199
202
  if (configured.length > 0) {
200
203
  if (healthOk) {
201
- console.log(`✅ Pilot MCP configured for: ${configured.join(', ')}\n`)
204
+ console.log(`✅ LMCP configured for: ${configured.join(', ')}\n`)
202
205
  console.log(' ✓ Server binary verified — 82 tools ready\n')
203
206
  } else {
204
- console.log(`⚠ Pilot MCP configured for: ${configured.join(', ')}`)
207
+ console.log(`⚠ LMCP configured for: ${configured.join(', ')}`)
205
208
  console.log(' Server binary could not be verified — it may still work after restart.\n')
206
209
  }
207
210
  console.log('┌─────────────────────────────────────────────────────┐')
208
211
  console.log('│ NEXT STEP — This is important: │')
209
212
  console.log('│ │')
210
213
  console.log(`│ Quit and reopen ${configured[0].padEnd(35)}│`)
211
- console.log('│ Pilot MCP will appear automatically. │')
214
+ console.log('│ LMCP will appear automatically. │')
212
215
  console.log('│ │')
213
216
  console.log('│ Then try: "Summarize my unread emails" │')
214
217
  console.log('└─────────────────────────────────────────────────────┘\n')
@@ -239,7 +242,7 @@ async function _installTray() {
239
242
  const { ensureTray } = require('./download')
240
243
  const trayApp = await ensureTray()
241
244
  if (!trayApp) return // x64 — skip silencioso
242
- console.log('\n✓ Tray installed — look for the Pilot MCP icon in your menu bar\n')
245
+ console.log('\n✓ Tray installed — look for the LMCP icon in your menu bar\n')
243
246
  // ensureTray() ya escribió el LaunchAgent y lo cargó con RunAtLoad=true
244
247
  // No hace falta llamar open() por separado
245
248
  } catch (err) {