@guiie/buda-mcp 1.0.0 → 1.1.0

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 (77) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/PUBLISH_CHECKLIST.md +192 -0
  3. package/README.md +308 -70
  4. package/dist/cache.d.ts +13 -0
  5. package/dist/cache.d.ts.map +1 -0
  6. package/dist/cache.js +25 -0
  7. package/dist/client.d.ts +9 -8
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +95 -12
  10. package/dist/http.d.ts +2 -0
  11. package/dist/http.d.ts.map +1 -0
  12. package/dist/http.js +262 -0
  13. package/dist/index.js +53 -9
  14. package/dist/tools/balances.d.ts +4 -0
  15. package/dist/tools/balances.d.ts.map +1 -0
  16. package/dist/tools/balances.js +23 -0
  17. package/dist/tools/cancel_order.d.ts +4 -0
  18. package/dist/tools/cancel_order.d.ts.map +1 -0
  19. package/dist/tools/cancel_order.js +53 -0
  20. package/dist/tools/compare_markets.d.ts +5 -0
  21. package/dist/tools/compare_markets.d.ts.map +1 -0
  22. package/dist/tools/compare_markets.js +65 -0
  23. package/dist/tools/markets.d.ts +2 -1
  24. package/dist/tools/markets.d.ts.map +1 -1
  25. package/dist/tools/markets.js +22 -8
  26. package/dist/tools/orderbook.d.ts +2 -1
  27. package/dist/tools/orderbook.d.ts.map +1 -1
  28. package/dist/tools/orderbook.js +27 -13
  29. package/dist/tools/orders.d.ts +4 -0
  30. package/dist/tools/orders.d.ts.map +1 -0
  31. package/dist/tools/orders.js +57 -0
  32. package/dist/tools/place_order.d.ts +4 -0
  33. package/dist/tools/place_order.d.ts.map +1 -0
  34. package/dist/tools/place_order.js +88 -0
  35. package/dist/tools/price_history.d.ts +5 -0
  36. package/dist/tools/price_history.d.ts.map +1 -0
  37. package/dist/tools/price_history.js +97 -0
  38. package/dist/tools/spread.d.ts +5 -0
  39. package/dist/tools/spread.d.ts.map +1 -0
  40. package/dist/tools/spread.js +55 -0
  41. package/dist/tools/ticker.d.ts +2 -1
  42. package/dist/tools/ticker.d.ts.map +1 -1
  43. package/dist/tools/ticker.js +19 -5
  44. package/dist/tools/trades.d.ts +2 -1
  45. package/dist/tools/trades.d.ts.map +1 -1
  46. package/dist/tools/trades.js +22 -10
  47. package/dist/tools/volume.d.ts +2 -1
  48. package/dist/tools/volume.d.ts.map +1 -1
  49. package/dist/tools/volume.js +17 -5
  50. package/dist/types.d.ts +42 -1
  51. package/dist/types.d.ts.map +1 -1
  52. package/marketplace/claude-listing.md +76 -8
  53. package/marketplace/cursor-mcp.json +2 -2
  54. package/marketplace/gemini-tools.json +51 -1
  55. package/marketplace/openapi.yaml +204 -4
  56. package/package.json +6 -2
  57. package/railway.json +12 -0
  58. package/server.json +1 -1
  59. package/src/cache.ts +34 -0
  60. package/src/client.ts +107 -12
  61. package/src/http.ts +305 -0
  62. package/src/index.ts +77 -9
  63. package/src/tools/balances.ts +30 -0
  64. package/src/tools/cancel_order.ts +65 -0
  65. package/src/tools/compare_markets.ts +82 -0
  66. package/src/tools/markets.ts +30 -11
  67. package/src/tools/orderbook.ts +31 -16
  68. package/src/tools/orders.ts +68 -0
  69. package/src/tools/place_order.ts +107 -0
  70. package/src/tools/price_history.ts +124 -0
  71. package/src/tools/spread.ts +71 -0
  72. package/src/tools/ticker.ts +23 -8
  73. package/src/tools/trades.ts +24 -12
  74. package/src/tools/volume.ts +20 -8
  75. package/src/types.ts +52 -1
  76. package/test/run-all.ts +122 -1
  77. package/tsconfig.json +1 -1
