grove-mcp 1.0.4 → 1.0.6
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/index.js +64 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -17,6 +17,10 @@
|
|
|
17
17
|
|
|
18
18
|
const https = require('https');
|
|
19
19
|
const readline = require('readline');
|
|
20
|
+
const crypto = require('crypto');
|
|
21
|
+
const fs = require('fs');
|
|
22
|
+
const path = require('path');
|
|
23
|
+
const os = require('os');
|
|
20
24
|
|
|
21
25
|
const HOSTNAME = 'mcp.lyra.tg';
|
|
22
26
|
const SSE_PATH = '/sse';
|
|
@@ -29,12 +33,64 @@ if (process.env.GROVE_OUTLINE_TOKEN)
|
|
|
29
33
|
TOKEN_HEADERS['Grove-Outline-Token'] = process.env.GROVE_OUTLINE_TOKEN;
|
|
30
34
|
if (process.env.GROVE_MATTERMOST_TOKEN)
|
|
31
35
|
TOKEN_HEADERS['Grove-Mattermost-Token'] = process.env.GROVE_MATTERMOST_TOKEN;
|
|
36
|
+
|
|
32
37
|
// Per-user session isolation: scopes Redis session keys so multiple users
|
|
33
38
|
// on the shared 3-pod cluster never overwrite each other's auth tokens.
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
// If GROVE_SESSION_KEY is set in the environment and is not the placeholder
|
|
40
|
+
// value, use it directly. Otherwise auto-generate a stable random key the
|
|
41
|
+
// first time and persist it to ~/.grove-mcp/session-key so that it survives
|
|
42
|
+
// restarts without any manual configuration.
|
|
43
|
+
(function resolveSessionKey() {
|
|
44
|
+
const PLACEHOLDER = '<your-session-key-here>';
|
|
45
|
+
const envKey = process.env.GROVE_SESSION_KEY;
|
|
46
|
+
|
|
47
|
+
if (envKey && envKey !== PLACEHOLDER) {
|
|
48
|
+
TOKEN_HEADERS['X-Grove-Session-Key'] = envKey;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const keyFile = path.join(os.homedir(), '.grove-mcp', 'session-key');
|
|
53
|
+
try {
|
|
54
|
+
const stored = fs.readFileSync(keyFile, 'utf8').trim();
|
|
55
|
+
if (stored) {
|
|
56
|
+
TOKEN_HEADERS['X-Grove-Session-Key'] = stored;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
} catch (_) {
|
|
60
|
+
// File doesn't exist yet — generate below.
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const generated = crypto.randomBytes(16).toString('hex');
|
|
64
|
+
try {
|
|
65
|
+
fs.mkdirSync(path.dirname(keyFile), { recursive: true });
|
|
66
|
+
fs.writeFileSync(keyFile, generated, { mode: 0o600 });
|
|
67
|
+
} catch (err) {
|
|
68
|
+
process.stderr.write(
|
|
69
|
+
`grove-mcp-bridge: warning: could not persist session key to ${keyFile}: ${err.message}\n`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
TOKEN_HEADERS['X-Grove-Session-Key'] = generated;
|
|
73
|
+
})();
|
|
74
|
+
|
|
75
|
+
// Strip MCP spec fields that older Claude Desktop clients don't handle.
|
|
76
|
+
// FastMCP 3.x auto-generates outputSchema from Python return type annotations;
|
|
77
|
+
// Claude Desktop silently drops ALL tools when it sees this field (claude-code#25081).
|
|
78
|
+
function stripMcpCompat(raw) {
|
|
79
|
+
try {
|
|
80
|
+
const msg = JSON.parse(raw);
|
|
81
|
+
if (msg.result && Array.isArray(msg.result.tools)) {
|
|
82
|
+
msg.result.tools = msg.result.tools.map(function (t) {
|
|
83
|
+
// eslint-disable-next-line no-unused-vars
|
|
84
|
+
var outputSchema = t.outputSchema, rest = Object.assign({}, t);
|
|
85
|
+
delete rest.outputSchema;
|
|
86
|
+
return rest;
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return JSON.stringify(msg);
|
|
90
|
+
} catch (_) {
|
|
91
|
+
return raw;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
38
94
|
|
|
39
95
|
let sessionPath = null;
|
|
40
96
|
let affinityCookie = null; // sticky-session cookie from SSE response headers
|
|
@@ -92,8 +148,10 @@ const sseReq = https.request(
|
|
|
92
148
|
for (const msg of pending) sendToServer(msg);
|
|
93
149
|
pending.length = 0;
|
|
94
150
|
} else if (eventType === 'message' && raw) {
|
|
95
|
-
//
|
|
96
|
-
|
|
151
|
+
// Strip modern MCP spec fields that cause Claude Desktop to silently
|
|
152
|
+
// drop all tools (anthropics/claude-code#25081): FastMCP 3.x emits
|
|
153
|
+
// outputSchema in tools/list which Claude Desktop doesn't understand.
|
|
154
|
+
process.stdout.write(stripMcpCompat(raw) + '\n');
|
|
97
155
|
}
|
|
98
156
|
|
|
99
157
|
eventType = '';
|