@noelclaw/mcp 3.1.0 → 3.2.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.
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runAgent = runAgent;
4
4
  const server_js_1 = require("./server.js");
5
5
  const llm_js_1 = require("./llm.js");
6
- const SYSTEM_PROMPT = "You are Noelclaw, a persistent AI with 74 tools covering memory, automations, DeFi execution, research, and code. " +
6
+ const SYSTEM_PROMPT = "You are Noelclaw, a persistent AI with 76 tools covering memory, automations, DeFi execution, research, and code. " +
7
7
  "Be concise and direct. Use tools when needed. Summarize tool results in plain English.";
8
8
  async function runAgent(userMessage, history, onToolCall) {
9
9
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
package/dist/cli.js CHANGED
@@ -49,7 +49,7 @@ const C = {
49
49
  yellow: "\x1b[33m",
50
50
  };
51
51
  const BANNER = `
52
- ${C.cyan}${C.bold} NOELCLAW${C.reset} ${C.dim}v3.0.0 · 74 tools · persistent AI${C.reset}
52
+ ${C.cyan}${C.bold} NOELCLAW${C.reset} ${C.dim}v3.2.0 · 76 tools · persistent AI${C.reset}
53
53
  ${C.dim}─────────────────────────────────────────${C.reset}
54
54
  ${C.dim}Type anything. /help for commands. Ctrl+C to exit.${C.reset}
55
55
  `;
package/dist/server.js CHANGED
@@ -50,9 +50,9 @@ exports.ALL_TOOLS = [
50
50
  ...scanner_js_1.SCANNER_TOOLS, // 4 — score_token, check_token, scan_dips, scan_momentum
51
51
  ...coder_js_1.CODER_TOOLS, // 5 — generate_contract, audit_contract, explain_code, review_code, generate_mcp_skill
52
52
  ...base_js_1.BASE_TOOLS, // 4 — query_vaults, list_markets, prepare_deposit, chain_stats
53
- ...memory_js_1.MEMORY_TOOLS, // 7 — memory_add, memory_search, memory_context, memory_profile, memory_list, memory_delete, memory_insight
53
+ ...memory_js_1.MEMORY_TOOLS, // 9 — memory_add, memory_search, memory_context, memory_profile, memory_list, memory_delete, memory_insight, memory_extract, memory_consolidate
54
54
  ...os_js_1.OS_TOOLS, // 3 — noel_status, noel_boot, noel_shutdown
55
- // total: 74
55
+ // total: 76
56
56
  ];
57
57
  exports.HANDLER_MAP = new Map([
58
58
  ...market_js_1.MARKET_TOOLS.map(t => [t.name, market_js_1.handleMarketTool]),
@@ -72,7 +72,7 @@ exports.HANDLER_MAP = new Map([
72
72
  ...memory_js_1.MEMORY_TOOLS.map(t => [t.name, memory_js_1.handleMemoryTool]),
73
73
  ...os_js_1.OS_TOOLS.map(t => [t.name, os_js_1.handleOsTool]),
74
74
  ]);
75
- exports.server = new index_js_1.Server({ name: "noelclaw", version: "3.0.0" }, { capabilities: { tools: {} } });
75
+ exports.server = new index_js_1.Server({ name: "noelclaw", version: "3.2.0" }, { capabilities: { tools: {} } });
76
76
  exports.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: exports.ALL_TOOLS }));
77
77
  exports.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
78
78
  const { name, arguments: args } = request.params;
@@ -123,6 +123,36 @@ exports.MEMORY_TOOLS = [
123
123
  required: ["topic"],
124
124
  },
125
125
  },
