local-mcp 3.0.82 → 3.0.83
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/README.md +1 -1
- package/package.json +1 -1
- package/setup.js +61 -5
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LMCP
|
|
2
2
|
|
|
3
|
-
> Give your AI assistant native access to Mac apps —
|
|
3
|
+
> Give your AI assistant native access to Mac apps — 106 tools for Mail, Calendar, Teams, OneDrive, and more. Everything runs locally. Your data never leaves your machine.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/local-mcp)
|
|
6
6
|
[](https://local-mcp.com?ref=npm)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-mcp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.83",
|
|
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
|
@@ -16,7 +16,8 @@ const { execSync, execFileSync } = require('child_process')
|
|
|
16
16
|
const HOME = os.homedir()
|
|
17
17
|
const NPX_COMMAND = 'npx'
|
|
18
18
|
const NPX_ARGS = ['-y', 'local-mcp@latest']
|
|
19
|
-
const STABLE_LINK
|
|
19
|
+
const STABLE_LINK = path.join(os.homedir(), '.local', 'share', 'local-mcp', 'bin', 'local-mcp-server')
|
|
20
|
+
const BACKEND_HOST = 'office-mcp-production.up.railway.app'
|
|
20
21
|
|
|
21
22
|
// ── Rutas de config de cada cliente ──────────────────────────────────────────
|
|
22
23
|
|
|
@@ -122,7 +123,7 @@ async function runSetup(opts = {}) {
|
|
|
122
123
|
try {
|
|
123
124
|
const https = require('https')
|
|
124
125
|
const req = https.request({
|
|
125
|
-
hostname:
|
|
126
|
+
hostname: BACKEND_HOST,
|
|
126
127
|
path: `/install/started/${_preToken}`,
|
|
127
128
|
method: 'POST',
|
|
128
129
|
timeout: 3000,
|
|
@@ -300,6 +301,9 @@ async function runSetup(opts = {}) {
|
|
|
300
301
|
await _installTeamsProxy()
|
|
301
302
|
await _installSlackProxy()
|
|
302
303
|
|
|
304
|
+
// Auto-launch primary configured AI client + show "Try this now" banner
|
|
305
|
+
_autoLaunchClient(configured)
|
|
306
|
+
|
|
303
307
|
// Interactive email prompt — only when running in a TTY and no email set yet
|
|
304
308
|
if (!email) {
|
|
305
309
|
const existingEmail = (() => {
|
|
@@ -470,7 +474,7 @@ function _pingInstall(clients, method, email = '') {
|
|
|
470
474
|
ref: _getRef(),
|
|
471
475
|
})
|
|
472
476
|
const req = https.request({
|
|
473
|
-
hostname:
|
|
477
|
+
hostname: BACKEND_HOST,
|
|
474
478
|
path: '/install/npm',
|
|
475
479
|
method: 'POST',
|
|
476
480
|
headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
|
|
@@ -489,7 +493,7 @@ function _pingInstall(clients, method, email = '') {
|
|
|
489
493
|
os_version: require('os').release(),
|
|
490
494
|
})
|
|
491
495
|
const pingReq = https.request({
|
|
492
|
-
hostname:
|
|
496
|
+
hostname: BACKEND_HOST,
|
|
493
497
|
path: '/install/ping',
|
|
494
498
|
method: 'POST',
|
|
495
499
|
headers: { 'Content-Type': 'application/json', 'Content-Length': pingData.length },
|
|
@@ -513,7 +517,7 @@ function _pingInstall(clients, method, email = '') {
|
|
|
513
517
|
started_at: new Date().toISOString(),
|
|
514
518
|
})
|
|
515
519
|
const hbReq = https.request({
|
|
516
|
-
hostname:
|
|
520
|
+
hostname: BACKEND_HOST,
|
|
517
521
|
path: '/heartbeat',
|
|
518
522
|
method: 'POST',
|
|
519
523
|
headers: { 'Content-Type': 'application/json', 'Content-Length': hb.length },
|
|
@@ -525,4 +529,56 @@ function _pingInstall(clients, method, email = '') {
|
|
|
525
529
|
} catch { /* no bloquear */ }
|
|
526
530
|
}
|
|
527
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Auto-launch the primary configured AI client and print a "Try this now" banner.
|
|
534
|
+
* Non-fatal — install succeeds even if open() fails.
|
|
535
|
+
*/
|
|
536
|
+
function _autoLaunchClient(configured) {
|
|
537
|
+
if (!configured || configured.length === 0) return
|
|
538
|
+
const appMap = {
|
|
539
|
+
'Claude Desktop': 'Claude',
|
|
540
|
+
'Cursor': 'Cursor',
|
|
541
|
+
'Windsurf': 'Windsurf',
|
|
542
|
+
'Zed': 'Zed',
|
|
543
|
+
'VS Code (Cline)': 'Visual Studio Code',
|
|
544
|
+
}
|
|
545
|
+
// Claude Code is a CLI tool — no app bundle to open
|
|
546
|
+
const launchOrder = ['Claude Desktop', 'Cursor', 'Windsurf', 'Zed', 'VS Code (Cline)']
|
|
547
|
+
let appName = null
|
|
548
|
+
let clientName = null
|
|
549
|
+
for (const name of launchOrder) {
|
|
550
|
+
if (configured.includes(name) && appMap[name]) {
|
|
551
|
+
appName = appMap[name]
|
|
552
|
+
clientName = name
|
|
553
|
+
break
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (!appName) return
|
|
557
|
+
|
|
558
|
+
try {
|
|
559
|
+
execFileSync('open', ['-a', appName], { stdio: 'pipe', timeout: 5000 })
|
|
560
|
+
console.log(`\n✅ LMCP is ready! ${clientName} is opening now.\n`)
|
|
561
|
+
console.log('Try asking Claude: "Read my last 3 emails and summarize them"\n')
|
|
562
|
+
} catch {
|
|
563
|
+
// open failed (app not installed or already open) — non-fatal
|
|
564
|
+
return
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Log auto-launch event (fire-and-forget)
|
|
568
|
+
try {
|
|
569
|
+
const https = require('https')
|
|
570
|
+
const data = JSON.stringify({ event: 'install_auto_launch', client: clientName })
|
|
571
|
+
const req = https.request({
|
|
572
|
+
hostname: BACKEND_HOST,
|
|
573
|
+
path: '/install-event',
|
|
574
|
+
method: 'POST',
|
|
575
|
+
headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
|
|
576
|
+
timeout: 5000,
|
|
577
|
+
})
|
|
578
|
+
req.on('error', () => {})
|
|
579
|
+
req.write(data)
|
|
580
|
+
req.end()
|
|
581
|
+
} catch {}
|
|
582
|
+
}
|
|
583
|
+
|
|
528
584
|
module.exports = { runSetup, injectMcpConfig, CLIENTS }
|