@guiie/buda-mcp 1.5.1 → 1.5.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/PUBLISH_CHECKLIST.md +39 -32
  3. package/dist/audit.d.ts +21 -0
  4. package/dist/audit.d.ts.map +1 -0
  5. package/dist/audit.js +14 -0
  6. package/dist/http.js +25 -3
  7. package/dist/tools/account.js +1 -1
  8. package/dist/tools/arbitrage.js +1 -1
  9. package/dist/tools/balance.js +1 -1
  10. package/dist/tools/balances.js +1 -1
  11. package/dist/tools/banks.js +1 -1
  12. package/dist/tools/batch_orders.d.ts +1 -1
  13. package/dist/tools/batch_orders.d.ts.map +1 -1
  14. package/dist/tools/batch_orders.js +12 -2
  15. package/dist/tools/cancel_all_orders.d.ts +1 -1
  16. package/dist/tools/cancel_all_orders.d.ts.map +1 -1
  17. package/dist/tools/cancel_all_orders.js +10 -13
  18. package/dist/tools/cancel_order.d.ts +1 -1
  19. package/dist/tools/cancel_order.d.ts.map +1 -1
  20. package/dist/tools/cancel_order.js +9 -9
  21. package/dist/tools/cancel_order_by_client_id.d.ts +1 -1
  22. package/dist/tools/cancel_order_by_client_id.d.ts.map +1 -1
  23. package/dist/tools/cancel_order_by_client_id.js +9 -9
  24. package/dist/tools/compare_markets.d.ts +9 -0
  25. package/dist/tools/compare_markets.d.ts.map +1 -1
  26. package/dist/tools/compare_markets.js +63 -53
  27. package/dist/tools/dead_mans_switch.d.ts +1 -1
  28. package/dist/tools/dead_mans_switch.d.ts.map +1 -1
  29. package/dist/tools/dead_mans_switch.js +35 -3
  30. package/dist/tools/deposits.js +2 -2
  31. package/dist/tools/fees.js +1 -1
  32. package/dist/tools/lightning.d.ts +1 -1
  33. package/dist/tools/lightning.d.ts.map +1 -1
  34. package/dist/tools/lightning.js +11 -9
  35. package/dist/tools/market_sentiment.js +1 -1
  36. package/dist/tools/market_summary.js +1 -1
  37. package/dist/tools/markets.js +1 -1
  38. package/dist/tools/order_lookup.js +2 -2
  39. package/dist/tools/orderbook.js +1 -1
  40. package/dist/tools/orders.js +1 -1
  41. package/dist/tools/place_order.d.ts +1 -1
  42. package/dist/tools/place_order.d.ts.map +1 -1
  43. package/dist/tools/place_order.js +22 -4
  44. package/dist/tools/price_history.js +1 -1
  45. package/dist/tools/quotation.js +1 -1
  46. package/dist/tools/receive_addresses.d.ts +1 -1
  47. package/dist/tools/receive_addresses.d.ts.map +1 -1
  48. package/dist/tools/receive_addresses.js +11 -11
  49. package/dist/tools/remittance_recipients.js +2 -2
  50. package/dist/tools/remittances.d.ts +2 -2
  51. package/dist/tools/remittances.d.ts.map +1 -1
  52. package/dist/tools/remittances.js +19 -20
  53. package/dist/tools/simulate_order.js +1 -1
  54. package/dist/tools/spread.js +1 -1
  55. package/dist/tools/technical_indicators.js +1 -1
  56. package/dist/tools/ticker.js +1 -1
  57. package/dist/tools/trades.js +1 -1
  58. package/dist/tools/volume.js +1 -1
  59. package/dist/tools/withdrawals.d.ts +1 -1
  60. package/dist/tools/withdrawals.d.ts.map +1 -1
  61. package/dist/tools/withdrawals.js +10 -10
  62. package/dist/utils.d.ts +10 -0
  63. package/dist/utils.d.ts.map +1 -1
  64. package/dist/utils.js +25 -0
  65. package/package.json +1 -1
  66. package/server.json +2 -2
  67. package/src/audit.ts +24 -0
  68. package/src/http.ts +27 -3
  69. package/src/tools/account.ts +1 -1
  70. package/src/tools/arbitrage.ts +1 -1
  71. package/src/tools/balance.ts +1 -1
  72. package/src/tools/balances.ts +1 -1
  73. package/src/tools/banks.ts +1 -1
  74. package/src/tools/batch_orders.ts +12 -1
  75. package/src/tools/cancel_all_orders.ts +10 -12
  76. package/src/tools/cancel_order.ts +9 -8
  77. package/src/tools/cancel_order_by_client_id.ts +9 -8
  78. package/src/tools/compare_markets.ts +78 -61
  79. package/src/tools/dead_mans_switch.ts +37 -2
  80. package/src/tools/deposits.ts +2 -2
  81. package/src/tools/fees.ts +1 -1
  82. package/src/tools/lightning.ts +12 -9
  83. package/src/tools/market_sentiment.ts +1 -1
  84. package/src/tools/market_summary.ts +1 -1
  85. package/src/tools/markets.ts +1 -1
  86. package/src/tools/order_lookup.ts +2 -2
  87. package/src/tools/orderbook.ts +1 -1
  88. package/src/tools/orders.ts +1 -1
  89. package/src/tools/place_order.ts +24 -5
  90. package/src/tools/price_history.ts +1 -1
  91. package/src/tools/quotation.ts +1 -1
  92. package/src/tools/receive_addresses.ts +11 -10
  93. package/src/tools/remittance_recipients.ts +2 -2
  94. package/src/tools/remittances.ts +19 -18
  95. package/src/tools/simulate_order.ts +1 -1
  96. package/src/tools/spread.ts +1 -1
  97. package/src/tools/technical_indicators.ts +1 -1
  98. package/src/tools/ticker.ts +1 -1
  99. package/src/tools/trades.ts +1 -1
  100. package/src/tools/volume.ts +1 -1
  101. package/src/tools/withdrawals.ts +10 -9
  102. package/src/utils.ts +33 -0
  103. package/test/unit.ts +362 -4