126
+ {
127
+ name: "memory_extract",
128
+ description: "Auto-extract discrete facts, preferences, and decisions from any text and save them individually to semantic memory. " +
129
+ "Instead of storing a wall of text, Noelclaw breaks it into 3-10 searchable atomic facts using AI. " +
130
+ "Best for processing chat logs, research notes, meeting summaries, or any unstructured content. " +
131
+ "Each extracted fact becomes independently searchable — 'what do I prefer about staking?' will find it.",
132
+ inputSchema: {
133
+ type: "object",
134
+ properties: {
135
+ text: { type: "string", description: "Text to extract facts from — notes, research, chat logs, any unstructured content" },
136
+ source: { type: "string", description: "Optional label for where this came from (e.g. 'telegram', 'research', 'meeting')" },
137
+ },
138
+ required: ["text"],
139
+ },
140
+ },
141
+ {
142
+ name: "memory_consolidate",
143
+ description: "Fetch all memories on a topic and consolidate them into a single comprehensive summary using AI. " +
144
+ "Removes redundancy, merges overlapping facts, and saves the result as a new 'consolidated' memory. " +
145
+ "Use this to clean up fragmented knowledge after heavy research sessions. " +
146
+ "Returns the summary and saves it automatically — the original memories remain intact.",
147
+ inputSchema: {
148
+ type: "object",
149
+ properties: {
150
+ topic: { type: "string", description: "Topic to consolidate memories for (e.g. 'ETH liquid staking', 'Base DeFi')" },
151
+ limit: { type: "number", description: "Max source memories to consolidate (default 12)" },
152
+ },
153
+ required: ["topic"],
154
+ },
155
+ },
126
156
  ];
127
157
  // ─── Zod schemas ─────────────────────────────────────────────────────────────
