local-mcp 3.0.16 → 3.0.18

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/index.js +39 -0
  2. package/package.json +1 -1
  3. package/setup.js +36 -0
package/index.js CHANGED
@@ -15,6 +15,41 @@ const { spawn, execFileSync, execSync } = require('child_process')
15
15
  const path = require('path')
16
16
  const os = require('os')
17
17
  const fs = require('fs')
18
+ const https = require('https')
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
+ }
18
53
 
19
54
  // Solo macOS
20
55
  if (process.platform !== 'darwin') {
@@ -97,6 +132,10 @@ async function main() {
97
132
  }
98
133
  // Version mismatch — fall through to download new binary
99
134
  process.stderr.write(`Updating LMCP server (${cachedVersion || '?'} → ${pkg.version})...\n`)
135
+ _pingFirstRun(true)
136
+ } else {
137
+ // No cached binary version → first run via default mode
138
+ _pingFirstRun(false)
100
139
  }
101
140
  if (stat.isSymbolicLink()) fs.unlinkSync(stableBin)
102
141
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-mcp",
3
- "version": "3.0.16",
3
+ "version": "3.0.18",
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
@@ -116,6 +116,22 @@ async function runSetup(opts = {}) {
116
116
  const refArg = process.argv.find(a => a.startsWith('--ref='))
117
117
  if (refArg) process.env.LMCP_REF = refArg.split('=')[1]
118
118
 
119
+ // Mark cloud→local pre-token as "started" if present (fire-and-forget)
120
+ const _preToken = process.env.LMCP_PRE_TOKEN || ''
121
+ if (_preToken.startsWith('lmcp-pre-')) {
122
+ try {
123
+ const https = require('https')
124
+ const req = https.request({
125
+ hostname: 'office-mcp-production.up.railway.app',
126
+ path: `/install/started/${_preToken}`,
127
+ method: 'POST',
128
+ timeout: 3000,
129
+ })
130
+ req.on('error', () => {})
131
+ req.end()
132
+ } catch {}
133
+ }
134
+
119
135
  console.log('\n╔══════════════════════════════════════╗')
120
136
  console.log('║ LMCP — Setup Wizard ║')
121
137
  console.log('╚══════════════════════════════════════╝\n')
@@ -324,6 +340,26 @@ function _pingInstall(clients, method) {
324
340
  req.write(data)
325
341
  req.end()
326
342
 
343
+ // Claim pre-token if present (cloud connector → install attribution)
344
+ const preToken = process.env.LMCP_PRE_TOKEN || ''
345
+ if (preToken && preToken.startsWith('lmcp-pre-')) {
346
+ const pingData = JSON.stringify({
347
+ pre_token: preToken,
348
+ version: pkg.version,
349
+ os_version: require('os').release(),
350
+ })
351
+ const pingReq = https.request({
352
+ hostname: 'office-mcp-production.up.railway.app',
353
+ path: '/install/ping',
354
+ method: 'POST',
355
+ headers: { 'Content-Type': 'application/json', 'Content-Length': pingData.length },
356
+ timeout: 5000,
357
+ })
358
+ pingReq.on('error', () => {})
359
+ pingReq.write(pingData)
360
+ pingReq.end()
361
+ }
362
+
327
363
  // Send initial heartbeat so the machine appears as "activated" immediately
328
364
  // Even if the user doesn't restart their AI client right away
329
365
  const hb = JSON.stringify({