package/CHANGELOG.md CHANGED
@@ -11,6 +11,41 @@ This project uses [Semantic Versioning](https://semver.org/).
11
11
 
12
12
  ---
13
13
 
14
+ ## [1.5.2] – 2026-04-11
15
+
16
+ ### Security
17
+
18
+ - **Trust proxy configured for Railway** — added `app.set("trust proxy", 1)` to Express before any middleware. Without this, `express-rate-limit` saw the proxy IP for every request instead of the real client IP, making per-IP rate limiting effectively useless in the Railway deployment.
19
+
20
+ - **Constant-time bearer token comparison** — `mcpAuthMiddleware` now uses `crypto.timingSafeEqual` via a new `safeTokenEqual()` helper (exported from `src/utils.ts`) instead of plain string equality, eliminating the theoretical timing side-channel on the `MCP_AUTH_TOKEN` comparison.
21
+
22
+ - **PORT and MCP_RATE_LIMIT startup validation** — both environment variables are now parsed through a new `parseEnvInt(raw, fallback, min, max, name)` helper that throws a descriptive error and exits on `NaN` or out-of-range values, preventing silent misconfigurations (e.g. `MCP_RATE_LIMIT=abc` previously resolved to `NaN` and could disable the rate limiter).
23
+
24
+ - **MCP_AUTH_TOKEN entropy warning** — server now emits a `console.warn` at startup if `MCP_AUTH_TOKEN` is set but shorter than 32 characters, nudging operators toward adequately random secrets.
25
+
26
+ - **Dead man's switch fully isolated to stdio transport** — `renew_cancel_timer` and `disarm_cancel_timer` now also return `TRANSPORT_NOT_SUPPORTED` on HTTP transport (previously only `schedule_cancel_all` was blocked). An attacker with HTTP access could previously disarm or renew a timer armed via the stdio process, since both share the same module-level `timers` Map.
27
+
28
+ - **Input validation in `compare_markets`** — `base_currency` is now validated with `validateCurrency()` before fetching tickers, consistent with all other tools that accept a currency parameter. Arbitrary-length strings no longer reach the cache or API.
29
+
30
+ - **BOLT-11 invoice regex strengthened** — regex updated from `/^ln(bc|tb|bcrt)\d/i` to `/^ln(bc|tb|bcrt)\d*[munp]?1[a-z0-9]{20,}$/i`. The new pattern requires the bech32 separator `1`, at least 20 characters of bech32 data after it, and anchors at `$` — rejecting malformed strings that happen to start with the right prefix.
31
+
32
+ - **API path redaction from error responses** — removed the `path` field from all `BudaApiError` catch blocks across 31 tool handlers. The field was included in MCP tool responses, leaking internal API endpoint patterns (e.g. `/currencies/BTC/withdrawals`) to clients. The `path` property still exists on `BudaApiError` for internal use in audit logs.
33
+
34
+ - **Structured audit logging for destructive operations** — new `src/audit.ts` module with `logAudit(event: AuditEvent)` writes newline-delimited JSON to `process.stderr` for all 11 handlers with financial side-effects: `place_order`, `cancel_order`, `cancel_all_orders`, `cancel_order_by_client_id`, `place_batch_orders`, `create_withdrawal`, `lightning_withdrawal`, `create_receive_address`, `quote_remittance`, `accept_remittance_quote`, `schedule_cancel_all`. Audit events include `ts`, `tool`, `transport`, `args_summary` (sanitized — never includes `confirmation_token`, `invoice`, or `address`), `success`, and `error_code`. Each handler exposes an optional `transport` parameter (default `"stdio"`) for future HTTP-aware logging.
35
+
36
+ ### Added
37
+
38
+ - **`safeTokenEqual(a, b)` utility** — exported from `src/utils.ts`; constant-time string comparison using `crypto.timingSafeEqual`. Usable by any future code that compares secrets.
39
+ - **`parseEnvInt(raw, fallback, min, max, name)` utility** — exported from `src/utils.ts`; safe environment variable integer parsing with range validation. Used for `PORT` and `MCP_RATE_LIMIT` at startup.
40
+ - **`handleCompareMarkets` exported handler** — `compare_markets.ts` logic extracted from the inline registration closure into a named, exported function for unit testability.
41
+
42
+ ### Tests
43
+
44
+ - **+28 unit tests** covering all new security behaviors: `safeTokenEqual` (5 cases), `parseEnvInt` (6 cases), `handleCompareMarkets` validateCurrency guard (4 cases), improved BOLT-11 regex (3 cases), DMS HTTP transport guard for renew and disarm (4 cases), `logAudit` output format and secret redaction (3 cases), audit integration with `handlePlaceOrder` (1 case), `path` field absence in error responses (2 cases).
45
+ - **Updated 3 existing test fixtures** — replaced placeholder invoice string `"lnbc1000u1ptest..."` (which contained dots — invalid bech32) with a well-formed test value that satisfies the improved BOLT-11 regex.
46
+
47
+ ---
48
+
14
49
  ## [1.5.1] – 2026-04-11
15
50
 
16
51
  ### Security
@@ -1,6 +1,6 @@
1
- # Publish Checklist — buda-mcp v1.5.1
1
+ # Publish Checklist — buda-mcp v1.5.2
2
2
 
3
- Steps to publish `v1.5.1` to npm, the MCP registry, and notify community directories.
3
+ Steps to publish `v1.5.2` to npm, the MCP registry, and notify community directories.
4
4
 
5
5
  ---
6
6
 
@@ -8,7 +8,7 @@ Steps to publish `v1.5.1` to npm, the MCP registry, and notify community directo
8
8
 
9
9
  ```bash
10
10
  # Confirm version
11
- node -e "console.log(require('./package.json').version)" # should print 1.5.1
11
+ node -e "console.log(require('./package.json').version)" # should print 1.5.2
12
12
 
13
13
  # Build and test
14
14
  npm run build
@@ -37,9 +37,9 @@ Verify: https://www.npmjs.com/package/@guiie/buda-mcp
37
37
 
38
38
  ## 3. GitHub release
39
39
 
40
- Tag and release already created via `gh release create v1.5.1`. Verify at:
40
+ Tag and release already created via `gh release create v1.5.2`. Verify at:
41
41
 
42
- https://github.com/gtorreal/buda-mcp/releases/tag/v1.5.1
42
+ https://github.com/gtorreal/buda-mcp/releases/tag/v1.5.2
43
43
 
44
44
  ---
45
45
 
@@ -64,20 +64,23 @@ Verify: https://smithery.ai/server/@guiie/buda-mcp
64
64
  **Email/message template:**
65
65
 
66
66
  ```
67
- Subject: [Update] buda-mcp v1.5.1 — Security hardening release
67
+ Subject: [Update] buda-mcp v1.5.2 — Security hardening (second pass)
68
68
 
69
69
  Hi mcp.so team,
70
70
 
71
- I've released v1.5.1 of buda-mcp (@guiie/buda-mcp on npm).
71
+ I've released v1.5.2 of buda-mcp (@guiie/buda-mcp on npm).
72
72
 
73
73
  Key changes (security hardening, no new tools):
74
- - HTTP startup guard: server exits if credentials are set without MCP_AUTH_TOKEN
75
- - Rate limiting: 120 req/min per IP on /mcp (configurable via MCP_RATE_LIMIT)
76
- - Crypto address validation in create_withdrawal (BTC, ETH, USDC, USDT, LTC, BCH, XRP)
77
- - BOLT-11 invoice format validation in lightning_withdrawal
78
- - Dead man's switch blocked on HTTP transport (process restarts drop timers)
79
- - place_batch_orders: optional max_notional spending cap
80
- - 156 unit tests (was 136)
74
+ - Constant-time token comparison (timing-safe Bearer token auth)
75
+ - Strict environment variable validation (PORT, MCP_RATE_LIMIT) with safe exit on bad config
76
+ - MCP_AUTH_TOKEN entropy warning (< 32 chars)
77
+ - trust proxy support for correct client IP detection behind reverse proxies
78
+ - Audit logging for all 11 destructive tool handlers (structured JSON to stderr)
79
+ - Dead man's switch: renew/disarm also blocked on HTTP transport
80
+ - validateCurrency() added to compare_markets tool
81
+ - Stronger BOLT-11 regex validation in lightning_withdrawal
82
+ - Internal API paths redacted from all error responses (31 tool handlers)
83
+ - 28 new unit tests (total now 184)
81
84
 
82
85
  Links:
83
86
  - npm: https://www.npmjs.com/package/@guiie/buda-mcp
@@ -96,24 +99,25 @@ Thank you!
96
99
  **Message template:**
97
100
 
98
101
  ```
99
- Subject: [Update] buda-mcp v1.5.1
102
+ Subject: [Update] buda-mcp v1.5.2
100
103
 
101
104
  Hi Glama team,
102
105
 
103
- buda-mcp has been updated to v1.5.1.
106
+ buda-mcp has been updated to v1.5.2.
104
107
 
105
108
  Package: @guiie/buda-mcp (npm)
106
109
  Registry: io.github.gtorreal/buda-mcp (MCP Registry)
107
- Version: 1.5.1
108
-
109
- Changes (security hardening):
110
- - HTTP startup guard for missing MCP_AUTH_TOKEN
111
- - Rate limiting on /mcp (120 req/min per IP)
112
- - Crypto address format validation in create_withdrawal
113
- - BOLT-11 invoice validation in lightning_withdrawal
114
- - Dead man's switch blocked on HTTP transport
115
- - place_batch_orders: optional max_notional cap
116
- - 156 unit tests
110
+ Version: 1.5.2
111
+
112
+ Changes (security hardening, second pass):
113
+ - Constant-time token comparison (timing-safe auth)
114
+ - Strict env var validation (PORT, MCP_RATE_LIMIT)
115
+ - Audit logging for all destructive handlers
116
+ - Dead man's switch: renew/disarm also blocked on HTTP
117
+ - validateCurrency() in compare_markets
118
+ - Stronger BOLT-11 regex
119
+ - Internal paths redacted from error responses
120
+ - 184 unit tests
117
121
 
118
122
  Quick start:
119
123
  npx @guiie/buda-mcp
@@ -128,17 +132,20 @@ Thank you!
128
132
 
129
133
  ## 8. Post-publish verification
130
134
 
131
- - [ ] `npx @guiie/buda-mcp@1.5.1` starts successfully
132
- - [ ] `npm info @guiie/buda-mcp version` returns `1.5.1`
133
- - [ ] GitHub release tag `v1.5.1` is visible
134
- - [ ] MCP Registry entry reflects v1.5.1
135
+ - [ ] `npx @guiie/buda-mcp@1.5.2` starts successfully
136
+ - [ ] `npm info @guiie/buda-mcp version` returns `1.5.2`
137
+ - [ ] GitHub release tag `v1.5.2` is visible
138
+ - [ ] MCP Registry entry reflects v1.5.2
135
139
  - [ ] Smithery server card lists all tools
136
- - [ ] `GET /health` returns `"version":"1.5.1"` on Railway deployment
140
+ - [ ] `GET /health` returns `"version":"1.5.2"` on Railway deployment
137
141
  - [ ] HTTP server exits if `BUDA_API_KEY` set but `MCP_AUTH_TOKEN` is absent
138
142
  - [ ] `create_withdrawal` rejects a truncated BTC address with `INVALID_ADDRESS`
139
143
  - [ ] `lightning_withdrawal` rejects a non-BOLT11 string with `INVALID_INVOICE`
140
144
  - [ ] `place_batch_orders` with `max_notional` rejects over-cap batch before API call
141
145
  - [ ] `schedule_cancel_all` via HTTP returns `TRANSPORT_NOT_SUPPORTED`
146
+ - [ ] `renew_cancel_timer` via HTTP returns `TRANSPORT_NOT_SUPPORTED`
147
+ - [ ] Error responses do NOT include internal `path` field
148
+ - [ ] Audit events appear in stderr as JSON with `audit: true`
142
149
  - [ ] mcp.so listing updated
143
150
  - [ ] Glama.ai listing updated
144
151
 
@@ -146,4 +153,4 @@ Thank you!
146
153
 
147
154
  ## ARCHIVED: previous checklists
148
155
 
149
- See git tags `v1.5.0`, `v1.4.0`, `v1.4.1`, `v1.4.2` for previous release notes and verification steps.
156
+ See git tags `v1.5.0`, `v1.5.1`, `v1.4.0`, `v1.4.1`, `v1.4.2` for previous release notes and verification steps.
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Structured audit logging for destructive MCP tool calls.
3
+ *
4
+ * Writes newline-delimited JSON to stderr so it never pollutes the stdio MCP transport
5
+ * and is captured by Railway / any log aggregator attached to the process.
6
+ *
7
+ * Rules for args_summary:
8
+ * - Include: market_id, currency, price_type, type, amount ranges
9
+ * - NEVER include: confirmation_token, invoice, address, bank_account_id
10
+ */
11
+ export interface AuditEvent {
12
+ ts: string;
13
+ tool: string;
14
+ transport: "http" | "stdio";
15
+ ip?: string;
16
+ args_summary: Record<string, unknown>;
17
+ success: boolean;
18
+ error_code?: string | number;
19
+ }
20
+ export declare function logAudit(event: AuditEvent): void;
21
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAEhD"}
package/dist/audit.js ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Structured audit logging for destructive MCP tool calls.
3
+ *
4
+ * Writes newline-delimited JSON to stderr so it never pollutes the stdio MCP transport
5
+ * and is captured by Railway / any log aggregator attached to the process.
6
+ *
7
+ * Rules for args_summary:
8
+ * - Include: market_id, currency, price_type, type, amount ranges
9
+ * - NEVER include: confirmation_token, invoice, address, bank_account_id
10
+ */
11
+ export function logAudit(event) {
12
+ process.stderr.write(JSON.stringify({ audit: true, ...event }) + "\n");
13
+ }
14
+ //# sourceMappingURL=audit.js.map
package/dist/http.js CHANGED
@@ -4,6 +4,7 @@ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mc
4
4
  import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
5
  import { BudaClient } from "./client.js";
6
6
  import { MemoryCache, CACHE_TTL } from "./cache.js";
7
+ import { safeTokenEqual, parseEnvInt } from "./utils.js";
7
8
  import { VERSION } from "./version.js";
8
9
  import { validateMarketId } from "./validation.js";
9
10
  import * as markets from "./tools/markets.js";
@@ -41,7 +42,14 @@ import * as cancelOrderByClientId from "./tools/cancel_order_by_client_id.js";
41
42
  import * as batchOrders from "./tools/batch_orders.js";
42
43
  import * as lightning from "./tools/lightning.js";
43
44
  import { handleMarketSummary } from "./tools/market_summary.js";
44
- const PORT = parseInt(process.env.PORT ?? "3000", 10);
45
+ let PORT;
46
+ try {
47
+ PORT = parseEnvInt(process.env.PORT, 3000, 1, 65535, "PORT");
48
+ }
49
+ catch (err) {
50
+ console.error(err instanceof Error ? err.message : String(err));
51
+ process.exit(1);
52
+ }
45
53
  const client = new BudaClient(undefined, process.env.BUDA_API_KEY, process.env.BUDA_API_SECRET);
46
54
  const authEnabled = client.hasAuth();
47
55
  // Schemas for the Smithery server-card — assembled from the same definitions used in register().
@@ -187,6 +195,9 @@ function createServer() {
187
195
  return server;
188
196
  }
189
197
  const app = express();
198
+ // Required for correct client IP detection behind Railway's reverse proxy.
199
+ // Without this, express-rate-limit sees the proxy IP instead of the real client.
200
+ app.set("trust proxy", 1);
190
201
  app.use(express.json());
191
202
  const MCP_AUTH_TOKEN = process.env.MCP_AUTH_TOKEN;
192
203
  if (authEnabled && !MCP_AUTH_TOKEN) {
@@ -195,9 +206,20 @@ if (authEnabled && !MCP_AUTH_TOKEN) {
195
206
  " Set MCP_AUTH_TOKEN to a long random secret, or run in stdio mode instead.");
196
207
  process.exit(1);
197
208
  }
209
+ if (MCP_AUTH_TOKEN && MCP_AUTH_TOKEN.length < 32) {
210
+ console.warn("[buda-mcp] WARNING: MCP_AUTH_TOKEN has fewer than 32 characters. Use a longer random secret.");
211
+ }
212
+ let rateLimitMax;
213
+ try {
214
+ rateLimitMax = parseEnvInt(process.env.MCP_RATE_LIMIT, 120, 1, 10_000, "MCP_RATE_LIMIT");
215
+ }
216
+ catch (err) {
217
+ console.error(err instanceof Error ? err.message : String(err));
218
+ process.exit(1);
219
+ }
198
220
  const mcpRateLimiter = rateLimit({
199
221
  windowMs: 60_000,
200
- max: parseInt(process.env.MCP_RATE_LIMIT ?? "120", 10),
222
+ max: rateLimitMax,
201
223
  standardHeaders: true,
202
224
  legacyHeaders: false,
203
225
  message: { error: "Too many requests. Retry after 60 seconds.", code: "RATE_LIMITED" },
@@ -208,7 +230,7 @@ function mcpAuthMiddleware(req, res, next) {
208
230
  return;
209
231
  }
210
232
  const auth = req.headers.authorization ?? "";
211
- if (auth !== `Bearer ${MCP_AUTH_TOKEN}`) {
233
+ if (!safeTokenEqual(auth, `Bearer ${MCP_AUTH_TOKEN}`)) {
212
234
  res.status(401).json({ error: "Unauthorized" });
213
235
  return;
214
236
  }
@@ -35,7 +35,7 @@ export async function handleGetAccountInfo(client) {
35
35
  }
36
36
  catch (err) {
37
37
  const msg = err instanceof BudaApiError
38
- ? { error: err.message, code: err.status, path: err.path }
38
+ ? { error: err.message, code: err.status }
39
39
  : { error: String(err), code: "UNKNOWN" };
40
40
  return {
41
41
  content: [{ type: "text", text: JSON.stringify(msg) }],
@@ -118,7 +118,7 @@ export async function handleArbitrageOpportunities({ base_currency, threshold_pc
118
118
  }
119
119
  catch (err) {
120
120
  const msg = err instanceof BudaApiError
121
- ? { error: err.message, code: err.status, path: err.path }
121
+ ? { error: err.message, code: err.status }
122
122
  : { error: String(err), code: "UNKNOWN" };
123
123
  return {
124
124
  content: [{ type: "text", text: JSON.stringify(msg) }],
@@ -56,7 +56,7 @@ export async function handleGetBalance(args, client) {
56
56
  }
57
57
  catch (err) {
58
58
  const msg = err instanceof BudaApiError
59
- ? { error: err.message, code: err.status, path: err.path }
59
+ ? { error: err.message, code: err.status }
60
60
  : { error: String(err), code: "UNKNOWN" };
61
61
  return {
62
62
  content: [{ type: "text", text: JSON.stringify(msg) }],
@@ -39,7 +39,7 @@ export function register(server, client) {
39
39
  }
40
40
  catch (err) {
41
41
  const msg = err instanceof BudaApiError
42
- ? { error: err.message, code: err.status, path: err.path }
42
+ ? { error: err.message, code: err.status }
43
43
  : { error: String(err), code: "UNKNOWN" };
44
44
  return {
45
45
  content: [{ type: "text", text: JSON.stringify(msg) }],
@@ -52,7 +52,7 @@ export async function handleGetAvailableBanks(args, client, cache) {
52
52
  };
53
53
  }
54
54
  const msg = err instanceof BudaApiError
55
- ? { error: err.message, code: err.status, path: err.path }
55
+ ? { error: err.message, code: err.status }
56
56
  : { error: String(err), code: "UNKNOWN" };
57
57
  return {
58
58
  content: [{ type: "text", text: JSON.stringify(msg) }],
@@ -70,7 +70,7 @@ type BatchOrdersArgs = {
70
70
  max_notional?: number;
71
71
  confirmation_token: string;
72
72
  };
73
- export declare function handlePlaceBatchOrders(args: BatchOrdersArgs, client: BudaClient): Promise<{
73
+ export declare function handlePlaceBatchOrders(args: BatchOrdersArgs, client: BudaClient, transport?: "http" | "stdio"): Promise<{
74
74
  content: Array<{
75
75
  type: "text";
76
76
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"batch_orders.d.ts","sourceRoot":"","sources":["../../src/tools/batch_orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CtB,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;iBAMd,CAAC;AAEH,KAAK,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAWnD,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAkIhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA2BpE"}
1
+ {"version":3,"file":"batch_orders.d.ts","sourceRoot":"","sources":["../../src/tools/batch_orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CtB,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;iBAMd,CAAC;AAEH,KAAK,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAWnD,KAAK,eAAe,GAAG;IACrB,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA2IhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA2BpE"}
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { BudaApiError } from "../client.js";
3
3
  import { validateMarketId } from "../validation.js";
4
+ import { logAudit } from "../audit.js";
4
5
  export const toolSchema = {
5
6
  name: "place_batch_orders",
6
7
  description: "Place multiple orders sequentially on Buda.com (up to 20). " +
@@ -48,7 +49,7 @@ const orderShape = z.object({
48
49
  amount: z.number().positive(),
49
50
  limit_price: z.number().positive().optional(),
50
51
  });
51
- export async function handlePlaceBatchOrders(args, client) {
52
+ export async function handlePlaceBatchOrders(args, client, transport = "stdio") {
52
53
  const { orders, max_notional, confirmation_token } = args;
53
54
  if (confirmation_token !== "CONFIRM") {
54
55
  return {
@@ -161,9 +162,18 @@ export async function handlePlaceBatchOrders(args, client) {
161
162
  if (failed > 0 && succeeded > 0) {
162
163
  response.warning = "Some orders failed. Already-placed orders were NOT rolled back.";
163
164
  }
165
+ const isError = failed > 0 && succeeded === 0 ? true : undefined;
166
+ logAudit({
167
+ ts: new Date().toISOString(),
168
+ tool: "place_batch_orders",
169
+ transport,
170
+ args_summary: { order_count: orders.length, succeeded, failed },
171
+ success: !isError,
172
+ error_code: isError ? "PARTIAL_OR_FULL_FAILURE" : undefined,
173
+ });
164
174
  return {
165
175
  content: [{ type: "text", text: JSON.stringify(response, null, 2) }],
166
- isError: failed > 0 && succeeded === 0 ? true : undefined,
176
+ isError,
167
177
  };
168
178
  }
169
179
  export function register(server, client) {
@@ -22,7 +22,7 @@ type CancelAllOrdersArgs = {
22
22
  market_id: string;
23
23
  confirmation_token: string;
24
24
  };
25
- export declare function handleCancelAllOrders(args: CancelAllOrdersArgs, client: BudaClient): Promise<{
25
+ export declare function handleCancelAllOrders(args: CancelAllOrdersArgs, client: BudaClient, transport?: "http" | "stdio"): Promise<{
26
26
  content: Array<{
27
27
  type: "text";
28
28
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"cancel_all_orders.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_all_orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAuBtB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAyDhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBpE"}
1
+ {"version":3,"file":"cancel_all_orders.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_all_orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAuBtB,CAAC;AAEF,KAAK,mBAAmB,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,mBAAmB,EACzB,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAqDhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBpE"}
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { BudaApiError } from "../client.js";
3
3
  import { validateMarketId } from "../validation.js";
4
+ import { logAudit } from "../audit.js";
4
5
  export const toolSchema = {
5
6
  name: "cancel_all_orders",
6
7
  description: "Cancel all open orders on Buda.com, optionally filtered by a specific market. " +
@@ -23,7 +24,7 @@ export const toolSchema = {
23
24
  required: ["market_id", "confirmation_token"],
24
25
  },
25
26
  };
26
- export async function handleCancelAllOrders(args, client) {
27
+ export async function handleCancelAllOrders(args, client, transport = "stdio") {
27
28
  const { market_id, confirmation_token } = args;
28
29
  if (confirmation_token !== "CONFIRM") {
29
30
  return {
@@ -55,23 +56,19 @@ export async function handleCancelAllOrders(args, client) {
55
56
  try {
56
57
  const params = market_id !== "*" ? { market_id: market_id.toLowerCase() } : undefined;
57
58
  const data = await client.delete(`/orders`, params);
58
- return {
59
- content: [
60
- {
61
- type: "text",
62
- text: JSON.stringify({ canceled_count: data.canceled_count, market_id }),
63
- },
64
- ],
59
+ const result = {
60
+ content: [{ type: "text", text: JSON.stringify({ canceled_count: data.canceled_count, market_id }) }],
65
61
  };
62
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_all_orders", transport, args_summary: { market_id }, success: true });
63
+ return result;
66
64
  }
67
65
  catch (err) {
68
66
  const msg = err instanceof BudaApiError
69
- ? { error: err.message, code: err.status, path: err.path }
67
+ ? { error: err.message, code: err.status }
70
68
  : { error: String(err), code: "UNKNOWN" };
71
- return {
72
- content: [{ type: "text", text: JSON.stringify(msg) }],
73
- isError: true,
74
- };
69
+ const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
70
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_all_orders", transport, args_summary: { market_id }, success: false, error_code: msg.code });
71
+ return result;
75
72
  }
76
73
  }
77
74
  export function register(server, client) {
@@ -22,7 +22,7 @@ type CancelOrderArgs = {
22
22
  order_id: number;
23
23
  confirmation_token: string;
24
24
  };
25
- export declare function handleCancelOrder(args: CancelOrderArgs, client: BudaClient): Promise<{
25
+ export declare function handleCancelOrder(args: CancelOrderArgs, client: BudaClient, transport?: "http" | "stdio"): Promise<{
26
26
  content: Array<{
27
27
  type: "text";
28
28
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"cancel_order.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAGxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAuBtB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAuChF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
1
+ {"version":3,"file":"cancel_order.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAuBtB,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAsChF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { BudaApiError } from "../client.js";
3
+ import { logAudit } from "../audit.js";
3
4
  export const toolSchema = {
4
5
  name: "cancel_order",
5
6
  description: "Cancel an open order by ID on Buda.com. " +
@@ -22,7 +23,7 @@ export const toolSchema = {
22
23
  required: ["order_id", "confirmation_token"],
23
24
  },
24
25
  };
25
- export async function handleCancelOrder(args, client) {
26
+ export async function handleCancelOrder(args, client, transport = "stdio") {
26
27
  const { order_id, confirmation_token } = args;
27
28
  if (confirmation_token !== "CONFIRM") {
28
29
  return {
@@ -44,18 +45,17 @@ export async function handleCancelOrder(args, client) {
44
45
  const data = await client.put(`/orders/${order_id}`, {
45
46
  order: { state: "canceling" },
46
47
  });
47
- return {
48
- content: [{ type: "text", text: JSON.stringify(data.order, null, 2) }],
49
- };
48
+ const result = { content: [{ type: "text", text: JSON.stringify(data.order, null, 2) }] };
49
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_order", transport, args_summary: { order_id }, success: true });
50
+ return result;
50
51
  }
51
52
  catch (err) {
52
53
  const msg = err instanceof BudaApiError
53
- ? { error: err.message, code: err.status, path: err.path }
54
+ ? { error: err.message, code: err.status }
54
55
  : { error: String(err), code: "UNKNOWN" };
55
- return {
56
- content: [{ type: "text", text: JSON.stringify(msg) }],
57
- isError: true,
58
- };
56
+ const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
57
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_order", transport, args_summary: { order_id }, success: false, error_code: msg.code });
58
+ return result;
59
59
  }
60
60
  }
61
61
  export function register(server, client) {
@@ -22,7 +22,7 @@ type CancelOrderByClientIdArgs = {
22
22
  client_id: string;
23
23
  confirmation_token: string;
24
24
  };
25
- export declare function handleCancelOrderByClientId(args: CancelOrderByClientIdArgs, client: BudaClient): Promise<{
25
+ export declare function handleCancelOrderByClientId(args: CancelOrderByClientIdArgs, client: BudaClient, transport?: "http" | "stdio"): Promise<{
26
26
  content: Array<{
27
27
  type: "text";
28
28
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"cancel_order_by_client_id.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_order_by_client_id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAsBtB,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAmCF,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,yBAAyB,EAC/B,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAwChF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBpE"}
1
+ {"version":3,"file":"cancel_order_by_client_id.d.ts","sourceRoot":"","sources":["../../src/tools/cancel_order_by_client_id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;CAsBtB,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAmCF,wBAAsB,2BAA2B,CAC/C,IAAI,EAAE,yBAAyB,EAC/B,MAAM,EAAE,UAAU,EAClB,SAAS,GAAE,MAAM,GAAG,OAAiB,GACpC,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAuChF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBpE"}
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { BudaApiError } from "../client.js";
3
3
  import { flattenAmount } from "../utils.js";
4
+ import { logAudit } from "../audit.js";
4
5
  export const toolSchema = {
5
6
  name: "cancel_order_by_client_id",
6
7
  description: "Cancel an open order by its client-assigned ID on Buda.com. " +
@@ -53,7 +54,7 @@ function normalizeOrder(o) {
53
54
  paid_fee_currency: paidFee.currency,
54
55
  };
55
56
  }
56
- export async function handleCancelOrderByClientId(args, client) {
57
+ export async function handleCancelOrderByClientId(args, client, transport = "stdio") {
57
58
  const { client_id, confirmation_token } = args;
58
59
  if (confirmation_token !== "CONFIRM") {
59
60
  return {
@@ -73,18 +74,17 @@ export async function handleCancelOrderByClientId(args, client) {
73
74
  }
74
75
  try {
75
76
  const data = await client.put(`/orders/by-client-id/${encodeURIComponent(client_id)}`, { order: { state: "canceling" } });
76
- return {
77
- content: [{ type: "text", text: JSON.stringify(normalizeOrder(data.order), null, 2) }],
78
- };
77
+ const result = { content: [{ type: "text", text: JSON.stringify(normalizeOrder(data.order), null, 2) }] };
78
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_order_by_client_id", transport, args_summary: {}, success: true });
79
+ return result;
79
80
  }
80
81
  catch (err) {
81
82
  const msg = err instanceof BudaApiError
82
- ? { error: err.message, code: err.status, path: err.path }
83
+ ? { error: err.message, code: err.status }
83
84
  : { error: String(err), code: "UNKNOWN" };
84
- return {
85
- content: [{ type: "text", text: JSON.stringify(msg) }],
86
- isError: true,
87
- };
85
+ const result = { content: [{ type: "text", text: JSON.stringify(msg) }], isError: true };
86
+ logAudit({ ts: new Date().toISOString(), tool: "cancel_order_by_client_id", transport, args_summary: {}, success: false, error_code: msg.code });
87
+ return result;
88
88
  }
89
89
  }
90
90
  export function register(server, client) {
@@ -15,5 +15,14 @@ export declare const toolSchema: {
15
15
  required: string[];
16
16
  };
17
17
  };
18
+ export declare function handleCompareMarkets(args: {
19
+ base_currency: string;
20
+ }, client: BudaClient, cache: MemoryCache): Promise<{
21
+ content: Array<{
22
+ type: "text";
23
+ text: string;
24
+ }>;
25
+ isError?: boolean;
26
+ }>;
18
27
  export declare function register(server: McpServer, client: BudaClient, cache: MemoryCache): void;
19
28
  //# sourceMappingURL=compare_markets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare_markets.d.ts","sourceRoot":"","sources":["../../src/tools/compare_markets.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,eAAO,MAAM,UAAU;;;;;;;;;;;;;CAkBtB,CAAC;AAEF,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAyExF"}
1
+ {"version":3,"file":"compare_markets.d.ts","sourceRoot":"","sources":["../../src/tools/compare_markets.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;AAIrD,eAAO,MAAM,UAAU;;;;;;;;;;;;;CAkBtB,CAAC;AAEF,wBAAsB,oBAAoB,CACxC,IAAI,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,EAC/B,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,WAAW,GACjB,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAsEhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAaxF"}