local-mcp 3.0.114 → 3.0.116
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 +47 -1
- package/index.js +5 -3
- package/package.json +1 -1
package/download.js
CHANGED
|
@@ -439,4 +439,50 @@ async function ensureHelper() {
|
|
|
439
439
|
}
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
-
|
|
442
|
+
/**
|
|
443
|
+
* Downloads local-mcp-jxa-runner on first install only.
|
|
444
|
+
* CRITICAL: never replaces an existing jxa-runner binary — the runner owns
|
|
445
|
+
* Automation (JXA) TCC grants for Mail, Messages, Safari, etc. via its cdhash.
|
|
446
|
+
* Replacing the binary silently resets those grants and users would have to
|
|
447
|
+
* re-authorize in System Settings → Privacy & Security → Automation.
|
|
448
|
+
* @returns {Promise<string|null>} Path to the binary, or null if it fails
|
|
449
|
+
*/
|
|
450
|
+
async function ensureJXARunner() {
|
|
451
|
+
const binPath = path.join(CACHE_DIR, 'local-mcp-jxa-runner')
|
|
452
|
+
|
|
453
|
+
// Already installed — never replace. Stable cdhash = stable TCC grants.
|
|
454
|
+
if (fs.existsSync(binPath)) return binPath
|
|
455
|
+
|
|
456
|
+
const info = await getLatestBinary()
|
|
457
|
+
const version = info.version
|
|
458
|
+
const arch = process.arch === 'arm64' ? 'darwin-arm64' : 'darwin-x64'
|
|
459
|
+
const url = `https://download.local-mcp.com/local-mcp-jxa-runner-${version}-${arch}.tar.gz`
|
|
460
|
+
process.stderr.write(`\nDownloading local-mcp-jxa-runner v${version}...\n`)
|
|
461
|
+
|
|
462
|
+
fs.mkdirSync(CACHE_DIR, { recursive: true })
|
|
463
|
+
const tarPath = path.join(CACHE_DIR, `local-mcp-jxa-runner-${version}.tar.gz`)
|
|
464
|
+
|
|
465
|
+
try {
|
|
466
|
+
await downloadFile(url, tarPath)
|
|
467
|
+
const stat = fs.statSync(tarPath)
|
|
468
|
+
if (stat.size < 1000) { fs.unlinkSync(tarPath); throw new Error(`Incomplete download (${stat.size} bytes)`) }
|
|
469
|
+
|
|
470
|
+
execFileSync('tar', ['-xzf', tarPath, '-C', CACHE_DIR], { stdio: 'pipe' })
|
|
471
|
+
fs.unlinkSync(tarPath)
|
|
472
|
+
|
|
473
|
+
if (!fs.existsSync(binPath)) throw new Error('local-mcp-jxa-runner not found after extraction')
|
|
474
|
+
fs.chmodSync(binPath, 0o755)
|
|
475
|
+
// Do NOT codesign: the pre-built binary's cdhash must remain exactly as
|
|
476
|
+
// distributed so the Automation TCC entry stays valid permanently.
|
|
477
|
+
|
|
478
|
+
fs.writeFileSync(path.join(CACHE_DIR, '.jxa-runner-version'), version, 'utf8')
|
|
479
|
+
process.stderr.write(` local-mcp-jxa-runner installed at ${binPath}\n`)
|
|
480
|
+
return binPath
|
|
481
|
+
} catch (err) {
|
|
482
|
+
try { if (fs.existsSync(tarPath)) fs.unlinkSync(tarPath) } catch {}
|
|
483
|
+
process.stderr.write(` (local-mcp-jxa-runner not available: ${err.message})\n`)
|
|
484
|
+
return null
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
module.exports = { ensureBinary, ensureRuntime, ensureTray, ensureTeamsProxy, ensureSlackProxy, ensureHelper, ensureJXARunner, CACHE_DIR, TRAY_DIR }
|
package/index.js
CHANGED
|
@@ -103,10 +103,11 @@ async function main() {
|
|
|
103
103
|
: ''
|
|
104
104
|
if (cachedVersion && semverGte(cachedVersion, pkg.version)) {
|
|
105
105
|
// Cached binary is same or newer — use fast path, no download needed
|
|
106
|
-
const { ensureTray, ensureTeamsProxy, ensureHelper } = require('./download')
|
|
106
|
+
const { ensureTray, ensureTeamsProxy, ensureHelper, ensureJXARunner } = require('./download')
|
|
107
107
|
ensureTray().catch(() => {})
|
|
108
108
|
ensureTeamsProxy().catch(() => {})
|
|
109
109
|
ensureHelper().catch(() => {})
|
|
110
|
+
ensureJXARunner().catch(() => {})
|
|
110
111
|
const child = spawn(stableBin, [], { stdio: 'inherit', env: process.env })
|
|
111
112
|
child.on('error', () => process.exit(1))
|
|
112
113
|
child.on('exit', (code) => process.exit(code ?? 0))
|
|
@@ -162,12 +163,13 @@ async function main() {
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// Slow path: download/repair binary
|
|
165
|
-
const { ensureRuntime, ensureTray, ensureTeamsProxy, ensureHelper } = require('./download')
|
|
166
|
+
const { ensureRuntime, ensureTray, ensureTeamsProxy, ensureHelper, ensureJXARunner } = require('./download')
|
|
166
167
|
|
|
167
|
-
// Update tray + proxies in background. Helper
|
|
168
|
+
// Update tray + proxies in background. Helper + jxa-runner downloaded only on first install.
|
|
168
169
|
ensureTray().catch(() => {})
|
|
169
170
|
ensureTeamsProxy().catch(() => {})
|
|
170
171
|
ensureHelper().catch(() => {})
|
|
172
|
+
ensureJXARunner().catch(() => {})
|
|
171
173
|
|
|
172
174
|
let runtime
|
|
173
175
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-mcp",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.116",
|
|
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": {
|