fathom-mcp 0.5.6 → 0.5.7

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": "fathom-mcp",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "MCP server for Fathom — vault operations, search, rooms, and cross-workspace communication",
5
5
  "type": "module",
6
6
  "bin": {
@@ -231,6 +231,9 @@ do_status() {
231
231
  echo "Status: running (headless)"
232
232
  echo "PID: $(cat "$PID_FILE")"
233
233
  echo "Log: $LOG_FILE"
234
+ if [[ -p "$PROJECT_DIR/.fathom/agent.pipe" ]]; then
235
+ echo "Pipe: $PROJECT_DIR/.fathom/agent.pipe"
236
+ fi
234
237
  else
235
238
  echo "Status: not running"
236
239
  fi
@@ -252,6 +255,15 @@ do_kill() {
252
255
  echo "Killed headless process: PID $pid"
253
256
  killed=true
254
257
  fi
258
+ # Clean up keeper process and FIFO
259
+ local keeper_pid_file="$PROJECT_DIR/.fathom/agent-keeper.pid"
260
+ if [[ -f "$keeper_pid_file" ]]; then
261
+ local keeper_pid
262
+ keeper_pid=$(cat "$keeper_pid_file")
263
+ kill "$keeper_pid" 2>/dev/null || true
264
+ rm -f "$keeper_pid_file"
265
+ fi
266
+ rm -f "$PROJECT_DIR/.fathom/agent.pipe"
255
267
  if [[ "$killed" == false ]]; then
256
268
  echo "No running session found for: $WORKSPACE"
257
269
  fi
@@ -262,7 +274,7 @@ do_start() {
262
274
  agent_cmd=$(resolve_agent_cmd)
263
275
 
264
276
  if [[ "$USE_TMUX" == false ]]; then
265
- # ── Headless mode — direct process, no tmux ──
277
+ # ── Headless mode — FIFO-based stdin ──
266
278
  if headless_is_running; then
267
279
  echo "Headless agent already running (PID $(cat "$PID_FILE"))"
268
280
  echo "Log: $LOG_FILE"
@@ -277,12 +289,28 @@ do_start() {
277
289
  unset CLAUDECODE 2>/dev/null || true
278
290
  mkdir -p .fathom
279
291
 
280
- # Run in background, log stdout/stderr
281
- nohup $agent_cmd >> "$LOG_FILE" 2>&1 &
292
+ local pipe_file="$PROJECT_DIR/.fathom/agent.pipe"
293
+
294
+ # Clean up stale pipe
295
+ rm -f "$pipe_file"
296
+ mkfifo "$pipe_file"
297
+
298
+ # Keep a writer FD open so the pipe never sends EOF to the reader.
299
+ # Without this, the agent reads EOF and exits when no writer is connected.
300
+ sleep infinity > "$pipe_file" &
301
+ local keeper_pid=$!
302
+
303
+ # Start agent reading from the FIFO, logging stdout/stderr
304
+ $agent_cmd < "$pipe_file" >> "$LOG_FILE" 2>&1 &
282
305
  local pid=$!
306
+
283
307
  echo "$pid" > "$PID_FILE"
308
+ echo "$keeper_pid" > "$PROJECT_DIR/.fathom/agent-keeper.pid"
309
+
284
310
  echo "PID: $pid"
311
+ echo "Pipe: $pipe_file"
285
312
  echo "Started. View logs: tail -f $LOG_FILE"
313
+ echo "Inject: echo 'your message' > $pipe_file"
286
314
  return 0
287
315
  fi
288
316
 
@@ -154,17 +154,37 @@ export function createWSConnection(config) {
154
154
  if (!text) return;
155
155
 
156
156
  if (agent === "claude-sdk") {
157
- // For headless SDK agents managed by fathom-server, injection goes through
158
- // the server's stdin pipe (persistent_session.inject_headless). The WS push
159
- // channel delivers the message to the server, which handles the actual write.
160
- // Fall back to tmux injection if the agent happens to be in a tmux session
161
- // (e.g., started with --claude-code-w-tmux override).
162
- injectToTmux(text);
157
+ // Headless SDK agents use a FIFO pipe for stdin injection.
158
+ // Server-managed (local): server handles via persistent_session._inject_headless()
159
+ // Standalone (remote): write to .fathom/agent.pipe FIFO
160
+ injectToFifo(text);
163
161
  } else {
164
162
  injectToTmux(text);
165
163
  }
166
164
  }
167
165
 
166
+ function injectToFifo(text) {
167
+ if (!text) return;
168
+
169
+ const projectDir = config._projectDir || process.cwd();
170
+ const pipePath = path.join(projectDir, ".fathom", "agent.pipe");
171
+
172
+ try {
173
+ const stat = fs.statSync(pipePath);
174
+ if (stat.isFIFO()) {
175
+ // Write to FIFO — opens, writes, closes in one shot.
176
+ // The newline terminates the message for claude -p.
177
+ fs.appendFileSync(pipePath, text + "\n");
178
+ return;
179
+ }
180
+ } catch {
181
+ // FIFO not found — fall back to tmux
182
+ }
183
+
184
+ // Fallback: try tmux injection (e.g., started with --claude-code-w-tmux override)
185
+ injectToTmux(text);
186
+ }
187
+
168
188
  function injectToTmux(text) {
169
189
  if (!text) return;
170
190
  const pane = resolvePaneTarget();