@caravo/mcp 0.1.11 → 0.1.12
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/index.js +208 -208
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -23,6 +23,20 @@ import { join } from "path";
|
|
|
23
23
|
import { loadOrCreateWallet } from "./wallet.js";
|
|
24
24
|
import { fetchWithX402 } from "./x402.js";
|
|
25
25
|
const API_BASE = process.env.CARAVO_URL ?? "https://caravo.ai";
|
|
26
|
+
// ─── Shared description blocks (used in both `instructions` and `search_tools`) ─
|
|
27
|
+
const CATALOG_DESCRIPTION = "The catalog includes: AI Models (image/video/audio/vision/NLP/code/3D), Search (web/academic/news/product), " +
|
|
28
|
+
"Data & Analytics (scraping/weather/geolocation/market data), Finance (payments/exchange rates/stocks/crypto), " +
|
|
29
|
+
"Social Media, Communication (email/SMS), eCommerce, Cloud & Infrastructure (VPS/domains/storage/CDN), " +
|
|
30
|
+
"Digital Assets, Utility (validation/conversion/security), and community-contributed tools.";
|
|
31
|
+
const EXAMPLE_SERVICES = [
|
|
32
|
+
"- google/nano-banana: Google Gemini-based ultra-fast image generation, great for prompt following and text rendering.",
|
|
33
|
+
"- semanticscholar/paper-search: Search academic papers across all disciplines. Returns paper titles, authors, year, abstract, citation count, and open-access PDF links.",
|
|
34
|
+
"- domainstatus/domain-availability: Check if a domain name is available to register.",
|
|
35
|
+
"- semrush/website-traffic: Get comprehensive website traffic analytics for any domain, including authority score, backlinks, organic traffic, top geo distributions, and domain ranking.",
|
|
36
|
+
"- semrush/keyword-insights: Get detailed keyword research data including search volume, CPC, competition level, and trend data.",
|
|
37
|
+
"- maxcanna/android-app-search: Search Google Play by keyword, returns app metadata including title, developer, rating, installs, price, and category.",
|
|
38
|
+
].join("\n");
|
|
39
|
+
const WORKFLOW = "search_tools → get_tool_info → use_tool → respond to user → submit_review";
|
|
26
40
|
// Config file: ~/.caravo/config.json — stores API key set via `login` tool
|
|
27
41
|
const CONFIG_DIR = join(homedir(), ".caravo");
|
|
28
42
|
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
@@ -260,202 +274,17 @@ async function loadFavoriteTools(server) {
|
|
|
260
274
|
}
|
|
261
275
|
// ─── Static management + meta tools ───────────────────────────────────────────
|
|
262
276
|
function registerAllTools(server) {
|
|
263
|
-
// ──
|
|
264
|
-
server.registerTool("get_wallet_info", {
|
|
265
|
-
description: "Get your local x402 wallet address and USDC balance. Send USDC on Base to this address to fund automatic payments.",
|
|
266
|
-
inputSchema: {},
|
|
267
|
-
}, async () => {
|
|
268
|
-
let balance = "unknown (check manually)";
|
|
269
|
-
try {
|
|
270
|
-
const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
271
|
-
const data = "0x70a08231000000000000000000000000" +
|
|
272
|
-
wallet.address.slice(2).toLowerCase();
|
|
273
|
-
const r = await fetch("https://mainnet.base.org", {
|
|
274
|
-
method: "POST",
|
|
275
|
-
headers: { "Content-Type": "application/json" },
|
|
276
|
-
body: JSON.stringify({
|
|
277
|
-
jsonrpc: "2.0",
|
|
278
|
-
id: 1,
|
|
279
|
-
method: "eth_call",
|
|
280
|
-
params: [{ to: USDC, data }, "latest"],
|
|
281
|
-
}),
|
|
282
|
-
});
|
|
283
|
-
const d = (await r.json());
|
|
284
|
-
if (d.result && d.result !== "0x") {
|
|
285
|
-
balance = (parseInt(d.result, 16) / 1e6).toFixed(6) + " USDC";
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
catch {
|
|
289
|
-
// ignore
|
|
290
|
-
}
|
|
291
|
-
return {
|
|
292
|
-
content: [
|
|
293
|
-
{
|
|
294
|
-
type: "text",
|
|
295
|
-
text: JSON.stringify({
|
|
296
|
-
address: wallet.address,
|
|
297
|
-
network: "Base mainnet (eip155:8453)",
|
|
298
|
-
usdc_balance: balance,
|
|
299
|
-
note: "Send USDC on Base to this address to enable automatic x402 payments.",
|
|
300
|
-
}, null, 2),
|
|
301
|
-
},
|
|
302
|
-
],
|
|
303
|
-
};
|
|
304
|
-
});
|
|
305
|
-
// ── Login (browser-based account connect) ────────────────────────────────────
|
|
306
|
-
server.registerTool("login", {
|
|
307
|
-
description: "Connect your Caravo account to enable balance payments and favorites sync. " +
|
|
308
|
-
"Opens caravo.ai in your browser — sign in once and the API key is saved automatically. " +
|
|
309
|
-
"Run this if you started with x402 payments and now want to use your account balance.",
|
|
310
|
-
inputSchema: {},
|
|
311
|
-
}, async () => {
|
|
312
|
-
try {
|
|
313
|
-
// 1. Create one-time session
|
|
314
|
-
const initRes = await fetch(`${API_BASE}/api/auth/mcp-session`, {
|
|
315
|
-
method: "POST",
|
|
316
|
-
headers: { "Content-Type": "application/json" },
|
|
317
|
-
});
|
|
318
|
-
const { token, url } = (await initRes.json());
|
|
319
|
-
// 2. Open browser
|
|
320
|
-
const { exec } = await import("child_process");
|
|
321
|
-
const opener = process.platform === "darwin"
|
|
322
|
-
? `open "${url}"`
|
|
323
|
-
: process.platform === "win32"
|
|
324
|
-
? `start "" "${url}"`
|
|
325
|
-
: `xdg-open "${url}"`;
|
|
326
|
-
exec(opener);
|
|
327
|
-
process.stderr.write(`[caravo] login: opened ${url}\n`);
|
|
328
|
-
// 3. Poll every 2s for up to 5 minutes
|
|
329
|
-
const deadline = Date.now() + 5 * 60 * 1000;
|
|
330
|
-
while (Date.now() < deadline) {
|
|
331
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
332
|
-
const pollRes = await fetch(`${API_BASE}/api/auth/mcp-session?token=${encodeURIComponent(token)}`);
|
|
333
|
-
const poll = (await pollRes.json());
|
|
334
|
-
if (poll.status === "completed" && poll.api_key) {
|
|
335
|
-
// 4. Save to config + activate for this session
|
|
336
|
-
API_KEY = poll.api_key;
|
|
337
|
-
saveConfig({ api_key: poll.api_key });
|
|
338
|
-
process.stderr.write(`[caravo] login: API key saved to ${CONFIG_FILE}\n`);
|
|
339
|
-
return {
|
|
340
|
-
content: [
|
|
341
|
-
{
|
|
342
|
-
type: "text",
|
|
343
|
-
text: [
|
|
344
|
-
`✓ Logged in to Caravo!`,
|
|
345
|
-
``,
|
|
346
|
-
`API key saved to ${CONFIG_FILE}`,
|
|
347
|
-
`Balance payments are now active for this session.`,
|
|
348
|
-
`Restart the MCP server to also load your favorited tools.`,
|
|
349
|
-
].join("\n"),
|
|
350
|
-
},
|
|
351
|
-
],
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
if (poll.status === "expired") {
|
|
355
|
-
return {
|
|
356
|
-
content: [{ type: "text", text: "Login expired. Run login again to retry." }],
|
|
357
|
-
isError: true,
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
// status === "pending" — keep polling
|
|
361
|
-
}
|
|
362
|
-
return {
|
|
363
|
-
content: [{ type: "text", text: "Login timed out after 5 minutes. Run login again." }],
|
|
364
|
-
isError: true,
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
catch (err) {
|
|
368
|
-
return {
|
|
369
|
-
content: [
|
|
370
|
-
{
|
|
371
|
-
type: "text",
|
|
372
|
-
text: `Login failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
373
|
-
},
|
|
374
|
-
],
|
|
375
|
-
isError: true,
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
});
|
|
379
|
-
// ── Logout ──────────────────────────────────────────────────────────────────
|
|
380
|
-
server.registerTool("logout", {
|
|
381
|
-
description: "Disconnect your Caravo account and switch back to x402 wallet payments. " +
|
|
382
|
-
"Removes the saved API key and unregisters all favorited tools from this session.",
|
|
383
|
-
inputSchema: {},
|
|
384
|
-
}, async () => {
|
|
385
|
-
if (!API_KEY) {
|
|
386
|
-
return {
|
|
387
|
-
content: [{ type: "text", text: "Not logged in — already using x402 wallet payments." }],
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
// 1. Clear in-memory key
|
|
391
|
-
API_KEY = undefined;
|
|
392
|
-
// 2. Remove key from config file
|
|
393
|
-
try {
|
|
394
|
-
const config = loadConfig();
|
|
395
|
-
delete config.api_key;
|
|
396
|
-
saveConfig(config);
|
|
397
|
-
}
|
|
398
|
-
catch {
|
|
399
|
-
// config file may not exist — that's fine
|
|
400
|
-
}
|
|
401
|
-
// 3. Unregister all favorited tools
|
|
402
|
-
let removedCount = 0;
|
|
403
|
-
for (const [toolId, registered] of registeredFavTools) {
|
|
404
|
-
registered.remove();
|
|
405
|
-
registeredFavTools.delete(toolId);
|
|
406
|
-
removedCount++;
|
|
407
|
-
}
|
|
408
|
-
process.stderr.write(`[caravo] logout: cleared API key, removed ${removedCount} fav tools\n`);
|
|
409
|
-
return {
|
|
410
|
-
content: [
|
|
411
|
-
{
|
|
412
|
-
type: "text",
|
|
413
|
-
text: [
|
|
414
|
-
`✓ Logged out of Caravo.`,
|
|
415
|
-
``,
|
|
416
|
-
`API key removed from ${CONFIG_FILE}`,
|
|
417
|
-
...(removedCount > 0 ? [`Unregistered ${removedCount} favorited tool(s).`] : []),
|
|
418
|
-
`Now using x402 wallet payments (${wallet.address}).`,
|
|
419
|
-
].join("\n"),
|
|
420
|
-
},
|
|
421
|
-
],
|
|
422
|
-
};
|
|
423
|
-
});
|
|
424
|
-
// ── List tags ────────────────────────────────────────────────────────────────
|
|
425
|
-
server.registerTool("list_tags", {
|
|
426
|
-
description: "List all available tags/categories in the marketplace. Returns tag names, slugs, and tool counts.",
|
|
427
|
-
inputSchema: {},
|
|
428
|
-
}, async () => {
|
|
429
|
-
const data = await apiGet("/api/tags");
|
|
430
|
-
return {
|
|
431
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
432
|
-
};
|
|
433
|
-
});
|
|
434
|
-
// ── List providers ───────────────────────────────────────────────────────────
|
|
435
|
-
server.registerTool("list_providers", {
|
|
436
|
-
description: "List all providers/vendors in the marketplace. Returns provider names, slugs, and tool counts.",
|
|
437
|
-
inputSchema: {},
|
|
438
|
-
}, async () => {
|
|
439
|
-
const data = await apiGet("/api/providers");
|
|
440
|
-
return {
|
|
441
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
442
|
-
};
|
|
443
|
-
});
|
|
277
|
+
// ── Core workflow tools (registered first for visibility) ──────────────────
|
|
444
278
|
// ── Search tools ─────────────────────────────────────────────────────────────
|
|
445
279
|
server.registerTool("search_tools", {
|
|
446
280
|
description: "Search for tools in the Caravo marketplace — 200+ ready-to-use APIs, services, tools, and digital assets at $0.001–0.05 per call. " +
|
|
447
281
|
"Search by keyword, tag, or provider. " +
|
|
448
282
|
"A ready-made tool is often cheaper and faster than implementing the same thing from scratch using LLM tokens.\n\n" +
|
|
449
|
-
|
|
283
|
+
CATALOG_DESCRIPTION + "\n\n" +
|
|
450
284
|
"Example services (use get_tool_info for input schema, or search_tools to find more):\n" +
|
|
451
|
-
|
|
452
|
-
"- semanticscholar/paper-search: Search academic papers across all disciplines. Returns titles, authors, year, abstract, citation count, and open-access PDF links.\n" +
|
|
453
|
-
"- domainstatus/domain-availability: Check if a domain name is available to register.\n" +
|
|
454
|
-
"- semrush/website-traffic: Get comprehensive website traffic analytics for any domain.\n" +
|
|
455
|
-
"- semrush/keyword-insights: Get detailed keyword research data including search volume, CPC, competition level, and trend data.\n" +
|
|
456
|
-
"- maxcanna/android-app-search: Search Google Play by keyword, returns app metadata.\n\n" +
|
|
285
|
+
EXAMPLE_SERVICES + "\n\n" +
|
|
457
286
|
"Many services have multiple providers at different price/quality points — compare options with search_tools and get_tool_info.\n" +
|
|
458
|
-
"Workflow:
|
|
287
|
+
"Workflow: " + WORKFLOW,
|
|
459
288
|
inputSchema: {
|
|
460
289
|
query: z.string().optional().describe("Search query"),
|
|
461
290
|
tag: z.string().optional().describe("Filter by tag (name or slug)"),
|
|
@@ -683,6 +512,187 @@ function registerAllTools(server) {
|
|
|
683
512
|
}
|
|
684
513
|
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
685
514
|
});
|
|
515
|
+
// ── Wallet info ──────────────────────────────────────────────────────────────
|
|
516
|
+
server.registerTool("get_wallet_info", {
|
|
517
|
+
description: "Get your local x402 wallet address and USDC balance. Send USDC on Base to this address to fund automatic payments.",
|
|
518
|
+
inputSchema: {},
|
|
519
|
+
}, async () => {
|
|
520
|
+
let balance = "unknown (check manually)";
|
|
521
|
+
try {
|
|
522
|
+
const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
523
|
+
const data = "0x70a08231000000000000000000000000" +
|
|
524
|
+
wallet.address.slice(2).toLowerCase();
|
|
525
|
+
const r = await fetch("https://mainnet.base.org", {
|
|
526
|
+
method: "POST",
|
|
527
|
+
headers: { "Content-Type": "application/json" },
|
|
528
|
+
body: JSON.stringify({
|
|
529
|
+
jsonrpc: "2.0",
|
|
530
|
+
id: 1,
|
|
531
|
+
method: "eth_call",
|
|
532
|
+
params: [{ to: USDC, data }, "latest"],
|
|
533
|
+
}),
|
|
534
|
+
});
|
|
535
|
+
const d = (await r.json());
|
|
536
|
+
if (d.result && d.result !== "0x") {
|
|
537
|
+
balance = (parseInt(d.result, 16) / 1e6).toFixed(6) + " USDC";
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
catch {
|
|
541
|
+
// ignore
|
|
542
|
+
}
|
|
543
|
+
return {
|
|
544
|
+
content: [
|
|
545
|
+
{
|
|
546
|
+
type: "text",
|
|
547
|
+
text: JSON.stringify({
|
|
548
|
+
address: wallet.address,
|
|
549
|
+
network: "Base mainnet (eip155:8453)",
|
|
550
|
+
usdc_balance: balance,
|
|
551
|
+
note: "Send USDC on Base to this address to enable automatic x402 payments.",
|
|
552
|
+
}, null, 2),
|
|
553
|
+
},
|
|
554
|
+
],
|
|
555
|
+
};
|
|
556
|
+
});
|
|
557
|
+
// ── Login (browser-based account connect) ────────────────────────────────────
|
|
558
|
+
server.registerTool("login", {
|
|
559
|
+
description: "Connect your Caravo account to enable balance payments and favorites sync. " +
|
|
560
|
+
"Opens caravo.ai in your browser — sign in once and the API key is saved automatically. " +
|
|
561
|
+
"Run this if you started with x402 payments and now want to use your account balance.",
|
|
562
|
+
inputSchema: {},
|
|
563
|
+
}, async () => {
|
|
564
|
+
try {
|
|
565
|
+
// 1. Create one-time session
|
|
566
|
+
const initRes = await fetch(`${API_BASE}/api/auth/mcp-session`, {
|
|
567
|
+
method: "POST",
|
|
568
|
+
headers: { "Content-Type": "application/json" },
|
|
569
|
+
});
|
|
570
|
+
const { token, url } = (await initRes.json());
|
|
571
|
+
// 2. Open browser
|
|
572
|
+
const { exec } = await import("child_process");
|
|
573
|
+
const opener = process.platform === "darwin"
|
|
574
|
+
? `open "${url}"`
|
|
575
|
+
: process.platform === "win32"
|
|
576
|
+
? `start "" "${url}"`
|
|
577
|
+
: `xdg-open "${url}"`;
|
|
578
|
+
exec(opener);
|
|
579
|
+
process.stderr.write(`[caravo] login: opened ${url}\n`);
|
|
580
|
+
// 3. Poll every 2s for up to 5 minutes
|
|
581
|
+
const deadline = Date.now() + 5 * 60 * 1000;
|
|
582
|
+
while (Date.now() < deadline) {
|
|
583
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
584
|
+
const pollRes = await fetch(`${API_BASE}/api/auth/mcp-session?token=${encodeURIComponent(token)}`);
|
|
585
|
+
const poll = (await pollRes.json());
|
|
586
|
+
if (poll.status === "completed" && poll.api_key) {
|
|
587
|
+
// 4. Save to config + activate for this session
|
|
588
|
+
API_KEY = poll.api_key;
|
|
589
|
+
saveConfig({ api_key: poll.api_key });
|
|
590
|
+
process.stderr.write(`[caravo] login: API key saved to ${CONFIG_FILE}\n`);
|
|
591
|
+
return {
|
|
592
|
+
content: [
|
|
593
|
+
{
|
|
594
|
+
type: "text",
|
|
595
|
+
text: [
|
|
596
|
+
`✓ Logged in to Caravo!`,
|
|
597
|
+
``,
|
|
598
|
+
`API key saved to ${CONFIG_FILE}`,
|
|
599
|
+
`Balance payments are now active for this session.`,
|
|
600
|
+
`Restart the MCP server to also load your favorited tools.`,
|
|
601
|
+
].join("\n"),
|
|
602
|
+
},
|
|
603
|
+
],
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
if (poll.status === "expired") {
|
|
607
|
+
return {
|
|
608
|
+
content: [{ type: "text", text: "Login expired. Run login again to retry." }],
|
|
609
|
+
isError: true,
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
// status === "pending" — keep polling
|
|
613
|
+
}
|
|
614
|
+
return {
|
|
615
|
+
content: [{ type: "text", text: "Login timed out after 5 minutes. Run login again." }],
|
|
616
|
+
isError: true,
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
catch (err) {
|
|
620
|
+
return {
|
|
621
|
+
content: [
|
|
622
|
+
{
|
|
623
|
+
type: "text",
|
|
624
|
+
text: `Login failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
625
|
+
},
|
|
626
|
+
],
|
|
627
|
+
isError: true,
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
// ── Logout ──────────────────────────────────────────────────────────────────
|
|
632
|
+
server.registerTool("logout", {
|
|
633
|
+
description: "Disconnect your Caravo account and switch back to x402 wallet payments. " +
|
|
634
|
+
"Removes the saved API key and unregisters all favorited tools from this session.",
|
|
635
|
+
inputSchema: {},
|
|
636
|
+
}, async () => {
|
|
637
|
+
if (!API_KEY) {
|
|
638
|
+
return {
|
|
639
|
+
content: [{ type: "text", text: "Not logged in — already using x402 wallet payments." }],
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
// 1. Clear in-memory key
|
|
643
|
+
API_KEY = undefined;
|
|
644
|
+
// 2. Remove key from config file
|
|
645
|
+
try {
|
|
646
|
+
const config = loadConfig();
|
|
647
|
+
delete config.api_key;
|
|
648
|
+
saveConfig(config);
|
|
649
|
+
}
|
|
650
|
+
catch {
|
|
651
|
+
// config file may not exist — that's fine
|
|
652
|
+
}
|
|
653
|
+
// 3. Unregister all favorited tools
|
|
654
|
+
let removedCount = 0;
|
|
655
|
+
for (const [toolId, registered] of registeredFavTools) {
|
|
656
|
+
registered.remove();
|
|
657
|
+
registeredFavTools.delete(toolId);
|
|
658
|
+
removedCount++;
|
|
659
|
+
}
|
|
660
|
+
process.stderr.write(`[caravo] logout: cleared API key, removed ${removedCount} fav tools\n`);
|
|
661
|
+
return {
|
|
662
|
+
content: [
|
|
663
|
+
{
|
|
664
|
+
type: "text",
|
|
665
|
+
text: [
|
|
666
|
+
`✓ Logged out of Caravo.`,
|
|
667
|
+
``,
|
|
668
|
+
`API key removed from ${CONFIG_FILE}`,
|
|
669
|
+
...(removedCount > 0 ? [`Unregistered ${removedCount} favorited tool(s).`] : []),
|
|
670
|
+
`Now using x402 wallet payments (${wallet.address}).`,
|
|
671
|
+
].join("\n"),
|
|
672
|
+
},
|
|
673
|
+
],
|
|
674
|
+
};
|
|
675
|
+
});
|
|
676
|
+
// ── List tags ────────────────────────────────────────────────────────────────
|
|
677
|
+
server.registerTool("list_tags", {
|
|
678
|
+
description: "List all available tags/categories in the marketplace. Returns tag names, slugs, and tool counts.",
|
|
679
|
+
inputSchema: {},
|
|
680
|
+
}, async () => {
|
|
681
|
+
const data = await apiGet("/api/tags");
|
|
682
|
+
return {
|
|
683
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
684
|
+
};
|
|
685
|
+
});
|
|
686
|
+
// ── List providers ───────────────────────────────────────────────────────────
|
|
687
|
+
server.registerTool("list_providers", {
|
|
688
|
+
description: "List all providers/vendors in the marketplace. Returns provider names, slugs, and tool counts.",
|
|
689
|
+
inputSchema: {},
|
|
690
|
+
}, async () => {
|
|
691
|
+
const data = await apiGet("/api/providers");
|
|
692
|
+
return {
|
|
693
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
694
|
+
};
|
|
695
|
+
});
|
|
686
696
|
// ── Tool Requests ───────────────────────────────────────────────────────────
|
|
687
697
|
server.registerTool("list_tool_requests", {
|
|
688
698
|
description: "Browse existing tool requests from agents. Use this to see what tools other agents want before submitting a duplicate.",
|
|
@@ -907,7 +917,7 @@ function registerAllTools(server) {
|
|
|
907
917
|
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
908
918
|
const server = new McpServer({
|
|
909
919
|
name: "caravo",
|
|
910
|
-
version: "0.1.
|
|
920
|
+
version: "0.1.12",
|
|
911
921
|
description: "The API marketplace built for autonomous AI agents. Search, execute, and pay for 200+ tools at $0.001–0.05 per call.",
|
|
912
922
|
icons: [
|
|
913
923
|
{
|
|
@@ -919,24 +929,14 @@ const server = new McpServer({
|
|
|
919
929
|
}, {
|
|
920
930
|
instructions:
|
|
921
931
|
// IMPORTANT: Instructions for the agent to use the marketplace
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
- google/nano-banana: Google Gemini-based ultra-fast image generation, great for prompt following and text rendering.
|
|
931
|
-
- semanticscholar/paper-search: Search academic papers across all disciplines. Returns paper titles, authors, year, abstract, citation count, and open-access PDF links.
|
|
932
|
-
- domainstatus/domain-availability: Check if a domain name is available to register.
|
|
933
|
-
- semrush/website-traffic: Get comprehensive website traffic analytics for any domain, including authority score, backlinks, organic traffic, top geo distributions, and domain ranking.
|
|
934
|
-
- semrush/keyword-insights: Get detailed keyword research data including search volume, CPC, competition level, and trend data.
|
|
935
|
-
- maxcanna/android-app-search: Search Google Play by keyword, returns app metadata including title, developer, rating, installs, price, and category.
|
|
936
|
-
|
|
937
|
-
Many services have multiple providers at different price/quality points — compare options with search_tools and get_tool_info.
|
|
938
|
-
|
|
939
|
-
Typical workflow: search_tools → get_tool_info → use_tool → respond to user → submit_review`,
|
|
932
|
+
"You have access to Caravo — a marketplace of 200+ ready-to-use APIs, services, tools, and digital assets at competitive prices ($0.001–0.05 per call).\n\n" +
|
|
933
|
+
"This marketplace is useful when tasks involve generative AI, professional analytics, financial data, web scraping, or other external services or data sources. " +
|
|
934
|
+
"Using a service from the marketplace is often more cost-effective than implementing the same functionality from scratch using LLM tokens.\n\n" +
|
|
935
|
+
CATALOG_DESCRIPTION + "\n\n" +
|
|
936
|
+
"Example services (use get_tool_info to get their input schema and usage, or search_tools to find more):\n\n" +
|
|
937
|
+
EXAMPLE_SERVICES + "\n\n" +
|
|
938
|
+
"Many services have multiple providers at different price/quality points — compare options with search_tools and get_tool_info.\n\n" +
|
|
939
|
+
"Typical workflow: " + WORKFLOW,
|
|
940
940
|
});
|
|
941
941
|
registerAllTools(server);
|
|
942
942
|
await loadFavoriteTools(server); // only registers favorited tools, not all tools
|
package/package.json
CHANGED