@caravo/mcp 0.1.28 → 0.1.29

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 (2) hide show
  1. package/dist/index.js +38 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -256,34 +256,60 @@ function stripDangerousFields(input) {
256
256
  }
257
257
  return cleaned;
258
258
  }
259
+ const MIME_MAP = {
260
+ ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png",
261
+ ".gif": "image/gif", ".webp": "image/webp", ".bmp": "image/bmp",
262
+ ".svg": "image/svg+xml", ".tif": "image/tiff", ".tiff": "image/tiff",
263
+ ".mp4": "video/mp4", ".webm": "video/webm", ".mov": "video/quicktime",
264
+ ".mp3": "audio/mpeg", ".wav": "audio/wav", ".ogg": "audio/ogg",
265
+ ".pdf": "application/pdf",
266
+ };
267
+ const FILE_EXTENSIONS = new Set(Object.keys(MIME_MAP));
259
268
  /**
260
- * Resolve local file paths in tool input to base64.
261
- * Detects file:// URIs and absolute paths with image extensions.
262
- * Runs locally so base64 never enters the LLM context.
269
+ * Resolve local file paths in tool input to data URIs.
270
+ * Detects file:// URIs, absolute paths, ~/ and ./ paths with known extensions.
271
+ * Data URIs preserve MIME type so the server can upload to Fal Storage.
263
272
  */
264
273
  function resolveLocalFiles(input) {
265
274
  const result = { ...input };
266
275
  for (const [key, value] of Object.entries(result)) {
267
276
  if (typeof value !== "string")
268
277
  continue;
278
+ // Skip URLs and existing data URIs
279
+ if (/^https?:\/\//i.test(value) || /^data:/i.test(value))
280
+ continue;
269
281
  const filePath = toLocalPath(value);
270
282
  if (!filePath)
271
283
  continue;
272
284
  if (!existsSync(filePath)) {
273
285
  throw new Error(`Local file not found: ${filePath}`);
274
286
  }
275
- result[key] = readFileSync(filePath).toString("base64");
287
+ const data = readFileSync(filePath);
288
+ const ext = filePath.substring(filePath.lastIndexOf(".")).toLowerCase();
289
+ const mime = MIME_MAP[ext] || "application/octet-stream";
290
+ result[key] = `data:${mime};base64,${data.toString("base64")}`;
291
+ process.stderr.write(`[caravo] file → data URI: ${filePath} (${mime}, ${data.length} bytes)\n`);
276
292
  }
277
293
  return result;
278
294
  }
279
295
  function toLocalPath(value) {
280
- if (value.startsWith("file:///"))
281
- return value.slice(7);
282
- if (value.startsWith("file://"))
283
- return value.slice(7);
284
- if (/^\//.test(value) && /\.(png|jpe?g|gif|webp|bmp|svg|tiff?)$/i.test(value))
285
- return value;
286
- return null;
296
+ let path = null;
297
+ if (value.startsWith("file://")) {
298
+ path = value.slice(7);
299
+ }
300
+ else if (value.startsWith("~/")) {
301
+ path = join(homedir(), value.slice(2));
302
+ }
303
+ else if (value.startsWith("./") || value.startsWith("../")) {
304
+ path = join(process.cwd(), value);
305
+ }
306
+ else if (/^\//.test(value)) {
307
+ path = value;
308
+ }
309
+ if (!path)
310
+ return null;
311
+ const ext = path.substring(path.lastIndexOf(".")).toLowerCase();
312
+ return FILE_EXTENSIONS.has(ext) ? path : null;
287
313
  }
288
314
  // ─── Favorites registration ────────────────────────────────────────────────────
289
315
  // Track registered fav tool handles for dynamic add/remove
@@ -607,7 +633,7 @@ function registerAllTools(server) {
607
633
  server.registerTool("use_tool", {
608
634
  description: "Execute any marketplace tool by ID. Use get_tool_info first to see the required input schema. " +
609
635
  "Paid tools auto-pay via x402 (wallet) or API key balance. " +
610
- "File upload tip: For tools that accept file input, you can pass a local file path (e.g., /path/to/photo.jpg) or file:// URI — it will be auto-converted to base64. Prefer passing a URL when available. " +
636
+ "File upload tip: For tools that accept file input, you can pass a local file path (e.g., /path/to/photo.jpg), ~/path, or file:// URI — it will be auto-uploaded to CDN. Prefer passing a URL when available. " +
611
637
  "After using a tool, check existing reviews first — upvote one if it matches your experience, or write a new review if none captures your feedback.",
612
638
  inputSchema: {
613
639
  tool_id: z.string().describe("The tool ID or slug to execute (e.g., 'black-forest-labs/flux.1-schnell' or 'alice/imagen-4')"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caravo/mcp",
3
- "version": "0.1.28",
3
+ "version": "0.1.29",
4
4
  "description": "The API marketplace built for autonomous AI agents. Search, execute, and pay for 200+ tools at $0.001–0.05 per call.",
5
5
  "type": "module",
6
6
  "bin": {