fathom-mcp 0.4.12 → 0.4.13
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 +1 -1
- package/src/index.js +224 -10
- package/src/server-client.js +70 -0
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -227,9 +227,8 @@ const tools = [
|
|
|
227
227
|
"to the latest message. Default: 60 minutes before the latest message. Use start to look " +
|
|
228
228
|
"further back. Example: minutes=15, start=120 returns 15 minutes of conversation starting " +
|
|
229
229
|
"2 hours before the latest message. Response includes window metadata with has_older flag " +
|
|
230
|
-
"for pseudo-pagination.
|
|
231
|
-
"
|
|
232
|
-
"For regular rooms, automatically marks as read unless mark_read=false.",
|
|
230
|
+
"for pseudo-pagination. All rooms are persistent — messages are never deleted on read. " +
|
|
231
|
+
"Automatically marks the room as read unless mark_read=false.",
|
|
233
232
|
inputSchema: {
|
|
234
233
|
type: "object",
|
|
235
234
|
properties: {
|
|
@@ -246,8 +245,8 @@ const tools = [
|
|
|
246
245
|
description:
|
|
247
246
|
"List all rooms with activity summary — message count, last activity time, last sender, " +
|
|
248
247
|
"description, and per-room unread_count for this workspace. Use to discover active rooms " +
|
|
249
|
-
"and see which have new messages.
|
|
250
|
-
"
|
|
248
|
+
"and see which have new messages. DM rooms (dm:a+b) are filtered by workspace param — " +
|
|
249
|
+
"only participants see them. Mention rooms (mentions:{workspace}) visible only to the target workspace.",
|
|
251
250
|
inputSchema: {
|
|
252
251
|
type: "object",
|
|
253
252
|
properties: {},
|
|
@@ -282,10 +281,9 @@ const tools = [
|
|
|
282
281
|
{
|
|
283
282
|
name: "fathom_send",
|
|
284
283
|
description:
|
|
285
|
-
"Send a message to another workspace's agent instance — stored in
|
|
286
|
-
"
|
|
287
|
-
"
|
|
288
|
-
"Message format: 'Message from workspace ({from}): {message}'",
|
|
284
|
+
"Send a message to another workspace's agent instance — stored in a shared dm:a+b room " +
|
|
285
|
+
"visible to both participants. Use fathom_workspaces first to discover valid targets. " +
|
|
286
|
+
"DMs are persistent and appear in both participants' room lists via fathom_room_list.",
|
|
289
287
|
inputSchema: {
|
|
290
288
|
type: "object",
|
|
291
289
|
properties: {
|
|
@@ -344,6 +342,99 @@ const tools = [
|
|
|
344
342
|
required: [],
|
|
345
343
|
},
|
|
346
344
|
},
|
|
345
|
+
{
|
|
346
|
+
name: "fathom_routine_list",
|
|
347
|
+
description:
|
|
348
|
+
"List all ping routines for a workspace with their status, intervals, " +
|
|
349
|
+
"enabled state, and next fire time. Use this to see what routines exist " +
|
|
350
|
+
"before updating or deleting them.",
|
|
351
|
+
inputSchema: {
|
|
352
|
+
type: "object",
|
|
353
|
+
properties: {
|
|
354
|
+
workspace: WORKSPACE_PROP,
|
|
355
|
+
},
|
|
356
|
+
required: [],
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
name: "fathom_routine_update",
|
|
361
|
+
description:
|
|
362
|
+
"Update an existing ping routine. Only provided fields are changed — " +
|
|
363
|
+
"omitted fields keep their current values. Use fathom_routine_list first " +
|
|
364
|
+
"to find the routine_id.",
|
|
365
|
+
inputSchema: {
|
|
366
|
+
type: "object",
|
|
367
|
+
properties: {
|
|
368
|
+
routine_id: { type: "string", description: "The routine ID to update. Use fathom_routine_list to find IDs." },
|
|
369
|
+
name: { type: "string", description: "New routine name." },
|
|
370
|
+
enabled: { type: "boolean", description: "Enable or disable the routine." },
|
|
371
|
+
interval_minutes: { type: "integer", description: "New interval in minutes.", minimum: 1 },
|
|
372
|
+
single_fire: { type: "boolean", description: "Auto-disable after firing once." },
|
|
373
|
+
workspace: WORKSPACE_PROP,
|
|
374
|
+
context_sources: {
|
|
375
|
+
type: "object",
|
|
376
|
+
description: "What to inject on each ping.",
|
|
377
|
+
properties: {
|
|
378
|
+
time: { type: "boolean", description: "Include current time/date. Default: true." },
|
|
379
|
+
scripts: {
|
|
380
|
+
type: "array",
|
|
381
|
+
description: "Shell commands to run and inject output.",
|
|
382
|
+
items: {
|
|
383
|
+
type: "object",
|
|
384
|
+
properties: {
|
|
385
|
+
label: { type: "string" },
|
|
386
|
+
command: { type: "string" },
|
|
387
|
+
enabled: { type: "boolean" },
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
texts: {
|
|
392
|
+
type: "array",
|
|
393
|
+
description: "Static text blocks to inject.",
|
|
394
|
+
items: {
|
|
395
|
+
type: "object",
|
|
396
|
+
properties: {
|
|
397
|
+
label: { type: "string" },
|
|
398
|
+
content: { type: "string" },
|
|
399
|
+
enabled: { type: "boolean" },
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
required: ["routine_id"],
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: "fathom_routine_delete",
|
|
411
|
+
description:
|
|
412
|
+
"Delete a ping routine permanently. Use fathom_routine_list first to find " +
|
|
413
|
+
"the routine_id. This cannot be undone — create a new routine if needed.",
|
|
414
|
+
inputSchema: {
|
|
415
|
+
type: "object",
|
|
416
|
+
properties: {
|
|
417
|
+
routine_id: { type: "string", description: "The routine ID to delete." },
|
|
418
|
+
workspace: WORKSPACE_PROP,
|
|
419
|
+
},
|
|
420
|
+
required: ["routine_id"],
|
|
421
|
+
},
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
name: "fathom_routine_fire",
|
|
425
|
+
description:
|
|
426
|
+
"Fire a ping routine immediately, regardless of its schedule. Non-blocking — " +
|
|
427
|
+
"returns immediately while the routine fires in the background. The routine's " +
|
|
428
|
+
"next scheduled fire time is not affected.",
|
|
429
|
+
inputSchema: {
|
|
430
|
+
type: "object",
|
|
431
|
+
properties: {
|
|
432
|
+
routine_id: { type: "string", description: "The routine ID to fire." },
|
|
433
|
+
workspace: WORKSPACE_PROP,
|
|
434
|
+
},
|
|
435
|
+
required: ["routine_id"],
|
|
436
|
+
},
|
|
437
|
+
},
|
|
347
438
|
];
|
|
348
439
|
|
|
349
440
|
// --- Vault routing by mode ---------------------------------------------------
|
|
@@ -381,6 +472,47 @@ function resolveVault(args) {
|
|
|
381
472
|
}
|
|
382
473
|
}
|
|
383
474
|
|
|
475
|
+
// --- Telegram tools (primary agent only) -------------------------------------
|
|
476
|
+
|
|
477
|
+
const telegramTools = [
|
|
478
|
+
{
|
|
479
|
+
name: "fathom_telegram_contacts",
|
|
480
|
+
description:
|
|
481
|
+
"List Telegram contacts who have messaged. Returns name, username, chat_id, " +
|
|
482
|
+
"last_message time, and unread count.",
|
|
483
|
+
inputSchema: { type: "object", properties: {} },
|
|
484
|
+
},
|
|
485
|
+
{
|
|
486
|
+
name: "fathom_telegram_read",
|
|
487
|
+
description:
|
|
488
|
+
"Read recent Telegram messages from a contact. Same windowing as fathom_room_read — " +
|
|
489
|
+
"anchored to latest message, default 60 minutes. Use start to look further back.",
|
|
490
|
+
inputSchema: {
|
|
491
|
+
type: "object",
|
|
492
|
+
properties: {
|
|
493
|
+
contact: { type: "string", description: "Contact name, @username, or chat_id" },
|
|
494
|
+
minutes: { type: "number", description: "Window duration in minutes. Default: 60." },
|
|
495
|
+
start: { type: "number", description: "Offset in minutes from latest message. Default: 0." },
|
|
496
|
+
mark_read: { type: "boolean", description: "Mark messages as read. Default: true." },
|
|
497
|
+
},
|
|
498
|
+
required: ["contact"],
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
name: "fathom_telegram_send",
|
|
503
|
+
description:
|
|
504
|
+
"Send a Telegram message to a contact via the persistent Telethon client.",
|
|
505
|
+
inputSchema: {
|
|
506
|
+
type: "object",
|
|
507
|
+
properties: {
|
|
508
|
+
contact: { type: "string", description: "Contact name, @username, or chat_id" },
|
|
509
|
+
message: { type: "string", description: "Message text to send" },
|
|
510
|
+
},
|
|
511
|
+
required: ["contact", "message"],
|
|
512
|
+
},
|
|
513
|
+
},
|
|
514
|
+
];
|
|
515
|
+
|
|
384
516
|
// --- Server setup & dispatch -------------------------------------------------
|
|
385
517
|
|
|
386
518
|
const server = new Server(
|
|
@@ -388,7 +520,19 @@ const server = new Server(
|
|
|
388
520
|
{ capabilities: { tools: {} } },
|
|
389
521
|
);
|
|
390
522
|
|
|
391
|
-
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
|
523
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
524
|
+
// Telegram tools only visible to the primary (default) workspace
|
|
525
|
+
let isPrimary = false;
|
|
526
|
+
try {
|
|
527
|
+
const settings = await client.getSettings();
|
|
528
|
+
const primaryAgent = settings.default_workspace;
|
|
529
|
+
isPrimary = config.workspace === primaryAgent;
|
|
530
|
+
} catch {
|
|
531
|
+
// If settings unavailable, hide telegram tools
|
|
532
|
+
}
|
|
533
|
+
const allTools = [...tools, ...(isPrimary ? telegramTools : [])];
|
|
534
|
+
return { tools: allTools };
|
|
535
|
+
});
|
|
392
536
|
|
|
393
537
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
394
538
|
const { name, arguments: args } = request.params;
|
|
@@ -543,6 +687,76 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
543
687
|
result = await client.createRoutine(routineParams, args.workspace || config.workspace);
|
|
544
688
|
break;
|
|
545
689
|
}
|
|
690
|
+
case "fathom_routine_list":
|
|
691
|
+
result = await client.listRoutines(args.workspace || config.workspace);
|
|
692
|
+
break;
|
|
693
|
+
case "fathom_routine_update": {
|
|
694
|
+
const updateParams = {};
|
|
695
|
+
if (args.name != null) updateParams.name = args.name;
|
|
696
|
+
if (args.enabled != null) updateParams.enabled = args.enabled;
|
|
697
|
+
if (args.interval_minutes != null) updateParams.intervalMinutes = args.interval_minutes;
|
|
698
|
+
if (args.single_fire != null) updateParams.singleFire = args.single_fire;
|
|
699
|
+
if (args.context_sources != null) updateParams.contextSources = args.context_sources;
|
|
700
|
+
result = await client.updateRoutine(args.routine_id, updateParams, args.workspace || config.workspace);
|
|
701
|
+
break;
|
|
702
|
+
}
|
|
703
|
+
case "fathom_routine_delete":
|
|
704
|
+
result = await client.deleteRoutine(args.routine_id, args.workspace || config.workspace);
|
|
705
|
+
break;
|
|
706
|
+
case "fathom_routine_fire":
|
|
707
|
+
result = await client.fireRoutine(args.routine_id, args.workspace || config.workspace);
|
|
708
|
+
break;
|
|
709
|
+
// --- Telegram ---
|
|
710
|
+
case "fathom_telegram_contacts":
|
|
711
|
+
result = await client.telegramContacts(config.workspace);
|
|
712
|
+
break;
|
|
713
|
+
case "fathom_telegram_read": {
|
|
714
|
+
// Resolve contact name to chat_id via contacts list
|
|
715
|
+
const contacts = await client.telegramContacts(config.workspace);
|
|
716
|
+
const contactList = contacts?.contacts || [];
|
|
717
|
+
const contactArg = (args.contact || "").trim();
|
|
718
|
+
let chatId = parseInt(contactArg, 10);
|
|
719
|
+
if (isNaN(chatId)) {
|
|
720
|
+
const lower = contactArg.toLowerCase().replace(/^@/, "");
|
|
721
|
+
const match = contactList.find(c =>
|
|
722
|
+
(c.username || "").toLowerCase() === lower ||
|
|
723
|
+
(c.first_name || "").toLowerCase() === lower ||
|
|
724
|
+
(c.first_name || "").toLowerCase().includes(lower)
|
|
725
|
+
);
|
|
726
|
+
chatId = match ? match.chat_id : null;
|
|
727
|
+
}
|
|
728
|
+
if (!chatId) {
|
|
729
|
+
result = { error: `Contact not found: ${contactArg}. Use fathom_telegram_contacts to list known contacts.` };
|
|
730
|
+
} else {
|
|
731
|
+
result = await client.telegramRead(
|
|
732
|
+
chatId, args.minutes, args.start,
|
|
733
|
+
args.mark_read !== false ? config.workspace : undefined,
|
|
734
|
+
args.mark_read,
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
break;
|
|
738
|
+
}
|
|
739
|
+
case "fathom_telegram_send": {
|
|
740
|
+
const sendContacts = await client.telegramContacts(config.workspace);
|
|
741
|
+
const sendList = sendContacts?.contacts || [];
|
|
742
|
+
const sendArg = (args.contact || "").trim();
|
|
743
|
+
let sendChatId = parseInt(sendArg, 10);
|
|
744
|
+
if (isNaN(sendChatId)) {
|
|
745
|
+
const lower = sendArg.toLowerCase().replace(/^@/, "");
|
|
746
|
+
const match = sendList.find(c =>
|
|
747
|
+
(c.username || "").toLowerCase() === lower ||
|
|
748
|
+
(c.first_name || "").toLowerCase() === lower ||
|
|
749
|
+
(c.first_name || "").toLowerCase().includes(lower)
|
|
750
|
+
);
|
|
751
|
+
sendChatId = match ? match.chat_id : null;
|
|
752
|
+
}
|
|
753
|
+
if (!sendChatId) {
|
|
754
|
+
result = { error: `Contact not found: ${sendArg}. Use fathom_telegram_contacts to list known contacts.` };
|
|
755
|
+
} else {
|
|
756
|
+
result = await client.telegramSend(sendChatId, args.message);
|
|
757
|
+
}
|
|
758
|
+
break;
|
|
759
|
+
}
|
|
546
760
|
default:
|
|
547
761
|
result = { error: `Unknown tool: ${name}` };
|
|
548
762
|
}
|
package/src/server-client.js
CHANGED
|
@@ -205,6 +205,37 @@ export function createClient(config) {
|
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
async function listRoutines(ws) {
|
|
209
|
+
return request("GET", "/api/activation/ping/routines", {
|
|
210
|
+
params: { workspace: ws },
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async function updateRoutine(routineId, params, ws) {
|
|
215
|
+
const body = {};
|
|
216
|
+
if (params.name != null) body.name = params.name;
|
|
217
|
+
if (params.enabled != null) body.enabled = params.enabled;
|
|
218
|
+
if (params.intervalMinutes != null) body.intervalMinutes = params.intervalMinutes;
|
|
219
|
+
if (params.singleFire != null) body.singleFire = params.singleFire;
|
|
220
|
+
if (params.contextSources != null) body.contextSources = params.contextSources;
|
|
221
|
+
return request("POST", `/api/activation/ping/routines/${encodeURIComponent(routineId)}`, {
|
|
222
|
+
params: { workspace: ws },
|
|
223
|
+
body,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
async function deleteRoutine(routineId, ws) {
|
|
228
|
+
return request("DELETE", `/api/activation/ping/routines/${encodeURIComponent(routineId)}`, {
|
|
229
|
+
params: { workspace: ws },
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function fireRoutine(routineId, ws) {
|
|
234
|
+
return request("POST", `/api/activation/ping/routines/${encodeURIComponent(routineId)}/now`, {
|
|
235
|
+
params: { workspace: ws },
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
208
239
|
// --- Heartbeat -------------------------------------------------------------
|
|
209
240
|
|
|
210
241
|
async function heartbeat(ws, agent, vaultMode) {
|
|
@@ -214,6 +245,36 @@ export function createClient(config) {
|
|
|
214
245
|
return request("POST", `/api/workspaces/${encodeURIComponent(ws)}/heartbeat`, { body });
|
|
215
246
|
}
|
|
216
247
|
|
|
248
|
+
// --- Telegram --------------------------------------------------------------
|
|
249
|
+
|
|
250
|
+
async function telegramContacts(ws) {
|
|
251
|
+
return request("GET", "/api/telegram/contacts", {
|
|
252
|
+
params: { workspace: ws },
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
async function telegramRead(chatId, minutes, start, ws, markRead) {
|
|
257
|
+
return request("GET", `/api/telegram/messages/${chatId}`, {
|
|
258
|
+
params: { minutes, start, workspace: ws, mark_read: markRead },
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
async function telegramSend(chatId, message) {
|
|
263
|
+
return request("POST", `/api/telegram/send/${chatId}`, {
|
|
264
|
+
body: { message },
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function telegramStatus() {
|
|
269
|
+
return request("GET", "/api/telegram/status");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// --- Settings --------------------------------------------------------------
|
|
273
|
+
|
|
274
|
+
async function getSettings() {
|
|
275
|
+
return request("GET", "/api/settings");
|
|
276
|
+
}
|
|
277
|
+
|
|
217
278
|
// --- Auth ------------------------------------------------------------------
|
|
218
279
|
|
|
219
280
|
async function getApiKey() {
|
|
@@ -254,7 +315,16 @@ export function createClient(config) {
|
|
|
254
315
|
pushFile,
|
|
255
316
|
syncManifest,
|
|
256
317
|
createRoutine,
|
|
318
|
+
listRoutines,
|
|
319
|
+
updateRoutine,
|
|
320
|
+
deleteRoutine,
|
|
321
|
+
fireRoutine,
|
|
257
322
|
heartbeat,
|
|
323
|
+
telegramContacts,
|
|
324
|
+
telegramRead,
|
|
325
|
+
telegramSend,
|
|
326
|
+
telegramStatus,
|
|
327
|
+
getSettings,
|
|
258
328
|
getApiKey,
|
|
259
329
|
healthCheck,
|
|
260
330
|
};
|