@hasna/conversations 0.1.20 → 0.1.22

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/mcp.js CHANGED
@@ -29252,10 +29252,6 @@ function getProjectByName(name) {
29252
29252
  }
29253
29253
  function updateProject(id, updates) {
29254
29254
  const db2 = getDb();
29255
- const existing = db2.prepare("SELECT * FROM projects WHERE id = ?").get(id);
29256
- if (!existing) {
29257
- throw new Error(`Project not found: ${id}`);
29258
- }
29259
29255
  const sets = [];
29260
29256
  const params = [];
29261
29257
  if (updates.name !== undefined) {
@@ -29291,10 +29287,15 @@ function updateProject(id, updates) {
29291
29287
  params.push(JSON.stringify(updates.settings));
29292
29288
  }
29293
29289
  if (sets.length === 0) {
29294
- return parseProject(existing);
29290
+ const row2 = db2.prepare("SELECT * FROM projects WHERE id = ?").get(id);
29291
+ if (!row2)
29292
+ throw new Error(`Project not found: ${id}`);
29293
+ return parseProject(row2);
29295
29294
  }
29296
29295
  params.push(id);
29297
29296
  const row = db2.prepare(`UPDATE projects SET ${sets.join(", ")} WHERE id = ? RETURNING *`).get(...params);
29297
+ if (!row)
29298
+ throw new Error(`Project not found: ${id}`);
29298
29299
  return parseProject(row);
29299
29300
  }
29300
29301
  function deleteProject(id) {
@@ -29777,7 +29778,7 @@ function renameAgent(oldName, newName) {
29777
29778
  // package.json
29778
29779
  var package_default = {
29779
29780
  name: "@hasna/conversations",
29780
- version: "0.1.20",
29781
+ version: "0.1.22",
29781
29782
  description: "Real-time CLI messaging for AI agents",
29782
29783
  type: "module",
29783
29784
  bin: {
@@ -29860,89 +29861,66 @@ var server = new McpServer({
29860
29861
  version: package_default.version
29861
29862
  });
29862
29863
  server.registerTool("send_message", {
29863
- title: "Send Message",
29864
- description: "Send a direct message to another agent.",
29864
+ description: "Send a DM to an agent.",
29865
29865
  inputSchema: {
29866
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
29867
- to: exports_external.string().describe("Recipient agent ID"),
29868
- content: exports_external.string().describe("Message content"),
29869
- session_id: exports_external.string().optional().describe("Session ID (auto-generated if omitted)"),
29870
- priority: exports_external.enum(["low", "normal", "high", "urgent"]).optional().describe("Message priority"),
29871
- working_dir: exports_external.string().optional().describe("Working directory context"),
29872
- repository: exports_external.string().optional().describe("Repository context"),
29873
- branch: exports_external.string().optional().describe("Branch context"),
29874
- metadata: exports_external.string().optional().describe("JSON metadata string"),
29875
- blocking: exports_external.boolean().optional().describe("Blocking message \u2014 recipients must acknowledge before continuing")
29876
- }
29877
- }, async ({ from: fromParam, to, content, session_id, priority, working_dir, repository, branch, metadata, blocking }) => {
29866
+ to: exports_external.string(),
29867
+ content: exports_external.string(),
29868
+ from: exports_external.string().optional(),
29869
+ priority: exports_external.string().optional(),
29870
+ blocking: exports_external.boolean().optional()
29871
+ }
29872
+ }, async (args) => {
29873
+ const { from: fromParam, to, content, priority, blocking } = args;
29878
29874
  const from = resolveIdentity(fromParam);
29879
- let parsedMetadata;
29880
- if (metadata) {
29881
- try {
29882
- parsedMetadata = JSON.parse(metadata);
29883
- } catch {
29884
- return {
29885
- content: [{ type: "text", text: "invalid JSON" }],
29886
- isError: true
29887
- };
29888
- }
29889
- }
29890
29875
  const msg = sendMessage({
29891
29876
  from,
29892
29877
  to,
29893
29878
  content,
29894
- session_id,
29895
29879
  priority,
29896
- working_dir,
29897
- repository,
29898
- branch,
29899
- metadata: parsedMetadata,
29900
29880
  blocking
29901
29881
  });
29902
29882
  return {
29903
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
29883
+ content: [{ type: "text", text: JSON.stringify(msg) }]
29904
29884
  };
29905
29885
  });
29906
29886
  server.registerTool("read_messages", {
29907
- title: "Read Messages",
29908
- description: "Read messages with filters, newest first.",
29887
+ description: "Read DMs with optional filters.",
29909
29888
  inputSchema: {
29910
- session_id: exports_external.string().optional().describe("Filter by session ID"),
29911
- from: exports_external.string().optional().describe("Filter by sender"),
29912
- to: exports_external.string().optional().describe("Filter by recipient"),
29913
- space: exports_external.string().optional().describe("Filter by space name"),
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")
29917
- }
29918
- }, async (opts) => {
29919
- const messages = readMessages(opts);
29889
+ session_id: exports_external.string().optional(),
29890
+ from: exports_external.string().optional(),
29891
+ to: exports_external.string().optional(),
29892
+ space: exports_external.string().optional(),
29893
+ since: exports_external.string().optional(),
29894
+ limit: exports_external.number().optional(),
29895
+ unread_only: exports_external.boolean().optional()
29896
+ }
29897
+ }, async (args) => {
29898
+ const messages = readMessages(args);
29920
29899
  return {
29921
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
29900
+ content: [{ type: "text", text: JSON.stringify(messages) }]
29922
29901
  };
29923
29902
  });
29924
29903
  server.registerTool("list_sessions", {
29925
- title: "List Sessions",
29926
- description: "List sessions, optionally filtered by agent.",
29904
+ description: "List all sessions by agent.",
29927
29905
  inputSchema: {
29928
- agent: exports_external.string().optional().describe("Filter sessions involving this agent")
29906
+ agent: exports_external.string().optional()
29929
29907
  }
29930
- }, async ({ agent }) => {
29908
+ }, async (args) => {
29909
+ const { agent } = args;
29931
29910
  const sessions = listSessions(agent);
29932
29911
  return {
29933
- content: [{ type: "text", text: JSON.stringify(sessions, null, 2) }]
29912
+ content: [{ type: "text", text: JSON.stringify(sessions) }]
29934
29913
  };
29935
29914
  });
29936
29915
  server.registerTool("reply", {
29937
- title: "Reply to Message",
29938
- description: "Reply to a message (same session, original sender).",
29916
+ description: "Reply to a message by ID.",
29939
29917
  inputSchema: {
29940
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
29941
- message_id: exports_external.number().describe("ID of the message to reply to"),
29942
- content: exports_external.string().describe("Reply content"),
29943
- priority: exports_external.enum(["low", "normal", "high", "urgent"]).optional().describe("Message priority")
29918
+ message_id: exports_external.number(),
29919
+ content: exports_external.string(),
29920
+ from: exports_external.string().optional()
29944
29921
  }
29945
- }, async ({ from: fromParam, message_id, content, priority }) => {
29922
+ }, async (args) => {
29923
+ const { from: fromParam, message_id, content } = args;
29946
29924
  const original = getMessageById(message_id);
29947
29925
  if (!original) {
29948
29926
  return {
@@ -29958,22 +29936,21 @@ server.registerTool("reply", {
29958
29936
  to,
29959
29937
  content,
29960
29938
  session_id: original.session_id,
29961
- priority,
29962
29939
  space
29963
29940
  });
29964
29941
  return {
29965
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
29942
+ content: [{ type: "text", text: JSON.stringify(msg) }]
29966
29943
  };
29967
29944
  });
29968
29945
  server.registerTool("mark_read", {
29969
- title: "Mark Read",
29970
- description: "Mark messages as read. Provide IDs or set 'all' to true.",
29946
+ description: "Mark messages read by IDs or all.",
29971
29947
  inputSchema: {
29972
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
29973
- ids: exports_external.array(exports_external.number()).optional().describe("Message IDs to mark as read"),
29974
- all: exports_external.boolean().optional().describe("Mark all unread messages as read")
29948
+ from: exports_external.string().optional(),
29949
+ ids: exports_external.array(exports_external.number()).optional(),
29950
+ all: exports_external.boolean().optional()
29975
29951
  }
29976
- }, async ({ from: fromParam, ids, all }) => {
29952
+ }, async (args) => {
29953
+ const { from: fromParam, ids, all } = args;
29977
29954
  const agent = resolveIdentity(fromParam);
29978
29955
  let count;
29979
29956
  if (all) {
@@ -29987,58 +29964,58 @@ server.registerTool("mark_read", {
29987
29964
  };
29988
29965
  }
29989
29966
  return {
29990
- content: [{ type: "text", text: JSON.stringify({ marked_read: count }, null, 2) }]
29967
+ content: [{ type: "text", text: JSON.stringify({ marked_read: count }) }]
29991
29968
  };
29992
29969
  });
29993
29970
  server.registerTool("search_messages", {
29994
- title: "Search Messages",
29995
- description: "Full-text search across message content, newest first.",
29971
+ description: "Full-text search across messages.",
29996
29972
  inputSchema: {
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)")
30002
- }
30003
- }, async ({ query, space, from, to, limit }) => {
29973
+ query: exports_external.string(),
29974
+ space: exports_external.string().optional(),
29975
+ from: exports_external.string().optional(),
29976
+ to: exports_external.string().optional(),
29977
+ limit: exports_external.number().optional()
29978
+ }
29979
+ }, async (args) => {
29980
+ const { query, space, from, to, limit } = args;
30004
29981
  const messages = searchMessages({ query, space, from, to, limit });
30005
29982
  return {
30006
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
29983
+ content: [{ type: "text", text: JSON.stringify(messages) }]
30007
29984
  };
30008
29985
  });
30009
29986
  server.registerTool("export_messages", {
30010
- title: "Export Messages",
30011
- description: "Export messages as JSON or CSV with optional filters.",
29987
+ description: "Export messages as JSON or CSV.",
30012
29988
  inputSchema: {
30013
- space: exports_external.string().optional().describe("Filter by space"),
30014
- session_id: exports_external.string().optional().describe("Filter by session ID"),
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"),
30018
- format: exports_external.enum(["json", "csv"]).optional().describe("Output format (default: json)")
30019
- }
30020
- }, async ({ space, session_id, from, since, until, format }) => {
29989
+ space: exports_external.string().optional(),
29990
+ session_id: exports_external.string().optional(),
29991
+ from: exports_external.string().optional(),
29992
+ since: exports_external.string().optional(),
29993
+ until: exports_external.string().optional(),
29994
+ format: exports_external.string().optional()
29995
+ }
29996
+ }, async (args) => {
29997
+ const { space, session_id, from, since, until, format } = args;
30021
29998
  const result = exportMessages({ space, session_id, from, since, until, format });
30022
29999
  return {
30023
30000
  content: [{ type: "text", text: result }]
30024
30001
  };
30025
30002
  });
30026
30003
  server.registerTool("create_space", {
30027
- title: "Create Space",
30028
- description: "Create a space. Auto-joined. Supports nesting and projects.",
30004
+ description: "Create a space and auto-join.",
30029
30005
  inputSchema: {
30030
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30031
- name: exports_external.string().describe("Space name"),
30032
- description: exports_external.string().optional().describe("Space description"),
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")
30035
- }
30036
- }, async ({ from: fromParam, name, description, parent_id, project_id }) => {
30006
+ name: exports_external.string(),
30007
+ from: exports_external.string().optional(),
30008
+ description: exports_external.string().optional(),
30009
+ parent_id: exports_external.string().optional(),
30010
+ project_id: exports_external.string().optional()
30011
+ }
30012
+ }, async (args) => {
30013
+ const { from: fromParam, name, description, parent_id, project_id } = args;
30037
30014
  const agent = resolveIdentity(fromParam);
30038
30015
  try {
30039
30016
  const sp = createSpace(name, agent, { description, parent_id, project_id });
30040
30017
  return {
30041
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
30018
+ content: [{ type: "text", text: JSON.stringify(sp) }]
30042
30019
  };
30043
30020
  } catch (e) {
30044
30021
  if (e.message?.includes("UNIQUE constraint")) {
@@ -30054,14 +30031,14 @@ server.registerTool("create_space", {
30054
30031
  }
30055
30032
  });
30056
30033
  server.registerTool("list_spaces", {
30057
- title: "List Spaces",
30058
- description: "List spaces with member/message counts.",
30034
+ description: "List spaces with counts.",
30059
30035
  inputSchema: {
30060
- project_id: exports_external.string().optional().describe("Filter by project ID"),
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")
30036
+ project_id: exports_external.string().optional(),
30037
+ parent_id: exports_external.string().optional(),
30038
+ include_archived: exports_external.boolean().optional()
30063
30039
  }
30064
- }, async ({ project_id, parent_id, include_archived }) => {
30040
+ }, async (args) => {
30041
+ const { project_id, parent_id, include_archived } = args;
30065
30042
  const opts = {};
30066
30043
  if (project_id)
30067
30044
  opts.project_id = project_id;
@@ -30074,20 +30051,20 @@ server.registerTool("list_spaces", {
30074
30051
  opts.include_archived = true;
30075
30052
  const spaces = listSpaces(opts);
30076
30053
  return {
30077
- content: [{ type: "text", text: JSON.stringify(spaces, null, 2) }]
30054
+ content: [{ type: "text", text: JSON.stringify(spaces) }]
30078
30055
  };
30079
30056
  });
30080
30057
  server.registerTool("send_to_space", {
30081
- title: "Send to Space",
30082
- description: "Send a message to a space. All members can see it.",
30058
+ description: "Post a message to a space.",
30083
30059
  inputSchema: {
30084
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30085
- space: exports_external.string().describe("Space name"),
30086
- content: exports_external.string().describe("Message content"),
30087
- priority: exports_external.enum(["low", "normal", "high", "urgent"]).optional().describe("Message priority"),
30088
- blocking: exports_external.boolean().optional().describe("Blocking message \u2014 all space members must acknowledge")
30089
- }
30090
- }, async ({ from: fromParam, space, content, priority, blocking }) => {
30060
+ space: exports_external.string(),
30061
+ content: exports_external.string(),
30062
+ from: exports_external.string().optional(),
30063
+ priority: exports_external.string().optional(),
30064
+ blocking: exports_external.boolean().optional()
30065
+ }
30066
+ }, async (args) => {
30067
+ const { from: fromParam, space, content, priority, blocking } = args;
30091
30068
  const from = resolveIdentity(fromParam);
30092
30069
  const sp = getSpace(space);
30093
30070
  if (!sp) {
@@ -30106,31 +30083,31 @@ server.registerTool("send_to_space", {
30106
30083
  blocking
30107
30084
  });
30108
30085
  return {
30109
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
30086
+ content: [{ type: "text", text: JSON.stringify(msg) }]
30110
30087
  };
30111
30088
  });
30112
30089
  server.registerTool("read_space", {
30113
- title: "Read Space",
30114
30090
  description: "Read messages from a space.",
30115
30091
  inputSchema: {
30116
- space: exports_external.string().describe("Space name"),
30117
- since: exports_external.string().optional().describe("ISO timestamp lower bound"),
30118
- limit: exports_external.number().optional().describe("Max messages to return")
30092
+ space: exports_external.string(),
30093
+ since: exports_external.string().optional(),
30094
+ limit: exports_external.number().optional()
30119
30095
  }
30120
- }, async ({ space, since, limit }) => {
30096
+ }, async (args) => {
30097
+ const { space, since, limit } = args;
30121
30098
  const messages = readMessages({ space, since, limit });
30122
30099
  return {
30123
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
30100
+ content: [{ type: "text", text: JSON.stringify(messages) }]
30124
30101
  };
30125
30102
  });
30126
30103
  server.registerTool("join_space", {
30127
- title: "Join Space",
30128
- description: "Join a space to receive messages.",
30104
+ description: "Join a space as a member.",
30129
30105
  inputSchema: {
30130
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30131
- space: exports_external.string().describe("Space name to join")
30106
+ space: exports_external.string(),
30107
+ from: exports_external.string().optional()
30132
30108
  }
30133
- }, async ({ from: fromParam, space }) => {
30109
+ }, async (args) => {
30110
+ const { from: fromParam, space } = args;
30134
30111
  const agent = resolveIdentity(fromParam);
30135
30112
  const ok = joinSpace(space, agent);
30136
30113
  if (!ok) {
@@ -30140,33 +30117,33 @@ server.registerTool("join_space", {
30140
30117
  };
30141
30118
  }
30142
30119
  return {
30143
- content: [{ type: "text", text: JSON.stringify({ space, agent, joined: true }, null, 2) }]
30120
+ content: [{ type: "text", text: JSON.stringify({ space, agent, joined: true }) }]
30144
30121
  };
30145
30122
  });
30146
30123
  server.registerTool("leave_space", {
30147
- title: "Leave Space",
30148
30124
  description: "Leave a space.",
30149
30125
  inputSchema: {
30150
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30151
- space: exports_external.string().describe("Space name to leave")
30126
+ space: exports_external.string(),
30127
+ from: exports_external.string().optional()
30152
30128
  }
30153
- }, async ({ from: fromParam, space }) => {
30129
+ }, async (args) => {
30130
+ const { from: fromParam, space } = args;
30154
30131
  const agent = resolveIdentity(fromParam);
30155
30132
  const left = leaveSpace(space, agent);
30156
30133
  return {
30157
- content: [{ type: "text", text: JSON.stringify({ space, agent, left }, null, 2) }]
30134
+ content: [{ type: "text", text: JSON.stringify({ space, agent, left }) }]
30158
30135
  };
30159
30136
  });
30160
30137
  server.registerTool("update_space", {
30161
- title: "Update Space",
30162
- description: "Update a space's description, parent, or project.",
30138
+ description: "Update space description or parent.",
30163
30139
  inputSchema: {
30164
- name: exports_external.string().describe("Space name"),
30165
- description: exports_external.string().optional().describe("New description"),
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)")
30140
+ name: exports_external.string(),
30141
+ description: exports_external.string().optional(),
30142
+ parent_id: exports_external.string().optional(),
30143
+ project_id: exports_external.string().optional()
30168
30144
  }
30169
- }, async ({ name, description, parent_id, project_id }) => {
30145
+ }, async (args) => {
30146
+ const { name, description, parent_id, project_id } = args;
30170
30147
  const updates = {};
30171
30148
  if (description !== undefined)
30172
30149
  updates.description = description;
@@ -30177,7 +30154,7 @@ server.registerTool("update_space", {
30177
30154
  try {
30178
30155
  const sp = updateSpace(name, updates);
30179
30156
  return {
30180
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
30157
+ content: [{ type: "text", text: JSON.stringify(sp) }]
30181
30158
  };
30182
30159
  } catch (e) {
30183
30160
  return {
@@ -30187,16 +30164,15 @@ server.registerTool("update_space", {
30187
30164
  }
30188
30165
  });
30189
30166
  server.registerTool("archive_space", {
30190
- title: "Archive Space",
30191
- description: "Archive a space. Hidden from list by default.",
30167
+ description: "Archive a space.",
30192
30168
  inputSchema: {
30193
- name: exports_external.string().describe("Space name to archive")
30169
+ name: exports_external.string()
30194
30170
  }
30195
30171
  }, async ({ name }) => {
30196
30172
  try {
30197
30173
  const sp = archiveSpace(name);
30198
30174
  return {
30199
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
30175
+ content: [{ type: "text", text: JSON.stringify(sp) }]
30200
30176
  };
30201
30177
  } catch (e) {
30202
30178
  return {
@@ -30206,16 +30182,15 @@ server.registerTool("archive_space", {
30206
30182
  }
30207
30183
  });
30208
30184
  server.registerTool("unarchive_space", {
30209
- title: "Unarchive Space",
30210
- description: "Unarchive a previously archived space.",
30185
+ description: "Unarchive a space.",
30211
30186
  inputSchema: {
30212
- name: exports_external.string().describe("Space name to unarchive")
30187
+ name: exports_external.string()
30213
30188
  }
30214
30189
  }, async ({ name }) => {
30215
30190
  try {
30216
30191
  const sp = unarchiveSpace(name);
30217
30192
  return {
30218
- content: [{ type: "text", text: JSON.stringify(sp, null, 2) }]
30193
+ content: [{ type: "text", text: JSON.stringify(sp) }]
30219
30194
  };
30220
30195
  } catch (e) {
30221
30196
  return {
@@ -30225,19 +30200,19 @@ server.registerTool("unarchive_space", {
30225
30200
  }
30226
30201
  });
30227
30202
  server.registerTool("create_project", {
30228
- title: "Create Project",
30229
- description: "Create a project for spaces and agent collaboration.",
30203
+ description: "Create a project for agent collaboration.",
30230
30204
  inputSchema: {
30231
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30232
- name: exports_external.string().describe("Project name (unique)"),
30233
- description: exports_external.string().optional().describe("Project description"),
30234
- path: exports_external.string().optional().describe("Absolute path on disk"),
30235
- repository: exports_external.string().optional().describe("Repository URL"),
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")
30239
- }
30240
- }, async ({ from: fromParam, name, description, path, repository, tags, metadata, settings }) => {
30205
+ name: exports_external.string(),
30206
+ from: exports_external.string().optional(),
30207
+ description: exports_external.string().optional(),
30208
+ path: exports_external.string().optional(),
30209
+ repository: exports_external.string().optional(),
30210
+ tags: exports_external.string().optional(),
30211
+ metadata: exports_external.string().optional(),
30212
+ settings: exports_external.string().optional()
30213
+ }
30214
+ }, async (args) => {
30215
+ const { from: fromParam, name, description, path, repository, tags, metadata, settings } = args;
30241
30216
  const agent = resolveIdentity(fromParam);
30242
30217
  let parsedTags;
30243
30218
  if (tags) {
@@ -30284,7 +30259,7 @@ server.registerTool("create_project", {
30284
30259
  settings: parsedSettings
30285
30260
  });
30286
30261
  return {
30287
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
30262
+ content: [{ type: "text", text: JSON.stringify(project) }]
30288
30263
  };
30289
30264
  } catch (e) {
30290
30265
  if (e.message?.includes("UNIQUE constraint")) {
@@ -30300,22 +30275,21 @@ server.registerTool("create_project", {
30300
30275
  }
30301
30276
  });
30302
30277
  server.registerTool("list_projects", {
30303
- title: "List Projects",
30304
- description: "List all registered projects.",
30278
+ description: "List all projects.",
30305
30279
  inputSchema: {
30306
- status: exports_external.enum(["active", "archived"]).optional().describe("Filter by status")
30280
+ status: exports_external.string().optional()
30307
30281
  }
30308
- }, async ({ status }) => {
30282
+ }, async (args) => {
30283
+ const { status } = args;
30309
30284
  const projects = listProjects(status ? { status } : undefined);
30310
30285
  return {
30311
- content: [{ type: "text", text: JSON.stringify(projects, null, 2) }]
30286
+ content: [{ type: "text", text: JSON.stringify(projects) }]
30312
30287
  };
30313
30288
  });
30314
30289
  server.registerTool("get_project", {
30315
- title: "Get Project",
30316
- description: "Get full details of a project by ID or name.",
30290
+ description: "Get a project by ID or name.",
30317
30291
  inputSchema: {
30318
- id: exports_external.string().describe("Project ID (UUID) or name")
30292
+ id: exports_external.string()
30319
30293
  }
30320
30294
  }, async ({ id }) => {
30321
30295
  let project = getProject(id);
@@ -30329,24 +30303,24 @@ server.registerTool("get_project", {
30329
30303
  };
30330
30304
  }
30331
30305
  return {
30332
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
30306
+ content: [{ type: "text", text: JSON.stringify(project) }]
30333
30307
  };
30334
30308
  });
30335
30309
  server.registerTool("update_project", {
30336
- title: "Update Project",
30337
- description: "Update a project's fields.",
30310
+ description: "Update project fields by ID.",
30338
30311
  inputSchema: {
30339
- id: exports_external.string().describe("Project ID (UUID)"),
30340
- name: exports_external.string().optional().describe("New name"),
30341
- description: exports_external.string().optional().describe("New description"),
30342
- path: exports_external.string().optional().describe("New path"),
30343
- status: exports_external.enum(["active", "archived"]).optional().describe("New status"),
30344
- repository: exports_external.string().optional().describe("New repository URL"),
30345
- tags: exports_external.string().optional().describe("JSON array of tags"),
30346
- metadata: exports_external.string().optional().describe("JSON metadata"),
30347
- settings: exports_external.string().optional().describe("JSON settings")
30348
- }
30349
- }, async ({ id, name, description, path, status, repository, tags, metadata, settings }) => {
30312
+ id: exports_external.string(),
30313
+ name: exports_external.string().optional(),
30314
+ description: exports_external.string().optional(),
30315
+ path: exports_external.string().optional(),
30316
+ status: exports_external.string().optional(),
30317
+ repository: exports_external.string().optional(),
30318
+ tags: exports_external.string().optional(),
30319
+ metadata: exports_external.string().optional(),
30320
+ settings: exports_external.string().optional()
30321
+ }
30322
+ }, async (args) => {
30323
+ const { id, name, description, path, status, repository, tags, metadata, settings } = args;
30350
30324
  const updates = {};
30351
30325
  if (name !== undefined)
30352
30326
  updates.name = name;
@@ -30391,7 +30365,7 @@ server.registerTool("update_project", {
30391
30365
  try {
30392
30366
  const project = updateProject(id, updates);
30393
30367
  return {
30394
- content: [{ type: "text", text: JSON.stringify(project, null, 2) }]
30368
+ content: [{ type: "text", text: JSON.stringify(project) }]
30395
30369
  };
30396
30370
  } catch (e) {
30397
30371
  return {
@@ -30401,10 +30375,9 @@ server.registerTool("update_project", {
30401
30375
  }
30402
30376
  });
30403
30377
  server.registerTool("delete_project", {
30404
- title: "Delete Project",
30405
- description: "Delete a project permanently. Fails if spaces reference it.",
30378
+ description: "Delete a project permanently.",
30406
30379
  inputSchema: {
30407
- id: exports_external.string().describe("Project ID (UUID)")
30380
+ id: exports_external.string()
30408
30381
  }
30409
30382
  }, async ({ id }) => {
30410
30383
  try {
@@ -30416,7 +30389,7 @@ server.registerTool("delete_project", {
30416
30389
  };
30417
30390
  }
30418
30391
  return {
30419
- content: [{ type: "text", text: JSON.stringify({ id, deleted: true }, null, 2) }]
30392
+ content: [{ type: "text", text: JSON.stringify({ id, deleted: true }) }]
30420
30393
  };
30421
30394
  } catch (e) {
30422
30395
  return {
@@ -30426,13 +30399,13 @@ server.registerTool("delete_project", {
30426
30399
  }
30427
30400
  });
30428
30401
  server.registerTool("delete_message", {
30429
- title: "Delete Message",
30430
- description: "Delete a message. Sender only.",
30402
+ description: "Delete a message (sender only).",
30431
30403
  inputSchema: {
30432
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30433
- id: exports_external.number().describe("Message ID to delete")
30404
+ id: exports_external.number(),
30405
+ from: exports_external.string().optional()
30434
30406
  }
30435
- }, async ({ from: fromParam, id }) => {
30407
+ }, async (args) => {
30408
+ const { from: fromParam, id } = args;
30436
30409
  const agent = resolveIdentity(fromParam);
30437
30410
  const deleted = deleteMessage(id, agent);
30438
30411
  if (!deleted) {
@@ -30442,18 +30415,18 @@ server.registerTool("delete_message", {
30442
30415
  };
30443
30416
  }
30444
30417
  return {
30445
- content: [{ type: "text", text: JSON.stringify({ deleted: true }, null, 2) }]
30418
+ content: [{ type: "text", text: JSON.stringify({ deleted: true }) }]
30446
30419
  };
30447
30420
  });
30448
30421
  server.registerTool("edit_message", {
30449
- title: "Edit Message",
30450
- description: "Edit a message's content. Sender only.",
30422
+ description: "Edit message content (sender only).",
30451
30423
  inputSchema: {
30452
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30453
- id: exports_external.number().describe("Message ID to edit"),
30454
- content: exports_external.string().describe("New message content")
30424
+ id: exports_external.number(),
30425
+ content: exports_external.string(),
30426
+ from: exports_external.string().optional()
30455
30427
  }
30456
- }, async ({ from: fromParam, id, content }) => {
30428
+ }, async (args) => {
30429
+ const { from: fromParam, id, content } = args;
30457
30430
  const agent = resolveIdentity(fromParam);
30458
30431
  const msg = editMessage(id, agent, content);
30459
30432
  if (!msg) {
@@ -30463,14 +30436,13 @@ server.registerTool("edit_message", {
30463
30436
  };
30464
30437
  }
30465
30438
  return {
30466
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
30439
+ content: [{ type: "text", text: JSON.stringify(msg) }]
30467
30440
  };
30468
30441
  });
30469
30442
  server.registerTool("pin_message", {
30470
- title: "Pin Message",
30471
- description: "Pin a message in a space or session.",
30443
+ description: "Pin a message.",
30472
30444
  inputSchema: {
30473
- id: exports_external.number().describe("Message ID to pin")
30445
+ id: exports_external.number()
30474
30446
  }
30475
30447
  }, async ({ id }) => {
30476
30448
  const msg = pinMessage(id);
@@ -30481,14 +30453,13 @@ server.registerTool("pin_message", {
30481
30453
  };
30482
30454
  }
30483
30455
  return {
30484
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
30456
+ content: [{ type: "text", text: JSON.stringify(msg) }]
30485
30457
  };
30486
30458
  });
30487
30459
  server.registerTool("unpin_message", {
30488
- title: "Unpin Message",
30489
- description: "Unpin a previously pinned message.",
30460
+ description: "Unpin a message.",
30490
30461
  inputSchema: {
30491
- id: exports_external.number().describe("Message ID to unpin")
30462
+ id: exports_external.number()
30492
30463
  }
30493
30464
  }, async ({ id }) => {
30494
30465
  const msg = unpinMessage(id);
@@ -30499,70 +30470,70 @@ server.registerTool("unpin_message", {
30499
30470
  };
30500
30471
  }
30501
30472
  return {
30502
- content: [{ type: "text", text: JSON.stringify(msg, null, 2) }]
30473
+ content: [{ type: "text", text: JSON.stringify(msg) }]
30503
30474
  };
30504
30475
  });
30505
30476
  server.registerTool("get_pinned_messages", {
30506
- title: "Get Pinned Messages",
30507
- description: "Get pinned messages, filtered by space or session.",
30477
+ description: "Get pinned messages by space or session.",
30508
30478
  inputSchema: {
30509
- space: exports_external.string().optional().describe("Filter by space"),
30510
- session_id: exports_external.string().optional().describe("Filter by session ID"),
30511
- limit: exports_external.number().optional().describe("Max messages to return")
30479
+ space: exports_external.string().optional(),
30480
+ session_id: exports_external.string().optional(),
30481
+ limit: exports_external.number().optional()
30512
30482
  }
30513
- }, async ({ space, session_id, limit }) => {
30483
+ }, async (args) => {
30484
+ const { space, session_id, limit } = args;
30514
30485
  const messages = getPinnedMessages({ space, session_id, limit });
30515
30486
  return {
30516
- content: [{ type: "text", text: JSON.stringify(messages, null, 2) }]
30487
+ content: [{ type: "text", text: JSON.stringify(messages) }]
30517
30488
  };
30518
30489
  });
30519
30490
  server.registerTool("heartbeat", {
30520
- title: "Heartbeat",
30521
- description: "Send heartbeat. Optionally set agent status.",
30491
+ description: "Send presence heartbeat.",
30522
30492
  inputSchema: {
30523
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30524
- status: exports_external.string().optional().describe("Agent status (e.g. 'online', 'busy', 'idle'). Defaults to 'online'.")
30493
+ from: exports_external.string().optional(),
30494
+ status: exports_external.string().optional()
30525
30495
  }
30526
- }, async ({ from: fromParam, status }) => {
30496
+ }, async (args) => {
30497
+ const { from: fromParam, status } = args;
30527
30498
  const agent = resolveIdentity(fromParam);
30528
30499
  heartbeat(agent, status);
30529
30500
  return {
30530
- content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }, null, 2) }]
30501
+ content: [{ type: "text", text: JSON.stringify({ agent, status: status || "online", heartbeat: true }) }]
30531
30502
  };
30532
30503
  });
30533
30504
  server.registerTool("list_agents", {
30534
- title: "List Agents",
30535
30505
  description: "List agents with presence status.",
30536
30506
  inputSchema: {
30537
- online_only: exports_external.boolean().optional().describe("Only return agents online within last 60s")
30507
+ online_only: exports_external.boolean().optional()
30538
30508
  }
30539
- }, async ({ online_only }) => {
30509
+ }, async (args) => {
30510
+ const { online_only } = args;
30540
30511
  const agents = listAgents({ online_only });
30541
30512
  return {
30542
- content: [{ type: "text", text: JSON.stringify(agents, null, 2) }]
30513
+ content: [{ type: "text", text: JSON.stringify(agents) }]
30543
30514
  };
30544
30515
  });
30545
30516
  server.registerTool("get_blockers", {
30546
- title: "Get Blockers",
30547
- description: "Check for unread blocking messages. Must acknowledge.",
30517
+ description: "Check for unread blocking messages.",
30548
30518
  inputSchema: {
30549
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var.")
30519
+ from: exports_external.string().optional()
30550
30520
  }
30551
- }, async ({ from: fromParam }) => {
30521
+ }, async (args) => {
30522
+ const { from: fromParam } = args;
30552
30523
  const agent = resolveIdentity(fromParam);
30553
30524
  const blockers = getUnreadBlockers(agent);
30554
30525
  return {
30555
- content: [{ type: "text", text: JSON.stringify(blockers, null, 2) }]
30526
+ content: [{ type: "text", text: JSON.stringify(blockers) }]
30556
30527
  };
30557
30528
  });
30558
30529
  server.registerTool("remove_agent", {
30559
- title: "Remove Agent",
30560
- description: "Remove an agent from the presence list.",
30530
+ description: "Remove an agent from presence.",
30561
30531
  inputSchema: {
30562
- from: exports_external.string().optional().describe("Your agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30563
- agent: exports_external.string().optional().describe("Agent to remove (defaults to yourself)")
30532
+ from: exports_external.string().optional(),
30533
+ agent: exports_external.string().optional()
30564
30534
  }
30565
- }, async ({ from: fromParam, agent: targetAgent }) => {
30535
+ }, async (args) => {
30536
+ const { from: fromParam, agent: targetAgent } = args;
30566
30537
  const self = resolveIdentity(fromParam);
30567
30538
  const agent = targetAgent?.trim() || self;
30568
30539
  const removed = removePresence(agent);
@@ -30573,17 +30544,17 @@ server.registerTool("remove_agent", {
30573
30544
  };
30574
30545
  }
30575
30546
  return {
30576
- content: [{ type: "text", text: JSON.stringify({ agent, removed: true }, null, 2) }]
30547
+ content: [{ type: "text", text: JSON.stringify({ agent, removed: true }) }]
30577
30548
  };
30578
30549
  });
30579
30550
  server.registerTool("rename_agent", {
30580
- title: "Rename Agent",
30581
- description: "Rename an agent in the presence list.",
30551
+ description: "Rename your agent in presence.",
30582
30552
  inputSchema: {
30583
- from: exports_external.string().optional().describe("Your current agent ID. Falls back to CONVERSATIONS_AGENT_ID env var."),
30584
- new_name: exports_external.string().describe("The new name for the agent")
30553
+ new_name: exports_external.string(),
30554
+ from: exports_external.string().optional()
30585
30555
  }
30586
- }, async ({ from: fromParam, new_name }) => {
30556
+ }, async (args) => {
30557
+ const { from: fromParam, new_name } = args;
30587
30558
  const oldName = resolveIdentity(fromParam);
30588
30559
  const newName = new_name.trim();
30589
30560
  if (!newName) {
@@ -30601,7 +30572,7 @@ server.registerTool("rename_agent", {
30601
30572
  };
30602
30573
  }
30603
30574
  return {
30604
- content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }, null, 2) }]
30575
+ content: [{ type: "text", text: JSON.stringify({ old_name: oldName, new_name: newName, renamed: true }) }]
30605
30576
  };
30606
30577
  } catch (e) {
30607
30578
  return {
@@ -30611,12 +30582,12 @@ server.registerTool("rename_agent", {
30611
30582
  }
30612
30583
  });
30613
30584
  server.registerTool("search_tools", {
30614
- title: "Search Tools",
30615
- description: "List tool names, optionally filtered by keyword.",
30585
+ description: "List tool names by keyword.",
30616
30586
  inputSchema: {
30617
- query: exports_external.string().optional().describe("Keyword filter")
30587
+ query: exports_external.string().optional()
30618
30588
  }
30619
- }, async ({ query }) => {
30589
+ }, async (args) => {
30590
+ const { query } = args;
30620
30591
  const all = [
30621
30592
  "send_message",
30622
30593
  "read_messages",
@@ -30657,26 +30628,45 @@ server.registerTool("search_tools", {
30657
30628
  return { content: [{ type: "text", text: matches.join(", ") }] };
30658
30629
  });
30659
30630
  server.registerTool("describe_tools", {
30660
- title: "Describe Tools",
30661
- description: "Get descriptions for specific tools by name.",
30631
+ description: "Get descriptions for tools by name.",
30662
30632
  inputSchema: {
30663
- names: exports_external.array(exports_external.string()).describe("Tool names from search_tools")
30633
+ names: exports_external.array(exports_external.string())
30664
30634
  }
30665
30635
  }, async ({ names }) => {
30666
30636
  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?"
30637
+ send_message: "Send DM to agent. Required: to, content. Optional: from?, priority?(low|normal|high|urgent), blocking?",
30638
+ read_messages: "Read messages with filters. Optional: session_id?, from?, to?, space?, since?(ISO), limit?, unread_only?",
30639
+ list_sessions: "List all DM sessions. Optional: agent?(filter by participant)",
30640
+ reply: "Reply to a message in same session. Required: message_id, content. Optional: from?",
30641
+ mark_read: "Mark messages as read. Optional: from?, ids?(array), all?(bool \u2014 mark all unread)",
30642
+ search_messages: "Full-text search messages. Required: query. Optional: space?, from?, to?, limit?",
30643
+ export_messages: "Export messages as JSON or CSV. Optional: space?, session_id?, from?, since?, until?, format?(json|csv)",
30644
+ create_space: "Create space and auto-join. Required: name. Optional: from?, description?, parent_id?(max 3 levels), project_id?",
30645
+ list_spaces: "List spaces with member/message counts. Optional: project_id?, parent_id?(use 'null' for top-level), include_archived?",
30646
+ send_to_space: "Post message to space. Required: space, content. Optional: from?, priority?(low|normal|high|urgent), blocking?",
30647
+ read_space: "Read messages in a space. Required: space. Optional: since?(ISO), limit?",
30648
+ join_space: "Join a space. Required: space. Optional: from?",
30649
+ leave_space: "Leave a space. Required: space. Optional: from?",
30650
+ update_space: "Update space fields. Required: name. Optional: description?, parent_id?(use 'null' to remove), project_id?(use 'null' to remove)",
30651
+ archive_space: "Archive a space (hidden from default list). Required: name",
30652
+ unarchive_space: "Restore archived space. Required: name",
30653
+ create_project: "Create a project. Required: name. Optional: from?, description?, path?, repository?, tags?(JSON array), metadata?(JSON), settings?(JSON)",
30654
+ list_projects: "List projects. Optional: status?(active|archived)",
30655
+ get_project: "Get project by UUID or name. Required: id",
30656
+ update_project: "Update project fields. Required: id. Optional: name?, description?, path?, status?(active|archived), repository?, tags?(JSON), metadata?(JSON), settings?(JSON)",
30657
+ delete_project: "Delete project (fails if spaces reference it). Required: id",
30658
+ delete_message: "Delete a message (sender only). Required: id. Optional: from?",
30659
+ edit_message: "Edit message content (sender only). Required: id, content. Optional: from?",
30660
+ pin_message: "Pin a message. Required: id",
30661
+ unpin_message: "Unpin a message. Required: id",
30662
+ get_pinned_messages: "Get pinned messages. Optional: space?, session_id?, limit?",
30663
+ heartbeat: "Register/refresh agent presence. Optional: from?, status?(online|busy|idle, default: online)",
30664
+ list_agents: "List agents with presence timestamps. Optional: online_only?(only agents seen in last 60s)",
30665
+ get_blockers: "Get unread blocking messages for agent. Optional: from?",
30666
+ remove_agent: "Remove agent from presence list. Optional: from?, agent?(defaults to self)",
30667
+ rename_agent: "Rename agent in presence list. Required: new_name. Optional: from?",
30668
+ search_tools: "Search tool names by keyword. Optional: query?",
30669
+ describe_tools: "Get full descriptions for tools. Required: names(array of tool names)"
30680
30670
  };
30681
30671
  const result = names.map((n) => `${n}: ${descriptions[n] || "See tool schema"}`).join(`
30682
30672
  `);