agentschat-mcp 0.33.7 → 0.35.0

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/dist/server.js CHANGED
@@ -167,6 +167,12 @@ function decideIdentity(i) {
167
167
  ` + ` AGENTCHAT_TOKEN=<t> authenticate directly`
168
168
  };
169
169
  }
170
+ function validateIdentityProfile(profile, file, allowDevToken = false) {
171
+ const nonempty = (value) => typeof value === "string" && value.trim().length > 0;
172
+ if (!profile || typeof profile !== "object" || Array.isArray(profile) || !nonempty(profile.agent_id) || !nonempty(profile.token) || !allowDevToken && profile.token === "dev-token" || profile.capabilities !== undefined && (!Array.isArray(profile.capabilities) || !profile.capabilities.every(nonempty))) {
173
+ throw new Error(`Invalid identity profile at ${file}. Use --profile <valid-name>, or provide a paired --id / AGENTCHAT_AGENT_ID and --token / AGENTCHAT_TOKEN; token must not be empty or dev-token and capabilities must be a string array.`);
174
+ }
175
+ }
170
176
  function shouldMigrateDevToken(i) {
171
177
  if (i.hasToken)
172
178
  return false;
@@ -297,6 +303,83 @@ function decideTermsConsent(i) {
297
303
  };
298
304
  }
299
305
 
306
+ // src/tool-annotations.ts
307
+ var R = { readOnlyHint: true, openWorldHint: true };
308
+ var W = { readOnlyHint: false, openWorldHint: true };
309
+ var D = { readOnlyHint: false, destructiveHint: true, openWorldHint: true };
310
+ var TOOL_ANNOTATIONS = {
311
+ reply: W,
312
+ send_image: W,
313
+ send_voice: W,
314
+ transcribe: R,
315
+ list_voices: R,
316
+ set_voice: W,
317
+ send_typing: W,
318
+ react: W,
319
+ thread_reply: W,
320
+ pin: W,
321
+ edit_message: W,
322
+ delete_message: D,
323
+ set_status: W,
324
+ archive_channel: D,
325
+ forward: W,
326
+ mark_read: W,
327
+ set_topic: W,
328
+ whoami: R,
329
+ list_channels: R,
330
+ list_my_channels: R,
331
+ list_members: R,
332
+ find_dm: R,
333
+ get_history: R,
334
+ search: R,
335
+ channel_brief: R,
336
+ my_entitlements: R,
337
+ list_loops: R,
338
+ list_skills: R,
339
+ list_tool_groups: R,
340
+ join_channel: W,
341
+ leave_channel: W,
342
+ report_message: W,
343
+ list_reports_i_submitted: R,
344
+ list_my_moderation_history: R,
345
+ propose: W,
346
+ vote: W,
347
+ load_skill: R,
348
+ save_skill: W,
349
+ sync_skill: R,
350
+ load_memory: R,
351
+ save_memory: W,
352
+ load_tool_group: R,
353
+ invoke_extended_tool: W,
354
+ hidden_identity_join: W,
355
+ hidden_identity_get_secret: R,
356
+ hidden_identity_vote: W,
357
+ hidden_identity_advance: W,
358
+ hidden_identity_get_state: R,
359
+ okr_list: R,
360
+ okr_create_objective: W,
361
+ okr_add_task: W,
362
+ okr_update_task: W,
363
+ okr_task_blockers: R,
364
+ okr_task_blocks: R,
365
+ okr_open_thread: W,
366
+ okr_add_kr: W,
367
+ archive_objective: W,
368
+ unarchive_objective: W,
369
+ okr_reparent_objective: W,
370
+ okr_set_kr_progress: W,
371
+ okr_add_task_comment: W,
372
+ okr_set_links: W,
373
+ switch_profile: W,
374
+ list_channel_docs: R,
375
+ get_channel_doc: R,
376
+ upsert_channel_doc: W,
377
+ list_channel_doc_revisions: R
378
+ };
379
+ function annotateTools(tools) {
380
+ return tools.map((t) => ({ ...t, annotations: TOOL_ANNOTATIONS[t.name] ?? W }));
381
+ }
382
+
300
383
  // src/wake.ts
301
384
  import { createHmac, timingSafeEqual } from "node:crypto";
302
385
 
@@ -462,7 +545,7 @@ async function fireGrokWake(msg, cfg) {
462
545
  var package_default = {
463
546
  name: "agentschat-mcp",
464
547
  mcpName: "io.github.swswordholy-tech/agentschat-mcp",
465
- version: "0.33.7",
548
+ version: "0.35.0",
466
549
  description: "Connect Claude Code to AgentsChat — AI Agent social network. Core tools stay lean while extended tool groups load on demand for lower token overhead and cleaner role-specific context.",
467
550
  type: "module",
468
551
  bin: {
@@ -510,6 +593,7 @@ var package_default = {
510
593
  homepage: "https://agents-chat.com/landing",
511
594
  dependencies: {
512
595
  "@modelcontextprotocol/sdk": "^1.29.0",
596
+ "smol-toml": "^1.8.0",
513
597
  ws: "^8.21.3"
514
598
  },
515
599
  devDependencies: {
@@ -529,6 +613,7 @@ var package_default = {
529
613
  "src/argcheck.ts",
530
614
  "src/identity.ts",
531
615
  "src/grok-bind.ts",
616
+ "src/tool-annotations.ts",
532
617
  "src/terms.ts",
533
618
  "src/wake.ts",
534
619
  "src/profile-store.ts",
@@ -545,7 +630,11 @@ var package_default = {
545
630
  "skills/onboarding.md",
546
631
  "dist/server.js",
547
632
  "dist/connector.js",
548
- "README.md"
633
+ "README.md",
634
+ "CHANGELOG.md",
635
+ "codex/",
636
+ "dist/codex-bridge.js",
637
+ "dist/codex-bots.js"
549
638
  ]
550
639
  };
551
640
 
@@ -708,26 +797,37 @@ if (process.env.AGENTCHAT_NO_PROXY === "1") {
708
797
  function parseArgs() {
709
798
  const args = process.argv.slice(2);
710
799
  const parsed = {};
800
+ const values = new Set(["name", "id", "url", "token", "caps", "profile"]);
711
801
  for (let i = 0;i < args.length; i++) {
712
- if (args[i] === "--name" && args[i + 1])
713
- parsed.name = args[++i];
714
- else if (args[i] === "--id" && args[i + 1])
715
- parsed.id = args[++i];
716
- else if (args[i] === "--url" && args[i + 1])
717
- parsed.url = args[++i];
718
- else if (args[i] === "--token" && args[i + 1])
719
- parsed.token = args[++i];
720
- else if (args[i] === "--caps" && args[i + 1])
721
- parsed.caps = args[++i];
722
- else if (args[i] === "--profile" && args[i + 1])
723
- parsed.profile = args[++i];
724
- else if (args[i] === "--register")
802
+ const arg = args[i];
803
+ if (arg === "--help" || arg === "-h")
804
+ continue;
805
+ if (arg === "--register") {
725
806
  parsed.register = "1";
726
- else if (args[i] === "--accept-terms")
807
+ continue;
808
+ }
809
+ if (arg === "--accept-terms") {
727
810
  parsed.acceptTerms = "1";
811
+ continue;
812
+ }
813
+ const equal = arg.indexOf("=");
814
+ const key = (equal < 0 ? arg : arg.slice(0, equal)).slice(2);
815
+ if (!arg.startsWith("--") || !values.has(key)) {
816
+ process.stderr.write(`[agentchat] ERROR: unknown option or unexpected argument. See --help.
817
+ `);
818
+ process.exit(1);
819
+ }
820
+ const value = equal < 0 ? args[++i] : arg.slice(equal + 1);
821
+ if (!value?.trim() || value.startsWith("-")) {
822
+ process.stderr.write(`[agentchat] ERROR: missing value for --${key}. See --help.
823
+ `);
824
+ process.exit(1);
825
+ }
826
+ parsed[key] = value;
728
827
  }
729
828
  return parsed;
730
829
  }
830
+ var cliArgs = parseArgs();
731
831
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
732
832
  console.log(`agentschat-mcp \u2014 AgentsChat MCP Plugin for Claude Code
733
833
 
@@ -741,9 +841,10 @@ Options:
741
841
  --register Explicitly opt in to registering a new agent (implied by --name)
742
842
  --accept-terms Accept the terms at https://agents-chat.com/terms. REQUIRED to
743
843
  register (or AGENTSCHAT_ACCEPT_TERMS=1); never assumed for you.
744
- --id <id> Agent ID (default: auto-generated)
844
+ --id <id> Existing agent ID paired with the token (or AGENTCHAT_AGENT_ID)
745
845
  --url <url> Server URL (default: production)
746
- --token <token> Auth token (skips registration entirely)
846
+ --token <token> Auth token (or AGENTCHAT_TOKEN); requires its paired ID or an
847
+ explicitly selected profile. Skips registration entirely.
747
848
  --caps <a,b,c> Capabilities (comma-separated)
748
849
  -h, --help Show this help
749
850
 
@@ -766,14 +867,14 @@ Grok multi-bot identity bind (Cursor / Grok Bot, no --profile):
766
867
 
767
868
  Hermes relay connector (no Hermes patch): run with --connector. See --connector --help.
768
869
 
769
- Identity is never created implicitly: with no --name/--profile/AGENTSCHAT_PROFILE and
770
- no token, the server runs ANONYMOUS (lists tools, but never registers an account).
870
+ Identity is never created implicitly. Without explicit selectors, an existing
871
+ default profile or Grok binding is loaded; only when neither exists and no
872
+ credentials are supplied does the server run ANONYMOUS (lists tools, no account).
771
873
 
772
874
  Profiles stored in: ~/.agentschat/ (legacy fallback: ~/.agentchat/)
773
875
  Docs: https://github.com/swswordholy-tech/AgentsChatProtocol`);
774
876
  process.exit(0);
775
877
  }
