@caravo/mcp 0.1.3 → 0.1.4
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 +99 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17,12 +17,33 @@
|
|
|
17
17
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
18
18
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
19
19
|
import { z } from "zod";
|
|
20
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
21
|
+
import { homedir } from "os";
|
|
22
|
+
import { join } from "path";
|
|
20
23
|
import { loadOrCreateWallet } from "./wallet.js";
|
|
21
24
|
import { fetchWithX402 } from "./x402.js";
|
|
22
25
|
const API_BASE = process.env.CARAVO_URL ?? "https://caravo.ai";
|
|
23
|
-
//
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
+
// Config file: ~/.caravo/config.json — stores API key set via `login` tool
|
|
27
|
+
const CONFIG_DIR = join(homedir(), ".caravo");
|
|
28
|
+
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
29
|
+
function loadConfig() {
|
|
30
|
+
try {
|
|
31
|
+
if (!existsSync(CONFIG_FILE))
|
|
32
|
+
return {};
|
|
33
|
+
return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return {};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function saveConfig(data) {
|
|
40
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
41
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), { mode: 0o600 });
|
|
42
|
+
}
|
|
43
|
+
// Optional API key: env takes priority, then config file; must have am_ prefix
|
|
44
|
+
const RAW_KEY = process.env.CARAVO_API_KEY || loadConfig().api_key;
|
|
45
|
+
// Mutable so the `login` tool can update it mid-session
|
|
46
|
+
let API_KEY = RAW_KEY && RAW_KEY.startsWith("am_") ? RAW_KEY : undefined;
|
|
26
47
|
const wallet = loadOrCreateWallet();
|
|
27
48
|
process.stderr.write(`[caravo] wallet: ${wallet.address}\n`);
|
|
28
49
|
process.stderr.write(API_KEY
|
|
@@ -282,6 +303,80 @@ function registerAllTools(server) {
|
|
|
282
303
|
],
|
|
283
304
|
};
|
|
284
305
|
});
|
|
306
|
+
// ── Login (browser-based account connect) ────────────────────────────────────
|
|
307
|
+
server.registerTool("login", {
|
|
308
|
+
description: "Connect your Caravo account to enable balance payments and favorites sync. " +
|
|
309
|
+
"Opens caravo.ai in your browser — sign in once and the API key is saved automatically. " +
|
|
310
|
+
"Run this if you started with x402 payments and now want to use your account balance.",
|
|
311
|
+
inputSchema: {},
|
|
312
|
+
}, async () => {
|
|
313
|
+
try {
|
|
314
|
+
// 1. Create one-time session
|
|
315
|
+
const initRes = await fetch(`${API_BASE}/api/auth/mcp-session`, {
|
|
316
|
+
method: "POST",
|
|
317
|
+
headers: { "Content-Type": "application/json" },
|
|
318
|
+
});
|
|
319
|
+
const { token, url } = (await initRes.json());
|
|
320
|
+
// 2. Open browser
|
|
321
|
+
const { exec } = await import("child_process");
|
|
322
|
+
const opener = process.platform === "darwin"
|
|
323
|
+
? `open "${url}"`
|
|
324
|
+
: process.platform === "win32"
|
|
325
|
+
? `start "" "${url}"`
|
|
326
|
+
: `xdg-open "${url}"`;
|
|
327
|
+
exec(opener);
|
|
328
|
+
process.stderr.write(`[caravo] login: opened ${url}\n`);
|
|
329
|
+
// 3. Poll every 2s for up to 5 minutes
|
|
330
|
+
const deadline = Date.now() + 5 * 60 * 1000;
|
|
331
|
+
while (Date.now() < deadline) {
|
|
332
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
333
|
+
const pollRes = await fetch(`${API_BASE}/api/auth/mcp-session?token=${encodeURIComponent(token)}`);
|
|
334
|
+
const poll = (await pollRes.json());
|
|
335
|
+
if (poll.status === "completed" && poll.api_key) {
|
|
336
|
+
// 4. Save to config + activate for this session
|
|
337
|
+
API_KEY = poll.api_key;
|
|
338
|
+
saveConfig({ api_key: poll.api_key });
|
|
339
|
+
process.stderr.write(`[caravo] login: API key saved to ${CONFIG_FILE}\n`);
|
|
340
|
+
return {
|
|
341
|
+
content: [
|
|
342
|
+
{
|
|
343
|
+
type: "text",
|
|
344
|
+
text: [
|
|
345
|
+
`✓ Logged in to Caravo!`,
|
|
346
|
+
``,
|
|
347
|
+
`API key saved to ${CONFIG_FILE}`,
|
|
348
|
+
`Balance payments are now active for this session.`,
|
|
349
|
+
`Restart the MCP server to also load your favorited tools.`,
|
|
350
|
+
].join("\n"),
|
|
351
|
+
},
|
|
352
|
+
],
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
if (poll.status === "expired") {
|
|
356
|
+
return {
|
|
357
|
+
content: [{ type: "text", text: "Login expired. Run login again to retry." }],
|
|
358
|
+
isError: true,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
// status === "pending" — keep polling
|
|
362
|
+
}
|
|
363
|
+
return {
|
|
364
|
+
content: [{ type: "text", text: "Login timed out after 5 minutes. Run login again." }],
|
|
365
|
+
isError: true,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
catch (err) {
|
|
369
|
+
return {
|
|
370
|
+
content: [
|
|
371
|
+
{
|
|
372
|
+
type: "text",
|
|
373
|
+
text: `Login failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
374
|
+
},
|
|
375
|
+
],
|
|
376
|
+
isError: true,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
});
|
|
285
380
|
// ── List tags ────────────────────────────────────────────────────────────────
|
|
286
381
|
server.registerTool("list_tags", {
|
|
287
382
|
description: "List all available tags/categories in the marketplace. Returns tag names, slugs, and tool counts.",
|
|
@@ -759,7 +854,7 @@ function registerAllTools(server) {
|
|
|
759
854
|
// ─── Main ─────────────────────────────────────────────────────────────────────
|
|
760
855
|
const server = new McpServer({
|
|
761
856
|
name: "caravo",
|
|
762
|
-
version: "1.
|
|
857
|
+
version: "0.1.4",
|
|
763
858
|
}, {
|
|
764
859
|
instructions: [
|
|
765
860
|
`You have access to Caravo — a comprehensive platform with a wide variety of ready-to-use tools, APIs, and digital assets at very competitive prices.`,
|