local-mcp 3.0.376 → 3.0.378
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 +31 -7
- package/index.js +34 -3
- package/package.json +1 -1
package/download.js
CHANGED
|
@@ -145,15 +145,22 @@ function _resetWinHardwareIdCacheForTests() {
|
|
|
145
145
|
_winHardwareIdCache = undefined
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
// deps existe SOLO como costura de test (#1705): los 8 tests de orden ejercitaban
|
|
149
|
+
// _probeWinHardwareId y el cache por separado, nunca los tres juntos por acá, asi
|
|
150
|
+
// que invertir la prioridad hardware-antes-que-cache —la decision irreversible de
|
|
151
|
+
// machineid.go— los pasaba a todos en verde. Sin argumentos se comporta igual que
|
|
152
|
+
// antes; ningun caller de produccion pasa deps.
|
|
153
|
+
function _getMachineId(deps = {}) {
|
|
154
|
+
const platform = deps.platform || process.platform
|
|
155
|
+
const cacheDir = deps.cacheDir || CACHE_DIR
|
|
149
156
|
// QA override, checked before any platform probe — same rank as go-server's
|
|
150
157
|
// Get() — so a smoke-* run stays a smoke-* run on every code path that
|
|
151
158
|
// reports machine_id, not just the ones that already remembered to check it.
|
|
152
159
|
const envId = (process.env.LMCP_MACHINE_ID || '').trim()
|
|
153
160
|
if (envId) return envId
|
|
154
161
|
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
162
|
+
const execSync = deps.execImpl || require('child_process').execSync
|
|
163
|
+
if (platform === 'darwin') {
|
|
157
164
|
try {
|
|
158
165
|
const r = execSync('security find-generic-password -s com.local-mcp.machine-id -a machine-id -w 2>/dev/null', { stdio: 'pipe' })
|
|
159
166
|
const id = r.toString().trim()
|
|
@@ -164,17 +171,17 @@ function _getMachineId() {
|
|
|
164
171
|
const match = ioreg.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/)
|
|
165
172
|
if (match) return match[1]
|
|
166
173
|
} catch {}
|
|
167
|
-
} else if (
|
|
168
|
-
const hw = _probeWinHardwareId()
|
|
174
|
+
} else if (platform === 'win32') {
|
|
175
|
+
const hw = _probeWinHardwareId(execSync)
|
|
169
176
|
if (hw) {
|
|
170
|
-
_writeWinMachineIdCache(
|
|
177
|
+
_writeWinMachineIdCache(cacheDir, hw)
|
|
171
178
|
return hw
|
|
172
179
|
}
|
|
173
180
|
// Both probes failed or are blocked — fall back to whatever the go-server
|
|
174
181
|
// already cached rather than diverging to the hostname hash (the poisoned-
|
|
175
182
|
// cache case go-server's own Get() guards against does not apply here:
|
|
176
183
|
// this file is only ever written with a hardware-derived id, by either side).
|
|
177
|
-
const cached = _readWinMachineIdCache(
|
|
184
|
+
const cached = _readWinMachineIdCache(cacheDir)
|
|
178
185
|
if (cached) return cached
|
|
179
186
|
} else {
|
|
180
187
|
try {
|
|
@@ -208,6 +215,22 @@ function versionFromArtifactUrl(url, arch) {
|
|
|
208
215
|
return m ? m[1] : null
|
|
209
216
|
}
|
|
210
217
|
|
|
218
|
+
// La version contra la que ESTA plataforma tiene que compararse, sacada del
|
|
219
|
+
// mismo manifiesto. Existe porque `info.version` es la linea de Mac: usarla en
|
|
220
|
+
// Windows/Linux compara dos series distintas, que es lo que fastPathVersionOK ya
|
|
221
|
+
// se niega a hacer en el fast path (#1394 §C).
|
|
222
|
+
//
|
|
223
|
+
// Devuelve null cuando no se puede determinar — sin artefacto para la
|
|
224
|
+
// plataforma, o con un nombre que no parsea. El llamador NO debe caer a
|
|
225
|
+
// info.version: preferimos no decidir antes que decidir sobre un numero que
|
|
226
|
+
// describe otra plataforma.
|
|
227
|
+
function latestVersionForPlatform(info, arch) {
|
|
228
|
+
if (!info) return null
|
|
229
|
+
if (String(arch).startsWith('darwin')) return info.version || null
|
|
230
|
+
const url = info[String(arch).replace('-', '_')]
|
|
231
|
+
return url ? versionFromArtifactUrl(url, arch) : null
|
|
232
|
+
}
|
|
233
|
+
|
|
211
234
|
/**
|
|
212
235
|
* Obtiene la versión más reciente del binario desde el backend.
|
|
213
236
|
* Si esta máquina está en beta_machines, el backend retorna la versión beta.
|
|
@@ -700,6 +723,7 @@ async function ensureSlackProxy(platform = process.platform) {
|
|
|
700
723
|
|
|
701
724
|
module.exports = {
|
|
702
725
|
ensureBinary, ensureRuntime, ensureTray, ensureTeamsProxy, ensureSlackProxy, versionFromArtifactUrl,
|
|
726
|
+
latestVersionForPlatform, getArch,
|
|
703
727
|
CACHE_DIR, TRAY_DIR, _getMachineId,
|
|
704
728
|
_probeWinHardwareId, _resetWinHardwareIdCacheForTests,
|
|
705
729
|
_readWinMachineIdCache, _writeWinMachineIdCache, WIN_MACHINE_ID_CACHE_NAME,
|
package/index.js
CHANGED
|
@@ -62,6 +62,32 @@ function fastPathVersionOK(platform, cachedVersion, pkgVersion) {
|
|
|
62
62
|
return true
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Whether the 24h background check should download a newer binary.
|
|
67
|
+
*
|
|
68
|
+
* fastPathVersionOK (arriba) declara que en Windows/Linux la version cacheada y
|
|
69
|
+
* `info.version` son series distintas por construccion, se niega a compararlas,
|
|
70
|
+
* y delega en "the 24h background check below". Ese chequeo hacia exactamente la
|
|
71
|
+
* comparacion declarada invalida: `semverGte(cachedVersion, info.version)`, con
|
|
72
|
+
* info.version = la release de MAC.
|
|
73
|
+
*
|
|
74
|
+
* Medido el 2026-08-27: las 21 Windows de la flota corrian 3.0.401 con 3.0.402
|
|
75
|
+
* publicado y Mac en 3.0.377. semverGte('3.0.401','3.0.377') es true, asi que
|
|
76
|
+
* ninguna se enteraba del update — en silencio. Y cuando la linea de Mac pasa a
|
|
77
|
+
* la de Windows, la misma cuenta se da vuelta y actualiza lo que ya esta al dia.
|
|
78
|
+
*
|
|
79
|
+
* Sin version resoluble para la plataforma NO se actualiza: fail-closed, el
|
|
80
|
+
* mismo criterio que download.js ("we FAIL rather than fall back to
|
|
81
|
+
* info.version").
|
|
82
|
+
*/
|
|
83
|
+
function backgroundUpdateNeeded(cachedVersion, info, arch) {
|
|
84
|
+
if (!cachedVersion) return false
|
|
85
|
+
const { latestVersionForPlatform } = require('./download')
|
|
86
|
+
const latest = latestVersionForPlatform(info, arch)
|
|
87
|
+
if (!latest) return false
|
|
88
|
+
return !semverGte(cachedVersion, latest)
|
|
89
|
+
}
|
|
90
|
+
|
|
65
91
|
/**
|
|
66
92
|
* PIDs of the lmcp/local-mcp servers running right now, or null when the answer
|
|
67
93
|
* cannot be determined.
|
|
@@ -557,8 +583,13 @@ async function main() {
|
|
|
557
583
|
res.on('data', c => buf += c)
|
|
558
584
|
res.on('end', () => {
|
|
559
585
|
try {
|
|
560
|
-
const
|
|
561
|
-
|
|
586
|
+
const info = JSON.parse(buf)
|
|
587
|
+
const { latestVersionForPlatform, getArch } = require('./download')
|
|
588
|
+
const _arch = getArch()
|
|
589
|
+
// El nombre que se escribe en .server-version si hay que bajar:
|
|
590
|
+
// el de ESTA plataforma, no el de la release de Mac.
|
|
591
|
+
const latestVersion = latestVersionForPlatform(info, _arch)
|
|
592
|
+
if (backgroundUpdateNeeded(_cachedVersion, info, _arch)) {
|
|
562
593
|
// New version available — download for next restart only while no server is running.
|
|
563
594
|
// Replacing stableBin mid-session changes its mtime and used to cause sibling
|
|
564
595
|
// stdio proxies to be SIGTERM'd → Cursor transport_closed (LMCA-1044).
|
|
@@ -644,4 +675,4 @@ if (require.main === module) {
|
|
|
644
675
|
})
|
|
645
676
|
}
|
|
646
677
|
|
|
647
|
-
module.exports = { semverGte, fastPathVersionOK, listRunningServerPids, countRunningServers, safeToReplaceBinary, replaceCachedBinary }
|
|
678
|
+
module.exports = { semverGte, fastPathVersionOK, backgroundUpdateNeeded, listRunningServerPids, countRunningServers, safeToReplaceBinary, replaceCachedBinary }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-mcp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.378",
|
|
4
4
|
"description": "Let ChatGPT, Claude, Cursor & any MCP client actually use your Mac — read & reply to email, manage your calendar, text over iMessage, find files, work with Teams, Slack & Office. On your Mac, no API keys, free.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|