@guiie/buda-mcp 1.4.2 → 1.5.1
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/.cursor/rules/marketplace-docs-sync.mdc +32 -0
- package/CHANGELOG.md +79 -0
- package/PUBLISH_CHECKLIST.md +40 -88
- package/README.md +446 -78
- package/dist/cache.d.ts +1 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -1
- package/dist/http.js +97 -6
- package/dist/index.js +42 -3
- package/dist/tools/account.d.ts +19 -0
- package/dist/tools/account.d.ts.map +1 -0
- package/dist/tools/account.js +49 -0
- package/dist/tools/balance.d.ts +29 -0
- package/dist/tools/balance.d.ts.map +1 -0
- package/dist/tools/balance.js +72 -0
- package/dist/tools/banks.d.ts +28 -0
- package/dist/tools/banks.d.ts.map +1 -0
- package/dist/tools/banks.js +68 -0
- package/dist/tools/batch_orders.d.ts +82 -0
- package/dist/tools/batch_orders.d.ts.map +1 -0
- package/dist/tools/batch_orders.js +188 -0
- package/dist/tools/cancel_all_orders.d.ts +34 -0
- package/dist/tools/cancel_all_orders.d.ts.map +1 -0
- package/dist/tools/cancel_all_orders.js +89 -0
- package/dist/tools/cancel_order.js +1 -1
- package/dist/tools/cancel_order_by_client_id.d.ts +34 -0
- package/dist/tools/cancel_order_by_client_id.d.ts.map +1 -0
- package/dist/tools/cancel_order_by_client_id.js +102 -0
- package/dist/tools/dead_mans_switch.d.ts +1 -1
- package/dist/tools/dead_mans_switch.d.ts.map +1 -1
- package/dist/tools/dead_mans_switch.js +33 -3
- package/dist/tools/deposits.d.ts +83 -0
- package/dist/tools/deposits.d.ts.map +1 -0
- package/dist/tools/deposits.js +174 -0
- package/dist/tools/fees.d.ts +34 -0
- package/dist/tools/fees.d.ts.map +1 -0
- package/dist/tools/fees.js +72 -0
- package/dist/tools/lightning.d.ts +68 -0
- package/dist/tools/lightning.d.ts.map +1 -0
- package/dist/tools/lightning.js +185 -0
- package/dist/tools/order_lookup.d.ts +50 -0
- package/dist/tools/order_lookup.d.ts.map +1 -0
- package/dist/tools/order_lookup.js +112 -0
- package/dist/tools/place_order.d.ts +30 -0
- package/dist/tools/place_order.d.ts.map +1 -1
- package/dist/tools/place_order.js +131 -2
- package/dist/tools/quotation.d.ts +44 -0
- package/dist/tools/quotation.d.ts.map +1 -0
- package/dist/tools/quotation.js +99 -0
- package/dist/tools/receive_addresses.d.ts +83 -0
- package/dist/tools/receive_addresses.d.ts.map +1 -0
- package/dist/tools/receive_addresses.js +185 -0
- package/dist/tools/remittance_recipients.d.ts +54 -0
- package/dist/tools/remittance_recipients.d.ts.map +1 -0
- package/dist/tools/remittance_recipients.js +106 -0
- package/dist/tools/remittances.d.ts +120 -0
- package/dist/tools/remittances.d.ts.map +1 -0
- package/dist/tools/remittances.js +261 -0
- package/dist/tools/simulate_order.d.ts.map +1 -1
- package/dist/tools/simulate_order.js +2 -1
- package/dist/tools/technical_indicators.d.ts.map +1 -1
- package/dist/tools/technical_indicators.js +2 -1
- package/dist/tools/withdrawals.d.ts +93 -0
- package/dist/tools/withdrawals.d.ts.map +1 -0
- package/dist/tools/withdrawals.js +225 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +4 -1
- package/dist/validation.d.ts +11 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +38 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +8 -1
- package/marketplace/README.md +1 -1
- package/marketplace/claude-listing.md +101 -2
- package/marketplace/gemini-tools.json +478 -1
- package/marketplace/openapi.yaml +160 -1
- package/package.json +2 -1
- package/server.json +2 -2
- package/src/cache.ts +1 -0
- package/src/client.ts +23 -1
- package/src/http.ts +105 -6
- package/src/index.ts +40 -3
- package/src/tools/account.ts +66 -0
- package/src/tools/balance.ts +94 -0
- package/src/tools/banks.ts +94 -0
- package/src/tools/batch_orders.ts +238 -0
- package/src/tools/cancel_all_orders.ts +117 -0
- package/src/tools/cancel_order.ts +1 -1
- package/src/tools/cancel_order_by_client_id.ts +132 -0
- package/src/tools/dead_mans_switch.ts +39 -3
- package/src/tools/deposits.ts +230 -0
- package/src/tools/fees.ts +91 -0
- package/src/tools/lightning.ts +247 -0
- package/src/tools/order_lookup.ts +139 -0
- package/src/tools/place_order.ts +151 -2
- package/src/tools/quotation.ts +124 -0
- package/src/tools/receive_addresses.ts +242 -0
- package/src/tools/remittance_recipients.ts +139 -0
- package/src/tools/remittances.ts +325 -0
- package/src/tools/simulate_order.ts +1 -0
- package/src/tools/technical_indicators.ts +2 -1
- package/src/tools/withdrawals.ts +287 -0
- package/src/types.ts +210 -0
- package/src/utils.ts +3 -1
- package/src/validation.ts +45 -0
- package/src/version.ts +11 -3
- package/test/run-all.ts +16 -0
- package/test/unit.ts +2149 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { BudaApiError } from "../client.js";
|
|
3
|
+
import { flattenAmount } from "../utils.js";
|
|
4
|
+
import { validateCurrency } from "../validation.js";
|
|
5
|
+
export const listRemittancesToolSchema = {
|
|
6
|
+
name: "list_remittances",
|
|
7
|
+
description: "Returns all fiat remittance transfers for the authenticated Buda.com account. " +
|
|
8
|
+
"Supports pagination. All amounts are floats with separate _currency fields. " +
|
|
9
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
10
|
+
"Example: 'List my recent remittances.'",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
per: {
|
|
15
|
+
type: "number",
|
|
16
|
+
description: "Results per page (default: 20, max: 300).",
|
|
17
|
+
},
|
|
18
|
+
page: {
|
|
19
|
+
type: "number",
|
|
20
|
+
description: "Page number (default: 1).",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
export const quoteRemittanceToolSchema = {
|
|
26
|
+
name: "quote_remittance",
|
|
27
|
+
description: "Creates a time-limited remittance quote without committing funds. " +
|
|
28
|
+
"Requests a price quote for a fiat remittance to a saved recipient. " +
|
|
29
|
+
"Returns a remittance object in 'quoted' state with an expiry timestamp. " +
|
|
30
|
+
"NOT idempotent — creates a new remittance record each call. " +
|
|
31
|
+
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
32
|
+
"To execute the transfer, call accept_remittance_quote with the returned ID before it expires. " +
|
|
33
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
34
|
+
"Example: 'Get a remittance quote to send 100000 CLP to recipient 5.'",
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
currency: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "Fiat currency code (e.g. 'CLP', 'COP').",
|
|
41
|
+
},
|
|
42
|
+
amount: {
|
|
43
|
+
type: "number",
|
|
44
|
+
description: "Amount to remit (positive number).",
|
|
45
|
+
},
|
|
46
|
+
recipient_id: {
|
|
47
|
+
type: "number",
|
|
48
|
+
description: "ID of the saved remittance recipient.",
|
|
49
|
+
},
|
|
50
|
+
confirmation_token: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to create the quote.",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
required: ["currency", "amount", "recipient_id", "confirmation_token"],
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
export const acceptRemittanceQuoteToolSchema = {
|
|
59
|
+
name: "accept_remittance_quote",
|
|
60
|
+
description: "Accepts and executes a pending remittance quote. " +
|
|
61
|
+
"Commits a previously quoted remittance, triggering a real fiat transfer. " +
|
|
62
|
+
"IRREVERSIBLE once the transfer is initiated. " +
|
|
63
|
+
"You must pass confirmation_token='CONFIRM' to proceed. " +
|
|
64
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
65
|
+
"Example: \"Accept remittance quote 77 — set confirmation_token='CONFIRM'.\"",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
id: {
|
|
70
|
+
type: "number",
|
|
71
|
+
description: "The numeric ID of the remittance quote to accept.",
|
|
72
|
+
},
|
|
73
|
+
confirmation_token: {
|
|
74
|
+
type: "string",
|
|
75
|
+
description: "Must be 'CONFIRM' to proceed. Any other value aborts.",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
required: ["id", "confirmation_token"],
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
export const getRemittanceToolSchema = {
|
|
82
|
+
name: "get_remittance",
|
|
83
|
+
description: "Returns a single remittance by its ID on Buda.com. " +
|
|
84
|
+
"Fetches current state and details. " +
|
|
85
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
86
|
+
"Example: 'What is the status of remittance 77?'",
|
|
87
|
+
inputSchema: {
|
|
88
|
+
type: "object",
|
|
89
|
+
properties: {
|
|
90
|
+
id: {
|
|
91
|
+
type: "number",
|
|
92
|
+
description: "The numeric ID of the remittance.",
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
required: ["id"],
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
function normalizeRemittance(r) {
|
|
99
|
+
const amount = flattenAmount(r.amount);
|
|
100
|
+
return {
|
|
101
|
+
id: r.id,
|
|
102
|
+
state: r.state,
|
|
103
|
+
currency: r.currency,
|
|
104
|
+
amount: amount.value,
|
|
105
|
+
amount_currency: amount.currency,
|
|
106
|
+
recipient_id: r.recipient_id,
|
|
107
|
+
created_at: r.created_at,
|
|
108
|
+
expires_at: r.expires_at ?? null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export async function handleListRemittances(args, client) {
|
|
112
|
+
try {
|
|
113
|
+
const params = {};
|
|
114
|
+
if (args.per !== undefined)
|
|
115
|
+
params.per = args.per;
|
|
116
|
+
if (args.page !== undefined)
|
|
117
|
+
params.page = args.page;
|
|
118
|
+
const data = await client.get("/remittances", Object.keys(params).length > 0 ? params : undefined);
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: JSON.stringify({
|
|
124
|
+
remittances: data.remittances.map(normalizeRemittance),
|
|
125
|
+
meta: data.meta,
|
|
126
|
+
}, null, 2),
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
const msg = err instanceof BudaApiError
|
|
133
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
134
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
137
|
+
isError: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
export async function handleGetRemittance(args, client) {
|
|
142
|
+
try {
|
|
143
|
+
const data = await client.get(`/remittances/${args.id}`);
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: "text", text: JSON.stringify(normalizeRemittance(data.remittance), null, 2) }],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
const msg = err instanceof BudaApiError
|
|
150
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
151
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
152
|
+
return {
|
|
153
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
154
|
+
isError: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export async function handleQuoteRemittance(args, client) {
|
|
159
|
+
const { currency, amount, recipient_id, confirmation_token } = args;
|
|
160
|
+
if (confirmation_token !== "CONFIRM") {
|
|
161
|
+
return {
|
|
162
|
+
content: [
|
|
163
|
+
{
|
|
164
|
+
type: "text",
|
|
165
|
+
text: JSON.stringify({
|
|
166
|
+
error: "Remittance quote not created. confirmation_token must equal 'CONFIRM' to execute. " +
|
|
167
|
+
"Review the details and set confirmation_token='CONFIRM' to proceed.",
|
|
168
|
+
code: "CONFIRMATION_REQUIRED",
|
|
169
|
+
preview: { currency, amount, recipient_id },
|
|
170
|
+
}),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
isError: true,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
const validationError = validateCurrency(currency);
|
|
177
|
+
if (validationError) {
|
|
178
|
+
return {
|
|
179
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
180
|
+
isError: true,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
try {
|
|
184
|
+
const data = await client.post("/remittances", {
|
|
185
|
+
remittance: {
|
|
186
|
+
currency: currency.toUpperCase(),
|
|
187
|
+
amount: String(amount),
|
|
188
|
+
recipient_id,
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
return {
|
|
192
|
+
content: [{ type: "text", text: JSON.stringify(normalizeRemittance(data.remittance), null, 2) }],
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
catch (err) {
|
|
196
|
+
const msg = err instanceof BudaApiError
|
|
197
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
198
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
199
|
+
return {
|
|
200
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
201
|
+
isError: true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
export async function handleAcceptRemittanceQuote(args, client) {
|
|
206
|
+
const { id, confirmation_token } = args;
|
|
207
|
+
if (confirmation_token !== "CONFIRM") {
|
|
208
|
+
return {
|
|
209
|
+
content: [
|
|
210
|
+
{
|
|
211
|
+
type: "text",
|
|
212
|
+
text: JSON.stringify({
|
|
213
|
+
error: "Accepting a remittance quote is irreversible. Pass confirmation_token='CONFIRM' to proceed.",
|
|
214
|
+
code: "CONFIRMATION_REQUIRED",
|
|
215
|
+
remittance_id: id,
|
|
216
|
+
}),
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
isError: true,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const data = await client.put(`/remittances/${id}`, {
|
|
224
|
+
remittance: { state: "confirming" },
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
content: [{ type: "text", text: JSON.stringify(normalizeRemittance(data.remittance), null, 2) }],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
const msg = err instanceof BudaApiError
|
|
232
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
233
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
234
|
+
return {
|
|
235
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
236
|
+
isError: true,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
export function register(server, client) {
|
|
241
|
+
server.tool(listRemittancesToolSchema.name, listRemittancesToolSchema.description, {
|
|
242
|
+
per: z.number().int().min(1).max(300).optional().describe("Results per page (default: 20, max: 300)."),
|
|
243
|
+
page: z.number().int().min(1).optional().describe("Page number (default: 1)."),
|
|
244
|
+
}, (args) => handleListRemittances(args, client));
|
|
245
|
+
server.tool(getRemittanceToolSchema.name, getRemittanceToolSchema.description, {
|
|
246
|
+
id: z.number().int().positive().describe("The numeric ID of the remittance."),
|
|
247
|
+
}, (args) => handleGetRemittance(args, client));
|
|
248
|
+
server.tool(quoteRemittanceToolSchema.name, quoteRemittanceToolSchema.description, {
|
|
249
|
+
currency: z.string().min(2).max(10).describe("Fiat currency code (e.g. 'CLP', 'COP')."),
|
|
250
|
+
amount: z.number().positive().describe("Amount to remit (positive number)."),
|
|
251
|
+
recipient_id: z.number().int().positive().describe("ID of the saved remittance recipient."),
|
|
252
|
+
confirmation_token: z
|
|
253
|
+
.string()
|
|
254
|
+
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to create the quote."),
|
|
255
|
+
}, (args) => handleQuoteRemittance(args, client));
|
|
256
|
+
server.tool(acceptRemittanceQuoteToolSchema.name, acceptRemittanceQuoteToolSchema.description, {
|
|
257
|
+
id: z.number().int().positive().describe("The numeric ID of the remittance quote to accept."),
|
|
258
|
+
confirmation_token: z.string().describe("Must be 'CONFIRM' to proceed. Any other value aborts."),
|
|
259
|
+
}, (args) => handleAcceptRemittanceQuote(args, client));
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=remittances.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulate_order.d.ts","sourceRoot":"","sources":["../../src/tools/simulate_order.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;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"simulate_order.d.ts","sourceRoot":"","sources":["../../src/tools/simulate_order.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;;;;;;;;;;;;;;;;;;;;;;;;;CAgCtB,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,iBAAiB,EACvB,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,CAyGhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAuBxF"}
|
|
@@ -4,7 +4,8 @@ import { CACHE_TTL } from "../cache.js";
|
|
|
4
4
|
import { validateMarketId } from "../validation.js";
|
|
5
5
|
export const toolSchema = {
|
|
6
6
|
name: "simulate_order",
|
|
7
|
-
description: "
|
|
7
|
+
description: "[DEPRECATED: prefer get_real_quotation for server-side accurate quotes] " +
|
|
8
|
+
"Simulates a buy or sell order on Buda.com using live ticker data — no order is placed. " +
|
|
8
9
|
"Returns estimated fill price, fee, total cost, and slippage vs mid-price. " +
|
|
9
10
|
"Omit 'price' for a market order simulation; supply 'price' for a limit order simulation. " +
|
|
10
11
|
"All outputs are labelled simulation: true — this tool never places a real order. " +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"technical_indicators.d.ts","sourceRoot":"","sources":["../../src/tools/technical_indicators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAsGF,KAAK,uBAAuB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,uBAAuB,EAC7B,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,
|
|
1
|
+
{"version":3,"file":"technical_indicators.d.ts","sourceRoot":"","sources":["../../src/tools/technical_indicators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;CA8BtB,CAAC;AAsGF,KAAK,uBAAuB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,uBAAuB,EAC7B,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,CA4GhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAyBpE"}
|
|
@@ -146,7 +146,7 @@ export async function handleTechnicalIndicators(args, client) {
|
|
|
146
146
|
const macdResult = macd(closes, 12, 26, 9);
|
|
147
147
|
const bbResult = bollingerBands(closes, 20, 2);
|
|
148
148
|
const sma20 = parseFloat(sma(closes, 20).toFixed(2));
|
|
149
|
-
const sma50 = parseFloat(sma(closes, 50).toFixed(2));
|
|
149
|
+
const sma50 = closes.length >= 50 ? parseFloat(sma(closes, 50).toFixed(2)) : null;
|
|
150
150
|
const lastClose = closes[closes.length - 1];
|
|
151
151
|
// Signal interpretations
|
|
152
152
|
const rsiSignal = rsiValue !== null && rsiValue > 70
|
|
@@ -180,6 +180,7 @@ export async function handleTechnicalIndicators(args, client) {
|
|
|
180
180
|
bollinger_bands: bbResult,
|
|
181
181
|
sma_20: sma20,
|
|
182
182
|
sma_50: sma50,
|
|
183
|
+
sma_50_warning: sma50 === null ? `insufficient data (need 50 candles, have ${closes.length})` : undefined,
|
|
183
184
|
},
|
|
184
185
|
signals: {
|
|
185
186
|
rsi_signal: rsiSignal,
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BudaClient } from "../client.js";
|
|
3
|
+
export declare const getWithdrawalHistoryToolSchema: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object";
|
|
8
|
+
properties: {
|
|
9
|
+
currency: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
state: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
per: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
page: {
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
required: string[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
type GetWithdrawalHistoryArgs = {
|
|
30
|
+
currency: string;
|
|
31
|
+
state?: "pending_signature" | "pending" | "confirmed" | "rejected" | "anulled";
|
|
32
|
+
per?: number;
|
|
33
|
+
page?: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function handleGetWithdrawalHistory(args: GetWithdrawalHistoryArgs, client: BudaClient): Promise<{
|
|
36
|
+
content: Array<{
|
|
37
|
+
type: "text";
|
|
38
|
+
text: string;
|
|
39
|
+
}>;
|
|
40
|
+
isError?: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
export declare const createWithdrawalToolSchema: {
|
|
43
|
+
name: string;
|
|
44
|
+
description: string;
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object";
|
|
47
|
+
properties: {
|
|
48
|
+
currency: {
|
|
49
|
+
type: string;
|
|
50
|
+
description: string;
|
|
51
|
+
};
|
|
52
|
+
amount: {
|
|
53
|
+
type: string;
|
|
54
|
+
description: string;
|
|
55
|
+
};
|
|
56
|
+
address: {
|
|
57
|
+
type: string;
|
|
58
|
+
description: string;
|
|
59
|
+
};
|
|
60
|
+
network: {
|
|
61
|
+
type: string;
|
|
62
|
+
description: string;
|
|
63
|
+
};
|
|
64
|
+
bank_account_id: {
|
|
65
|
+
type: string;
|
|
66
|
+
description: string;
|
|
67
|
+
};
|
|
68
|
+
confirmation_token: {
|
|
69
|
+
type: string;
|
|
70
|
+
description: string;
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
required: string[];
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
type CreateWithdrawalArgs = {
|
|
77
|
+
currency: string;
|
|
78
|
+
amount: number;
|
|
79
|
+
address?: string;
|
|
80
|
+
network?: string;
|
|
81
|
+
bank_account_id?: number;
|
|
82
|
+
confirmation_token: string;
|
|
83
|
+
};
|
|
84
|
+
export declare function handleCreateWithdrawal(args: CreateWithdrawalArgs, client: BudaClient): Promise<{
|
|
85
|
+
content: Array<{
|
|
86
|
+
type: "text";
|
|
87
|
+
text: string;
|
|
88
|
+
}>;
|
|
89
|
+
isError?: boolean;
|
|
90
|
+
}>;
|
|
91
|
+
export declare function register(server: McpServer, client: BudaClient): void;
|
|
92
|
+
export {};
|
|
93
|
+
//# sourceMappingURL=withdrawals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withdrawals.d.ts","sourceRoot":"","sources":["../../src/tools/withdrawals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;CA8B1C,CAAC;AAEF,KAAK,wBAAwB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,SAAS,CAAC;IAC/E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAqBF,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE,wBAAwB,EAC9B,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,CA+ChF;AAED,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuBtC,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,oBAAoB,EAC1B,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,CAmGhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA+BpE"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { BudaApiError } from "../client.js";
|
|
3
|
+
import { validateCurrency, validateCryptoAddress } from "../validation.js";
|
|
4
|
+
import { flattenAmount } from "../utils.js";
|
|
5
|
+
export const getWithdrawalHistoryToolSchema = {
|
|
6
|
+
name: "get_withdrawal_history",
|
|
7
|
+
description: "Returns withdrawal history for a currency on the authenticated Buda.com account. " +
|
|
8
|
+
"Supports state filtering and pagination. All amounts are floats with separate _currency fields. " +
|
|
9
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
10
|
+
"Example: 'Show my pending CLP withdrawals.'",
|
|
11
|
+
inputSchema: {
|
|
12
|
+
type: "object",
|
|
13
|
+
properties: {
|
|
14
|
+
currency: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Currency code (e.g. 'BTC', 'CLP').",
|
|
17
|
+
},
|
|
18
|
+
state: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Filter by state: 'pending_signature', 'pending', 'confirmed', 'rejected', 'anulled'.",
|
|
21
|
+
},
|
|
22
|
+
per: {
|
|
23
|
+
type: "number",
|
|
24
|
+
description: "Results per page (default: 20, max: 300).",
|
|
25
|
+
},
|
|
26
|
+
page: {
|
|
27
|
+
type: "number",
|
|
28
|
+
description: "Page number (default: 1).",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
required: ["currency"],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
function normalizeWithdrawal(w) {
|
|
35
|
+
const amount = flattenAmount(w.amount);
|
|
36
|
+
const fee = flattenAmount(w.fee);
|
|
37
|
+
return {
|
|
38
|
+
id: w.id,
|
|
39
|
+
state: w.state,
|
|
40
|
+
currency: w.currency,
|
|
41
|
+
amount: amount.value,
|
|
42
|
+
amount_currency: amount.currency,
|
|
43
|
+
fee: fee.value,
|
|
44
|
+
fee_currency: fee.currency,
|
|
45
|
+
address: w.address,
|
|
46
|
+
tx_hash: w.tx_hash,
|
|
47
|
+
bank_account_id: w.bank_account_id,
|
|
48
|
+
created_at: w.created_at,
|
|
49
|
+
updated_at: w.updated_at,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export async function handleGetWithdrawalHistory(args, client) {
|
|
53
|
+
const { currency, state, per, page } = args;
|
|
54
|
+
const validationError = validateCurrency(currency);
|
|
55
|
+
if (validationError) {
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
58
|
+
isError: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const params = {};
|
|
63
|
+
if (state)
|
|
64
|
+
params.state = state;
|
|
65
|
+
if (per !== undefined)
|
|
66
|
+
params.per = per;
|
|
67
|
+
if (page !== undefined)
|
|
68
|
+
params.page = page;
|
|
69
|
+
const data = await client.get(`/currencies/${currency.toUpperCase()}/withdrawals`, Object.keys(params).length > 0 ? params : undefined);
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
withdrawals: data.withdrawals.map(normalizeWithdrawal),
|
|
76
|
+
meta: data.meta,
|
|
77
|
+
}, null, 2),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const msg = err instanceof BudaApiError
|
|
84
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
85
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
88
|
+
isError: true,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export const createWithdrawalToolSchema = {
|
|
93
|
+
name: "create_withdrawal",
|
|
94
|
+
description: "Create a withdrawal on Buda.com. Supports both crypto (address) and fiat (bank_account_id) withdrawals. " +
|
|
95
|
+
"Exactly one of address or bank_account_id must be provided. " +
|
|
96
|
+
"WARNING: Crypto withdrawals are irreversible — verify the destination address carefully before confirming. " +
|
|
97
|
+
"IMPORTANT: Pass confirmation_token='CONFIRM' to execute. " +
|
|
98
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
currency: { type: "string", description: "Currency code (e.g. 'BTC', 'CLP')." },
|
|
103
|
+
amount: { type: "number", description: "Withdrawal amount." },
|
|
104
|
+
address: { type: "string", description: "Destination crypto address. Mutually exclusive with bank_account_id." },
|
|
105
|
+
network: { type: "string", description: "Blockchain network for crypto withdrawals (e.g. 'bitcoin', 'ethereum')." },
|
|
106
|
+
bank_account_id: { type: "number", description: "Fiat bank account ID. Mutually exclusive with address." },
|
|
107
|
+
confirmation_token: {
|
|
108
|
+
type: "string",
|
|
109
|
+
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute.",
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
required: ["currency", "amount", "confirmation_token"],
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
export async function handleCreateWithdrawal(args, client) {
|
|
116
|
+
const { currency, amount, address, network, bank_account_id, confirmation_token } = args;
|
|
117
|
+
if (confirmation_token !== "CONFIRM") {
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
text: JSON.stringify({
|
|
123
|
+
error: "Withdrawal not created. confirmation_token must equal 'CONFIRM' to execute. " +
|
|
124
|
+
"Review the details and set confirmation_token='CONFIRM' to proceed.",
|
|
125
|
+
code: "CONFIRMATION_REQUIRED",
|
|
126
|
+
preview: { currency, amount, destination: address ?? bank_account_id },
|
|
127
|
+
}),
|
|
128
|
+
},
|
|
129
|
+
],
|
|
130
|
+
isError: true,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const hasAddress = address !== undefined;
|
|
134
|
+
const hasBankAccount = bank_account_id !== undefined;
|
|
135
|
+
if (hasAddress && hasBankAccount) {
|
|
136
|
+
return {
|
|
137
|
+
content: [
|
|
138
|
+
{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: JSON.stringify({
|
|
141
|
+
error: "Provide either address (crypto) or bank_account_id (fiat), not both.",
|
|
142
|
+
code: "VALIDATION_ERROR",
|
|
143
|
+
}),
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
isError: true,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (!hasAddress && !hasBankAccount) {
|
|
150
|
+
return {
|
|
151
|
+
content: [
|
|
152
|
+
{
|
|
153
|
+
type: "text",
|
|
154
|
+
text: JSON.stringify({
|
|
155
|
+
error: "Either address (crypto) or bank_account_id (fiat) must be provided.",
|
|
156
|
+
code: "VALIDATION_ERROR",
|
|
157
|
+
}),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
isError: true,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const validationError = validateCurrency(currency);
|
|
164
|
+
if (validationError) {
|
|
165
|
+
return {
|
|
166
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
167
|
+
isError: true,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (hasAddress) {
|
|
171
|
+
const addrError = validateCryptoAddress(address, currency);
|
|
172
|
+
if (addrError) {
|
|
173
|
+
return {
|
|
174
|
+
content: [{ type: "text", text: JSON.stringify({ error: addrError, code: "INVALID_ADDRESS" }) }],
|
|
175
|
+
isError: true,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
const payload = { amount: String(amount) };
|
|
181
|
+
if (hasAddress) {
|
|
182
|
+
payload.address = address;
|
|
183
|
+
if (network)
|
|
184
|
+
payload.network = network;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
payload.bank_account_id = bank_account_id;
|
|
188
|
+
}
|
|
189
|
+
const data = await client.post(`/currencies/${currency.toUpperCase()}/withdrawals`, payload);
|
|
190
|
+
return {
|
|
191
|
+
content: [{ type: "text", text: JSON.stringify(normalizeWithdrawal(data.withdrawal), null, 2) }],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
const msg = err instanceof BudaApiError
|
|
196
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
197
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
198
|
+
return {
|
|
199
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
200
|
+
isError: true,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export function register(server, client) {
|
|
205
|
+
server.tool(getWithdrawalHistoryToolSchema.name, getWithdrawalHistoryToolSchema.description, {
|
|
206
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'CLP')."),
|
|
207
|
+
state: z
|
|
208
|
+
.enum(["pending_signature", "pending", "confirmed", "rejected", "anulled"])
|
|
209
|
+
.optional()
|
|
210
|
+
.describe("Filter by state."),
|
|
211
|
+
per: z.number().int().min(1).max(300).optional().describe("Results per page (default: 20, max: 300)."),
|
|
212
|
+
page: z.number().int().min(1).optional().describe("Page number (default: 1)."),
|
|
213
|
+
}, (args) => handleGetWithdrawalHistory(args, client));
|
|
214
|
+
server.tool(createWithdrawalToolSchema.name, createWithdrawalToolSchema.description, {
|
|
215
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'CLP')."),
|
|
216
|
+
amount: z.number().positive().describe("Withdrawal amount."),
|
|
217
|
+
address: z.string().optional().describe("Destination crypto address. Mutually exclusive with bank_account_id."),
|
|
218
|
+
network: z.string().optional().describe("Blockchain network for crypto withdrawals (e.g. 'bitcoin', 'ethereum')."),
|
|
219
|
+
bank_account_id: z.number().int().positive().optional().describe("Fiat bank account ID. Mutually exclusive with address."),
|
|
220
|
+
confirmation_token: z
|
|
221
|
+
.string()
|
|
222
|
+
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute."),
|
|
223
|
+
}, (args) => handleCreateWithdrawal(args, client));
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=withdrawals.js.map
|