screenpipe-mcp 0.16.1 → 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.
- package/dist/index.js +36 -11
- package/package.json +1 -1
- package/src/index.ts +34 -10
package/dist/index.js
CHANGED
|
@@ -53,25 +53,50 @@ for (let i = 0; i < args.length; i++) {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
const SCREENPIPE_API = `http://localhost:${port}`;
|
|
56
|
-
// Discover API key: env var >
|
|
56
|
+
// Discover API key: env var > db.sqlite direct read > npx fallbacks
|
|
57
57
|
function discoverApiKey() {
|
|
58
58
|
const envKey = process.env.SCREENPIPE_LOCAL_API_KEY || process.env.SCREENPIPE_API_KEY;
|
|
59
59
|
if (envKey)
|
|
60
60
|
return envKey;
|
|
61
|
-
const
|
|
61
|
+
const os = require("os");
|
|
62
62
|
const path = require("path");
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
const fs = require("fs");
|
|
64
|
+
const { execFileSync, execSync } = require("child_process");
|
|
65
|
+
// Read api_auth_key directly from ~/.screenpipe/db.sqlite.
|
|
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.
|
|
65
69
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
const dbPath = path.join(os.homedir(), ".screenpipe", "db.sqlite");
|
|
71
|
+
if (fs.existsSync(dbPath)) {
|
|
72
|
+
const sqliteBin = process.platform === "win32" ? "sqlite3.exe" : "sqlite3";
|
|
73
|
+
// Check nonce — all zeros means plaintext base64, non-zero means encrypted
|
|
74
|
+
const row = execFileSync(sqliteBin, [
|
|
75
|
+
dbPath,
|
|
76
|
+
"SELECT hex(nonce), value FROM secrets WHERE key = 'api_auth_key';",
|
|
77
|
+
], {
|
|
78
|
+
timeout: 5000,
|
|
79
|
+
encoding: "utf-8",
|
|
80
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
81
|
+
}).trim();
|
|
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
|
|
95
|
+
}
|
|
96
|
+
}
|
|
70
97
|
}
|
|
71
98
|
catch { }
|
|
72
|
-
// Fallback: use the current Node binary to
|
|
73
|
-
// Claude Code and other MCP hosts may strip PATH, making bare `npx` unfindable.
|
|
74
|
-
// process.execPath is the absolute path to the Node binary running this MCP.
|
|
99
|
+
// Fallback: use the current Node binary to find npx (no PATH dependency)
|
|
75
100
|
try {
|
|
76
101
|
const npxPath = path.join(path.dirname(process.execPath), "npx");
|
|
77
102
|
const token = execFileSync(npxPath, ["screenpipe@latest", "auth", "token"], {
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -28,25 +28,49 @@ for (let i = 0; i < args.length; i++) {
|
|
|
28
28
|
|
|
29
29
|
const SCREENPIPE_API = `http://localhost:${port}`;
|
|
30
30
|
|
|
31
|
-
// Discover API key: env var >
|
|
31
|
+
// Discover API key: env var > db.sqlite direct read > npx fallbacks
|
|
32
32
|
function discoverApiKey(): string {
|
|
33
33
|
const envKey = process.env.SCREENPIPE_LOCAL_API_KEY || process.env.SCREENPIPE_API_KEY;
|
|
34
34
|
if (envKey) return envKey;
|
|
35
35
|
|
|
36
|
-
const
|
|
36
|
+
const os = require("os");
|
|
37
37
|
const path = require("path");
|
|
38
|
+
const fs = require("fs");
|
|
39
|
+
const { execFileSync, execSync } = require("child_process");
|
|
38
40
|
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
+
// Read api_auth_key directly from ~/.screenpipe/db.sqlite.
|
|
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.
|
|
41
45
|
try {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
const dbPath = path.join(os.homedir(), ".screenpipe", "db.sqlite");
|
|
47
|
+
if (fs.existsSync(dbPath)) {
|
|
48
|
+
const sqliteBin = process.platform === "win32" ? "sqlite3.exe" : "sqlite3";
|
|
49
|
+
// Check nonce — all zeros means plaintext base64, non-zero means encrypted
|
|
50
|
+
const row = execFileSync(sqliteBin, [
|
|
51
|
+
dbPath,
|
|
52
|
+
"SELECT hex(nonce), value FROM secrets WHERE key = 'api_auth_key';",
|
|
53
|
+
], {
|
|
54
|
+
timeout: 5000,
|
|
55
|
+
encoding: "utf-8",
|
|
56
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
57
|
+
}).trim();
|
|
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
|
|
69
|
+
}
|
|
70
|
+
}
|
|
45
71
|
} catch {}
|
|
46
72
|
|
|
47
|
-
// Fallback: use the current Node binary to
|
|
48
|
-
// Claude Code and other MCP hosts may strip PATH, making bare `npx` unfindable.
|
|
49
|
-
// process.execPath is the absolute path to the Node binary running this MCP.
|
|
73
|
+
// Fallback: use the current Node binary to find npx (no PATH dependency)
|
|
50
74
|
try {
|
|
51
75
|
const npxPath = path.join(path.dirname(process.execPath), "npx");
|
|
52
76
|
const token = execFileSync(npxPath, ["screenpipe@latest", "auth", "token"], {
|