128
158
  const AddSchema = zod_1.z.object({
@@ -148,6 +178,14 @@ const InsightSchema = zod_1.z.object({
148
178
  topic: zod_1.z.string().min(1),
149
179
  depth: zod_1.z.enum(["quick", "standard", "deep"]).optional(),
150
180
  });
181
+ const ExtractSchema = zod_1.z.object({
182
+ text: zod_1.z.string().min(1),
183
+ source: zod_1.z.string().optional(),
184
+ });
185
+ const ConsolidateSchema = zod_1.z.object({
186
+ topic: zod_1.z.string().min(1),
187
+ limit: zod_1.z.number().optional(),
188
+ });
151
189
  // ─── Handler ─────────────────────────────────────────────────────────────────
152
190
  async function handleMemoryTool(name, args) {
153
191
  switch (name) {
@@ -361,6 +399,51 @@ async function handleMemoryTool(name, args) {
361
399
  lines.push(`• \`swarm_watch topic: "${topic}"\` — monitor this topic continuously`);
362
400
  return { content: [{ type: "text", text: lines.filter(l => l !== undefined).join("\n") }] };
363
401
  }
402
+ case "memory_extract": {
403
+ const parsed = ExtractSchema.safeParse(args);
404
+ if (!parsed.success)
405
+ return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
406
+ const { text, source = "extract" } = parsed.data;
407
+ const data = await (0, convex_js_1.callConvex)("/memory/extract", "POST", { text, source }).catch((err) => ({ error: err.message }));
408
+ if (data?.error)
409
+ return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
410
+ const facts = data?.facts ?? [];
411
+ return {
412
+ content: [{
413
+ type: "text",
414
+ text: [
415
+ `🧠 **Auto-extracted ${data?.extracted ?? facts.length} facts** (${data?.saved ?? 0} saved)`,
416
+ ``,
417
+ ...facts.map((f, i) => `${i + 1}. ${f}`),
418
+ ``,
419
+ `All facts are now searchable via \`memory_search\`.`,
420
+ ].join("\n"),
421
+ }],
422
+ };
423
+ }
424
+ case "memory_consolidate": {
425
+ const parsed = ConsolidateSchema.safeParse(args);
426
+ if (!parsed.success)
427
+ return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
428
+ const { topic, limit = 12 } = parsed.data;
429
+ const data = await (0, convex_js_1.callConvex)("/memory/consolidate", "POST", { topic, n: limit }).catch((err) => ({ error: err.message }));
430
+ if (data?.error)
431
+ return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
432
+ return {
433
+ content: [{
434
+ type: "text",
435
+ text: [
436
+ `🧠 **Consolidated "${topic}"** — merged ${data?.consolidatedFrom ?? "?"} memories`,
437
+ `Saved as: \`${data?.id ?? "consolidated"}\``,
438
+ ``,
439
+ `**Summary:**`,
440
+ data?.summary ?? "",
441
+ ``,
442
+ `Use \`memory_search query: "${topic}"\` to find it.`,
443
+ ].join("\n"),
444
+ }],
445
+ };
446
+ }
364
447
  default:
365
448
  return null;
366
449
  }
package/dist/tools/os.js CHANGED
@@ -108,18 +108,21 @@ async function handleOsTool(name, args) {
108
108
  if (!parsed.success)
109
109
  return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
110
110
  const { focus } = parsed.data;
111
- const [swarmRes, marketRes, autoRes, memRes, focusRes] = await Promise.allSettled([
111
+ const [swarmRes, marketRes, autoRes, memRes, focusRes, prefRes] = await Promise.allSettled([
112
112
  (0, convex_js_1.callConvex)("/swarm/start", "POST", {}, "start_swarm"),
113
113
  (0, market_js_1.fetchMarketSnapshot)(),
114
114
  (0, convex_js_1.callConvex)("/automations/list", "GET", undefined, "list_automations"),
115
115
  (0, convex_js_1.callConvex)("/memory/profile", "GET"),
116
- focus ? (0, memory_js_1.searchSupermemory)(focus, 4) : Promise.resolve([]),
116
+ focus ? (0, memory_js_1.searchSupermemory)(focus, 5) : Promise.resolve([]),
117
+ // Always load user preference/context memories for smart boot
118
+ (0, memory_js_1.searchSupermemory)("user preferences style goals priorities", 4),
117
119
  ]);
118
120
  const swarm = swarmRes.status === "fulfilled" ? swarmRes.value : null;
119
121
  const market = marketRes.status === "fulfilled" ? marketRes.value : null;
120
122
  const autos = autoRes.status === "fulfilled" ? autoRes.value : null;
121
123
  const mem = memRes.status === "fulfilled" ? memRes.value : null;
122
124
  const focusMem = focusRes.status === "fulfilled" ? focusRes.value : [];
125
+ const prefMem = prefRes.status === "fulfilled" ? prefRes.value : [];
123
126
  const automations = autos?.automations ?? [];
124
127
  const activeAutos = automations.filter((a) => a.status === "active");
125
128
  const memTotal = mem?.total ?? 0;
@@ -148,6 +151,15 @@ async function handleOsTool(name, args) {
148
151
  }
149
152
  lines.push("");
150
153
  }
154
+ // Always show user context memories if available
155
+ if (prefMem.length > 0) {
156
+ lines.push(`**User context loaded (${prefMem.length} preferences):**`);
157
+ for (const r of prefMem) {
158
+ const title = r.metadata?.title ?? r.content.slice(0, 80).replace(/\n/g, " ");
159
+ lines.push(` • ${title}`);
160
+ }
161
+ lines.push("");
162
+ }
151
163
  if (focus && focusMem.length > 0) {
152
164
  lines.push(`**Memory context for "${focus}" (${focusMem.length} items):**`);
153
165
  for (const r of focusMem) {
@@ -166,6 +178,7 @@ async function handleOsTool(name, args) {
166
178
  lines.push(` • \`swarm_research topic: "BTC"\` — start morning research`);
167
179
  lines.push(` • \`noel_status\` — full system dashboard`);
168
180
  }
181
+ lines.push(` • \`memory_extract text: "...\"\` — auto-save facts from any note`);
169
182
  return { content: [{ type: "text", text: lines.join("\n") }] };
170
183
  }
171
184
  case "noel_shutdown": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noelclaw/mcp",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Noelclaw AI Operating System — persistent memory, multi-agent swarm, DeFi execution, market intelligence, and Sentinel-gated playbooks.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {