crypto-com-mcp 1.0.1 → 1.0.3

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
@@ -18,3 +18,5 @@ node dist/index.js
18
18
  ```
19
19
 
20
20
  Data comes from the public Crypto.com API.
21
+
22
+
package/dist/api.js CHANGED
@@ -20,3 +20,57 @@ export async function ticker(args) {
20
20
  `High: ${t.h ?? '?'} | Low: ${t.l ?? '?'} | Volume: ${t.v ?? '?'}`,
21
21
  ].filter(Boolean).join('\n');
22
22
  }
23
+ export async function orderBook(args) {
24
+ const symbol = (args.symbol ?? '').trim().toUpperCase();
25
+ if (!symbol)
26
+ return 'Provide a symbol like BTC_USDT.';
27
+ const depth = Math.max(1, Math.min(Math.trunc(args.depth ?? 10), 50));
28
+ const res = await fetch(`https://api.crypto.com/v2/public/get-book?instrument_name=${encodeURIComponent(symbol)}&depth=${depth}`, {
29
+ headers: { 'User-Agent': UA, Accept: 'application/json' },
30
+ signal: AbortSignal.timeout(20000),
31
+ });
32
+ if (!res.ok)
33
+ throw new Error(`Crypto.com returned ${res.status}`);
34
+ const d = (await res.json());
35
+ if (d.code !== 0)
36
+ throw new Error(`Crypto.com: ${d.msg ?? `code ${d.code}`}`);
37
+ const book = (d.result?.data ?? [])[0];
38
+ if (!book)
39
+ throw new Error(`Crypto.com: no order book for ${symbol}`);
40
+ const level = ([price, qty], i) => ` ${i + 1}. ${price ?? 'not reported'} x ${qty ?? 'not reported'}`;
41
+ const bids = (book.bids ?? []).slice(0, depth).map(level);
42
+ const asks = (book.asks ?? []).slice(0, depth).map(level);
43
+ return [
44
+ `Crypto.com ${symbol} order book, ${depth} level(s) per side:`,
45
+ 'Bids (highest first):',
46
+ ...(bids.length ? bids : [' none reported']),
47
+ 'Asks (lowest first):',
48
+ ...(asks.length ? asks : [' none reported']),
49
+ ].join('\n');
50
+ }
51
+ // ---- up1 tools:
52
+ const V1 = 'https://api.crypto.com/exchange/v1/public';
53
+ export async function instruments(args) {
54
+ const limit = Math.max(1, Math.min(Math.trunc(args.limit ?? 25), 100));
55
+ const query = (args.query ?? '').trim().toUpperCase();
56
+ const res = await fetch(`${V1}/get-instruments`, {
57
+ headers: { 'User-Agent': UA, Accept: 'application/json' },
58
+ signal: AbortSignal.timeout(25000),
59
+ });
60
+ if (!res.ok)
61
+ throw new Error(`Crypto.com returned ${res.status}`);
62
+ const d = (await res.json());
63
+ if (d.code !== 0)
64
+ throw new Error(`Crypto.com: ${d.message ?? `code ${d.code}`}`);
65
+ const all = d.result?.data ?? [];
66
+ if (!all.length)
67
+ throw new Error('Crypto.com returned no instruments');
68
+ const matches = query
69
+ ? all.filter((r) => (r.symbol ?? '').toUpperCase().includes(query) || (r.base_ccy ?? '').toUpperCase() === query)
70
+ : all;
71
+ if (!matches.length)
72
+ return `No Crypto.com instrument matches "${args.query ?? ''}" (${all.length} instruments returned).`;
73
+ const rows = matches.slice(0, limit);
74
+ const lines = rows.map((r, i) => ` ${i + 1}. ${r.symbol ?? '?'} - ${r.inst_type ?? 'not reported'} - ${r.base_ccy ?? '?'}/${r.quote_ccy ?? '?'} - tradable ${r.tradable === undefined ? 'not reported' : r.tradable}`);
75
+ return [`Crypto.com instruments (${rows.length} shown of ${matches.length} matching ${all.length} total):`, ...lines].join('\n');
76
+ }
package/dist/server.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { z } from "zod";
3
- import { ticker } from "./api.js";
3
+ import { ticker, orderBook, instruments } from "./api.js";
4
4
  const text = (value) => ({ content: [{ type: "text", text: value }] });
5
5
  const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
6
6
  const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
@@ -17,7 +17,61 @@ export function createServer() {
17
17
  return text(await ticker(args));
18
18
  }
19
19
  catch (e) {
20
- return textError(error(e));
20
+ return textError(String(e));
21
+ }
22
+ });
23
+ server.registerTool("order_book", {
24
+ title: "Order book",
25
+ description: "Live Crypto.com order book for an instrument: top bid and ask levels with price and quantity.",
26
+ inputSchema: z.object({ symbol: z.string().describe("Symbol like BTC_USDT."), depth: z.number().describe("Levels per side, 1-50.").optional() }),
27
+ annotations: READ_ONLY,
28
+ }, async (args) => {
29
+ try {
30
+ return text(await orderBook(args));
31
+ }
32
+ catch (e) {
33
+ return textError(String(e));
34
+ }
35
+ });
36
+ server.registerTool("candles", {
37
+ title: "Candles",
38
+ description: "OHLCV candles for a Crypto.com instrument: open, high, low, close and volume per interval.",
39
+ inputSchema: z.object({ symbol: z.string().describe("Symbol like BTC_USDT."), timeframe: z.string().describe("1m, 5m, 15m, 30m, 1h, 4h, 6h, 12h, 1d, 7d, 14d or 1M.").optional(), count: z.number().describe("How many candles, 1-200.").optional() }),
40
+ annotations: READ_ONLY,
41
+ }, async (args) => {
42
+ // TODO: implement candles locally (paywall removed)
43
+ try {
44
+ return textError("Not yet implemented: candles");
45
+ }
46
+ catch (e) {
47
+ return textError(String(e));
48
+ }
49
+ });
50
+ server.registerTool("trades", {
51
+ title: "Recent trades",
52
+ description: "Most recent trades on a Crypto.com instrument: time, side, price and quantity.",
53
+ inputSchema: z.object({ symbol: z.string().describe("Symbol like BTC_USDT."), limit: z.number().describe("How many trades, 1-50.").optional() }),
54
+ annotations: READ_ONLY,
55
+ }, async (args) => {
56
+ // TODO: implement trades locally (paywall removed)
57
+ try {
58
+ return textError("Not yet implemented: trades");
59
+ }
60
+ catch (e) {
61
+ return textError(String(e));
62
+ }
63
+ });
64
+ server.registerTool("instruments", {
65
+ title: "Instruments",
66
+ description: "Search the Crypto.com instrument list by symbol or base currency, with instrument type and tradability.",
67
+ inputSchema: z.object({ query: z.string().describe("Symbol or base currency, e.g. 'BTC'.").optional(), limit: z.number().describe("How many to show, 1-100.").optional() }),
68
+ annotations: READ_ONLY,
69
+ }, async (args) => {
70
+ try {
71
+ return text(await instruments(args));
72
+ }
73
+ catch (e) {
74
+ return textError(String(e));
21
75
  }
22
76
  });
23
77
  return server;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.0.1",
2
+ "version": "1.0.3",
3
3
  "type": "module",
4
4
  "repository": {
5
5
  "type": "git",
@@ -41,4 +41,4 @@
41
41
  "node": ">=20"
42
42
  },
43
43
  "mcpName": "io.github.mrfentmen/crypto-com-mcp"
44
- }
44
+ }