local-mcp 3.0.113 → 3.0.114
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/index.js +39 -35
- package/package.json +1 -1
- package/setup.js +3 -16
package/index.js
CHANGED
|
@@ -17,39 +17,6 @@ const os = require('os')
|
|
|
17
17
|
const fs = require('fs')
|
|
18
18
|
const https = require('https')
|
|
19
19
|
|
|
20
|
-
// Track first run / version change so analytics catch users who launch
|
|
21
|
-
// via `npx local-mcp` without going through `setup` (manual MCP config).
|
|
22
|
-
function _pingFirstRun(versionChanged) {
|
|
23
|
-
try {
|
|
24
|
-
const pkg = require('./package.json')
|
|
25
|
-
const machineId = (() => {
|
|
26
|
-
try {
|
|
27
|
-
const out = execSync("system_profiler SPHardwareDataType 2>/dev/null | awk '/Hardware UUID/ { print $3 }'", { encoding: 'utf8' }).trim()
|
|
28
|
-
return out || ''
|
|
29
|
-
} catch { return '' }
|
|
30
|
-
})()
|
|
31
|
-
const data = JSON.stringify({
|
|
32
|
-
version: pkg.version,
|
|
33
|
-
os_version: os.release(),
|
|
34
|
-
arch: process.arch,
|
|
35
|
-
node_version: process.version,
|
|
36
|
-
method: 'npx-default',
|
|
37
|
-
machine_id: machineId,
|
|
38
|
-
source: process.env.LMCP_SOURCE || '',
|
|
39
|
-
ref: process.env.LMCP_REF || '',
|
|
40
|
-
})
|
|
41
|
-
const req = https.request({
|
|
42
|
-
hostname: 'office-mcp-production.up.railway.app',
|
|
43
|
-
path: '/install/npm',
|
|
44
|
-
method: 'POST',
|
|
45
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
|
|
46
|
-
timeout: 5000,
|
|
47
|
-
})
|
|
48
|
-
req.on('error', () => {})
|
|
49
|
-
req.write(data)
|
|
50
|
-
req.end()
|
|
51
|
-
} catch { /* fire and forget */ }
|
|
52
|
-
}
|
|
53
20
|
|
|
54
21
|
// Solo macOS
|
|
55
22
|
if (process.platform !== 'darwin') {
|
|
@@ -143,14 +110,51 @@ async function main() {
|
|
|
143
110
|
const child = spawn(stableBin, [], { stdio: 'inherit', env: process.env })
|
|
144
111
|
child.on('error', () => process.exit(1))
|
|
145
112
|
child.on('exit', (code) => process.exit(code ?? 0))
|
|
113
|
+
|
|
114
|
+
// Background update check — fires 10s after startup, at most once per 24h.
|
|
115
|
+
// Covers machines where the tray is dead and Sparkle can't update the binary.
|
|
116
|
+
const lastCheckFile = path.join(CACHE_DIR, '.last-update-check')
|
|
117
|
+
function _needsUpdateCheck() {
|
|
118
|
+
try { return Date.now() - parseInt(fs.readFileSync(lastCheckFile, 'utf8').trim(), 10) > 86400000 } catch { return true }
|
|
119
|
+
}
|
|
120
|
+
if (_needsUpdateCheck()) {
|
|
121
|
+
try { fs.writeFileSync(lastCheckFile, String(Date.now())) } catch {}
|
|
122
|
+
const _cachedVersion = cachedVersion // capture for closure
|
|
123
|
+
setTimeout(() => {
|
|
124
|
+
const req = https.get('https://office-mcp-production.up.railway.app/runtime/latest', { timeout: 8000 }, (res) => {
|
|
125
|
+
let buf = ''
|
|
126
|
+
res.on('data', c => buf += c)
|
|
127
|
+
res.on('end', () => {
|
|
128
|
+
try {
|
|
129
|
+
const { version: latestVersion } = JSON.parse(buf)
|
|
130
|
+
if (latestVersion && !semverGte(_cachedVersion, latestVersion)) {
|
|
131
|
+
// New version available — download silently for next restart
|
|
132
|
+
const { ensureRuntime } = require('./download')
|
|
133
|
+
ensureRuntime().then(({ binPath, version: downloadedVersion }) => {
|
|
134
|
+
try {
|
|
135
|
+
const tmpPath = stableBin + '.tmp'
|
|
136
|
+
fs.copyFileSync(binPath, tmpPath)
|
|
137
|
+
fs.chmodSync(tmpPath, 0o755)
|
|
138
|
+
try { execFileSync('codesign', ['--force', '--sign', '-', '--identifier', 'com.local-mcp.server', tmpPath], { stdio: 'pipe' }) } catch {}
|
|
139
|
+
fs.renameSync(tmpPath, stableBin)
|
|
140
|
+
fs.writeFileSync(versionFile, downloadedVersion || latestVersion)
|
|
141
|
+
} catch {}
|
|
142
|
+
}).catch(() => {})
|
|
143
|
+
}
|
|
144
|
+
} catch {}
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
req.on('error', () => {})
|
|
148
|
+
req.on('timeout', () => { try { req.destroy() } catch {} })
|
|
149
|
+
}, 10000)
|
|
150
|
+
}
|
|
151
|
+
|
|
146
152
|
return
|
|
147
153
|
}
|
|
148
154
|
// Cached binary is older than our npm package — download/update
|
|
149
155
|
process.stderr.write(`Updating LMCP server (${cachedVersion || '?'} → ${pkg.version})...\n`)
|
|
150
|
-
_pingFirstRun(true)
|
|
151
156
|
} else {
|
|
152
157
|
// No cached binary version → first run via default mode
|
|
153
|
-
_pingFirstRun(false)
|
|
154
158
|
}
|
|
155
159
|
if (stat.isSymbolicLink()) fs.unlinkSync(stableBin)
|
|
156
160
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-mcp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.114",
|
|
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
|
@@ -327,7 +327,9 @@ async function runSetup(opts = {}) {
|
|
|
327
327
|
} catch { /* non-fatal */ }
|
|
328
328
|
}
|
|
329
329
|
|
|
330
|
-
|
|
330
|
+
// LMCP_METHOD lets install.sh pass 'curl' so we can distinguish it from
|
|
331
|
+
// a direct 'npx local-mcp setup' invocation in the analytics.
|
|
332
|
+
_pingInstall(configured, process.env.LMCP_METHOD || opts.method || 'npx-setup', email)
|
|
331
333
|
}
|
|
332
334
|
|
|
333
335
|
async function _installTeamsProxy() {
|
|
@@ -576,21 +578,6 @@ function _autoLaunchClient(configured) {
|
|
|
576
578
|
return
|
|
577
579
|
}
|
|
578
580
|
|
|
579
|
-
// Log auto-launch event (fire-and-forget)
|
|
580
|
-
try {
|
|
581
|
-
const https = require('https')
|
|
582
|
-
const data = JSON.stringify({ event: 'install_auto_launch', client: clientName })
|
|
583
|
-
const req = https.request({
|
|
584
|
-
hostname: BACKEND_HOST,
|
|
585
|
-
path: '/install-event',
|
|
586
|
-
method: 'POST',
|
|
587
|
-
headers: { 'Content-Type': 'application/json', 'Content-Length': data.length },
|
|
588
|
-
timeout: 5000,
|
|
589
|
-
})
|
|
590
|
-
req.on('error', () => {})
|
|
591
|
-
req.write(data)
|
|
592
|
-
req.end()
|
|
593
|
-
} catch {}
|
|
594
581
|
}
|
|
595
582
|
|
|
596
583
|
module.exports = { runSetup, injectMcpConfig, CLIENTS }
|