local-mcp 3.0.293 → 3.0.294

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/README.md +4 -4
  2. package/index.js +49 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # LMCP
2
2
 
3
- > Give your AI assistant native access to your apps — 161 local tools on macOS for Outlook, Mail, Calendar, Contacts, iMessage, Teams, Slack, WhatsApp, OneDrive, Google Drive, Zoom, Notion, Notes, Reminders, To Do, OmniFocus, Safari, Word, Excel, PowerPoint, Stocks, NordVPN, Microsoft 365, ServiceNow, Image Playground, and more. Everything runs locally. Your data never leaves your machine.
3
+ > Give your AI assistant native access to your apps — 159 local tools on macOS for Outlook, Mail, Calendar, Contacts, iMessage, Teams, Slack, WhatsApp, OneDrive, Google Drive, Zoom, Notion, Notes, Reminders, To Do, OmniFocus, Safari, Word, Excel, PowerPoint, Stocks, NordVPN, Microsoft 365, ServiceNow, Image Playground, and more. Everything runs locally. Your data never leaves your machine.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/local-mcp)](https://www.npmjs.com/package/local-mcp)
6
6
  [![macOS 13+](https://img.shields.io/badge/macOS-13%2B-blue)](https://local-mcp.com?ref=npm)
@@ -68,7 +68,7 @@ LMCP runs a native MCP server that bridges your Mac apps to any AI client:
68
68
  | **NordVPN** | Status, server recommendations, diagnostics |
69
69
  | **Image Playground** | Generate images on-device from a text prompt — Apple Intelligence, no cloud, no API key (requires macOS 15.4+) |
70
70
 
71
- ## 161 MCP Tools (macOS)
71
+ ## 159 MCP Tools (macOS)
72
72
 
73
73
  Email (10): `list_accounts` `list_email_accounts` `list_emails` `read_email` `send_email` `reply_email` `search_emails` `move_email` `save_attachment` `create_email_folder`
74
74
 
@@ -123,9 +123,9 @@ NordVPN (3): `nordvpn_status` `nordvpn_servers` `nordvpn_diagnose`
123
123
 
124
124
  Referral (2): `create_referral_invites` `list_referral_candidates`
125
125
 
126
- System (13): `lmcp_state` `get_config` `get_datetime` `daily_brief` `run_diagnostics` `run_qa` `get_audit_log` `update_local_mcp` `update_self_diagnosis` `report_problem` `request_feature` `signal_friction` `submit_qa_report`
126
+ System (11): `lmcp_state` `get_config` `get_datetime` `daily_brief` `run_diagnostics` `get_audit_log` `update_local_mcp` `update_self_diagnosis` `report_problem` `request_feature` `signal_friction`
127
127
 
128
- _Coming soon (not included in the 161 count above): **Evernote** (support is being rebuilt)._
128
+ _Coming soon (not included in the 159 count above): **Evernote** (support is being rebuilt)._
129
129
 
130
130
  ## Safety
131
131
 
package/index.js CHANGED
@@ -42,6 +42,28 @@ if (parseInt(process.version.slice(1)) < 16) {
42
42
 
43
43
  const cmd = process.argv[2]
44
44
 
45
+ // Detect a MANUAL uninstall — the user dragged LocalMCPTray.app to the Trash (by far the
46
+ // most common way to remove a Mac app) instead of running `npx local-mcp uninstall` or the
47
+ // tray's Uninstall button, so no `.uninstalled` sentinel was written. Signature: the tray
48
+ // WAS installed before (its LaunchAgent or version marker is still on disk) but the .app is
49
+ // now gone from both /Applications and ~/Applications. Without this, the next time an AI
50
+ // client respawns `npx local-mcp` from its in-memory config, ensureTray() silently
51
+ // re-downloads the .app and the machine comes back to life (FB-A30CDC; ~40% of uninstalls
52
+ // resurrected within minutes). A user who never had a tray (npm-only, first run) has no
53
+ // LaunchAgent/version marker, so this returns false for them — no false positive.
54
+ function detectManualUninstall() {
55
+ if (process.platform !== 'darwin') return false
56
+ const home = os.homedir()
57
+ const appPresent =
58
+ fs.existsSync(path.join(home, 'Applications', 'LocalMCPTray.app')) ||
59
+ fs.existsSync('/Applications/LocalMCPTray.app')
60
+ if (appPresent) return false
61
+ return (
62
+ fs.existsSync(path.join(home, 'Library', 'LaunchAgents', 'com.local-mcp.tray.plist')) ||
63
+ fs.existsSync(path.join(home, '.local', 'share', 'local-mcp', 'tray', '.version'))
64
+ )
65
+ }
66
+
45
67
  async function main() {
46
68
  if (cmd === 'setup') {
47
69
  // Clear uninstall sentinel — user explicitly wants to (re-)install
@@ -145,6 +167,33 @@ async function main() {
145
167
  }
146
168
  }
147
169
 
170
+ // ── Honor a MANUAL uninstall (.app trashed, no sentinel written) ────────────
171
+ // Same intent as the sentinel check above, for the common case where the user removes the
172
+ // app via the Trash instead of the uninstaller. Adopt it as an uninstall: write the
173
+ // sentinel (so future respawns short-circuit at the check above), remove the orphaned tray
174
+ // LaunchAgent (so launchd stops trying to relaunch a deleted app), and refuse to start —
175
+ // NOT ensureTray(), which would re-download and resurrect a machine the user removed
176
+ // (FB-A30CDC). The AI client's stale MCP config entry is left alone; it just respawns us
177
+ // and we short-circuit here, which is harmless.
178
+ {
179
+ const { CACHE_DIR: _cacheDir2 } = require('./download')
180
+ if (detectManualUninstall()) {
181
+ const sentinelDir = path.dirname(_cacheDir2)
182
+ try { fs.mkdirSync(sentinelDir, { recursive: true }) } catch {}
183
+ try { fs.writeFileSync(path.join(sentinelDir, '.uninstalled'), String(Date.now())) } catch {}
184
+ const trayPlist = path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.local-mcp.tray.plist')
185
+ if (fs.existsSync(trayPlist)) {
186
+ try { execSync(`launchctl unload -w "${trayPlist}" 2>/dev/null`, { stdio: 'pipe' }) } catch {}
187
+ try { fs.unlinkSync(trayPlist) } catch {}
188
+ }
189
+ process.stderr.write(
190
+ '[LMCP] LocalMCPTray.app was removed — treating it as an uninstall, not starting.\n' +
191
+ ' Reinstall: npx local-mcp setup\n'
192
+ )
193
+ process.exit(0)
194
+ }
195
+ }
196
+
148
197
  // ── Modo default: stdio MCP server ──────────────────────────────────────────
149
198
  const { CACHE_DIR } = require('./download')
150
199
  const binName = process.platform === 'win32' ? 'local-mcp-server.exe' : 'local-mcp-server'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "3.0.293",
3
+ "version": "3.0.294",
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": {