@noelclaw/mcp 2.2.1 → 2.2.3

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/llm.js CHANGED
@@ -3,11 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.callLLM = callLLM;
4
4
  const ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
5
5
  const BANKR_URL = "https://llm.bankr.bot/v1/chat/completions";
6
+ const CONVEX_SITE = process.env.NOELCLAW_CONVEX_URL ?? "https://api.noelclaw.com";
6
7
  /**
7
8
  * Call the best available LLM.
8
- * Priority: ANTHROPIC_API_KEY → BANKR_API_KEY → throws
9
- * Claude Desktop automatically injects ANTHROPIC_API_KEY, so users
10
- * pay for their own AI usage without the server owner absorbing the cost.
9
+ * Priority: ANTHROPIC_API_KEY → BANKR_API_KEY → Convex backend (owner pays)
11
10
  */
12
11
  async function callLLM(systemPrompt, userPrompt, maxTokens = 1024, history = [], timeoutMs = 60000) {
13
12
  const anthropicKey = process.env.ANTHROPIC_API_KEY;
@@ -16,8 +15,25 @@ async function callLLM(systemPrompt, userPrompt, maxTokens = 1024, history = [],
16
15
  return callAnthropic(anthropicKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs);
17
16
  if (bankrKey)
18
17
  return callBankr(bankrKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs);
19
- throw new Error("No LLM API key available. Claude Desktop users: make sure ANTHROPIC_API_KEY is in your MCP config. " +
20
- "Standalone users: set BANKR_API_KEY.");
18
+ // Fallback: route through Convex backend owner covers cost
19
+ return callViaConvex(systemPrompt, userPrompt, history, timeoutMs);
20
+ }
21
+ async function callViaConvex(systemPrompt, userPrompt, history, timeoutMs) {
22
+ const fullQuestion = systemPrompt
23
+ ? `[System: ${systemPrompt}]\n\n${userPrompt}`
24
+ : userPrompt;
25
+ const res = await fetch(`${CONVEX_SITE}/mcp/chat`, {
26
+ method: "POST",
27
+ headers: { "Content-Type": "application/json" },
28
+ body: JSON.stringify({ question: fullQuestion, messages: history }),
29
+ signal: AbortSignal.timeout(timeoutMs),
30
+ });
31
+ if (!res.ok) {
32
+ const body = await res.text().catch(() => "");
33
+ throw new Error(`LLM error ${res.status}: ${body.slice(0, 200)}`);
34
+ }
35
+ const data = await res.json();
36
+ return data.answer ?? "";
21
37
  }
22
38
  async function callAnthropic(apiKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs) {
23
39
  const messages = [...history, { role: "user", content: userPrompt }];
@@ -67,10 +67,9 @@ exports.SWARM_TOOLS = [
67
67
  },
68
68
  {
69
69
  name: "swarm_research",
70
- description: "Task the swarm to research a topic right now triggers market-monitor and sentiment-tracker immediately, " +
71
- "and saves all findings to your vault as persistent research entries. " +
72
- "Unlike regular swarm runs (which only write to ephemeral memory), swarm_research always persists to vault. " +
73
- "Use this when you want the swarm to build up your knowledge base on a specific topic.",
70
+ description: "Research any topic using the multi-agent swarm automatically starts the swarm if needed, " +
71
+ "triggers market-monitor and sentiment-tracker immediately, and saves all findings to vault. " +
72
+ "Use this when the user asks the swarm to research, analyze, or dig into any token, protocol, or market topic.",
74
73
  inputSchema: {
75
74
  type: "object",
76
75
  properties: {
@@ -82,8 +81,8 @@ exports.SWARM_TOOLS = [
82
81
  },
83
82
  {
84
83
  name: "trigger_agent",
85
- description: "Manually trigger a single swarm agent to run right now without starting the full swarm. " +
86
- "Costs 100 credits per call (same as automatic runs). " +
84
+ description: "Run a single swarm agent immediatelyautomatically starts the swarm if needed. " +
85
+ "Costs 100 credits per call. " +
87
86
  "market-monitor fetches live price data, sentiment-tracker analyzes sentiment, " +
88
87
  "memory-manager compresses ephemeral memory, risk-verifier evaluates an action for risk. " +
89
88
  "Results are saved to vault automatically.",
@@ -243,6 +242,8 @@ async function handleSwarmTool(name, args) {
243
242
  if (!parsed.success)
244
243
  return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
245
244
  const { topic, depth = "standard" } = parsed.data;
245
+ // Auto-start swarm if not already running
246
+ await (0, convex_js_1.callConvex)("/swarm/start", "POST", {}, "start_swarm").catch(() => { });
246
247
  const data = await (0, convex_js_1.callConvex)("/swarm/research", "POST", { topic, depth }, "swarm_research");
247
248
  if (data.error)
248
249
  return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
@@ -266,6 +267,8 @@ async function handleSwarmTool(name, args) {
266
267
  if (!parsed.success)
267
268
  return { content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }], isError: true };
268
269
  const { agentId, params = {} } = parsed.data;
270
+ // Auto-start swarm if not already running
271
+ await (0, convex_js_1.callConvex)("/swarm/start", "POST", {}, "start_swarm").catch(() => { });
269
272
  const data = await (0, convex_js_1.callConvex)("/swarm/trigger", "POST", { agentId, params }, "trigger_agent");
270
273
  if (data.error)
271
274
  return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noelclaw/mcp",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "Noelclaw as an MCP skill — persistent memory, multi-agent coordination, scenario simulation, DeFi execution, and Sentinel-gated playbooks.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {