screenpipe-mcp 0.16.2 → 0.16.3

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/dist/index.js +19 -13
  2. package/package.json +1 -1
  3. package/src/index.ts +17 -11
package/dist/index.js CHANGED
@@ -63,29 +63,35 @@ function discoverApiKey() {
63
63
  const fs = require("fs");
64
64
  const { execFileSync, execSync } = require("child_process");
65
65
  // Read api_auth_key directly from ~/.screenpipe/db.sqlite.
66
- // The local API key is stored as base64 plaintext (nonce=zeros, not encrypted).
67
- // This is the most reliable method no PATH, no subprocess, no keychain.
66
+ // The key may be stored as plaintext base64 (nonce=zeros, keychain unavailable)
67
+ // or encrypted (non-zero nonce, keychain was available at write time).
68
+ // If plaintext: decode and return. If encrypted: skip, fall through to CLI.
68
69
  try {
69
70
  const dbPath = path.join(os.homedir(), ".screenpipe", "db.sqlite");
70
71
  if (fs.existsSync(dbPath)) {
71
- // Use sqlite3 CLI which is pre-installed on macOS/Linux
72
72
  const sqliteBin = process.platform === "win32" ? "sqlite3.exe" : "sqlite3";
73
- const result = execFileSync(sqliteBin, [
73
+ // Check nonce — all zeros means plaintext base64, non-zero means encrypted
74
+ const row = execFileSync(sqliteBin, [
74
75
  dbPath,
75
- "SELECT value FROM secrets WHERE key = 'api_auth_key';",
76
+ "SELECT hex(nonce), value FROM secrets WHERE key = 'api_auth_key';",
76
77
  ], {
77
78
  timeout: 5000,
78
79
  encoding: "utf-8",
79
80
  stdio: ["pipe", "pipe", "pipe"],
80
81
  }).trim();
81
- if (result) {
82
- // Value is base64-encoded — decode it
83
- const decoded = Buffer.from(result, "base64").toString("utf-8");
84
- if (decoded && decoded.startsWith("sp-"))
85
- return decoded;
86
- // If not base64 or not sp- prefixed, use raw value
87
- if (result.startsWith("sp-"))
88
- return result;
82
+ if (row) {
83
+ const sepIdx = row.indexOf("|");
84
+ const nonceHex = sepIdx >= 0 ? row.substring(0, sepIdx) : "";
85
+ const value = sepIdx >= 0 ? row.substring(sepIdx + 1) : row;
86
+ const isPlaintext = !nonceHex || /^0+$/.test(nonceHex);
87
+ if (isPlaintext && value) {
88
+ const decoded = Buffer.from(value, "base64").toString("utf-8");
89
+ if (decoded && decoded.startsWith("sp-"))
90
+ return decoded;
91
+ if (value.startsWith("sp-"))
92
+ return value;
93
+ }
94
+ // Non-zero nonce = encrypted — fall through to CLI which can decrypt via keychain
89
95
  }
90
96
  }
91
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenpipe-mcp",
3
- "version": "0.16.2",
3
+ "version": "0.16.3",
4
4
  "description": "MCP server for screenpipe - search your screen recordings and audio transcriptions",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -39,27 +39,33 @@ function discoverApiKey(): string {
39
39
  const { execFileSync, execSync } = require("child_process");
40
40
 
41
41
  // Read api_auth_key directly from ~/.screenpipe/db.sqlite.
42
- // The local API key is stored as base64 plaintext (nonce=zeros, not encrypted).
43
- // This is the most reliable method no PATH, no subprocess, no keychain.
42
+ // The key may be stored as plaintext base64 (nonce=zeros, keychain unavailable)
43
+ // or encrypted (non-zero nonce, keychain was available at write time).
44
+ // If plaintext: decode and return. If encrypted: skip, fall through to CLI.
44
45
  try {
45
46
  const dbPath = path.join(os.homedir(), ".screenpipe", "db.sqlite");
46
47
  if (fs.existsSync(dbPath)) {
47
- // Use sqlite3 CLI which is pre-installed on macOS/Linux
48
48
  const sqliteBin = process.platform === "win32" ? "sqlite3.exe" : "sqlite3";
49
- const result = execFileSync(sqliteBin, [
49
+ // Check nonce — all zeros means plaintext base64, non-zero means encrypted
50
+ const row = execFileSync(sqliteBin, [
50
51
  dbPath,
51
- "SELECT value FROM secrets WHERE key = 'api_auth_key';",
52
+ "SELECT hex(nonce), value FROM secrets WHERE key = 'api_auth_key';",
52
53
  ], {
53
54
  timeout: 5000,
54
55
  encoding: "utf-8",
55
56
  stdio: ["pipe", "pipe", "pipe"],
56
57
  }).trim();
57
- if (result) {
58
- // Value is base64-encoded — decode it
59
- const decoded = Buffer.from(result, "base64").toString("utf-8");
60
- if (decoded && decoded.startsWith("sp-")) return decoded;
61
- // If not base64 or not sp- prefixed, use raw value
62
- if (result.startsWith("sp-")) return result;
58
+ if (row) {
59
+ const sepIdx = row.indexOf("|");
60
+ const nonceHex = sepIdx >= 0 ? row.substring(0, sepIdx) : "";
61
+ const value = sepIdx >= 0 ? row.substring(sepIdx + 1) : row;
62
+ const isPlaintext = !nonceHex || /^0+$/.test(nonceHex);
63
+ if (isPlaintext && value) {
64
+ const decoded = Buffer.from(value, "base64").toString("utf-8");
65
+ if (decoded && decoded.startsWith("sp-")) return decoded;
66
+ if (value.startsWith("sp-")) return value;
67
+ }
68
+ // Non-zero nonce = encrypted — fall through to CLI which can decrypt via keychain
63
69
  }
64
70
  }
65
71
  } catch {}