local-mcp 3.0.70 → 3.0.71

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
@@ -310,4 +310,49 @@ function _writeTrayLaunchAgent(trayApp) {
310
310
  } catch { /* no crítico */ }
311
311
  }
312
312
 
313
- module.exports = { ensureBinary, ensureRuntime, ensureTray, ensureTeamsProxy, CACHE_DIR, TRAY_DIR }
313
+ /**
314
+ * Descarga el co-proceso m365-proxy si no está instalado o es una versión diferente.
315
+ * El binary se instala en ~/.local/share/local-mcp/bin/m365-proxy
316
+ * @returns {Promise<string|null>} Ruta al binary, o null si falla
317
+ */
318
+ async function ensureM365Proxy() {
319
+ const info = await getLatestBinary()
320
+ const version = info.version
321
+ const arch = process.arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64'
322
+ const binPath = path.join(CACHE_DIR, 'm365-proxy')
323
+ const verFile = path.join(CACHE_DIR, '.m365-proxy-version')
324
+
325
+ // Ya instalado y actualizado
326
+ if (fs.existsSync(binPath) && fs.existsSync(verFile)) {
327
+ if (fs.readFileSync(verFile, 'utf8').trim() === version) return binPath
328
+ }
329
+
330
+ const url = `https://download.local-mcp.com/m365-proxy-${version}-${arch}.tar.gz`
331
+ process.stderr.write(`\nDescargando m365-proxy v${version}...\n`)
332
+
333
+ fs.mkdirSync(CACHE_DIR, { recursive: true })
334
+ const tarPath = path.join(CACHE_DIR, `m365-proxy-${version}.tar.gz`)
335
+
336
+ try {
337
+ await downloadFile(url, tarPath)
338
+ const stat = fs.statSync(tarPath)
339
+ if (stat.size < 1000) { fs.unlinkSync(tarPath); throw new Error(`Descarga incompleta (${stat.size} bytes)`) }
340
+
341
+ execFileSync('tar', ['-xzf', tarPath, '-C', CACHE_DIR], { stdio: 'pipe' })
342
+ fs.unlinkSync(tarPath)
343
+
344
+ if (!fs.existsSync(binPath)) throw new Error('m365-proxy no encontrado tras extraer')
345
+ fs.chmodSync(binPath, 0o755)
346
+ try { execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.m365-proxy', binPath], { stdio: 'pipe' }) } catch { /* no crítico */ }
347
+
348
+ fs.writeFileSync(verFile, version, 'utf8')
349
+ process.stderr.write(` m365-proxy instalado en ${binPath}\n`)
350
+ return binPath
351
+ } catch (err) {
352
+ try { if (fs.existsSync(tarPath)) fs.unlinkSync(tarPath) } catch {}
353
+ process.stderr.write(` (m365-proxy no disponible: ${err.message})\n`)
354
+ return null
355
+ }
356
+ }
357
+
358
+ module.exports = { ensureBinary, ensureRuntime, ensureTray, ensureTeamsProxy, ensureM365Proxy, CACHE_DIR, TRAY_DIR }
package/index.js CHANGED
@@ -122,9 +122,10 @@ async function main() {
122
122
  : ''
123
123
  if (cachedVersion === pkg.version) {
124
124
  // Version matches — use fast path
125
- const { ensureTray, ensureTeamsProxy } = require('./download')
125
+ const { ensureTray, ensureTeamsProxy, ensureM365Proxy } = require('./download')
126
126
  ensureTray().catch(() => {})
127
127
  ensureTeamsProxy().catch(() => {})
128
+ ensureM365Proxy().catch(() => {})
128
129
  const child = spawn(stableBin, [], { stdio: 'inherit', env: process.env })
129
130
  child.on('error', () => process.exit(1))
130
131
  child.on('exit', (code) => process.exit(code ?? 0))
@@ -143,11 +144,12 @@ async function main() {
143
144
  }
144
145
 
145
146
  // Slow path: download/repair binary
146
- const { ensureRuntime, ensureTray, ensureTeamsProxy } = require('./download')
147
+ const { ensureRuntime, ensureTray, ensureTeamsProxy, ensureM365Proxy } = require('./download')
147
148
 
148
- // Actualizar tray + teams-proxy en background
149
+ // Actualizar tray + teams-proxy + m365-proxy en background
149
150
  ensureTray().catch(() => {})
150
151
  ensureTeamsProxy().catch(() => {})
152
+ ensureM365Proxy().catch(() => {})
151
153
 
152
154
  let runtime
153
155
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "3.0.70",
3
+ "version": "3.0.71",
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
@@ -170,13 +170,32 @@ async function runSetup(opts = {}) {
170
170
  const detected = CLIENTS.filter(c => c.detect())
171
171
 
172
172
  if (detected.length === 0) {
173
- console.log('No AI clients detected.')
174
- console.log('Install Claude Desktop, Cursor, Windsurf, or VS Code and run this command again.\n')
175
- console.log('Or add this manually to your AI client config:')
176
- const manualEntry = stableArgs !== undefined
173
+ const entry = stableArgs !== undefined
177
174
  ? { command: stableCommand, args: stableArgs }
178
175
  : { command: stableCommand }
179
- console.log(JSON.stringify({ mcpServers: { 'local-mcp': manualEntry } }, null, 2))
176
+ const snippet = JSON.stringify({ mcpServers: { 'local-mcp': entry } }, null, 2)
177
+ .split('\n').map(l => ' ' + l).join('\n')
178
+
179
+ console.log('╔══════════════════════════════════════════════════════════╗')
180
+ console.log('║ LMCP installed — no AI client detected yet ║')
181
+ console.log('╚══════════════════════════════════════════════════════════╝\n')
182
+ console.log(' To get started, add LMCP to your AI client config:\n')
183
+ console.log(' ── Claude Desktop ────────────────────────────────────────')
184
+ console.log(' File: ~/Library/Application Support/Claude/claude_desktop_config.json\n')
185
+ console.log(snippet)
186
+ console.log('\n ── Cursor ────────────────────────────────────────────────')
187
+ console.log(' File: ~/.cursor/mcp.json\n')
188
+ console.log(snippet)
189
+ console.log('\n ── VS Code (Cline / GitHub Copilot) ──────────────────────')
190
+ console.log(' File: ~/.vscode/mcp.json\n')
191
+ console.log(snippet)
192
+ console.log('\n Then restart your AI client and try:')
193
+ console.log(' "Summarize my unread emails"\n')
194
+ console.log(' ── Already installed an AI client? ───────────────────────')
195
+ console.log(' Run this to auto-configure it:')
196
+ console.log(' npx local-mcp setup\n')
197
+ console.log(' Full setup guide: https://local-mcp.com/setup')
198
+ console.log('─────────────────────────────────────────────────────────────\n')
180
199
  return
181
200
  }
182
201
 
@@ -215,27 +234,47 @@ async function runSetup(opts = {}) {
215
234
  // Health check — verify binary works before showing success
216
235
  const healthOk = _runHealthCheck()
217
236
 
237
+ const hasCursor = configured.includes('Cursor')
238
+
218
239
  console.log('\n──────────────────────────────────────')
219
240
  if (configured.length > 0) {
220
241
  if (healthOk) {
221
242
  console.log(`✅ LMCP configured for: ${configured.join(', ')}\n`)
222
- console.log(' ✓ Server binary verified — 82 tools ready\n')
243
+ console.log(' ✓ Server binary verified — 95 tools ready\n')
223
244
  } else {
224
245
  console.log(`⚠ LMCP configured for: ${configured.join(', ')}`)
225
246
  console.log(' Server binary could not be verified — it may still work after restart.\n')
226
247
  }
227
- console.log('┌─────────────────────────────────────────────────────┐')
228
- console.log('│ NEXT STEP — This is important: │')
229
- console.log('│ │')
230
- console.log(`│ Quit and reopen ${configured[0].padEnd(35)}│`)
231
- console.log('│ LMCP will appear automatically. │')
232
- console.log('│ │')
233
- console.log('│ Then try: "Summarize my unread emails" │')
234
- console.log('└─────────────────────────────────────────────────────┘\n')
248
+
249
+ if (hasCursor) {
250
+ console.log('┌─────────────────────────────────────────────────────┐')
251
+ console.log('│ CURSOR 3 steps to activate: │')
252
+ console.log('│ │')
253
+ console.log('│ 1. Quit Cursor completely (Cmd+Q) │')
254
+ console.log('│ 2. Reopen Cursor │')
255
+ console.log('│ 3. Cursor Settings (⚙) → MCP → find "local-mcp" │')
256
+ console.log('│ → toggle it ON if not already enabled │')
257
+ console.log('│ │')
258
+ console.log('│ Then ask: "Summarize my unread emails" │')
259
+ console.log('│ │')
260
+ console.log('│ Guide: local-mcp.com/guides/cursor-mcp-setup │')
261
+ console.log('└─────────────────────────────────────────────────────┘\n')
262
+ } else {
263
+ const primaryClient = configured[0]
264
+ console.log('┌─────────────────────────────────────────────────────┐')
265
+ console.log('│ NEXT STEP — This is important: │')
266
+ console.log('│ │')
267
+ console.log(`│ Quit and reopen ${primaryClient.padEnd(35)}│`)
268
+ console.log('│ LMCP will appear automatically. │')
269
+ console.log('│ │')
270
+ console.log('│ Then try: "Summarize my unread emails" │')
271
+ console.log('└─────────────────────────────────────────────────────┘\n')
272
+ }
235
273
  }
236
274
  if (failed.length > 0) {
237
275
  console.log(`⚠ Could not configure: ${failed.join(', ')} — check permissions and try again.\n`)
238
276
  }
277
+ console.log(' Setup guide & troubleshooting: https://local-mcp.com/setup\n')
239
278
 
240
279
  // Instalar y lanzar el tray (menu bar app) — arm64 only, non-fatal
241
280
  await _installTray()