crossfin-mcp 1.8.1 → 1.8.2

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/README.md CHANGED
@@ -39,7 +39,7 @@ crossfin-mcp
39
39
 
40
40
  ### Routing engine
41
41
 
42
- - `find_optimal_route` — find optimal crypto transfer route across 6 exchanges
42
+ - `find_optimal_route` — find optimal crypto transfer route across 6 exchanges (paid via x402, requires `EVM_PRIVATE_KEY`)
43
43
  - `list_exchange_fees` — compare trading and withdrawal fees across exchanges
44
44
  - `compare_exchange_prices` — compare live prices for a coin across Korean exchanges
45
45
 
package/dist/index.js CHANGED
@@ -5,11 +5,15 @@ import { z } from 'zod/v4';
5
5
  import { x402Client, wrapFetchWithPayment, x402HTTPClient } from '@x402/fetch';
6
6
  import { registerExactEvmScheme } from '@x402/evm/exact/client';
7
7
  import { privateKeyToAccount } from 'viem/accounts';
8
+ import { createRequire } from 'node:module';
8
9
  import { createWallet, defaultLedgerPath, getBalance, listTransactions, setBudget, transfer, } from './ledgerStore.js';
9
10
  const LEDGER_PATH = process.env.CROSSFIN_LEDGER_PATH?.trim() || defaultLedgerPath();
10
11
  const API_BASE = (process.env.CROSSFIN_API_URL?.trim() || 'https://crossfin.dev').replace(/\/$/, '');
11
12
  const EVM_PRIVATE_KEY = process.env.EVM_PRIVATE_KEY?.trim() ?? '';
12
13
  const API_ORIGIN = new URL(API_BASE).origin;
14
+ const require = createRequire(import.meta.url);
15
+ const pkg = require('../package.json');
16
+ const MCP_VERSION = typeof pkg.version === 'string' && pkg.version.trim() ? pkg.version.trim() : '0.0.0';
13
17
  function ensureCrossfinPaidUrl(raw) {
14
18
  let url;
15
19
  try {
@@ -53,7 +57,7 @@ function basescanLink(networkId, txHash) {
53
57
  return `https://basescan.org/tx/${txHash}`;
54
58
  return null;
55
59
  }
56
- const server = new McpServer({ name: 'crossfin', version: '1.7.1' });
60
+ const server = new McpServer({ name: 'crossfin', version: MCP_VERSION });
57
61
  const railSchema = z.enum(['manual', 'kakaopay', 'toss', 'stripe', 'x402']);
58
62
  async function apiFetch(path) {
59
63
  const res = await fetch(`${API_BASE}${path}`);
@@ -399,7 +403,8 @@ server.registerTool('find_optimal_route', {
399
403
  title: 'Find optimal route',
400
404
  description: 'Find the cheapest/fastest path to move money across Asian exchanges. ' +
401
405
  'Example: KRW on Bithumb → USDC on Binance. ' +
402
- 'Supports 6 exchanges (Bithumb, Upbit, Coinone, Korbit, GoPax, Binance) and 12 bridge coins.',
406
+ 'Supports 6 exchanges (Bithumb, Upbit, Coinone, Korbit, GoPax, Binance) and 12 bridge coins. ' +
407
+ 'Paid tool: calls /api/premium/route/find ($0.10) via x402 (requires EVM_PRIVATE_KEY).',
403
408
  inputSchema: z.object({
404
409
  from: z
405
410
  .string()
@@ -414,6 +419,12 @@ server.registerTool('find_optimal_route', {
414
419
  .describe('Routing strategy: cheapest (default), fastest, or balanced'),
415
420
  }),
416
421
  }, async ({ from, to, amount, strategy }) => {
422
+ if (!paidFetch || !httpClient) {
423
+ return {
424
+ content: [{ type: 'text', text: 'EVM_PRIVATE_KEY not configured — cannot call paid routing endpoint' }],
425
+ isError: true,
426
+ };
427
+ }
417
428
  try {
418
429
  const qs = new URLSearchParams({
419
430
  from,
@@ -422,8 +433,29 @@ server.registerTool('find_optimal_route', {
422
433
  });
423
434
  if (strategy)
424
435
  qs.set('strategy', strategy);
425
- const data = await apiFetch(`/api/route/find?${qs.toString()}`);
426
- return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
436
+ const targetUrl = ensureCrossfinPaidUrl(`${API_BASE}/api/premium/route/find?${qs.toString()}`);
437
+ const res = await paidFetch(targetUrl, { method: 'GET' });
438
+ const body = await res.text();
439
+ let data;
440
+ try {
441
+ data = JSON.parse(body);
442
+ }
443
+ catch {
444
+ data = body;
445
+ }
446
+ const settle = httpClient.getPaymentSettleResponse((name) => res.headers.get(name));
447
+ const txHash = settle?.transaction;
448
+ const networkId = settle?.network;
449
+ const scanLink = basescanLink(networkId, txHash);
450
+ const result = {
451
+ status: res.status,
452
+ payer: payerAddress,
453
+ paid: !!settle,
454
+ txHash: txHash ?? null,
455
+ basescan: scanLink,
456
+ data,
457
+ };
458
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
427
459
  }
428
460
  catch (e) {
429
461
  return {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "crossfin-mcp",
3
3
  "private": false,
4
- "version": "1.8.1",
4
+ "version": "1.8.2",
5
5
  "description": "CrossFin MCP server for service discovery and paid x402 API execution",
6
6
  "bin": {
7
7
  "crossfin-mcp": "dist/index.js"