@cachly-dev/mcp-server 0.5.16 → 0.5.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cachly-dev/mcp-server",
3
- "version": "0.5.16",
3
+ "version": "0.5.18",
4
4
  "mcpName": "io.github.cachly-dev/mcp-server",
5
5
  "description": "AI memory brain for Claude Code, Cursor, Copilot & Windsurf — persistent sessions, lessons learned, semantic search, team brain. 38 MCP tools.",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -52,6 +52,7 @@ import { Redis } from 'ioredis';
52
52
  const API_URL = process.env.CACHLY_API_URL ?? 'https://api.cachly.dev';
53
53
  const JWT = process.env.CACHLY_JWT ?? '';
54
54
  const EMBED_MODEL = process.env.CACHLY_EMBED_MODEL ?? '';
55
+ const CURRENT_VERSION = '0.5.17';
55
56
  /**
56
57
  * ┌──────────────────────────────────────────────────────────────────────┐
57
58
  * │ EMBEDDING PROVIDER — pluggable, client-side first │
@@ -1865,9 +1866,32 @@ function buildConnectionString(inst: Instance): string {
1865
1866
  return `${scheme}://${pw}${inst.host}:${inst.port}`;
1866
1867
  }
1867
1868
 
1869
+ // Fires once per process when no JWT is set (anonymous, opt-out via CACHLY_NO_TELEMETRY=1)
1870
+ let _telemetryPingSent = false;
1871
+ async function sendAnonymousTelemetry(toolName: string): Promise<void> {
1872
+ if (_telemetryPingSent) return;
1873
+ if (process.env.CACHLY_NO_TELEMETRY === '1') return;
1874
+ _telemetryPingSent = true;
1875
+ // Detect editor from common env vars injected by IDE extensions
1876
+ const editor = process.env.CURSOR_TRACE_ID ? 'cursor'
1877
+ : process.env.WINDSURF_SESSION_ID ? 'windsurf'
1878
+ : process.env.GITHUB_COPILOT_WORKSPACE ? 'copilot'
1879
+ : process.env.CLAUDE_CODE_ENTRYPOINT ? 'claude'
1880
+ : 'unknown';
1881
+ try {
1882
+ await fetch(`${API_URL}/api/v1/telemetry/mcp`, {
1883
+ method: 'POST',
1884
+ headers: { 'Content-Type': 'application/json' },
1885
+ body: JSON.stringify({ event: 'first_call_no_jwt', version: CURRENT_VERSION, editor, tool: toolName }),
1886
+ signal: AbortSignal.timeout(3000),
1887
+ });
1888
+ } catch { /* fire-and-forget, never block the user */ }
1889
+ }
1890
+
1868
1891
  async function handleTool(name: string, args: Record<string, unknown>): Promise<string> {
1869
1892
  // Guard: if no JWT, return actionable onboarding message instead of HTTP 401
1870
1893
  if (!JWT) {
1894
+ void sendAnonymousTelemetry(name);
1871
1895
  return [
1872
1896
  '🧠 **cachly AI Brain — Setup required**',
1873
1897
  '',
@@ -4763,7 +4787,7 @@ async function handleBulkLockStream(name: string, args: Record<string, unknown>)
4763
4787
  // ── Server setup ──────────────────────────────────────────────────────────────
4764
4788
 
4765
4789
  const server = new Server(
4766
- { name: 'cachly-mcp', version: '0.4.0' },
4790
+ { name: 'cachly-mcp', version: CURRENT_VERSION },
4767
4791
  { capabilities: { tools: {} } }
4768
4792
  );
4769
4793
 
@@ -5100,7 +5124,21 @@ if (process.argv[2] === 'setup') {
5100
5124
  : editorsRaw.split(/[,\s]+/).map(s => s.toLowerCase()).filter(s => EDITOR_FILES[s]);
5101
5125
  console.log('');
5102
5126
 
5103
- // ── Step 4: Write editor configs ──────────────────────────────────────────
5127
+ // ── Step 4: Email opt-in ──────────────────────────────────────────────────
5128
+ console.log('Step 4: Stay in the loop (optional)');
5129
+ const email = await ask(' Email for release notes & tips? [Enter to skip]: ');
5130
+ if (email && email.includes('@')) {
5131
+ try {
5132
+ await fetch(`${API_URL}/api/newsletter/subscribe`, {
5133
+ method: 'POST', headers: { 'Content-Type': 'application/json' },
5134
+ body: JSON.stringify({ email: email.trim().toLowerCase(), source: 'mcp-setup' }),
5135
+ signal: AbortSignal.timeout(5000),
5136
+ });
5137
+ console.log('✅ Subscribed — you\'ll only hear from us when it matters.\n');
5138
+ } catch { console.log('⚠️ Could not subscribe (no internet?). Continuing...\n'); }
5139
+ } else { console.log(' Skipped.\n'); }
5140
+
5141
+ // ── Step 5: Write editor configs ──────────────────────────────────────────
5104
5142
  for (const editor of editorsToSetup) {
5105
5143
  const configFile = EDITOR_FILES[editor] ?? '.mcp.json';
5106
5144
  const configPath = resolve(cwd, configFile);
@@ -5109,7 +5147,7 @@ if (process.argv[2] === 'setup') {
5109
5147
  console.log(`✅ Written: ${configFile}`);
5110
5148
  }
5111
5149
 
5112
- // ── Step 5: CLAUDE.md (always — idempotent) ───────────────────────────────
5150
+ // ── Step 6: CLAUDE.md (always — idempotent) ───────────────────────────────
5113
5151
  const mdResult = await writeClaudeMd(cwd, instance.id);
5114
5152
  const mdLabel = mdResult === 'updated' ? '✅ Updated' : mdResult === 'appended' ? '✅ Appended to' : '✅ Written';
5115
5153
  console.log(`${mdLabel}: CLAUDE.md`);
@@ -5145,6 +5183,30 @@ if (!JWT) {
5145
5183
  );
5146
5184
  }
5147
5185
 
5186
+ // ── Update nudge (non-blocking, fire-and-forget) ─────────────────────────────
5187
+ // Check npm registry once per process start; if outdated, log to stderr so
5188
+ // the editor's MCP log shows an actionable one-liner. Skipped if opted out.
5189
+ if (!process.env.CACHLY_NO_UPDATE_CHECK) {
5190
+ (async () => {
5191
+ try {
5192
+ const res = await fetch(
5193
+ `https://registry.npmjs.org/@cachly-dev/mcp-server/latest`,
5194
+ { signal: AbortSignal.timeout(4000) },
5195
+ );
5196
+ if (res.ok) {
5197
+ const data = await res.json() as { version: string };
5198
+ const latest = data?.version ?? '';
5199
+ if (latest && latest !== CURRENT_VERSION) {
5200
+ process.stderr.write(
5201
+ `\n⚡ cachly update available: ${CURRENT_VERSION} → ${latest}\n` +
5202
+ ` Run: npx @cachly-dev/mcp-server@latest setup\n\n`,
5203
+ );
5204
+ }
5205
+ }
5206
+ } catch { /* ignore – network unavailable or timeout */ }
5207
+ })();
5208
+ }
5209
+
5148
5210
  const transport = new StdioServerTransport();
5149
5211
  await server.connect(transport);
5150
5212