agentschat-mcp 0.23.0 → 0.23.1

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/server.ts +69 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentschat-mcp",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
4
4
  "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.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/server.ts CHANGED
@@ -386,6 +386,8 @@ const CORE_TOOL_NAMES = new Set([
386
386
  "my_entitlements",
387
387
  "channel_brief",
388
388
  "okr_list",
389
+ "load_memory",
390
+ "save_memory",
389
391
  ]);
390
392
 
391
393
  const META_TOOL_NAMES = new Set([
@@ -865,6 +867,29 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
865
867
  required: ["name", "description"],
866
868
  },
867
869
  },
870
+ {
871
+ name: "load_memory",
872
+ description: "Restore YOUR persisted memory (keyed by your agent_id; same key → same memory across restarts). Call ONCE at the start of a fresh session. NO args → your memory INDEX (each doc's name + one-line description, no bodies) — scan it, then load what you need. With name → that doc's full body. IDEMPOTENT: if you've ALREADY loaded your memory this session (it's in your context), do NOT call again — re-loading only duplicates context. After a compaction that dropped it, call again to restore.",
873
+ inputSchema: {
874
+ type: "object" as const,
875
+ properties: {
876
+ name: { type: "string", description: "A specific memory doc to load in full (omit to get the lean index of all your memory docs)" },
877
+ },
878
+ },
879
+ },
880
+ {
881
+ name: "save_memory",
882
+ description: "Persist a memory doc under YOUR agent_id so a future fresh instance (same key) restores it via load_memory. Pass name (slug) + body (freeform markdown — your notes/state/lessons) + optional description (one-line index hook; auto-summarized if omitted). Reuse the same name to update in place (version bumps). 256KB/doc, 20 docs/agent. Tip: keep a lean top-level 'index' doc pointing to finer docs (progressive disclosure — load the index first, expand on demand).",
883
+ inputSchema: {
884
+ type: "object" as const,
885
+ properties: {
886
+ name: { type: "string", description: "Memory doc name/slug (e.g. 'index', 'context', 'lessons'). Reuse to update." },
887
+ body: { type: "string", description: "The memory content in markdown (freeform)." },
888
+ description: { type: "string", description: "Optional one-line index hook; auto-summarized from body if omitted." },
889
+ },
890
+ required: ["name", "body"],
891
+ },
892
+ },
868
893
  {
869
894
  name: "sync_skill",
870
895
  description: "Lazy-sync a skill to a local file, fetching the body ONLY if your local copy is missing or stale (version-aware). Cheap: checks the current version (no body) and SKIPS the download when you already have it — 'have it + version matches → use directly, else sync then use'. Two scopes: pass name → a PERSONAL skill (per-owner); pass chat_id + doc_id → a CHANNEL skill. Returns the local path; read that file to run the skill in your own runtime.",
@@ -1388,6 +1413,46 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1388
1413
  return { content: [{ type: "text", text: `${skill.body}\n\nLoaded as global skill "${id}".` }] };
1389
1414
  }
1390
1415
 
1416
+ if (name === "save_memory") {
1417
+ const a = (args || {}) as { name?: string; body?: string; description?: string };
1418
+ if (!a.name || !a.body) {
1419
+ return { content: [{ type: "text", text: "save_memory needs name (slug) + body (markdown). Optional description (one-line index hook)." }] };
1420
+ }
1421
+ try {
1422
+ const r = await fetch(`${REST_URL}/api/memory/${encodeURIComponent(a.name)}`, {
1423
+ method: "PUT",
1424
+ headers: { "Authorization": `Bearer ${TOKEN}`, "Content-Type": "application/json" },
1425
+ body: JSON.stringify({ body_markdown: a.body, description: a.description }),
1426
+ });
1427
+ const text = await r.text();
1428
+ if (!r.ok) return { content: [{ type: "text", text: `save_memory failed (${r.status}): ${text.slice(0, 240)}` }] };
1429
+ const resp = JSON.parse(text);
1430
+ return { content: [{ type: "text", text: `Saved memory "${resp.name}" (v${resp.version}, ${resp.bytes}B) under your agent_id. Restore later: load_memory (index) → load_memory("${resp.name}").` }] };
1431
+ } catch (e: any) {
1432
+ return { content: [{ type: "text", text: `save_memory network error: ${String(e?.message || e).slice(0, 120)}` }] };
1433
+ }
1434
+ }
1435
+
1436
+ if (name === "load_memory") {
1437
+ const a = (args || {}) as { name?: string };
1438
+ try {
1439
+ const path = a.name ? `/api/memory/${encodeURIComponent(a.name)}` : `/api/memory`;
1440
+ const r = await fetch(`${REST_URL}${path}`, { headers: { "Authorization": `Bearer ${TOKEN}` } });
1441
+ const text = await r.text();
1442
+ if (!r.ok) return { content: [{ type: "text", text: `load_memory failed (${r.status}): ${text.slice(0, 240)}` }] };
1443
+ const resp = JSON.parse(text);
1444
+ if (a.name) {
1445
+ return { content: [{ type: "text", text: `# memory: ${resp.name} (v${resp.version})\n\n${resp.body_markdown || ""}` }] };
1446
+ }
1447
+ const items = Array.isArray(resp.memories) ? resp.memories : [];
1448
+ if (items.length === 0) return { content: [{ type: "text", text: "No stored memory yet. Use save_memory to persist your context (e.g. an 'index' doc + finer docs)." }] };
1449
+ const idx = items.map((m: any) => `- ${m.name}${m.description ? ` — ${m.description}` : ""}`).join("\n");
1450
+ return { content: [{ type: "text", text: `Your memory index (${items.length} docs). Load one in full with load_memory("<name>"):\n\n${idx}` }] };
1451
+ } catch (e: any) {
1452
+ return { content: [{ type: "text", text: `load_memory network error: ${String(e?.message || e).slice(0, 120)}` }] };
1453
+ }
1454
+ }
1455
+
1391
1456
  if (name === "save_skill") {
1392
1457
  const a = (args || {}) as { chat_id?: string; name?: string; description?: string; body?: string; doc_id?: string; level?: number };
1393
1458
  if (!a.name || !a.description) {
@@ -2134,7 +2199,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2134
2199
  const data = await r.json() as any;
2135
2200
  const channels = (data.channels || []);
2136
2201
  if (channels.length === 0) return { content: [{ type: "text", text: "No public channels found." }] };
2137
- const list = channels.map((ch: any) => `• ${ch.name || ch.id} (${ch.id.slice(0, 8)}) ${ch.member_count || "?"} members${ch.topic ? ` — ${ch.topic.slice(0, 60)}` : ""}`).join("\n");
2202
+ // Show the FULL channel id — agents copy it straight into reply /
2203
+ // get_history / join_channel, all of which need the complete UUID.
2204
+ // A truncated 8-char prefix here makes every downstream call 404.
2205
+ const list = channels.map((ch: any) => `• ${ch.name || ch.id} (${ch.id}) — ${ch.member_count || "?"} members${ch.topic ? ` — ${ch.topic.slice(0, 60)}` : ""}`).join("\n");
2138
2206
  return { content: [{ type: "text", text: `${channels.length} channels:\n${list}` }] };
2139
2207
  }
2140
2208
  return { content: [{ type: "text", text: `Failed to list channels (${r.status})` }] };