@@ -0,0 +1,57 @@
1
+ import { z } from "zod";
2
+ import { BudaApiError } from "../client.js";
3
+ export function register(server, client) {
4
+ server.tool("get_orders", "Get orders for a given Buda.com market. Filter by state (pending, active, traded, canceled). " +
5
+ "Requires BUDA_API_KEY and BUDA_API_SECRET environment variables.", {
6
+ market_id: z
7
+ .string()
8
+ .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
9
+ state: z
10
+ .enum(["pending", "active", "traded", "canceled", "canceled_and_traded"])
11
+ .optional()
12
+ .describe("Filter by order state. Omit to return all orders. " +
13
+ "Values: 'pending', 'active', 'traded', 'canceled', 'canceled_and_traded'."),
14
+ per: z
15
+ .number()
16
+ .int()
17
+ .min(1)
18
+ .max(300)
19
+ .optional()
20
+ .describe("Results per page (default: 20, max: 300)."),
21
+ page: z
22
+ .number()
23
+ .int()
24
+ .min(1)
25
+ .optional()
26
+ .describe("Page number (default: 1)."),
27
+ }, async ({ market_id, state, per, page }) => {
28
+ try {
29
+ const params = {};
30
+ if (state)
31
+ params.state = state;
32
+ if (per !== undefined)
33
+ params.per = per;
34
+ if (page !== undefined)
35
+ params.page = page;
36
+ const data = await client.get(`/markets/${market_id.toLowerCase()}/orders`, Object.keys(params).length > 0 ? params : undefined);
37
+ return {
38
+ content: [
39
+ {
40
+ type: "text",
41
+ text: JSON.stringify({ orders: data.orders, meta: data.meta }, null, 2),
42
+ },
43
+ ],
44
+ };
45
+ }
46
+ catch (err) {
47
+ const msg = err instanceof BudaApiError
48
+ ? { error: err.message, code: err.status, path: err.path }
49
+ : { error: String(err), code: "UNKNOWN" };
50
+ return {
51
+ content: [{ type: "text", text: JSON.stringify(msg) }],
52
+ isError: true,
53
+ };
54
+ }
55
+ });
56
+ }
57
+ //# sourceMappingURL=orders.js.map
@@ -0,0 +1,4 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BudaClient } from "../client.js";
3
+ export declare function register(server: McpServer, client: BudaClient): void;
4
+ //# sourceMappingURL=place_order.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"place_order.d.ts","sourceRoot":"","sources":["../../src/tools/place_order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAGxD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAqGpE"}
@@ -0,0 +1,88 @@
1
+ import { z } from "zod";
2
+ import { BudaApiError } from "../client.js";
3
+ export function register(server, client) {
4
+ server.tool("place_order", "Place a limit or market order on Buda.com. " +
5
+ "IMPORTANT: To prevent accidental execution from ambiguous prompts, you must pass " +
6
+ "confirmation_token='CONFIRM' to execute the order. " +
7
+ "Requires BUDA_API_KEY and BUDA_API_SECRET environment variables. " +
8
+ "WARNING: Only use this tool on a locally-run instance — never on a publicly exposed server.", {
9
+ market_id: z
10
+ .string()
11
+ .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
12
+ type: z
13
+ .enum(["Bid", "Ask"])
14
+ .describe("Order side: 'Bid' to buy, 'Ask' to sell."),
15
+ price_type: z
16
+ .enum(["limit", "market"])
17
+ .describe("Order type: 'limit' places at a specific price, 'market' executes immediately."),
18
+ amount: z
19
+ .number()
20
+ .positive()
21
+ .describe("Order size in the market's base currency (e.g. BTC amount for BTC-CLP)."),
22
+ limit_price: z
23
+ .number()
24
+ .positive()
25
+ .optional()
26
+ .describe("Limit price in quote currency. Required when price_type is 'limit'. " +
27
+ "For Bid orders: highest price you will pay. For Ask orders: lowest price you will accept."),
28
+ confirmation_token: z
29
+ .string()
30
+ .describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute the order. " +
31
+ "Any other value will reject the request without placing an order."),
32
+ }, async ({ market_id, type, price_type, amount, limit_price, confirmation_token }) => {
33
+ if (confirmation_token !== "CONFIRM") {
34
+ return {
35
+ content: [
36
+ {
37
+ type: "text",
38
+ text: JSON.stringify({
39
+ error: "Order not placed. confirmation_token must equal 'CONFIRM' to execute. " +
40
+ "Review the order details and set confirmation_token='CONFIRM' to proceed.",
41
+ code: "CONFIRMATION_REQUIRED",
42
+ order_preview: { market_id, type, price_type, amount, limit_price },
43
+ }),
44
+ },
45
+ ],
46
+ isError: true,
47
+ };
48
+ }
49
+ try {
50
+ const payload = {
51
+ type,
52
+ price_type,
53
+ amount,
54
+ };
55
+ if (price_type === "limit") {
56
+ if (limit_price === undefined) {
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: JSON.stringify({
62
+ error: "limit_price is required when price_type is 'limit'.",
63
+ code: "VALIDATION_ERROR",
64
+ }),
65
+ },
66
+ ],
67
+ isError: true,
68
+ };
69
+ }
70
+ payload.limit = { price: limit_price, type: "gtc" };
71
+ }
72
+ const data = await client.post(`/markets/${market_id.toLowerCase()}/orders`, payload);
73
+ return {
74
+ content: [{ type: "text", text: JSON.stringify(data.order, null, 2) }],
75
+ };
76
+ }
77
+ catch (err) {
78
+ const msg = err instanceof BudaApiError
79
+ ? { error: err.message, code: err.status, path: err.path }
80
+ : { error: String(err), code: "UNKNOWN" };
81
+ return {
82
+ content: [{ type: "text", text: JSON.stringify(msg) }],
83
+ isError: true,
84
+ };
85
+ }
86
+ });
87
+ }
88
+ //# sourceMappingURL=place_order.js.map
@@ -0,0 +1,5 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BudaClient } from "../client.js";
3
+ import { MemoryCache } from "../cache.js";
4
+ export declare function register(server: McpServer, client: BudaClient, _cache: MemoryCache): void;
5
+ //# sourceMappingURL=price_history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price_history.d.ts","sourceRoot":"","sources":["../../src/tools/price_history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAmB1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAqGzF"}
@@ -0,0 +1,97 @@
1
+ import { z } from "zod";
2
+ import { BudaApiError } from "../client.js";
3
+ const PERIOD_MS = {
4
+ "1h": 60 * 60 * 1000,
5
+ "4h": 4 * 60 * 60 * 1000,
6
+ "1d": 24 * 60 * 60 * 1000,
7
+ };
8
+ export function register(server, client, _cache) {
9
+ server.tool("get_price_history", "Get OHLCV (open/high/low/close/volume) price history for a Buda.com market, derived from " +
10
+ "recent trade history (up to 100 trades). Buda does not provide a native candlestick endpoint; " +
11
+ "candles are aggregated client-side from raw trades. Use the 'period' parameter to control " +
12
+ "candle size (1h, 4h, or 1d).", {
13
+ market_id: z
14
+ .string()
15
+ .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
16
+ period: z
17
+ .enum(["1h", "4h", "1d"])
18
+ .default("1h")
19
+ .describe("Candle period: '1h' (1 hour), '4h' (4 hours), or '1d' (1 day). Default: '1h'."),
20
+ limit: z
21
+ .number()
22
+ .int()
23
+ .min(1)
24
+ .max(100)
25
+ .optional()
26
+ .describe("Number of raw trades to fetch before aggregation (default: 100, max: 100)."),
27
+ }, async ({ market_id, period, limit }) => {
28
+ try {
29
+ const id = market_id.toLowerCase();
30
+ const tradesLimit = limit ?? 100;
31
+ const data = await client.get(`/markets/${id}/trades`, { limit: tradesLimit });
32
+ const entries = data.trades.entries;
33
+ if (entries.length === 0) {
34
+ return {
35
+ content: [
36
+ {
37
+ type: "text",
38
+ text: JSON.stringify({ market_id: market_id.toUpperCase(), period, candles: [] }),
39
+ },
40
+ ],
41
+ };
42
+ }
43
+ const periodMs = PERIOD_MS[period];
44
+ const buckets = new Map();
45
+ for (const [tsMs, amount, price, _direction] of entries) {
46
+ const ts = parseInt(tsMs, 10);
47
+ const bucketStart = Math.floor(ts / periodMs) * periodMs;
48
+ const p = parseFloat(price);
49
+ const v = parseFloat(amount);
50
+ if (!buckets.has(bucketStart)) {
51
+ buckets.set(bucketStart, {
52
+ time: new Date(bucketStart).toISOString(),
53
+ open: price,
54
+ high: price,
55
+ low: price,
56
+ close: price,
57
+ volume: amount,
58
+ trade_count: 1,
59
+ });
60
+ }
61
+ else {
62
+ const candle = buckets.get(bucketStart);
63
+ if (p > parseFloat(candle.high))
64
+ candle.high = price;
65
+ if (p < parseFloat(candle.low))
66
+ candle.low = price;
67
+ candle.close = price;
68
+ candle.volume = (parseFloat(candle.volume) + v).toFixed(8);
69
+ candle.trade_count++;
70
+ }
71
+ }
72
+ const candles = Array.from(buckets.entries())
73
+ .sort(([a], [b]) => a - b)
74
+ .map(([, candle]) => candle);
75
+ const result = {
76
+ market_id: market_id.toUpperCase(),
77
+ period,
78
+ candle_count: candles.length,
79
+ note: "Candles derived from trade history (up to 100 trades). For deeper history, use pagination via the get_trades tool.",
80
+ candles,
81
+ };
82
+ return {
83
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
84
+ };
85
+ }
86
+ catch (err) {
87
+ const msg = err instanceof BudaApiError
88
+ ? { error: err.message, code: err.status, path: err.path }
89
+ : { error: String(err), code: "UNKNOWN" };
90
+ return {
91
+ content: [{ type: "text", text: JSON.stringify(msg) }],
92
+ isError: true,
93
+ };
94
+ }
95
+ });
96
+ }
97
+ //# sourceMappingURL=price_history.js.map
@@ -0,0 +1,5 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { BudaClient } from "../client.js";
3
+ import { MemoryCache } from "../cache.js";
4
+ export declare function register(server: McpServer, client: BudaClient, cache: MemoryCache): void;
5
+ //# sourceMappingURL=spread.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spread.d.ts","sourceRoot":"","sources":["../../src/tools/spread.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAGrD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAgExF"}
@@ -0,0 +1,55 @@
1
+ import { z } from "zod";
2
+ import { BudaApiError } from "../client.js";
3
+ import { CACHE_TTL } from "../cache.js";
4
+ export function register(server, client, cache) {
5
+ server.tool("get_spread", "Calculate the bid/ask spread for a Buda.com market. " +
6
+ "Returns the best bid, best ask, absolute spread, and spread as a percentage of the ask price.", {
7
+ market_id: z
8
+ .string()
9
+ .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC', 'BTC-COP')."),
10
+ }, async ({ market_id }) => {
11
+ try {
12
+ const id = market_id.toLowerCase();
13
+ const data = await cache.getOrFetch(`ticker:${id}`, CACHE_TTL.TICKER, () => client.get(`/markets/${id}/ticker`));
14
+ const ticker = data.ticker;
15
+ const bid = parseFloat(ticker.max_bid[0]);
16
+ const ask = parseFloat(ticker.min_ask[0]);
17
+ const currency = ticker.max_bid[1];
18
+ if (isNaN(bid) || isNaN(ask) || ask === 0) {
19
+ return {
20
+ content: [
21
+ {
22
+ type: "text",
23
+ text: JSON.stringify({ error: "Unable to calculate spread: invalid bid/ask values" }),
24
+ },
25
+ ],
26
+ isError: true,
27
+ };
28
+ }
29
+ const spreadAbs = ask - bid;
30
+ const spreadPct = (spreadAbs / ask) * 100;
31
+ const result = {
32
+ market_id: ticker.market_id,
33
+ currency,
34
+ best_bid: bid.toString(),
35
+ best_ask: ask.toString(),
36
+ spread_absolute: spreadAbs.toFixed(2),
37
+ spread_percentage: spreadPct.toFixed(4) + "%",
38
+ last_price: ticker.last_price[0],
39
+ };
40
+ return {
41
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
42
+ };
43
+ }
44
+ catch (err) {
45
+ const msg = err instanceof BudaApiError
46
+ ? { error: err.message, code: err.status, path: err.path }
47
+ : { error: String(err), code: "UNKNOWN" };
48
+ return {
49
+ content: [{ type: "text", text: JSON.stringify(msg) }],
50
+ isError: true,
51
+ };
52
+ }
53
+ });
54
+ }
55
+ //# sourceMappingURL=spread.js.map
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { BudaClient } from "../client.js";
3
- export declare function register(server: McpServer, client: BudaClient): void;
3
+ import { MemoryCache } from "../cache.js";
4
+ export declare function register(server: McpServer, client: BudaClient, cache: MemoryCache): void;
4
5
  //# sourceMappingURL=ticker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../src/tools/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