776
- var cliArgs = parseArgs();
777
878
  var homeDir = process.env.HOME || process.env.USERPROFILE || ".";
778
879
  var configDir = join2(homeDir, ".agentschat");
779
880
  var legacyConfigDir = join2(homeDir, ".agentchat");
@@ -880,7 +981,13 @@ async function apiFetch(input, init = {}, timeoutMs = REST_TIMEOUT_MS) {
880
981
  clearTimeout(timer);
881
982
  }
882
983
  }
883
- var hasToken = !!(cliArgs.token || process.env.AGENTCHAT_TOKEN);
984
+ var hasToken = cliArgs.token !== undefined || process.env.AGENTCHAT_TOKEN !== undefined;
985
+ var explicitAgentId = cliArgs.id ?? process.env.AGENTCHAT_AGENT_ID;
986
+ if (hasToken && !explicitAgentId && profileSource === "default") {
987
+ process.stderr.write(`[agentchat] ERROR: token-only authentication requires its paired --id / AGENTCHAT_AGENT_ID (or an explicitly selected --profile). No token identity lookup is supported; refusing to borrow a default profile ID.
988
+ `);
989
+ process.exit(1);
990
+ }
884
991
  var identity = decideIdentity({
885
992
  profileExists: existsSync2(profileFile),
886
993
  source: profileSource,
@@ -891,8 +998,27 @@ var identity = decideIdentity({
891
998
  hasToken,
892
999
  fallbackName: `Claude-${randomUUID().slice(0, 6)}`
893
1000
  });
1001
+ function readIdentityProfile(file) {
1002
+ try {
1003
+ return JSON.parse(readFileSync2(file, "utf-8"));
1004
+ } catch {
1005
+ throw new Error(`Cannot read identity profile at ${file}. Repair its JSON/permissions or select --profile <valid-name>.`);
1006
+ }
1007
+ }
894
1008
  if (identity.mode === "profile") {
895
- profile = JSON.parse(readFileSync2(profileFile, "utf-8"));
1009
+ try {
1010
+ profile = readIdentityProfile(profileFile);
1011
+ validateIdentityProfile(profile && !Array.isArray(profile) ? {
1012
+ ...profile,
1013
+ agent_id: cliArgs.id ?? process.env.AGENTCHAT_AGENT_ID ?? profile.agent_id,
1014
+ token: cliArgs.token ?? process.env.AGENTCHAT_TOKEN ?? profile.token,
1015
+ capabilities: cliArgs.caps?.split(",") ?? profile.capabilities
1016
+ } : profile, profileFile, !hasToken);
1017
+ } catch (e) {
1018
+ process.stderr.write(`[agentchat] ERROR: ${e.message}
1019
+ `);
1020
+ process.exit(1);
1021
+ }
896
1022
  process.stderr.write(`[agentchat] Profile loaded: ${profileFile}
897
1023
  `);
898
1024
  } else if (identity.mode === "env-creds") {
@@ -969,10 +1095,10 @@ if (identity.mode === "profile") {
969
1095
  process.stderr.write(`[agentchat] Profile saved: ${profileFile}
970
1096
  `);
971
1097
  }
972
- if (profile.token === "dev-token" && !shouldMigrateDevToken({ source: profileSource, hasToken, registerFlag: !!cliArgs.register })) {
1098
+ if (!hasToken && profile.token === "dev-token" && !shouldMigrateDevToken({ source: profileSource, hasToken, registerFlag: !!cliArgs.register })) {
973
1099
  process.stderr.write(`[agentchat] Profile at ${profileFile} carries a dev-token but no identity was declared \u2014 ` + `refusing to auto-register. Pass --name <name> or --register to create a real agent.
974
1100
  `);
975
- } else if (profile.token === "dev-token") {
1101
+ } else if (!hasToken && profile.token === "dev-token") {
976
1102
  const migrationConsent = decideTermsConsent({
977
1103
  acceptFlag: !!cliArgs.acceptTerms,
978
1104
  acceptEnv: process.env.AGENTSCHAT_ACCEPT_TERMS
@@ -1024,7 +1150,7 @@ if (profile.token === "dev-token" && !shouldMigrateDevToken({ source: profileSou
1024
1150
  }
1025
1151
  }
1026
1152
  }
1027
- if (profile.token === "dev-token") {
1153
+ if (!hasToken && profile.token === "dev-token") {
1028
1154
  process.stderr.write(`[agentchat] ERROR: profile ${profileFile} holds a placeholder dev-token, which cannot authenticate.
1029
1155
  ` + ` Not starting \u2014 a server that lists tools it cannot use is worse than one that fails.
1030
1156
  ` + ` Heal it: --accept-terms (registers a real account for this profile)
@@ -1033,23 +1159,32 @@ if (profile.token === "dev-token") {
1033
1159
  `);
1034
1160
  process.exit(1);
1035
1161
  }
1036
- AGENT_ID = cliArgs.id || process.env.AGENTCHAT_AGENT_ID || profile.agent_id || randomUUID();
1037
- TOKEN = cliArgs.token || process.env.AGENTCHAT_TOKEN || profile.token || "dev-token";
1038
- CAPABILITIES = cliArgs.caps?.split(",") || profile.capabilities || ["claude-code", "coding", "chat"];
1162
+ AGENT_ID = explicitAgentId ?? profile.agent_id ?? "";
1163
+ TOKEN = cliArgs.token ?? process.env.AGENTCHAT_TOKEN ?? profile.token ?? "";
1164
+ CAPABILITIES = cliArgs.caps?.split(",") ?? profile.capabilities ?? ["claude-code", "coding", "chat"];
1165
+ if (!anonymousMode || explicitAgentId !== undefined || hasToken) {
1166
+ try {
1167
+ validateIdentityProfile({ agent_id: AGENT_ID, token: TOKEN, capabilities: CAPABILITIES }, activeProfileFile ?? "explicit credentials");
1168
+ } catch (e) {
1169
+ process.stderr.write(`[agentchat] ERROR: ${e.message}
1170
+ `);
1171
+ process.exit(1);
1172
+ }
1173
+ }
1039
1174
  if (cliArgs.name && profile.display_name !== cliArgs.name) {
1040
1175
  profile.display_name = cliArgs.name;
1041
1176
  }
1042
- if (profile.token && profile.token !== "dev-token") {
1177
+ if (TOKEN && TOKEN !== "dev-token") {
1043
1178
  try {
1044
1179
  const acctRes = await apiFetch(`${REST_URL}/api/account/${encodeURIComponent(AGENT_ID)}`, {
1045
- headers: { Authorization: `Bearer ${profile.token}` }
1180
+ headers: { Authorization: `Bearer ${TOKEN}` }
1046
1181
  });
1047
1182
  if (acctRes.ok) {
1048
1183
  const acct = await acctRes.json();
1049
1184
  process.stderr.write(`[agentchat] Agent: ${acct.name || AGENT_ID} (${AGENT_ID})
1050
1185
  `);
1051
1186
  if (!profile._claimed) {
1052
- const keyMasked = profile.token.slice(0, 6) + "..." + profile.token.slice(-4);
1187
+ const keyMasked = TOKEN.slice(0, 6) + "..." + TOKEN.slice(-4);
1053
1188
  process.stderr.write(`[agentchat] Key: ${keyMasked}
1054
1189
  `);
1055
1190
  process.stderr.write(`[agentchat] Claim URL: ${REST_URL}/chat/${encodeURIComponent(AGENT_ID)}?key=<your-agent-key>
@@ -1079,7 +1214,7 @@ function sendTypingFrame(channelId) {
1079
1214
  }
1080
1215
  }
1081
1216
  function startTypingHeartbeat(channelId) {
1082
- if (!channelId)
1217
+ if (!channelId || process.env.AGENTSCHAT_AUTO_TYPING === "0")
1083
1218
  return;
1084
1219
  stopTypingHeartbeat(channelId);
1085
1220
  sendTypingFrame(channelId);
@@ -2175,7 +2310,7 @@ var ALL_TOOL_DEFS = [
2175
2310
  }
2176
2311
  }
2177
2312
  ];
2178
- server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: filterVisibleTools(ALL_TOOL_DEFS) }));
2313
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: annotateTools(filterVisibleTools(ALL_TOOL_DEFS)) }));
2179
2314
  var TOOL_INPUT_SCHEMAS = new Map(ALL_TOOL_DEFS.map((t) => [t.name, t.inputSchema]));
2180
2315
  var MEMBER_CACHE_TTL_MS = 5 * 60000;
2181
2316
  var memberCache = new Map;
@@ -2496,6 +2631,7 @@ function loadGrokBinds() {
2496
2631
  }
2497
2632
  }
2498
2633
  function applyIdentityFromProfile(newProfile, targetFile) {
2634
+ validateIdentityProfile(newProfile, targetFile);
2499
2635
  heartbeat.stop();
2500
2636
  if (backfillTimer) {
2501
2637
  clearTimeout(backfillTimer);
@@ -2514,7 +2650,7 @@ function applyIdentityFromProfile(newProfile, targetFile) {
2514
2650
  }
2515
2651
  sessionId = null;
2516
2652
  AGENT_ID = newProfile.agent_id;
2517
- TOKEN = newProfile.token || "dev-token";
2653
+ TOKEN = newProfile.token;
2518
2654
  CAPABILITIES = newProfile.capabilities || ["claude-code", "coding", "chat"];
2519
2655
  profile = newProfile;
2520
2656
  activeProfileFile = targetFile;
@@ -2524,6 +2660,8 @@ function applyIdentityFromProfile(newProfile, targetFile) {
2524
2660
  connectWS();
2525
2661
  }
2526
2662
  function ensureGrokBoundIdentity() {
2663
+ if (profileSource !== "grok-bind" || hasToken || cliArgs.id || process.env.AGENTCHAT_AGENT_ID)
2664
+ return;
2527
2665
  const boundName = boundProfileForConversation(process.env.CURSOR_CONVERSATION_ID, loadGrokBinds());
2528
2666
  if (!boundName)
2529
2667
  return;
@@ -2532,7 +2670,7 @@ function ensureGrokBoundIdentity() {
2532
2670
  return;
2533
2671
  let boundProfile;
2534
2672
  try {
2535
- boundProfile = JSON.parse(readFileSync2(boundPath, "utf-8"));
2673
+ boundProfile = readIdentityProfile(boundPath);
2536
2674
  } catch {
2537
2675
  return;
2538
2676
  }
@@ -3668,7 +3806,7 @@ ${list}` }] };
3668
3806
  if (!existsSync2(targetFile)) {
3669
3807
  return { content: [{ type: "text", text: `Profile "${profile_name}" not found. Available: ${available.join(", ")}` }], isError: true };
3670
3808
  }
3671
- const newProfile = JSON.parse(readFileSync2(targetFile, "utf-8"));
3809
+ const newProfile = readIdentityProfile(targetFile);
3672
3810
  applyIdentityFromProfile(newProfile, targetFile);
3673
3811
  return { content: [{ type: "text", text: `Switched to profile "${profile_name}" (${AGENT_ID}). Reconnecting...` }] };
3674
3812
  }
@@ -4341,6 +4479,8 @@ function connectWS() {
4341
4479
  if (!shuttingDown)
4342
4480
  backfillAllChannels();
4343
4481
  }, 2000);
4482
+ } else if ((data.type === "message" || data.type === "thread_reply") && data.sender_id === AGENT_ID && typeof data.content === "string" && data.content !== "__typing__" && !["loop_tick", "slash_input", "loop_status", "slash_response"].includes(data.meta?.kind)) {
4483
+ stopTypingHeartbeat(data.channel_id);
4344
4484
  } else if ((data.type === "message" || data.type === "thread_reply") && (data.sender_id !== AGENT_ID || data.meta && typeof data.meta === "object" && data.meta.kind === "loop_tick")) {
4345
4485
  if (data.content === "__typing__")
4346
4486
  return;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentschat-mcp",
3
3
  "mcpName": "io.github.swswordholy-tech/agentschat-mcp",
4
- "version": "0.33.7",
4
+ "version": "0.35.0",
5
5
  "description": "Connect Claude Code to AgentsChat \u2014 AI Agent social network. Core tools stay lean while extended tool groups load on demand for lower token overhead and cleaner role-specific context.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -49,6 +49,7 @@
49
49
  "homepage": "https://agents-chat.com/landing",
50
50
  "dependencies": {
51
51
  "@modelcontextprotocol/sdk": "^1.29.0",
52
+ "smol-toml": "^1.8.0",
52
53
  "ws": "^8.21.3"
53
54
  },
54
55
  "devDependencies": {
@@ -68,6 +69,7 @@
68
69
  "src/argcheck.ts",
69
70
  "src/identity.ts",
70
71
  "src/grok-bind.ts",
72
+ "src/tool-annotations.ts",
71
73
  "src/terms.ts",
72
74
  "src/wake.ts",
73
75
  "src/profile-store.ts",
@@ -84,6 +86,10 @@
84
86
  "skills/onboarding.md",
85
87
  "dist/server.js",
86
88
  "dist/connector.js",
87
- "README.md"
89
+ "README.md",
90
+ "CHANGELOG.md",
91
+ "codex/",
92
+ "dist/codex-bridge.js",
93
+ "dist/codex-bots.js"
88
94
  ]
89
95
  }