agent402-mcp 0.6.0 → 0.7.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 (3) hide show
  1. package/README.md +14 -0
  2. package/index.js +52 -5
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -45,6 +45,20 @@ Claude Code: `claude mcp add agent402 -- npx -y agent402-mcp`
45
45
  - When a call hits HTTP 402: with `AGENT_KEY` set, the server signs an x402 USDC payment and retries; without a key it solves the tool's proof-of-work challenge (~0.2 s of CPU) on the eligible tools.
46
46
  - `payment_info` tells the model which mode it's in and what a wallet would unlock.
47
47
 
48
+ ## Workflows (skill packs)
49
+
50
+ For jobs that no single tool covers (e.g. "audit a domain", "build a stock
51
+ brief"), Agent402 ships curated multi-tool **skill packs**. They're surfaced
52
+ as standard MCP **prompts**, so any MCP-aware client picks them up
53
+ automatically:
54
+
55
+ - `prompts/list` returns each pack with typed arguments.
56
+ - `prompts/get { name: "<slug>", arguments: { … } }` returns the rendered
57
+ task template — a Claude-ready plan with the chosen tools wired in.
58
+ - `search_tools` also surfaces matching workflows alongside individual tools,
59
+ so a task-shaped query points the agent at the right plan, not just the
60
+ raw tools.
61
+
48
62
  ## Configuration
49
63
 
50
64
  | env | default | meaning |
package/index.js CHANGED
@@ -219,6 +219,46 @@ function searchTools(query, limit = 10) {
219
219
  }));
220
220
  }
221
221
 
222
+ // Rank the curated multi-tool skill packs against the same query, so a single
223
+ // search_tools call also tells the agent "this looks like a `security-audit`
224
+ // or `email-deliverability` job — fetch the whole template via prompts/get".
225
+ // Weighted slug/title/tagline/useCase/toolSlugs match — same shape as the
226
+ // hosted /api/find ranking, kept inline here so the stdio package stays
227
+ // dependency-free. Returns [] when no pack scores above the noise floor.
228
+ function rankWorkflows(query, k = 2) {
229
+ const terms = String(query).toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length > 1);
230
+ if (!terms.length || !skillPacks.length) return [];
231
+ const scored = [];
232
+ for (const p of skillPacks) {
233
+ const slug = p.slug.toLowerCase();
234
+ const title = (p.title || "").toLowerCase();
235
+ const tagline = (p.tagline || "").toLowerCase();
236
+ const useCase = (p.useCase || "").toLowerCase();
237
+ const toolSet = new Set((p.toolSlugs || []).map((s) => String(s).toLowerCase()));
238
+ const workflowHay = (p.workflow || []).join(" ").toLowerCase();
239
+ let score = 0;
240
+ for (const term of terms) {
241
+ if (slug === term) score += 12;
242
+ else if (slug.includes(term)) score += 5;
243
+ if (title.includes(term)) score += 3;
244
+ if (tagline.includes(term)) score += 2;
245
+ if (useCase.includes(term)) score += 1;
246
+ if (toolSet.has(term)) score += 4;
247
+ if (workflowHay.includes(term)) score += 1;
248
+ }
249
+ if (score >= 4) scored.push([score, p]);
250
+ }
251
+ scored.sort((a, b) => b[0] - a[0] || a[1].slug.length - b[1].slug.length);
252
+ return scored.slice(0, k).map(([score, p]) => ({
253
+ slug: p.slug,
254
+ title: p.title,
255
+ tagline: p.tagline,
256
+ toolCount: (p.toolSlugs || []).length,
257
+ promptName: p.slug,
258
+ score,
259
+ }));
260
+ }
261
+
222
262
  // ---------------------------------------------------------------------------
223
263
  // MCP wiring
224
264
  const server = new Server({ name: "agent402", version: VERSION }, { capabilities: { tools: {}, prompts: {} } });
@@ -265,7 +305,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
265
305
  {
266
306
  name: "search_tools",
267
307
  description:
268
- `Search the full Agent402 catalog (${catalog.size} pay-per-call tools: encoding, crypto, data conversion, text, time, validation, math, unit conversions, network, browser, memory). Returns matching tools with their price, payment options, and input schema. Call them with call_tool.`,
308
+ `Search the full Agent402 catalog (${catalog.size} pay-per-call tools: encoding, crypto, data conversion, text, time, validation, math, unit conversions, network, browser, memory). Returns matching tools with price, payment options, and input schema call them with call_tool. Also returns matching multi-tool workflow templates (skill packs) when the query is task-shaped; fetch the whole template via prompts/get { name: "<slug>", arguments: { … } }.`,
269
309
  inputSchema: {
270
310
  type: "object",
271
311
  properties: {
@@ -301,13 +341,19 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
301
341
  const { name, arguments: args = {} } = req.params;
302
342
  try {
303
343
  if (name === "search_tools") {
304
- const results = searchTools(args.query ?? "", args.limit ?? 10);
344
+ const q = args.query ?? "";
345
+ const results = searchTools(q, args.limit ?? 10);
346
+ const workflows = rankWorkflows(q, 2);
305
347
  return {
306
348
  content: [{
307
349
  type: "text",
308
- text: results.length
309
- ? JSON.stringify({ results, usage: "call_tool {\"slug\": …, \"params\": …}" }, null, 2)
310
- : `No tools matched "${args.query}". Browse the catalog at ${BASE}/tools or ${BASE}/api/pricing.`,
350
+ text: results.length || workflows.length
351
+ ? JSON.stringify({
352
+ results,
353
+ ...(workflows.length ? { workflows, workflowsUsage: "prompts/get { name: workflows[i].promptName, arguments: { …per-pack args } } returns the full Claude-ready task template." } : {}),
354
+ usage: "call_tool {\"slug\": …, \"params\": …}",
355
+ }, null, 2)
356
+ : `No tools matched "${q}". Browse the catalog at ${BASE}/tools or ${BASE}/api/pricing.`,
311
357
  }],
312
358
  };
313
359
  }
@@ -329,6 +375,7 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
329
375
  tools: catalog.size,
330
376
  payableWithCompute: computePayable,
331
377
  walletOnly: catalog.size - computePayable,
378
+ workflows: skillPacks.length,
332
379
  spendControls: AGENT_KEY
333
380
  ? {
334
381
  maxPerCallUsd: MAX_PER_CALL === Infinity ? "unlimited" : MAX_PER_CALL,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent402-mcp",
3
- "version": "0.6.0",
3
+ "version": "0.7.1",
4
4
  "mcpName": "io.github.MikeyPetrillo/agent402",
5
5
  "author": "Mikey Petrillo (https://github.com/MikeyPetrillo)",
6
6
  "homepage": "https://agent402.tools",