@hasna/conversations 0.1.18 → 0.1.20
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/bin/hook.js +37 -0
- package/bin/index.js +533 -298
- package/bin/mcp.js +312 -95
- package/dashboard/dist/assets/index-Bw0wMcXE.js +186 -0
- package/dashboard/dist/assets/index-CF_GDtNp.css +1 -0
- package/dashboard/dist/index.html +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +168 -16
- package/dist/lib/messages.d.ts +3 -0
- package/dist/lib/terminal-markdown.d.ts +11 -0
- package/dist/lib/webhooks.d.ts +11 -0
- package/dist/lib/webhooks.test.d.ts +1 -0
- package/dist/types.d.ts +3 -0
- package/package.json +1 -1
- package/dashboard/dist/assets/index-CCdh63JU.js +0 -186
- package/dashboard/dist/assets/index-VFT0_0LI.css +0 -1
package/bin/mcp.js
CHANGED
|
@@ -6677,6 +6677,43 @@ function getDb() {
|
|
|
6677
6677
|
if (!colNames2.includes("attachments")) {
|
|
6678
6678
|
db.exec("ALTER TABLE messages ADD COLUMN attachments TEXT");
|
|
6679
6679
|
}
|
|
6680
|
+
if (!colNames2.includes("reply_to")) {
|
|
6681
|
+
db.exec("ALTER TABLE messages ADD COLUMN reply_to INTEGER REFERENCES messages(id)");
|
|
6682
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_messages_reply_to ON messages(reply_to)");
|
|
6683
|
+
}
|
|
6684
|
+
const ftsExists = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='messages_fts'").get();
|
|
6685
|
+
if (!ftsExists) {
|
|
6686
|
+
db.exec(`
|
|
6687
|
+
CREATE VIRTUAL TABLE messages_fts USING fts5(
|
|
6688
|
+
content, from_agent, to_agent, space,
|
|
6689
|
+
content_rowid='id', content='messages'
|
|
6690
|
+
)
|
|
6691
|
+
`);
|
|
6692
|
+
db.exec(`
|
|
6693
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
6694
|
+
SELECT id, content, from_agent, to_agent, space FROM messages
|
|
6695
|
+
`);
|
|
6696
|
+
db.exec(`
|
|
6697
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_insert AFTER INSERT ON messages BEGIN
|
|
6698
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
6699
|
+
VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
|
|
6700
|
+
END
|
|
6701
|
+
`);
|
|
6702
|
+
db.exec(`
|
|
6703
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_delete AFTER DELETE ON messages BEGIN
|
|
6704
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
|
|
6705
|
+
VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
|
|
6706
|
+
END
|
|
6707
|
+
`);
|
|
6708
|
+
db.exec(`
|
|
6709
|
+
CREATE TRIGGER IF NOT EXISTS messages_fts_update AFTER UPDATE OF content ON messages BEGIN
|
|
6710
|
+
INSERT INTO messages_fts(messages_fts, rowid, content, from_agent, to_agent, space)
|
|
6711
|
+
VALUES ('delete', old.id, old.content, old.from_agent, old.to_agent, old.space);
|
|
6712
|
+
INSERT INTO messages_fts(rowid, content, from_agent, to_agent, space)
|
|
6713
|
+
VALUES (new.id, new.content, new.from_agent, new.to_agent, new.space);
|
|
6714
|
+
END
|
|
6715
|
+
`);
|
|
6716
|
+
}
|
|
6680
6717
|
return db;
|
|
6681
6718
|
}
|
|
6682
6719
|
function closeDb() {
|
|
@@ -28509,8 +28546,84 @@ class StdioServerTransport {
|
|
|
28509
28546
|
init_db();
|
|
28510
28547
|
import { randomUUID } from "crypto";
|
|
28511
28548
|
import { mkdirSync as mkdirSync2, copyFileSync, statSync } from "fs";
|
|
28549
|
+
import { join as join3 } from "path";
|
|
28550
|
+
import { homedir as homedir3 } from "os";
|
|
28551
|
+
|
|
28552
|
+
// src/lib/webhooks.ts
|
|
28553
|
+
import { readFileSync } from "fs";
|
|
28512
28554
|
import { join as join2 } from "path";
|
|
28513
28555
|
import { homedir as homedir2 } from "os";
|
|
28556
|
+
var cachedConfig = null;
|
|
28557
|
+
var configLoadedAt = 0;
|
|
28558
|
+
var CONFIG_CACHE_MS = 1e4;
|
|
28559
|
+
function getConfigPath() {
|
|
28560
|
+
return process.env.CONVERSATIONS_CONFIG_PATH || join2(homedir2(), ".conversations", "config.json");
|
|
28561
|
+
}
|
|
28562
|
+
function loadConfig() {
|
|
28563
|
+
const now = Date.now();
|
|
28564
|
+
if (cachedConfig && now - configLoadedAt < CONFIG_CACHE_MS)
|
|
28565
|
+
return cachedConfig;
|
|
28566
|
+
try {
|
|
28567
|
+
const raw = readFileSync(getConfigPath(), "utf-8");
|
|
28568
|
+
cachedConfig = JSON.parse(raw);
|
|
28569
|
+
configLoadedAt = now;
|
|
28570
|
+
return cachedConfig;
|
|
28571
|
+
} catch {
|
|
28572
|
+
cachedConfig = {};
|
|
28573
|
+
configLoadedAt = now;
|
|
28574
|
+
return cachedConfig;
|
|
28575
|
+
}
|
|
28576
|
+
}
|
|
28577
|
+
function matchesEvent(webhook, msg) {
|
|
28578
|
+
for (const event of webhook.events) {
|
|
28579
|
+
if (event === "dm" && !msg.space)
|
|
28580
|
+
return true;
|
|
28581
|
+
if (event === "blocker" && msg.blocking)
|
|
28582
|
+
return true;
|
|
28583
|
+
if (event === "space" && msg.space)
|
|
28584
|
+
return true;
|
|
28585
|
+
if (event === "mention" && webhook.agent && msg.content.includes(`@${webhook.agent}`))
|
|
28586
|
+
return true;
|
|
28587
|
+
}
|
|
28588
|
+
return false;
|
|
28589
|
+
}
|
|
28590
|
+
function fireWebhooks(msg) {
|
|
28591
|
+
const config2 = loadConfig();
|
|
28592
|
+
if (!config2.webhooks || config2.webhooks.length === 0)
|
|
28593
|
+
return;
|
|
28594
|
+
for (const webhook of config2.webhooks) {
|
|
28595
|
+
if (webhook.agent && msg.to_agent !== webhook.agent && !msg.space)
|
|
28596
|
+
continue;
|
|
28597
|
+
if (!matchesEvent(webhook, msg))
|
|
28598
|
+
continue;
|
|
28599
|
+
fetch(webhook.url, {
|
|
28600
|
+
method: "POST",
|
|
28601
|
+
headers: { "Content-Type": "application/json" },
|
|
28602
|
+
body: JSON.stringify({
|
|
28603
|
+
id: msg.id,
|
|
28604
|
+
from: msg.from_agent,
|
|
28605
|
+
to: msg.to_agent,
|
|
28606
|
+
space: msg.space,
|
|
28607
|
+
content: msg.content,
|
|
28608
|
+
priority: msg.priority,
|
|
28609
|
+
blocking: msg.blocking,
|
|
28610
|
+
created_at: msg.created_at
|
|
28611
|
+
})
|
|
28612
|
+
}).catch(() => {});
|
|
28613
|
+
}
|
|
28614
|
+
}
|
|
28615
|
+
|
|
28616
|
+
// src/lib/messages.ts
|
|
28617
|
+
function compactMessage(msg) {
|
|
28618
|
+
const result = {};
|
|
28619
|
+
for (const key of Object.keys(msg)) {
|
|
28620
|
+
const val = msg[key];
|
|
28621
|
+
if (val !== null && val !== undefined) {
|
|
28622
|
+
result[key] = val;
|
|
28623
|
+
}
|
|
28624
|
+
}
|
|
28625
|
+
return result;
|
|
28626
|
+
}
|
|
28514
28627
|
function parseMessage(row) {
|
|
28515
28628
|
let metadata = null;
|
|
28516
28629
|
if (row.metadata) {
|
|
@@ -28532,13 +28645,14 @@ function parseMessage(row) {
|
|
|
28532
28645
|
...row,
|
|
28533
28646
|
metadata,
|
|
28534
28647
|
attachments,
|
|
28535
|
-
blocking: !!row.blocking
|
|
28648
|
+
blocking: !!row.blocking,
|
|
28649
|
+
reply_to: row.reply_to || null
|
|
28536
28650
|
};
|
|
28537
28651
|
}
|
|
28538
28652
|
function getAttachmentsDir() {
|
|
28539
28653
|
if (process.env.CONVERSATIONS_ATTACHMENTS_DIR)
|
|
28540
28654
|
return process.env.CONVERSATIONS_ATTACHMENTS_DIR;
|
|
28541
|
-
return
|
|
28655
|
+
return join3(homedir3(), ".conversations", "attachments");
|
|
28542
28656
|
}
|
|
28543
28657
|
function guessMimeType(name) {
|
|
28544
28658
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
@@ -28574,19 +28688,20 @@ function sendMessage(opts) {
|
|
|
28574
28688
|
const metadata = opts.metadata ? JSON.stringify(opts.metadata) : null;
|
|
28575
28689
|
const normalizedPriority = opts.priority === "low" || opts.priority === "normal" || opts.priority === "high" || opts.priority === "urgent" ? opts.priority : "normal";
|
|
28576
28690
|
const blocking = opts.blocking ? 1 : 0;
|
|
28691
|
+
const replyTo = opts.reply_to || null;
|
|
28577
28692
|
const stmt = db2.prepare(`
|
|
28578
|
-
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking)
|
|
28579
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
28693
|
+
INSERT INTO messages (session_id, from_agent, to_agent, space, content, priority, working_dir, repository, branch, metadata, blocking, reply_to)
|
|
28694
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
28580
28695
|
RETURNING *
|
|
28581
28696
|
`);
|
|
28582
|
-
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking);
|
|
28697
|
+
const row = stmt.get(sessionId, opts.from, opts.to, opts.space || null, opts.content, normalizedPriority, opts.working_dir || null, opts.repository || null, opts.branch || null, metadata, blocking, replyTo);
|
|
28583
28698
|
const message = parseMessage(row);
|
|
28584
28699
|
if (opts.attachments && opts.attachments.length > 0) {
|
|
28585
|
-
const attachmentsDir =
|
|
28700
|
+
const attachmentsDir = join3(getAttachmentsDir(), String(message.id));
|
|
28586
28701
|
mkdirSync2(attachmentsDir, { recursive: true });
|
|
28587
28702
|
const attachmentInfos = [];
|
|
28588
28703
|
for (const att of opts.attachments) {
|
|
28589
|
-
const destPath =
|
|
28704
|
+
const destPath = join3(attachmentsDir, att.name);
|
|
28590
28705
|
copyFileSync(att.source_path, destPath);
|
|
28591
28706
|
const stat = statSync(destPath);
|
|
28592
28707
|
attachmentInfos.push({
|
|
@@ -28600,6 +28715,7 @@ function sendMessage(opts) {
|
|
|
28600
28715
|
db2.prepare("UPDATE messages SET attachments = ? WHERE id = ?").run(attachmentsJson, message.id);
|
|
28601
28716
|
message.attachments = attachmentInfos;
|
|
28602
28717
|
}
|
|
28718
|
+
fireWebhooks(message);
|
|
28603
28719
|
return message;
|
|
28604
28720
|
}
|
|
28605
28721
|
function readMessages(opts = {}) {
|
|
@@ -28634,10 +28750,13 @@ function readMessages(opts = {}) {
|
|
|
28634
28750
|
conditions.push("read_at IS NULL");
|
|
28635
28751
|
}
|
|
28636
28752
|
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
28637
|
-
const
|
|
28753
|
+
const resolvedLimit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
28638
28754
|
const order = opts.order?.toLowerCase() === "desc" ? "DESC" : "ASC";
|
|
28639
|
-
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} ${
|
|
28640
|
-
|
|
28755
|
+
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at ${order}, id ${order} LIMIT ${resolvedLimit}`).all(...params);
|
|
28756
|
+
const messages = rows.map(parseMessage);
|
|
28757
|
+
if (opts.compact)
|
|
28758
|
+
return messages.map(compactMessage);
|
|
28759
|
+
return messages;
|
|
28641
28760
|
}
|
|
28642
28761
|
function markRead(ids, reader) {
|
|
28643
28762
|
const db2 = getDb();
|
|
@@ -28771,6 +28890,33 @@ function getUnreadBlockers(agent) {
|
|
|
28771
28890
|
}
|
|
28772
28891
|
function searchMessages(opts) {
|
|
28773
28892
|
const db2 = getDb();
|
|
28893
|
+
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 20;
|
|
28894
|
+
try {
|
|
28895
|
+
const ftsConditions = [];
|
|
28896
|
+
const ftsParams = [];
|
|
28897
|
+
const words = opts.query.trim().split(/\s+/).filter(Boolean);
|
|
28898
|
+
const ftsQuery = words.map((w) => `"${w.replace(/"/g, '""')}"`).join(" ");
|
|
28899
|
+
ftsConditions.push("messages_fts MATCH ?");
|
|
28900
|
+
ftsParams.push(ftsQuery);
|
|
28901
|
+
let extraWhere = "";
|
|
28902
|
+
if (opts.space) {
|
|
28903
|
+
extraWhere += " AND m.space = ?";
|
|
28904
|
+
ftsParams.push(opts.space);
|
|
28905
|
+
}
|
|
28906
|
+
if (opts.from) {
|
|
28907
|
+
extraWhere += " AND m.from_agent = ?";
|
|
28908
|
+
ftsParams.push(opts.from);
|
|
28909
|
+
}
|
|
28910
|
+
if (opts.to) {
|
|
28911
|
+
extraWhere += " AND m.to_agent = ?";
|
|
28912
|
+
ftsParams.push(opts.to);
|
|
28913
|
+
}
|
|
28914
|
+
const rows2 = db2.prepare(`SELECT m.* FROM messages m
|
|
28915
|
+
JOIN messages_fts ON messages_fts.rowid = m.id
|
|
28916
|
+
WHERE ${ftsConditions.join(" AND ")}${extraWhere}
|
|
28917
|
+
ORDER BY m.created_at DESC, m.id DESC LIMIT ${limit}`).all(...ftsParams);
|
|
28918
|
+
return rows2.map(parseMessage);
|
|
28919
|
+
} catch {}
|
|
28774
28920
|
const conditions = ["content LIKE ?"];
|
|
28775
28921
|
const params = [`%${opts.query}%`];
|
|
28776
28922
|
if (opts.space) {
|
|
@@ -28785,7 +28931,6 @@ function searchMessages(opts) {
|
|
|
28785
28931
|
conditions.push("to_agent = ?");
|
|
28786
28932
|
params.push(opts.to);
|
|
28787
28933
|
}
|
|
28788
|
-
const limit = Number.isFinite(opts.limit) && opts.limit > 0 ? Math.floor(opts.limit) : 50;
|
|
28789
28934
|
const where = `WHERE ${conditions.join(" AND ")}`;
|
|
28790
28935
|
const rows = db2.prepare(`SELECT * FROM messages ${where} ORDER BY created_at DESC, id DESC LIMIT ${limit}`).all(...params);
|
|
28791
28936
|
return rows.map(parseMessage);
|
|
@@ -29163,9 +29308,9 @@ function deleteProject(id) {
|
|
|
29163
29308
|
}
|
|
29164
29309
|
|
|
29165
29310
|
// src/lib/identity.ts
|
|
29166
|
-
import { readFileSync, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
29167
|
-
import { join as
|
|
29168
|
-
import { homedir as
|
|
29311
|
+
import { readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
29312
|
+
import { join as join4, dirname as dirname2 } from "path";
|
|
29313
|
+
import { homedir as homedir4 } from "os";
|
|
29169
29314
|
|
|
29170
29315
|
// src/lib/names.ts
|
|
29171
29316
|
var AGENT_NAMES = [
|
|
@@ -29517,7 +29662,7 @@ var AGENT_NAMES = [
|
|
|
29517
29662
|
];
|
|
29518
29663
|
|
|
29519
29664
|
// src/lib/identity.ts
|
|
29520
|
-
var AGENT_ID_FILE =
|
|
29665
|
+
var AGENT_ID_FILE = join4(homedir4(), ".conversations", "agent-id");
|
|
29521
29666
|
var cachedAutoName = null;
|
|
29522
29667
|
function isNameTaken(name) {
|
|
29523
29668
|
try {
|
|
@@ -29533,7 +29678,7 @@ function getAutoName() {
|
|
|
29533
29678
|
if (cachedAutoName)
|
|
29534
29679
|
return cachedAutoName;
|
|
29535
29680
|
try {
|
|
29536
|
-
const name2 =
|
|
29681
|
+
const name2 = readFileSync2(AGENT_ID_FILE, "utf-8").trim();
|
|
29537
29682
|
if (name2) {
|
|
29538
29683
|
cachedAutoName = name2;
|
|
29539
29684
|
return name2;
|
|
@@ -29632,7 +29777,7 @@ function renameAgent(oldName, newName) {
|
|
|
29632
29777
|
// package.json
|
|
29633
29778
|
var package_default = {
|
|
29634
29779
|
name: "@hasna/conversations",
|
|
29635
|
-
version: "0.1.
|
|
29780
|
+
version: "0.1.20",
|
|
29636
29781
|
description: "Real-time CLI messaging for AI agents",
|
|
29637
29782
|
type: "module",
|
|
29638
29783
|
bin: {
|
|
@@ -29716,9 +29861,9 @@ var server = new McpServer({
|
|
|
29716
29861
|
});
|
|
29717
29862
|
server.registerTool("send_message", {
|
|
29718
29863
|
title: "Send Message",
|
|
29719
|
-
description: "Send a direct message to another agent.
|
|
29864
|
+
description: "Send a direct message to another agent.",
|
|
29720
29865
|
inputSchema: {
|
|
29721
|
-
from: exports_external.string().optional().describe("Your agent ID
|
|
29866
|
+
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
29722
29867
|
to: exports_external.string().describe("Recipient agent ID"),
|
|
29723
29868
|
content: exports_external.string().describe("Message content"),
|
|
29724
29869
|
session_id: exports_external.string().optional().describe("Session ID (auto-generated if omitted)"),
|
|
@@ -29727,7 +29872,7 @@ server.registerTool("send_message", {
|
|
|
29727
29872
|
repository: exports_external.string().optional().describe("Repository context"),
|
|
29728
29873
|
branch: exports_external.string().optional().describe("Branch context"),
|
|
29729
29874
|
metadata: exports_external.string().optional().describe("JSON metadata string"),
|
|
29730
|
-
blocking: exports_external.boolean().optional().describe("
|
|
29875
|
+
blocking: exports_external.boolean().optional().describe("Blocking message \u2014 recipients must acknowledge before continuing")
|
|
29731
29876
|
}
|
|
29732
29877
|
}, async ({ from: fromParam, to, content, session_id, priority, working_dir, repository, branch, metadata, blocking }) => {
|
|
29733
29878
|
const from = resolveIdentity(fromParam);
|
|
@@ -29737,7 +29882,7 @@ server.registerTool("send_message", {
|
|
|
29737
29882
|
parsedMetadata = JSON.parse(metadata);
|
|
29738
29883
|
} catch {
|
|
29739
29884
|
return {
|
|
29740
|
-
content: [{ type: "text", text: "
|
|
29885
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
29741
29886
|
isError: true
|
|
29742
29887
|
};
|
|
29743
29888
|
}
|
|
@@ -29760,15 +29905,15 @@ server.registerTool("send_message", {
|
|
|
29760
29905
|
});
|
|
29761
29906
|
server.registerTool("read_messages", {
|
|
29762
29907
|
title: "Read Messages",
|
|
29763
|
-
description: "Read messages with
|
|
29908
|
+
description: "Read messages with filters, newest first.",
|
|
29764
29909
|
inputSchema: {
|
|
29765
29910
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
29766
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
29767
|
-
to: exports_external.string().optional().describe("Filter by recipient
|
|
29911
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
29912
|
+
to: exports_external.string().optional().describe("Filter by recipient"),
|
|
29768
29913
|
space: exports_external.string().optional().describe("Filter by space name"),
|
|
29769
|
-
since: exports_external.string().optional().describe("
|
|
29770
|
-
limit: exports_external.number().optional().describe("Max messages to return"),
|
|
29771
|
-
unread_only: exports_external.boolean().optional().describe("Only
|
|
29914
|
+
since: exports_external.string().optional().describe("ISO timestamp lower bound"),
|
|
29915
|
+
limit: exports_external.number().optional().describe("Max messages to return (default 20)"),
|
|
29916
|
+
unread_only: exports_external.boolean().optional().describe("Only unread messages")
|
|
29772
29917
|
}
|
|
29773
29918
|
}, async (opts) => {
|
|
29774
29919
|
const messages = readMessages(opts);
|
|
@@ -29778,7 +29923,7 @@ server.registerTool("read_messages", {
|
|
|
29778
29923
|
});
|
|
29779
29924
|
server.registerTool("list_sessions", {
|
|
29780
29925
|
title: "List Sessions",
|
|
29781
|
-
description: "List
|
|
29926
|
+
description: "List sessions, optionally filtered by agent.",
|
|
29782
29927
|
inputSchema: {
|
|
29783
29928
|
agent: exports_external.string().optional().describe("Filter sessions involving this agent")
|
|
29784
29929
|
}
|
|
@@ -29790,7 +29935,7 @@ server.registerTool("list_sessions", {
|
|
|
29790
29935
|
});
|
|
29791
29936
|
server.registerTool("reply", {
|
|
29792
29937
|
title: "Reply to Message",
|
|
29793
|
-
description: "Reply to a message
|
|
29938
|
+
description: "Reply to a message (same session, original sender).",
|
|
29794
29939
|
inputSchema: {
|
|
29795
29940
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
29796
29941
|
message_id: exports_external.number().describe("ID of the message to reply to"),
|
|
@@ -29822,7 +29967,7 @@ server.registerTool("reply", {
|
|
|
29822
29967
|
});
|
|
29823
29968
|
server.registerTool("mark_read", {
|
|
29824
29969
|
title: "Mark Read",
|
|
29825
|
-
description: "Mark
|
|
29970
|
+
description: "Mark messages as read. Provide IDs or set 'all' to true.",
|
|
29826
29971
|
inputSchema: {
|
|
29827
29972
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
29828
29973
|
ids: exports_external.array(exports_external.number()).optional().describe("Message IDs to mark as read"),
|
|
@@ -29837,7 +29982,7 @@ server.registerTool("mark_read", {
|
|
|
29837
29982
|
count = markRead(ids, agent);
|
|
29838
29983
|
} else {
|
|
29839
29984
|
return {
|
|
29840
|
-
content: [{ type: "text", text: "
|
|
29985
|
+
content: [{ type: "text", text: "provide ids or set all=true" }],
|
|
29841
29986
|
isError: true
|
|
29842
29987
|
};
|
|
29843
29988
|
}
|
|
@@ -29847,13 +29992,13 @@ server.registerTool("mark_read", {
|
|
|
29847
29992
|
});
|
|
29848
29993
|
server.registerTool("search_messages", {
|
|
29849
29994
|
title: "Search Messages",
|
|
29850
|
-
description: "Full-text search across message content
|
|
29995
|
+
description: "Full-text search across message content, newest first.",
|
|
29851
29996
|
inputSchema: {
|
|
29852
|
-
query: exports_external.string().describe("Search query
|
|
29853
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
29854
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
29855
|
-
to: exports_external.string().optional().describe("Filter by recipient
|
|
29856
|
-
limit: exports_external.number().optional().describe("Max results
|
|
29997
|
+
query: exports_external.string().describe("Search query"),
|
|
29998
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
29999
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
30000
|
+
to: exports_external.string().optional().describe("Filter by recipient"),
|
|
30001
|
+
limit: exports_external.number().optional().describe("Max results (default 20)")
|
|
29857
30002
|
}
|
|
29858
30003
|
}, async ({ query, space, from, to, limit }) => {
|
|
29859
30004
|
const messages = searchMessages({ query, space, from, to, limit });
|
|
@@ -29865,11 +30010,11 @@ server.registerTool("export_messages", {
|
|
|
29865
30010
|
title: "Export Messages",
|
|
29866
30011
|
description: "Export messages as JSON or CSV with optional filters.",
|
|
29867
30012
|
inputSchema: {
|
|
29868
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
30013
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
29869
30014
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
29870
|
-
from: exports_external.string().optional().describe("Filter by sender
|
|
29871
|
-
since: exports_external.string().optional().describe("
|
|
29872
|
-
until: exports_external.string().optional().describe("
|
|
30015
|
+
from: exports_external.string().optional().describe("Filter by sender"),
|
|
30016
|
+
since: exports_external.string().optional().describe("ISO date lower bound"),
|
|
30017
|
+
until: exports_external.string().optional().describe("ISO date upper bound"),
|
|
29873
30018
|
format: exports_external.enum(["json", "csv"]).optional().describe("Output format (default: json)")
|
|
29874
30019
|
}
|
|
29875
30020
|
}, async ({ space, session_id, from, since, until, format }) => {
|
|
@@ -29880,13 +30025,13 @@ server.registerTool("export_messages", {
|
|
|
29880
30025
|
});
|
|
29881
30026
|
server.registerTool("create_space", {
|
|
29882
30027
|
title: "Create Space",
|
|
29883
|
-
description: "Create a
|
|
30028
|
+
description: "Create a space. Auto-joined. Supports nesting and projects.",
|
|
29884
30029
|
inputSchema: {
|
|
29885
30030
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
29886
|
-
name: exports_external.string().describe("Space name
|
|
30031
|
+
name: exports_external.string().describe("Space name"),
|
|
29887
30032
|
description: exports_external.string().optional().describe("Space description"),
|
|
29888
|
-
parent_id: exports_external.string().optional().describe("Parent space name
|
|
29889
|
-
project_id: exports_external.string().optional().describe("Project ID to associate
|
|
30033
|
+
parent_id: exports_external.string().optional().describe("Parent space name (max 3 levels deep)"),
|
|
30034
|
+
project_id: exports_external.string().optional().describe("Project ID to associate with")
|
|
29890
30035
|
}
|
|
29891
30036
|
}, async ({ from: fromParam, name, description, parent_id, project_id }) => {
|
|
29892
30037
|
const agent = resolveIdentity(fromParam);
|
|
@@ -29898,7 +30043,7 @@ server.registerTool("create_space", {
|
|
|
29898
30043
|
} catch (e) {
|
|
29899
30044
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
29900
30045
|
return {
|
|
29901
|
-
content: [{ type: "text", text: `
|
|
30046
|
+
content: [{ type: "text", text: `space "${name}" already exists` }],
|
|
29902
30047
|
isError: true
|
|
29903
30048
|
};
|
|
29904
30049
|
}
|
|
@@ -29910,11 +30055,11 @@ server.registerTool("create_space", {
|
|
|
29910
30055
|
});
|
|
29911
30056
|
server.registerTool("list_spaces", {
|
|
29912
30057
|
title: "List Spaces",
|
|
29913
|
-
description: "List
|
|
30058
|
+
description: "List spaces with member/message counts.",
|
|
29914
30059
|
inputSchema: {
|
|
29915
30060
|
project_id: exports_external.string().optional().describe("Filter by project ID"),
|
|
29916
|
-
parent_id: exports_external.string().optional().describe("Filter by parent space
|
|
29917
|
-
include_archived: exports_external.boolean().optional().describe("Include archived spaces
|
|
30061
|
+
parent_id: exports_external.string().optional().describe("Filter by parent space. Use 'null' for top-level only."),
|
|
30062
|
+
include_archived: exports_external.boolean().optional().describe("Include archived spaces")
|
|
29918
30063
|
}
|
|
29919
30064
|
}, async ({ project_id, parent_id, include_archived }) => {
|
|
29920
30065
|
const opts = {};
|
|
@@ -29940,14 +30085,14 @@ server.registerTool("send_to_space", {
|
|
|
29940
30085
|
space: exports_external.string().describe("Space name"),
|
|
29941
30086
|
content: exports_external.string().describe("Message content"),
|
|
29942
30087
|
priority: exports_external.enum(["low", "normal", "high", "urgent"]).optional().describe("Message priority"),
|
|
29943
|
-
blocking: exports_external.boolean().optional().describe("
|
|
30088
|
+
blocking: exports_external.boolean().optional().describe("Blocking message \u2014 all space members must acknowledge")
|
|
29944
30089
|
}
|
|
29945
30090
|
}, async ({ from: fromParam, space, content, priority, blocking }) => {
|
|
29946
30091
|
const from = resolveIdentity(fromParam);
|
|
29947
30092
|
const sp = getSpace(space);
|
|
29948
30093
|
if (!sp) {
|
|
29949
30094
|
return {
|
|
29950
|
-
content: [{ type: "text", text: `
|
|
30095
|
+
content: [{ type: "text", text: `space "${space}" not found` }],
|
|
29951
30096
|
isError: true
|
|
29952
30097
|
};
|
|
29953
30098
|
}
|
|
@@ -29969,7 +30114,7 @@ server.registerTool("read_space", {
|
|
|
29969
30114
|
description: "Read messages from a space.",
|
|
29970
30115
|
inputSchema: {
|
|
29971
30116
|
space: exports_external.string().describe("Space name"),
|
|
29972
|
-
since: exports_external.string().optional().describe("
|
|
30117
|
+
since: exports_external.string().optional().describe("ISO timestamp lower bound"),
|
|
29973
30118
|
limit: exports_external.number().optional().describe("Max messages to return")
|
|
29974
30119
|
}
|
|
29975
30120
|
}, async ({ space, since, limit }) => {
|
|
@@ -29990,7 +30135,7 @@ server.registerTool("join_space", {
|
|
|
29990
30135
|
const ok = joinSpace(space, agent);
|
|
29991
30136
|
if (!ok) {
|
|
29992
30137
|
return {
|
|
29993
|
-
content: [{ type: "text", text: `
|
|
30138
|
+
content: [{ type: "text", text: `space "${space}" not found` }],
|
|
29994
30139
|
isError: true
|
|
29995
30140
|
};
|
|
29996
30141
|
}
|
|
@@ -30014,12 +30159,12 @@ server.registerTool("leave_space", {
|
|
|
30014
30159
|
});
|
|
30015
30160
|
server.registerTool("update_space", {
|
|
30016
30161
|
title: "Update Space",
|
|
30017
|
-
description: "Update a space's description, parent, or project
|
|
30162
|
+
description: "Update a space's description, parent, or project.",
|
|
30018
30163
|
inputSchema: {
|
|
30019
|
-
name: exports_external.string().describe("Space name
|
|
30164
|
+
name: exports_external.string().describe("Space name"),
|
|
30020
30165
|
description: exports_external.string().optional().describe("New description"),
|
|
30021
|
-
parent_id: exports_external.string().optional().describe("New parent space
|
|
30022
|
-
project_id: exports_external.string().optional().describe("New project ID (use 'null' to remove
|
|
30166
|
+
parent_id: exports_external.string().optional().describe("New parent space (use 'null' to remove)"),
|
|
30167
|
+
project_id: exports_external.string().optional().describe("New project ID (use 'null' to remove)")
|
|
30023
30168
|
}
|
|
30024
30169
|
}, async ({ name, description, parent_id, project_id }) => {
|
|
30025
30170
|
const updates = {};
|
|
@@ -30043,7 +30188,7 @@ server.registerTool("update_space", {
|
|
|
30043
30188
|
});
|
|
30044
30189
|
server.registerTool("archive_space", {
|
|
30045
30190
|
title: "Archive Space",
|
|
30046
|
-
description: "Archive a space.
|
|
30191
|
+
description: "Archive a space. Hidden from list by default.",
|
|
30047
30192
|
inputSchema: {
|
|
30048
30193
|
name: exports_external.string().describe("Space name to archive")
|
|
30049
30194
|
}
|
|
@@ -30081,16 +30226,16 @@ server.registerTool("unarchive_space", {
|
|
|
30081
30226
|
});
|
|
30082
30227
|
server.registerTool("create_project", {
|
|
30083
30228
|
title: "Create Project",
|
|
30084
|
-
description: "Create a
|
|
30229
|
+
description: "Create a project for spaces and agent collaboration.",
|
|
30085
30230
|
inputSchema: {
|
|
30086
30231
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30087
30232
|
name: exports_external.string().describe("Project name (unique)"),
|
|
30088
30233
|
description: exports_external.string().optional().describe("Project description"),
|
|
30089
|
-
path: exports_external.string().optional().describe("Absolute path
|
|
30234
|
+
path: exports_external.string().optional().describe("Absolute path on disk"),
|
|
30090
30235
|
repository: exports_external.string().optional().describe("Repository URL"),
|
|
30091
|
-
tags: exports_external.string().optional().describe(
|
|
30092
|
-
metadata: exports_external.string().optional().describe("JSON metadata
|
|
30093
|
-
settings: exports_external.string().optional().describe("JSON settings
|
|
30236
|
+
tags: exports_external.string().optional().describe("JSON array of tags"),
|
|
30237
|
+
metadata: exports_external.string().optional().describe("JSON metadata"),
|
|
30238
|
+
settings: exports_external.string().optional().describe("JSON settings")
|
|
30094
30239
|
}
|
|
30095
30240
|
}, async ({ from: fromParam, name, description, path, repository, tags, metadata, settings }) => {
|
|
30096
30241
|
const agent = resolveIdentity(fromParam);
|
|
@@ -30100,7 +30245,7 @@ server.registerTool("create_project", {
|
|
|
30100
30245
|
parsedTags = JSON.parse(tags);
|
|
30101
30246
|
} catch {
|
|
30102
30247
|
return {
|
|
30103
|
-
content: [{ type: "text", text: "
|
|
30248
|
+
content: [{ type: "text", text: "invalid tags JSON (expected array)" }],
|
|
30104
30249
|
isError: true
|
|
30105
30250
|
};
|
|
30106
30251
|
}
|
|
@@ -30111,7 +30256,7 @@ server.registerTool("create_project", {
|
|
|
30111
30256
|
parsedMetadata = JSON.parse(metadata);
|
|
30112
30257
|
} catch {
|
|
30113
30258
|
return {
|
|
30114
|
-
content: [{ type: "text", text: "
|
|
30259
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
30115
30260
|
isError: true
|
|
30116
30261
|
};
|
|
30117
30262
|
}
|
|
@@ -30122,7 +30267,7 @@ server.registerTool("create_project", {
|
|
|
30122
30267
|
parsedSettings = JSON.parse(settings);
|
|
30123
30268
|
} catch {
|
|
30124
30269
|
return {
|
|
30125
|
-
content: [{ type: "text", text: "
|
|
30270
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
30126
30271
|
isError: true
|
|
30127
30272
|
};
|
|
30128
30273
|
}
|
|
@@ -30144,7 +30289,7 @@ server.registerTool("create_project", {
|
|
|
30144
30289
|
} catch (e) {
|
|
30145
30290
|
if (e.message?.includes("UNIQUE constraint")) {
|
|
30146
30291
|
return {
|
|
30147
|
-
content: [{ type: "text", text: `
|
|
30292
|
+
content: [{ type: "text", text: `project "${name}" already exists` }],
|
|
30148
30293
|
isError: true
|
|
30149
30294
|
};
|
|
30150
30295
|
}
|
|
@@ -30158,7 +30303,7 @@ server.registerTool("list_projects", {
|
|
|
30158
30303
|
title: "List Projects",
|
|
30159
30304
|
description: "List all registered projects.",
|
|
30160
30305
|
inputSchema: {
|
|
30161
|
-
status: exports_external.enum(["active", "archived"]).optional().describe("Filter by
|
|
30306
|
+
status: exports_external.enum(["active", "archived"]).optional().describe("Filter by status")
|
|
30162
30307
|
}
|
|
30163
30308
|
}, async ({ status }) => {
|
|
30164
30309
|
const projects = listProjects(status ? { status } : undefined);
|
|
@@ -30179,7 +30324,7 @@ server.registerTool("get_project", {
|
|
|
30179
30324
|
}
|
|
30180
30325
|
if (!project) {
|
|
30181
30326
|
return {
|
|
30182
|
-
content: [{ type: "text", text: `
|
|
30327
|
+
content: [{ type: "text", text: `project "${id}" not found` }],
|
|
30183
30328
|
isError: true
|
|
30184
30329
|
};
|
|
30185
30330
|
}
|
|
@@ -30192,14 +30337,14 @@ server.registerTool("update_project", {
|
|
|
30192
30337
|
description: "Update a project's fields.",
|
|
30193
30338
|
inputSchema: {
|
|
30194
30339
|
id: exports_external.string().describe("Project ID (UUID)"),
|
|
30195
|
-
name: exports_external.string().optional().describe("New
|
|
30340
|
+
name: exports_external.string().optional().describe("New name"),
|
|
30196
30341
|
description: exports_external.string().optional().describe("New description"),
|
|
30197
30342
|
path: exports_external.string().optional().describe("New path"),
|
|
30198
30343
|
status: exports_external.enum(["active", "archived"]).optional().describe("New status"),
|
|
30199
30344
|
repository: exports_external.string().optional().describe("New repository URL"),
|
|
30200
30345
|
tags: exports_external.string().optional().describe("JSON array of tags"),
|
|
30201
|
-
metadata: exports_external.string().optional().describe("JSON metadata
|
|
30202
|
-
settings: exports_external.string().optional().describe("JSON settings
|
|
30346
|
+
metadata: exports_external.string().optional().describe("JSON metadata"),
|
|
30347
|
+
settings: exports_external.string().optional().describe("JSON settings")
|
|
30203
30348
|
}
|
|
30204
30349
|
}, async ({ id, name, description, path, status, repository, tags, metadata, settings }) => {
|
|
30205
30350
|
const updates = {};
|
|
@@ -30218,7 +30363,7 @@ server.registerTool("update_project", {
|
|
|
30218
30363
|
updates.tags = JSON.parse(tags);
|
|
30219
30364
|
} catch {
|
|
30220
30365
|
return {
|
|
30221
|
-
content: [{ type: "text", text: "
|
|
30366
|
+
content: [{ type: "text", text: "invalid tags JSON" }],
|
|
30222
30367
|
isError: true
|
|
30223
30368
|
};
|
|
30224
30369
|
}
|
|
@@ -30228,7 +30373,7 @@ server.registerTool("update_project", {
|
|
|
30228
30373
|
updates.metadata = JSON.parse(metadata);
|
|
30229
30374
|
} catch {
|
|
30230
30375
|
return {
|
|
30231
|
-
content: [{ type: "text", text: "
|
|
30376
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
30232
30377
|
isError: true
|
|
30233
30378
|
};
|
|
30234
30379
|
}
|
|
@@ -30238,7 +30383,7 @@ server.registerTool("update_project", {
|
|
|
30238
30383
|
updates.settings = JSON.parse(settings);
|
|
30239
30384
|
} catch {
|
|
30240
30385
|
return {
|
|
30241
|
-
content: [{ type: "text", text: "
|
|
30386
|
+
content: [{ type: "text", text: "invalid JSON" }],
|
|
30242
30387
|
isError: true
|
|
30243
30388
|
};
|
|
30244
30389
|
}
|
|
@@ -30257,7 +30402,7 @@ server.registerTool("update_project", {
|
|
|
30257
30402
|
});
|
|
30258
30403
|
server.registerTool("delete_project", {
|
|
30259
30404
|
title: "Delete Project",
|
|
30260
|
-
description: "Delete a project permanently. Fails if spaces
|
|
30405
|
+
description: "Delete a project permanently. Fails if spaces reference it.",
|
|
30261
30406
|
inputSchema: {
|
|
30262
30407
|
id: exports_external.string().describe("Project ID (UUID)")
|
|
30263
30408
|
}
|
|
@@ -30266,7 +30411,7 @@ server.registerTool("delete_project", {
|
|
|
30266
30411
|
const deleted = deleteProject(id);
|
|
30267
30412
|
if (!deleted) {
|
|
30268
30413
|
return {
|
|
30269
|
-
content: [{ type: "text", text: `
|
|
30414
|
+
content: [{ type: "text", text: `project "${id}" not found` }],
|
|
30270
30415
|
isError: true
|
|
30271
30416
|
};
|
|
30272
30417
|
}
|
|
@@ -30282,7 +30427,7 @@ server.registerTool("delete_project", {
|
|
|
30282
30427
|
});
|
|
30283
30428
|
server.registerTool("delete_message", {
|
|
30284
30429
|
title: "Delete Message",
|
|
30285
|
-
description: "Delete a message.
|
|
30430
|
+
description: "Delete a message. Sender only.",
|
|
30286
30431
|
inputSchema: {
|
|
30287
30432
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30288
30433
|
id: exports_external.number().describe("Message ID to delete")
|
|
@@ -30292,7 +30437,7 @@ server.registerTool("delete_message", {
|
|
|
30292
30437
|
const deleted = deleteMessage(id, agent);
|
|
30293
30438
|
if (!deleted) {
|
|
30294
30439
|
return {
|
|
30295
|
-
content: [{ type: "text", text: `
|
|
30440
|
+
content: [{ type: "text", text: `not found or forbidden` }],
|
|
30296
30441
|
isError: true
|
|
30297
30442
|
};
|
|
30298
30443
|
}
|
|
@@ -30302,7 +30447,7 @@ server.registerTool("delete_message", {
|
|
|
30302
30447
|
});
|
|
30303
30448
|
server.registerTool("edit_message", {
|
|
30304
30449
|
title: "Edit Message",
|
|
30305
|
-
description: "Edit a message's content.
|
|
30450
|
+
description: "Edit a message's content. Sender only.",
|
|
30306
30451
|
inputSchema: {
|
|
30307
30452
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30308
30453
|
id: exports_external.number().describe("Message ID to edit"),
|
|
@@ -30313,7 +30458,7 @@ server.registerTool("edit_message", {
|
|
|
30313
30458
|
const msg = editMessage(id, agent, content);
|
|
30314
30459
|
if (!msg) {
|
|
30315
30460
|
return {
|
|
30316
|
-
content: [{ type: "text", text: `
|
|
30461
|
+
content: [{ type: "text", text: `not found or forbidden` }],
|
|
30317
30462
|
isError: true
|
|
30318
30463
|
};
|
|
30319
30464
|
}
|
|
@@ -30323,7 +30468,7 @@ server.registerTool("edit_message", {
|
|
|
30323
30468
|
});
|
|
30324
30469
|
server.registerTool("pin_message", {
|
|
30325
30470
|
title: "Pin Message",
|
|
30326
|
-
description: "Pin a message
|
|
30471
|
+
description: "Pin a message in a space or session.",
|
|
30327
30472
|
inputSchema: {
|
|
30328
30473
|
id: exports_external.number().describe("Message ID to pin")
|
|
30329
30474
|
}
|
|
@@ -30331,7 +30476,7 @@ server.registerTool("pin_message", {
|
|
|
30331
30476
|
const msg = pinMessage(id);
|
|
30332
30477
|
if (!msg) {
|
|
30333
30478
|
return {
|
|
30334
|
-
content: [{ type: "text", text: `
|
|
30479
|
+
content: [{ type: "text", text: `message #${id} not found` }],
|
|
30335
30480
|
isError: true
|
|
30336
30481
|
};
|
|
30337
30482
|
}
|
|
@@ -30349,7 +30494,7 @@ server.registerTool("unpin_message", {
|
|
|
30349
30494
|
const msg = unpinMessage(id);
|
|
30350
30495
|
if (!msg) {
|
|
30351
30496
|
return {
|
|
30352
|
-
content: [{ type: "text", text: `
|
|
30497
|
+
content: [{ type: "text", text: `message #${id} not found` }],
|
|
30353
30498
|
isError: true
|
|
30354
30499
|
};
|
|
30355
30500
|
}
|
|
@@ -30359,9 +30504,9 @@ server.registerTool("unpin_message", {
|
|
|
30359
30504
|
});
|
|
30360
30505
|
server.registerTool("get_pinned_messages", {
|
|
30361
30506
|
title: "Get Pinned Messages",
|
|
30362
|
-
description: "
|
|
30507
|
+
description: "Get pinned messages, filtered by space or session.",
|
|
30363
30508
|
inputSchema: {
|
|
30364
|
-
space: exports_external.string().optional().describe("Filter by space
|
|
30509
|
+
space: exports_external.string().optional().describe("Filter by space"),
|
|
30365
30510
|
session_id: exports_external.string().optional().describe("Filter by session ID"),
|
|
30366
30511
|
limit: exports_external.number().optional().describe("Max messages to return")
|
|
30367
30512
|
}
|
|
@@ -30373,7 +30518,7 @@ server.registerTool("get_pinned_messages", {
|
|
|
30373
30518
|
});
|
|
30374
30519
|
server.registerTool("heartbeat", {
|
|
30375
30520
|
title: "Heartbeat",
|
|
30376
|
-
description: "Send
|
|
30521
|
+
description: "Send heartbeat. Optionally set agent status.",
|
|
30377
30522
|
inputSchema: {
|
|
30378
30523
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30379
30524
|
status: exports_external.string().optional().describe("Agent status (e.g. 'online', 'busy', 'idle'). Defaults to 'online'.")
|
|
@@ -30387,9 +30532,9 @@ server.registerTool("heartbeat", {
|
|
|
30387
30532
|
});
|
|
30388
30533
|
server.registerTool("list_agents", {
|
|
30389
30534
|
title: "List Agents",
|
|
30390
|
-
description: "List
|
|
30535
|
+
description: "List agents with presence status.",
|
|
30391
30536
|
inputSchema: {
|
|
30392
|
-
online_only: exports_external.boolean().optional().describe("Only return agents
|
|
30537
|
+
online_only: exports_external.boolean().optional().describe("Only return agents online within last 60s")
|
|
30393
30538
|
}
|
|
30394
30539
|
}, async ({ online_only }) => {
|
|
30395
30540
|
const agents = listAgents({ online_only });
|
|
@@ -30399,7 +30544,7 @@ server.registerTool("list_agents", {
|
|
|
30399
30544
|
});
|
|
30400
30545
|
server.registerTool("get_blockers", {
|
|
30401
30546
|
title: "Get Blockers",
|
|
30402
|
-
description: "Check for unread blocking messages
|
|
30547
|
+
description: "Check for unread blocking messages. Must acknowledge.",
|
|
30403
30548
|
inputSchema: {
|
|
30404
30549
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var.")
|
|
30405
30550
|
}
|
|
@@ -30412,7 +30557,7 @@ server.registerTool("get_blockers", {
|
|
|
30412
30557
|
});
|
|
30413
30558
|
server.registerTool("remove_agent", {
|
|
30414
30559
|
title: "Remove Agent",
|
|
30415
|
-
description: "Remove an agent from the presence list.
|
|
30560
|
+
description: "Remove an agent from the presence list.",
|
|
30416
30561
|
inputSchema: {
|
|
30417
30562
|
from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30418
30563
|
agent: exports_external.string().optional().describe("Agent to remove (defaults to yourself)")
|
|
@@ -30423,7 +30568,7 @@ server.registerTool("remove_agent", {
|
|
|
30423
30568
|
const removed = removePresence(agent);
|
|
30424
30569
|
if (!removed) {
|
|
30425
30570
|
return {
|
|
30426
|
-
content: [{ type: "text", text: `
|
|
30571
|
+
content: [{ type: "text", text: `agent "${agent}" not found` }],
|
|
30427
30572
|
isError: true
|
|
30428
30573
|
};
|
|
30429
30574
|
}
|
|
@@ -30433,7 +30578,7 @@ server.registerTool("remove_agent", {
|
|
|
30433
30578
|
});
|
|
30434
30579
|
server.registerTool("rename_agent", {
|
|
30435
30580
|
title: "Rename Agent",
|
|
30436
|
-
description: "Rename an agent in the presence list.
|
|
30581
|
+
description: "Rename an agent in the presence list.",
|
|
30437
30582
|
inputSchema: {
|
|
30438
30583
|
from: exports_external.string().optional().describe("Your current agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
|
|
30439
30584
|
new_name: exports_external.string().describe("The new name for the agent")
|
|
@@ -30443,7 +30588,7 @@ server.registerTool("rename_agent", {
|
|
|
30443
30588
|
const newName = new_name.trim();
|
|
30444
30589
|
if (!newName) {
|
|
30445
30590
|
return {
|
|
30446
|
-
content: [{ type: "text", text: "
|
|
30591
|
+
content: [{ type: "text", text: "new name cannot be empty" }],
|
|
30447
30592
|
isError: true
|
|
30448
30593
|
};
|
|
30449
30594
|
}
|
|
@@ -30451,7 +30596,7 @@ server.registerTool("rename_agent", {
|
|
|
30451
30596
|
const renamed = renameAgent(oldName, newName);
|
|
30452
30597
|
if (!renamed) {
|
|
30453
30598
|
return {
|
|
30454
|
-
content: [{ type: "text", text: `
|
|
30599
|
+
content: [{ type: "text", text: `agent "${oldName}" not found` }],
|
|
30455
30600
|
isError: true
|
|
30456
30601
|
};
|
|
30457
30602
|
}
|
|
@@ -30465,6 +30610,78 @@ server.registerTool("rename_agent", {
|
|
|
30465
30610
|
};
|
|
30466
30611
|
}
|
|
30467
30612
|
});
|
|
30613
|
+
server.registerTool("search_tools", {
|
|
30614
|
+
title: "Search Tools",
|
|
30615
|
+
description: "List tool names, optionally filtered by keyword.",
|
|
30616
|
+
inputSchema: {
|
|
30617
|
+
query: exports_external.string().optional().describe("Keyword filter")
|
|
30618
|
+
}
|
|
30619
|
+
}, async ({ query }) => {
|
|
30620
|
+
const all = [
|
|
30621
|
+
"send_message",
|
|
30622
|
+
"read_messages",
|
|
30623
|
+
"list_sessions",
|
|
30624
|
+
"reply",
|
|
30625
|
+
"mark_read",
|
|
30626
|
+
"search_messages",
|
|
30627
|
+
"export_messages",
|
|
30628
|
+
"create_space",
|
|
30629
|
+
"list_spaces",
|
|
30630
|
+
"send_to_space",
|
|
30631
|
+
"read_space",
|
|
30632
|
+
"join_space",
|
|
30633
|
+
"leave_space",
|
|
30634
|
+
"update_space",
|
|
30635
|
+
"archive_space",
|
|
30636
|
+
"unarchive_space",
|
|
30637
|
+
"create_project",
|
|
30638
|
+
"list_projects",
|
|
30639
|
+
"get_project",
|
|
30640
|
+
"update_project",
|
|
30641
|
+
"delete_project",
|
|
30642
|
+
"delete_message",
|
|
30643
|
+
"edit_message",
|
|
30644
|
+
"pin_message",
|
|
30645
|
+
"unpin_message",
|
|
30646
|
+
"get_pinned_messages",
|
|
30647
|
+
"heartbeat",
|
|
30648
|
+
"list_agents",
|
|
30649
|
+
"get_blockers",
|
|
30650
|
+
"remove_agent",
|
|
30651
|
+
"rename_agent",
|
|
30652
|
+
"search_tools",
|
|
30653
|
+
"describe_tools"
|
|
30654
|
+
];
|
|
30655
|
+
const q = query?.toLowerCase();
|
|
30656
|
+
const matches = q ? all.filter((n) => n.includes(q)) : all;
|
|
30657
|
+
return { content: [{ type: "text", text: matches.join(", ") }] };
|
|
30658
|
+
});
|
|
30659
|
+
server.registerTool("describe_tools", {
|
|
30660
|
+
title: "Describe Tools",
|
|
30661
|
+
description: "Get descriptions for specific tools by name.",
|
|
30662
|
+
inputSchema: {
|
|
30663
|
+
names: exports_external.array(exports_external.string()).describe("Tool names from search_tools")
|
|
30664
|
+
}
|
|
30665
|
+
}, async ({ names }) => {
|
|
30666
|
+
const descriptions = {
|
|
30667
|
+
send_message: "Send DM to agent. Params: to, content, from?, priority?",
|
|
30668
|
+
read_messages: "Read messages. Params: space?, from?, to?, unread_only?, limit?",
|
|
30669
|
+
list_sessions: "List sessions. Params: agent?",
|
|
30670
|
+
reply: "Reply to message. Params: id, content, from?",
|
|
30671
|
+
send_to_space: "Send message to space. Params: space, content, from?",
|
|
30672
|
+
read_space: "Read space messages. Params: space, limit?, since?",
|
|
30673
|
+
join_space: "Join a space. Params: space, from?",
|
|
30674
|
+
create_space: "Create space. Params: name, description?, parent_id?",
|
|
30675
|
+
list_spaces: "List spaces with counts. No required params.",
|
|
30676
|
+
heartbeat: "Send heartbeat. Params: from?, status?",
|
|
30677
|
+
list_agents: "List agents with presence. No required params.",
|
|
30678
|
+
get_blockers: "Check for blocking messages. Params: name?",
|
|
30679
|
+
search_messages: "Search messages. Params: query, space?, limit?"
|
|
30680
|
+
};
|
|
30681
|
+
const result = names.map((n) => `${n}: ${descriptions[n] || "See tool schema"}`).join(`
|
|
30682
|
+
`);
|
|
30683
|
+
return { content: [{ type: "text", text: result }] };
|
|
30684
|
+
});
|
|
30468
30685
|
async function startMcpServer() {
|
|
30469
30686
|
const transport = new StdioServerTransport;
|
|
30470
30687
|
await server.connect(transport);
|