1
+ {"version":3,"file":"ticker.d.ts","sourceRoot":"","sources":["../../src/tools/ticker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAGrD,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAiCxF"}
@@ -1,15 +1,29 @@
1
1
  import { z } from "zod";
2
- export function register(server, client) {
2
+ import { BudaApiError } from "../client.js";
3
+ import { CACHE_TTL } from "../cache.js";
4
+ export function register(server, client, cache) {
3
5
  server.tool("get_ticker", "Get the current ticker for a Buda.com market: last traded price, best bid/ask, " +
4
6
  "24h volume, and price change over 24h and 7d.", {
5
7
  market_id: z
6
8
  .string()
7
9
  .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC', 'BTC-COP')."),
8
10
  }, async ({ market_id }) => {
9
- const data = await client.get(`/markets/${market_id.toLowerCase()}/ticker`);
10
- return {
11
- content: [{ type: "text", text: JSON.stringify(data.ticker, null, 2) }],
12
- };
11
+ try {
12
+ const id = market_id.toLowerCase();
13
+ const data = await cache.getOrFetch(`ticker:${id}`, CACHE_TTL.TICKER, () => client.get(`/markets/${id}/ticker`));
14
+ return {
15
+ content: [{ type: "text", text: JSON.stringify(data.ticker, null, 2) }],
16
+ };
17
+ }
18
+ catch (err) {
19
+ const msg = err instanceof BudaApiError
20
+ ? { error: err.message, code: err.status, path: err.path }
21
+ : { error: String(err), code: "UNKNOWN" };
22
+ return {
23
+ content: [{ type: "text", text: JSON.stringify(msg) }],
24
+ isError: true,
25
+ };
26
+ }
13
27
  });
14
28
  }
15
29
  //# sourceMappingURL=ticker.js.map
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { BudaClient } from "../client.js";
3
- export declare function register(server: McpServer, client: BudaClient): void;
3
+ import { MemoryCache } from "../cache.js";
4
+ export declare function register(server: McpServer, client: BudaClient, _cache: MemoryCache): void;
4
5
  //# sourceMappingURL=trades.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"trades.d.ts","sourceRoot":"","sources":["../../src/tools/trades.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAuCpE"}
1
+ {"version":3,"file":"trades.d.ts","sourceRoot":"","sources":["../../src/tools/trades.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CAkDzF"}
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- export function register(server, client) {
2
+ import { BudaApiError } from "../client.js";
3
+ export function register(server, client, _cache) {
3
4
  server.tool("get_trades", "Get recent trade history for a Buda.com market. Each entry contains " +
4
5
  "[timestamp_ms, amount, price, direction]. Direction is 'buy' or 'sell'.", {
5
6
  market_id: z
@@ -18,15 +19,26 @@ export function register(server, client) {
18
19
  .optional()
19
20
  .describe("Unix timestamp (seconds) to paginate from. Returns trades older than this timestamp."),
20
21
  }, async ({ market_id, limit, timestamp }) => {
21
- const params = {};
22
- if (limit !== undefined)
23
- params.limit = limit;
24
- if (timestamp !== undefined)
25
- params.timestamp = timestamp;
26
- const data = await client.get(`/markets/${market_id.toLowerCase()}/trades`, Object.keys(params).length > 0 ? params : undefined);
27
- return {
28
- content: [{ type: "text", text: JSON.stringify(data.trades, null, 2) }],
29
- };
22
+ try {
23
+ const params = {};
24
+ if (limit !== undefined)
25
+ params.limit = limit;
26
+ if (timestamp !== undefined)
27
+ params.timestamp = timestamp;
28
+ const data = await client.get(`/markets/${market_id.toLowerCase()}/trades`, Object.keys(params).length > 0 ? params : undefined);
29
+ return {
30
+ content: [{ type: "text", text: JSON.stringify(data.trades, null, 2) }],
31
+ };
32
+ }
33
+ catch (err) {
34
+ const msg = err instanceof BudaApiError
35
+ ? { error: err.message, code: err.status, path: err.path }
36
+ : { error: String(err), code: "UNKNOWN" };
37
+ return {
38
+ content: [{ type: "text", text: JSON.stringify(msg) }],
39
+ isError: true,
40
+ };
41
+ }
30
42
  });
31
43
  }
32
44
  //# sourceMappingURL=trades.js.map
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { BudaClient } from "../client.js";
3
- export declare function register(server: McpServer, client: BudaClient): void;
3
+ import { MemoryCache } from "../cache.js";
4
+ export declare function register(server: McpServer, client: BudaClient, _cache: MemoryCache): void;
4
5
  //# sourceMappingURL=volume.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"volume.d.ts","sourceRoot":"","sources":["../../src/tools/volume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
1
+ {"version":3,"file":"volume.d.ts","sourceRoot":"","sources":["../../src/tools/volume.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,IAAI,CA8BzF"}
@@ -1,15 +1,27 @@
1
1
  import { z } from "zod";
2
- export function register(server, client) {
2
+ import { BudaApiError } from "../client.js";
3
+ export function register(server, client, _cache) {
3
4
  server.tool("get_market_volume", "Get 24h and 7-day transacted volume for a Buda.com market. " +
4
5
  "Returns ask (sell) and bid (buy) volumes in the market's base currency.", {
5
6
  market_id: z
6
7
  .string()
7
8
  .describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
8
9
  }, async ({ market_id }) => {
9
- const data = await client.get(`/markets/${market_id.toLowerCase()}/volume`);
10
- return {
11
- content: [{ type: "text", text: JSON.stringify(data.volume, null, 2) }],
12
- };
10
+ try {
11
+ const data = await client.get(`/markets/${market_id.toLowerCase()}/volume`);
12
+ return {
13
+ content: [{ type: "text", text: JSON.stringify(data.volume, null, 2) }],
14
+ };
15
+ }
16
+ catch (err) {
17
+ const msg = err instanceof BudaApiError
18
+ ? { error: err.message, code: err.status, path: err.path }
19
+ : { error: String(err), code: "UNKNOWN" };
20
+ return {
21
+ content: [{ type: "text", text: JSON.stringify(msg) }],
22
+ isError: true,
23
+ };
24
+ }
13
25
  });
14
26
  }
15
27
  //# sourceMappingURL=volume.js.map
package/dist/types.d.ts CHANGED
@@ -31,6 +31,9 @@ export interface Ticker {
31
31
  export interface TickerResponse {
32
32
  ticker: Ticker;
33
33
  }
34
+ export interface AllTickersResponse {
35
+ tickers: Ticker[];
36
+ }
34
37
  export interface OrderBook {
35
38
  asks: [string, string][];
36
39
  bids: [string, string][];
@@ -42,7 +45,7 @@ export interface Trades {
42
45
  timestamp: string;
43
46
  last_timestamp: string;
44
47
  market_id: string;
45
- /** Each entry: [timestamp, amount, price, direction] */
48
+ /** Each entry: [timestamp_ms, amount, price, direction] */
46
49
  entries: [string, string, string, string][];
47
50
  }
48
51
  export interface TradesResponse {
@@ -58,4 +61,42 @@ export interface MarketVolume {
58
61
  export interface VolumeResponse {
59
62
  volume: MarketVolume;
60
63
  }
64
+ export interface Balance {
65
+ id: string;
66
+ amount: Amount;
67
+ available_amount: Amount;
68
+ frozen_amount: Amount;
69
+ pending_withdraw_amount: Amount;
70
+ }
71
+ export interface BalancesResponse {
72
+ balances: Balance[];
73
+ }
74
+ export interface Order {
75
+ id: number;
76
+ type: string;
77
+ state: string;
78
+ created_at: string;
79
+ market_id: string;
80
+ fee_currency: string;
81
+ price_type: string;
82
+ order_type: string;
83
+ client_id: string | null;
84
+ limit: Amount | null;
85
+ amount: Amount;
86
+ original_amount: Amount;
87
+ traded_amount: Amount;
88
+ total_exchanged: Amount;
89
+ paid_fee: Amount;
90
+ }
91
+ export interface OrderResponse {
92
+ order: Order;
93
+ }
94
+ export interface OrdersResponse {
95
+ orders: Order[];
96
+ meta: {
97
+ current_page: number;
98
+ total_count: number;
99
+ total_pages: number;
100
+ };
101
+ }
61
102
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAItC,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,yBAAyB,EAAE,MAAM,CAAC;IAClC,yBAAyB,EAAE,MAAM,CAAC;IAClC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,SAAS,CAAC;CACvB;AAID,MAAM,WAAW,MAAM;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,YAAY,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}