fathom-mcp 0.5.13 → 0.5.14
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 +3 -2
- package/src/agents.js +1 -1
- package/src/cli.js +5 -0
- package/src/config.js +1 -1
- package/src/index.js +28 -1
- package/src/server-client.js +9 -0
- package/src/ws-connection.js +17 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fathom-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.14",
|
|
4
4
|
"description": "MCP server for Fathom — vault operations, search, rooms, and cross-workspace communication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"main": "src/index.js",
|
|
10
10
|
"files": [
|
|
11
11
|
"src/",
|
|
12
|
-
"scripts
|
|
12
|
+
"scripts/*.sh",
|
|
13
|
+
"scripts/*.py",
|
|
13
14
|
"fathom-agents.md",
|
|
14
15
|
"README.md",
|
|
15
16
|
"CHANGELOG.md",
|
package/src/agents.js
CHANGED
|
@@ -9,7 +9,7 @@ import fs from "fs";
|
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { execSync, execFileSync } from "child_process";
|
|
11
11
|
|
|
12
|
-
const CONFIG_DIR = path.join(process.env.HOME || "/tmp", ".config", "fathom-mcp");
|
|
12
|
+
const CONFIG_DIR = process.env.FATHOM_CONFIG_DIR || path.join(process.env.HOME || "/tmp", ".config", "fathom-mcp");
|
|
13
13
|
const AGENTS_FILE = path.join(CONFIG_DIR, "agents.json");
|
|
14
14
|
|
|
15
15
|
const EMPTY_CONFIG = { version: 1, agents: {} };
|
package/src/cli.js
CHANGED
|
@@ -584,6 +584,11 @@ async function runInit(flags = {}) {
|
|
|
584
584
|
}
|
|
585
585
|
}
|
|
586
586
|
|
|
587
|
+
// Register in CLI agent registry (for ls/start/stop)
|
|
588
|
+
const entry = buildEntryFromConfig(cwd, configData);
|
|
589
|
+
registryAddAgent(workspace, entry);
|
|
590
|
+
console.log(` ✓ Registered agent "${workspace}" in CLI registry`);
|
|
591
|
+
|
|
587
592
|
// Context-aware next steps
|
|
588
593
|
console.log(`\n Done! Fathom MCP is configured for workspace "${workspace}".`);
|
|
589
594
|
console.log(` Vault mode: ${vaultMode}`);
|
package/src/config.js
CHANGED
package/src/index.js
CHANGED
|
@@ -483,6 +483,26 @@ const telegramTools = [
|
|
|
483
483
|
},
|
|
484
484
|
];
|
|
485
485
|
|
|
486
|
+
// --- Primary-agent-only tools (policy gate) ----------------------------------
|
|
487
|
+
|
|
488
|
+
const primaryAgentTools = [
|
|
489
|
+
{
|
|
490
|
+
name: "fathom_session_inject",
|
|
491
|
+
description:
|
|
492
|
+
"Inject a keystroke into a workspace's tmux session. Primary agent only. " +
|
|
493
|
+
"Used by the policy gate to respond to permission prompts. " +
|
|
494
|
+
"Keys must be a single digit 1-9 (to select a numbered option) or a named key (Enter, Escape).",
|
|
495
|
+
inputSchema: {
|
|
496
|
+
type: "object",
|
|
497
|
+
properties: {
|
|
498
|
+
workspace: { type: "string", description: "Target workspace name (e.g. 'navier-stokes')" },
|
|
499
|
+
keys: { type: "string", description: "Keys to send — single digit 1-9 or named key (Enter, Escape)" },
|
|
500
|
+
},
|
|
501
|
+
required: ["workspace", "keys"],
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
];
|
|
505
|
+
|
|
486
506
|
// --- Server setup & dispatch -------------------------------------------------
|
|
487
507
|
|
|
488
508
|
const server = new Server(
|
|
@@ -501,7 +521,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
501
521
|
} catch {
|
|
502
522
|
// If settings unavailable, hide telegram tools
|
|
503
523
|
}
|
|
504
|
-
const allTools = [...tools, ...(showTelegram ? telegramTools : [])];
|
|
524
|
+
const allTools = [...tools, ...(showTelegram ? [...telegramTools, ...primaryAgentTools] : [])];
|
|
505
525
|
return { tools: allTools };
|
|
506
526
|
});
|
|
507
527
|
|
|
@@ -797,6 +817,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
797
817
|
}
|
|
798
818
|
break;
|
|
799
819
|
}
|
|
820
|
+
// --- Session injection (policy gate) ---
|
|
821
|
+
case "fathom_session_inject": {
|
|
822
|
+
if (!args.workspace) { result = { error: "workspace is required" }; break; }
|
|
823
|
+
if (!args.keys) { result = { error: "keys is required" }; break; }
|
|
824
|
+
result = await client.injectKeys(args.workspace, args.keys);
|
|
825
|
+
break;
|
|
826
|
+
}
|
|
800
827
|
case "fathom_telegram_send_voice": {
|
|
801
828
|
const voiceContactArg = args.contact;
|
|
802
829
|
if (!voiceContactArg) { result = { error: "contact is required" }; break; }
|
package/src/server-client.js
CHANGED
|
@@ -298,6 +298,14 @@ export function createClient(config) {
|
|
|
298
298
|
});
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
// --- Session injection (policy gate) ----------------------------------------
|
|
302
|
+
|
|
303
|
+
async function injectKeys(targetWorkspace, keys) {
|
|
304
|
+
return request("POST", `/api/session/${encodeURIComponent(targetWorkspace)}/inject`, {
|
|
305
|
+
body: { keys },
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
301
309
|
// --- Settings --------------------------------------------------------------
|
|
302
310
|
|
|
303
311
|
async function getSettings() {
|
|
@@ -361,6 +369,7 @@ export function createClient(config) {
|
|
|
361
369
|
telegramSendVoice,
|
|
362
370
|
telegramStatus,
|
|
363
371
|
speak,
|
|
372
|
+
injectKeys,
|
|
364
373
|
getSettings,
|
|
365
374
|
getApiKey,
|
|
366
375
|
rotateKey,
|
package/src/ws-connection.js
CHANGED
|
@@ -54,14 +54,20 @@ export function createWSConnection(config) {
|
|
|
54
54
|
function connect() {
|
|
55
55
|
if (closed) return;
|
|
56
56
|
|
|
57
|
+
// Redact token from URL for logging
|
|
58
|
+
const redactedUrl = wsUrl.replace(/token=[^&]+/, "token=***");
|
|
59
|
+
console.error(`[ws] connecting to ${redactedUrl}`);
|
|
60
|
+
|
|
57
61
|
try {
|
|
58
62
|
ws = new WebSocket(wsUrl);
|
|
59
|
-
} catch {
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error(`[ws] connection constructor failed: ${err.message}`);
|
|
60
65
|
scheduleReconnect();
|
|
61
66
|
return;
|
|
62
67
|
}
|
|
63
68
|
|
|
64
69
|
ws.on("open", () => {
|
|
70
|
+
console.error(`[ws] connected — sending hello (agent=${agent}, vault_mode=${vaultMode})`);
|
|
65
71
|
reconnectDelay = INITIAL_RECONNECT_MS;
|
|
66
72
|
|
|
67
73
|
// Send hello handshake
|
|
@@ -85,10 +91,12 @@ export function createWSConnection(config) {
|
|
|
85
91
|
|
|
86
92
|
switch (msg.type) {
|
|
87
93
|
case "welcome":
|
|
94
|
+
console.error(`[ws] welcome received — connection established for workspace=${workspace}`);
|
|
88
95
|
break;
|
|
89
96
|
|
|
90
97
|
case "inject":
|
|
91
98
|
case "ping_fire":
|
|
99
|
+
console.error(`[ws] received ${msg.type} (${(msg.text || "").length} chars)`);
|
|
92
100
|
injectMessage(msg.text || "");
|
|
93
101
|
break;
|
|
94
102
|
|
|
@@ -101,18 +109,21 @@ export function createWSConnection(config) {
|
|
|
101
109
|
break;
|
|
102
110
|
|
|
103
111
|
case "error":
|
|
112
|
+
console.error(`[ws] server error: ${msg.message || JSON.stringify(msg)}`);
|
|
104
113
|
// Server rejected us — don't reconnect immediately
|
|
105
114
|
reconnectDelay = MAX_RECONNECT_MS;
|
|
106
115
|
break;
|
|
107
116
|
}
|
|
108
117
|
});
|
|
109
118
|
|
|
110
|
-
ws.on("close", () => {
|
|
119
|
+
ws.on("close", (code, reason) => {
|
|
120
|
+
console.error(`[ws] closed (code=${code}, reason=${reason || "none"})`);
|
|
111
121
|
stopKeepalive();
|
|
112
122
|
if (!closed) scheduleReconnect();
|
|
113
123
|
});
|
|
114
124
|
|
|
115
|
-
ws.on("error", () => {
|
|
125
|
+
ws.on("error", (err) => {
|
|
126
|
+
console.error(`[ws] error: ${err.message}`);
|
|
116
127
|
// Error always followed by close event — reconnect handled there
|
|
117
128
|
stopKeepalive();
|
|
118
129
|
});
|
|
@@ -144,6 +155,7 @@ export function createWSConnection(config) {
|
|
|
144
155
|
|
|
145
156
|
function scheduleReconnect() {
|
|
146
157
|
if (closed) return;
|
|
158
|
+
console.error(`[ws] reconnecting in ${reconnectDelay}ms`);
|
|
147
159
|
setTimeout(connect, reconnectDelay);
|
|
148
160
|
reconnectDelay = Math.min(reconnectDelay * 2, MAX_RECONNECT_MS);
|
|
149
161
|
}
|
|
@@ -177,8 +189,8 @@ export function createWSConnection(config) {
|
|
|
177
189
|
timeout: 5000,
|
|
178
190
|
stdio: "ignore",
|
|
179
191
|
});
|
|
180
|
-
} catch {
|
|
181
|
-
|
|
192
|
+
} catch (err) {
|
|
193
|
+
console.error(`[ws] tmux inject failed for ${pane}: ${err.message}`);
|
|
182
194
|
}
|
|
183
195
|
}
|
|
184
196
|
|