@guiie/buda-mcp 1.4.2 → 1.5.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.
- package/CHANGELOG.md +39 -0
- 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 +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +16 -0
- package/dist/http.js +55 -0
- package/dist/index.js +30 -0
- 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 +77 -0
- package/dist/tools/batch_orders.d.ts.map +1 -0
- package/dist/tools/batch_orders.js +154 -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_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/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 +171 -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 +100 -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 +78 -0
- package/dist/tools/receive_addresses.d.ts.map +1 -0
- package/dist/tools/receive_addresses.js +161 -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 +115 -0
- package/dist/tools/remittances.d.ts.map +1 -0
- package/dist/tools/remittances.js +237 -0
- package/dist/tools/simulate_order.d.ts.map +1 -1
- package/dist/tools/simulate_order.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 +215 -0
- package/dist/types.d.ts +155 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +5 -0
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +12 -0
- package/marketplace/README.md +1 -1
- package/marketplace/claude-listing.md +30 -2
- package/marketplace/gemini-tools.json +155 -1
- package/marketplace/openapi.yaml +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/src/cache.ts +1 -0
- package/src/client.ts +20 -0
- package/src/http.ts +55 -0
- package/src/index.ts +30 -0
- 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 +199 -0
- package/src/tools/cancel_all_orders.ts +117 -0
- package/src/tools/cancel_order_by_client_id.ts +132 -0
- package/src/tools/deposits.ts +230 -0
- package/src/tools/fees.ts +91 -0
- package/src/tools/lightning.ts +231 -0
- package/src/tools/order_lookup.ts +139 -0
- package/src/tools/place_order.ts +119 -2
- package/src/tools/quotation.ts +124 -0
- package/src/tools/receive_addresses.ts +216 -0
- package/src/tools/remittance_recipients.ts +139 -0
- package/src/tools/remittances.ts +299 -0
- package/src/tools/simulate_order.ts +1 -0
- package/src/tools/withdrawals.ts +276 -0
- package/src/types.ts +210 -0
- package/src/validation.ts +16 -0
- package/test/run-all.ts +16 -0
- package/test/unit.ts +1905 -0
|
@@ -4,6 +4,7 @@ import { validateMarketId } from "../validation.js";
|
|
|
4
4
|
export const toolSchema = {
|
|
5
5
|
name: "place_order",
|
|
6
6
|
description: "Place a limit or market order on Buda.com. " +
|
|
7
|
+
"Supports optional time-in-force flags (ioc, fok, post_only, gtd_timestamp) and stop orders. " +
|
|
7
8
|
"IMPORTANT: To prevent accidental execution from ambiguous prompts, you must pass " +
|
|
8
9
|
"confirmation_token='CONFIRM' to execute the order. " +
|
|
9
10
|
"Requires BUDA_API_KEY and BUDA_API_SECRET environment variables. " +
|
|
@@ -32,6 +33,30 @@ export const toolSchema = {
|
|
|
32
33
|
description: "Limit price in quote currency. Required when price_type is 'limit'. " +
|
|
33
34
|
"For Bid orders: highest price you will pay. For Ask orders: lowest price you will accept.",
|
|
34
35
|
},
|
|
36
|
+
ioc: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
description: "Immediate-or-cancel: fill as much as possible, cancel the rest. Mutually exclusive with fok, post_only, gtd_timestamp.",
|
|
39
|
+
},
|
|
40
|
+
fok: {
|
|
41
|
+
type: "boolean",
|
|
42
|
+
description: "Fill-or-kill: fill the entire order or cancel it entirely. Mutually exclusive with ioc, post_only, gtd_timestamp.",
|
|
43
|
+
},
|
|
44
|
+
post_only: {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Post-only: rejected if it would execute immediately as a taker. Mutually exclusive with ioc, fok, gtd_timestamp.",
|
|
47
|
+
},
|
|
48
|
+
gtd_timestamp: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Good-till-date: ISO 8601 datetime after which the order is canceled. Mutually exclusive with ioc, fok, post_only.",
|
|
51
|
+
},
|
|
52
|
+
stop_price: {
|
|
53
|
+
type: "number",
|
|
54
|
+
description: "Stop trigger price. Must be paired with stop_type.",
|
|
55
|
+
},
|
|
56
|
+
stop_type: {
|
|
57
|
+
type: "string",
|
|
58
|
+
description: "Stop trigger direction: '>=' triggers when price rises to stop_price, '<=' when it falls. Must be paired with stop_price.",
|
|
59
|
+
},
|
|
35
60
|
confirmation_token: {
|
|
36
61
|
type: "string",
|
|
37
62
|
description: "Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute the order. " +
|
|
@@ -42,7 +67,7 @@ export const toolSchema = {
|
|
|
42
67
|
},
|
|
43
68
|
};
|
|
44
69
|
export async function handlePlaceOrder(args, client) {
|
|
45
|
-
const { market_id, type, price_type, amount, limit_price, confirmation_token } = args;
|
|
70
|
+
const { market_id, type, price_type, amount, limit_price, ioc, fok, post_only, gtd_timestamp, stop_price, stop_type, confirmation_token, } = args;
|
|
46
71
|
if (confirmation_token !== "CONFIRM") {
|
|
47
72
|
return {
|
|
48
73
|
content: [
|
|
@@ -66,6 +91,39 @@ export async function handlePlaceOrder(args, client) {
|
|
|
66
91
|
isError: true,
|
|
67
92
|
};
|
|
68
93
|
}
|
|
94
|
+
// Validate TIF mutual exclusivity
|
|
95
|
+
const tifFlags = [ioc, fok, post_only, gtd_timestamp !== undefined].filter(Boolean);
|
|
96
|
+
if (tifFlags.length > 1) {
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: JSON.stringify({
|
|
102
|
+
error: "ioc, fok, post_only, and gtd_timestamp are mutually exclusive. Specify at most one.",
|
|
103
|
+
code: "VALIDATION_ERROR",
|
|
104
|
+
}),
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
isError: true,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Validate stop_price / stop_type must both be present or both absent
|
|
111
|
+
const hasStopPrice = stop_price !== undefined;
|
|
112
|
+
const hasStopType = stop_type !== undefined;
|
|
113
|
+
if (hasStopPrice !== hasStopType) {
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: JSON.stringify({
|
|
119
|
+
error: "stop_price and stop_type must both be provided together.",
|
|
120
|
+
code: "VALIDATION_ERROR",
|
|
121
|
+
}),
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
isError: true,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
69
127
|
try {
|
|
70
128
|
const payload = {
|
|
71
129
|
type,
|
|
@@ -87,7 +145,22 @@ export async function handlePlaceOrder(args, client) {
|
|
|
87
145
|
isError: true,
|
|
88
146
|
};
|
|
89
147
|
}
|
|
90
|
-
|
|
148
|
+
let limitType = "gtc";
|
|
149
|
+
if (ioc)
|
|
150
|
+
limitType = "ioc";
|
|
151
|
+
else if (fok)
|
|
152
|
+
limitType = "fok";
|
|
153
|
+
else if (post_only)
|
|
154
|
+
limitType = "post_only";
|
|
155
|
+
else if (gtd_timestamp !== undefined)
|
|
156
|
+
limitType = "gtd";
|
|
157
|
+
const limitObj = { price: limit_price, type: limitType };
|
|
158
|
+
if (gtd_timestamp !== undefined)
|
|
159
|
+
limitObj.expiration = gtd_timestamp;
|
|
160
|
+
payload.limit = limitObj;
|
|
161
|
+
}
|
|
162
|
+
if (hasStopPrice && hasStopType) {
|
|
163
|
+
payload.stop = { price: stop_price, type: stop_type };
|
|
91
164
|
}
|
|
92
165
|
const data = await client.post(`/markets/${market_id.toLowerCase()}/orders`, payload);
|
|
93
166
|
return {
|
|
@@ -125,6 +198,31 @@ export function register(server, client) {
|
|
|
125
198
|
.optional()
|
|
126
199
|
.describe("Limit price in quote currency. Required when price_type is 'limit'. " +
|
|
127
200
|
"For Bid orders: highest price you will pay. For Ask orders: lowest price you will accept."),
|
|
201
|
+
ioc: z
|
|
202
|
+
.boolean()
|
|
203
|
+
.optional()
|
|
204
|
+
.describe("Immediate-or-cancel: fill as much as possible, cancel the rest. Mutually exclusive with fok, post_only, gtd_timestamp."),
|
|
205
|
+
fok: z
|
|
206
|
+
.boolean()
|
|
207
|
+
.optional()
|
|
208
|
+
.describe("Fill-or-kill: fill the entire order or cancel it entirely. Mutually exclusive with ioc, post_only, gtd_timestamp."),
|
|
209
|
+
post_only: z
|
|
210
|
+
.boolean()
|
|
211
|
+
.optional()
|
|
212
|
+
.describe("Post-only: rejected if it would execute immediately as a taker. Mutually exclusive with ioc, fok, gtd_timestamp."),
|
|
213
|
+
gtd_timestamp: z
|
|
214
|
+
.string()
|
|
215
|
+
.optional()
|
|
216
|
+
.describe("Good-till-date: ISO 8601 datetime after which the order is canceled. Mutually exclusive with ioc, fok, post_only."),
|
|
217
|
+
stop_price: z
|
|
218
|
+
.number()
|
|
219
|
+
.positive()
|
|
220
|
+
.optional()
|
|
221
|
+
.describe("Stop trigger price. Must be paired with stop_type."),
|
|
222
|
+
stop_type: z
|
|
223
|
+
.enum([">=", "<="])
|
|
224
|
+
.optional()
|
|
225
|
+
.describe("Stop trigger direction: '>=' triggers when price rises to stop_price, '<=' when it falls. Must be paired with stop_price."),
|
|
128
226
|
confirmation_token: z
|
|
129
227
|
.string()
|
|
130
228
|
.describe("Safety confirmation. Must equal exactly 'CONFIRM' (case-sensitive) to execute the order. " +
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BudaClient } from "../client.js";
|
|
3
|
+
export declare const toolSchema: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object";
|
|
8
|
+
properties: {
|
|
9
|
+
market_id: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
type: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
amount: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
limit: {
|
|
22
|
+
type: string;
|
|
23
|
+
description: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
required: string[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
type GetRealQuotationArgs = {
|
|
30
|
+
market_id: string;
|
|
31
|
+
type: "Bid" | "Ask";
|
|
32
|
+
amount: number;
|
|
33
|
+
limit?: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function handleGetRealQuotation(args: GetRealQuotationArgs, client: BudaClient): Promise<{
|
|
36
|
+
content: Array<{
|
|
37
|
+
type: "text";
|
|
38
|
+
text: string;
|
|
39
|
+
}>;
|
|
40
|
+
isError?: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function register(server: McpServer, client: BudaClient): void;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=quotation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quotation.d.ts","sourceRoot":"","sources":["../../src/tools/quotation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAKxD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;CA+BtB,CAAC;AAEF,KAAK,oBAAoB,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,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,CA2DhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAYpE"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { BudaApiError } from "../client.js";
|
|
3
|
+
import { validateMarketId } from "../validation.js";
|
|
4
|
+
import { flattenAmount } from "../utils.js";
|
|
5
|
+
export const toolSchema = {
|
|
6
|
+
name: "get_real_quotation",
|
|
7
|
+
description: "Gets a server-side price quotation for a buy or sell on Buda.com. " +
|
|
8
|
+
"Calls the Buda quotation API to compute an accurate fill estimate including fees, " +
|
|
9
|
+
"based on live order book state. Prefer this over simulate_order for accurate fee-tier-aware quotes. " +
|
|
10
|
+
"This is a POST (not idempotent) but does not place an order. Public endpoint — no API key required. " +
|
|
11
|
+
"Parameters: market_id, type ('Bid'|'Ask'), amount, optional limit price. " +
|
|
12
|
+
"Example: 'Get an accurate quote to sell 0.05 BTC on BTC-CLP.'",
|
|
13
|
+
inputSchema: {
|
|
14
|
+
type: "object",
|
|
15
|
+
properties: {
|
|
16
|
+
market_id: {
|
|
17
|
+
type: "string",
|
|
18
|
+
description: "Market ID (e.g. 'BTC-CLP', 'ETH-BTC').",
|
|
19
|
+
},
|
|
20
|
+
type: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "'Bid' to buy base currency, 'Ask' to sell base currency.",
|
|
23
|
+
},
|
|
24
|
+
amount: {
|
|
25
|
+
type: "number",
|
|
26
|
+
description: "Order size (positive number).",
|
|
27
|
+
},
|
|
28
|
+
limit: {
|
|
29
|
+
type: "number",
|
|
30
|
+
description: "Optional limit price in quote currency.",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ["market_id", "type", "amount"],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
export async function handleGetRealQuotation(args, client) {
|
|
37
|
+
const { market_id, type, amount, limit } = args;
|
|
38
|
+
const validationError = validateMarketId(market_id);
|
|
39
|
+
if (validationError) {
|
|
40
|
+
return {
|
|
41
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_MARKET_ID" }) }],
|
|
42
|
+
isError: true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
const id = market_id.toLowerCase();
|
|
46
|
+
const payload = { type, amount: String(amount) };
|
|
47
|
+
if (limit !== undefined)
|
|
48
|
+
payload.limit = String(limit);
|
|
49
|
+
try {
|
|
50
|
+
const data = await client.post(`/markets/${id}/quotations`, {
|
|
51
|
+
quotation: payload,
|
|
52
|
+
});
|
|
53
|
+
const q = data.quotation;
|
|
54
|
+
const flatAmount = flattenAmount(q.amount);
|
|
55
|
+
const flatLimit = q.limit ? flattenAmount(q.limit) : null;
|
|
56
|
+
const flatBase = flattenAmount(q.base_balance_change);
|
|
57
|
+
const flatQuote = flattenAmount(q.quote_balance_change);
|
|
58
|
+
const flatFee = flattenAmount(q.fee_amount);
|
|
59
|
+
const flatOrder = flattenAmount(q.order_amount);
|
|
60
|
+
const result = {
|
|
61
|
+
id: q.id ?? null,
|
|
62
|
+
type: q.type,
|
|
63
|
+
market_id: q.market_id,
|
|
64
|
+
amount: flatAmount.value,
|
|
65
|
+
amount_currency: flatAmount.currency,
|
|
66
|
+
limit: flatLimit ? flatLimit.value : null,
|
|
67
|
+
limit_currency: flatLimit ? flatLimit.currency : null,
|
|
68
|
+
base_balance_change: flatBase.value,
|
|
69
|
+
base_balance_change_currency: flatBase.currency,
|
|
70
|
+
quote_balance_change: flatQuote.value,
|
|
71
|
+
quote_balance_change_currency: flatQuote.currency,
|
|
72
|
+
fee_amount: flatFee.value,
|
|
73
|
+
fee_currency: flatFee.currency,
|
|
74
|
+
order_amount: flatOrder.value,
|
|
75
|
+
order_amount_currency: flatOrder.currency,
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const msg = err instanceof BudaApiError
|
|
83
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
84
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
85
|
+
return {
|
|
86
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
87
|
+
isError: true,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export function register(server, client) {
|
|
92
|
+
server.tool(toolSchema.name, toolSchema.description, {
|
|
93
|
+
market_id: z.string().describe("Market ID (e.g. 'BTC-CLP', 'ETH-BTC')."),
|
|
94
|
+
type: z.enum(["Bid", "Ask"]).describe("'Bid' to buy base currency, 'Ask' to sell base currency."),
|
|
95
|
+
amount: z.number().positive().describe("Order size (positive number)."),
|
|
96
|
+
limit: z.number().positive().optional().describe("Optional limit price in quote currency."),
|
|
97
|
+
}, (args) => handleGetRealQuotation(args, client));
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=quotation.js.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BudaClient } from "../client.js";
|
|
3
|
+
export declare const createReceiveAddressToolSchema: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object";
|
|
8
|
+
properties: {
|
|
9
|
+
currency: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
required: string[];
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
export declare const listReceiveAddressesToolSchema: {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object";
|
|
22
|
+
properties: {
|
|
23
|
+
currency: {
|
|
24
|
+
type: string;
|
|
25
|
+
description: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
required: string[];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export declare const getReceiveAddressToolSchema: {
|
|
32
|
+
name: string;
|
|
33
|
+
description: string;
|
|
34
|
+
inputSchema: {
|
|
35
|
+
type: "object";
|
|
36
|
+
properties: {
|
|
37
|
+
currency: {
|
|
38
|
+
type: string;
|
|
39
|
+
description: string;
|
|
40
|
+
};
|
|
41
|
+
id: {
|
|
42
|
+
type: string;
|
|
43
|
+
description: string;
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
required: string[];
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
export declare function handleListReceiveAddresses(args: {
|
|
50
|
+
currency: string;
|
|
51
|
+
}, client: BudaClient): Promise<{
|
|
52
|
+
content: Array<{
|
|
53
|
+
type: "text";
|
|
54
|
+
text: string;
|
|
55
|
+
}>;
|
|
56
|
+
isError?: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
export declare function handleGetReceiveAddress(args: {
|
|
59
|
+
currency: string;
|
|
60
|
+
id: number;
|
|
61
|
+
}, client: BudaClient): Promise<{
|
|
62
|
+
content: Array<{
|
|
63
|
+
type: "text";
|
|
64
|
+
text: string;
|
|
65
|
+
}>;
|
|
66
|
+
isError?: boolean;
|
|
67
|
+
}>;
|
|
68
|
+
export declare function handleCreateReceiveAddress(args: {
|
|
69
|
+
currency: string;
|
|
70
|
+
}, client: BudaClient): Promise<{
|
|
71
|
+
content: Array<{
|
|
72
|
+
type: "text";
|
|
73
|
+
text: string;
|
|
74
|
+
}>;
|
|
75
|
+
isError?: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
export declare function register(server: McpServer, client: BudaClient): void;
|
|
78
|
+
//# sourceMappingURL=receive_addresses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive_addresses.d.ts","sourceRoot":"","sources":["../../src/tools/receive_addresses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAIxD,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;CAmB1C,CAAC;AAEF,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;CAiB1C,CAAC;AAEF,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;CAoBvC,CAAC;AAYF,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,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,CAqChF;AAED,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EACtC,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,CA4BhF;AAED,wBAAsB,0BAA0B,CAC9C,IAAI,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,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,CA6BhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CA4BpE"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { BudaApiError } from "../client.js";
|
|
3
|
+
import { validateCurrency } from "../validation.js";
|
|
4
|
+
export const createReceiveAddressToolSchema = {
|
|
5
|
+
name: "create_receive_address",
|
|
6
|
+
description: "Generates a new receive address for a crypto currency. " +
|
|
7
|
+
"Creates a new blockchain deposit address for the given currency. " +
|
|
8
|
+
"Each call generates a distinct address. Not idempotent. " +
|
|
9
|
+
"Only applicable to crypto currencies (BTC, ETH, etc.). " +
|
|
10
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
11
|
+
"Example: 'Give me a fresh Bitcoin deposit address.'",
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
currency: {
|
|
16
|
+
type: "string",
|
|
17
|
+
description: "Currency code (e.g. 'BTC', 'ETH').",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
required: ["currency"],
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
export const listReceiveAddressesToolSchema = {
|
|
24
|
+
name: "list_receive_addresses",
|
|
25
|
+
description: "Lists all receive (deposit) addresses for a crypto currency on the authenticated Buda.com account. " +
|
|
26
|
+
"Returns an empty array if no addresses have been created yet. " +
|
|
27
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
28
|
+
"Example: 'What are my Bitcoin deposit addresses?'",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: {
|
|
32
|
+
currency: {
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "Currency code (e.g. 'BTC', 'ETH').",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
required: ["currency"],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export const getReceiveAddressToolSchema = {
|
|
41
|
+
name: "get_receive_address",
|
|
42
|
+
description: "Returns a single receive address by its ID for a given currency on Buda.com. " +
|
|
43
|
+
"Requires BUDA_API_KEY and BUDA_API_SECRET. " +
|
|
44
|
+
"Example: 'Get the details of my BTC receive address ID 42.'",
|
|
45
|
+
inputSchema: {
|
|
46
|
+
type: "object",
|
|
47
|
+
properties: {
|
|
48
|
+
currency: {
|
|
49
|
+
type: "string",
|
|
50
|
+
description: "Currency code (e.g. 'BTC', 'ETH').",
|
|
51
|
+
},
|
|
52
|
+
id: {
|
|
53
|
+
type: "number",
|
|
54
|
+
description: "The numeric ID of the receive address.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
required: ["currency", "id"],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
function normalizeAddress(a) {
|
|
61
|
+
return {
|
|
62
|
+
id: a.id,
|
|
63
|
+
address: a.address,
|
|
64
|
+
currency: a.currency,
|
|
65
|
+
created_at: a.created_at,
|
|
66
|
+
label: a.label ?? null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export async function handleListReceiveAddresses(args, client) {
|
|
70
|
+
const { currency } = args;
|
|
71
|
+
const validationError = validateCurrency(currency);
|
|
72
|
+
if (validationError) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
75
|
+
isError: true,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const data = await client.get(`/currencies/${currency.toUpperCase()}/receive_addresses`);
|
|
80
|
+
return {
|
|
81
|
+
content: [
|
|
82
|
+
{
|
|
83
|
+
type: "text",
|
|
84
|
+
text: JSON.stringify({ receive_addresses: data.receive_addresses.map(normalizeAddress) }, null, 2),
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
const msg = err instanceof BudaApiError
|
|
91
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
92
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
93
|
+
return {
|
|
94
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
95
|
+
isError: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export async function handleGetReceiveAddress(args, client) {
|
|
100
|
+
const { currency, id } = args;
|
|
101
|
+
const validationError = validateCurrency(currency);
|
|
102
|
+
if (validationError) {
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
105
|
+
isError: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const data = await client.get(`/currencies/${currency.toUpperCase()}/receive_addresses/${id}`);
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: "text", text: JSON.stringify(normalizeAddress(data.receive_address), null, 2) }],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
const msg = err instanceof BudaApiError
|
|
116
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
117
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
118
|
+
return {
|
|
119
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
120
|
+
isError: true,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export async function handleCreateReceiveAddress(args, client) {
|
|
125
|
+
const { currency } = args;
|
|
126
|
+
const validationError = validateCurrency(currency);
|
|
127
|
+
if (validationError) {
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: "text", text: JSON.stringify({ error: validationError, code: "INVALID_CURRENCY" }) }],
|
|
130
|
+
isError: true,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const data = await client.post(`/currencies/${currency.toUpperCase()}/receive_addresses`, {});
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: "text", text: JSON.stringify(normalizeAddress(data.receive_address), null, 2) }],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
const msg = err instanceof BudaApiError
|
|
141
|
+
? { error: err.message, code: err.status, path: err.path }
|
|
142
|
+
: { error: String(err), code: "UNKNOWN" };
|
|
143
|
+
return {
|
|
144
|
+
content: [{ type: "text", text: JSON.stringify(msg) }],
|
|
145
|
+
isError: true,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export function register(server, client) {
|
|
150
|
+
server.tool(listReceiveAddressesToolSchema.name, listReceiveAddressesToolSchema.description, {
|
|
151
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'ETH')."),
|
|
152
|
+
}, (args) => handleListReceiveAddresses(args, client));
|
|
153
|
+
server.tool(getReceiveAddressToolSchema.name, getReceiveAddressToolSchema.description, {
|
|
154
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'ETH')."),
|
|
155
|
+
id: z.number().int().positive().describe("The numeric ID of the receive address."),
|
|
156
|
+
}, (args) => handleGetReceiveAddress(args, client));
|
|
157
|
+
server.tool(createReceiveAddressToolSchema.name, createReceiveAddressToolSchema.description, {
|
|
158
|
+
currency: z.string().min(2).max(10).describe("Currency code (e.g. 'BTC', 'ETH')."),
|
|
159
|
+
}, (args) => handleCreateReceiveAddress(args, client));
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=receive_addresses.js.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { BudaClient } from "../client.js";
|
|
3
|
+
export declare const listToolSchema: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object";
|
|
8
|
+
properties: {
|
|
9
|
+
per: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
page: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export declare const getToolSchema: {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: "object";
|
|
25
|
+
properties: {
|
|
26
|
+
id: {
|
|
27
|
+
type: string;
|
|
28
|
+
description: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
required: string[];
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
export declare function handleListRemittanceRecipients(args: {
|
|
35
|
+
per?: number;
|
|
36
|
+
page?: number;
|
|
37
|
+
}, client: BudaClient): Promise<{
|
|
38
|
+
content: Array<{
|
|
39
|
+
type: "text";
|
|
40
|
+
text: string;
|
|
41
|
+
}>;
|
|
42
|
+
isError?: boolean;
|
|
43
|
+
}>;
|
|
44
|
+
export declare function handleGetRemittanceRecipient(args: {
|
|
45
|
+
id: number;
|
|
46
|
+
}, client: BudaClient): Promise<{
|
|
47
|
+
content: Array<{
|
|
48
|
+
type: "text";
|
|
49
|
+
text: string;
|
|
50
|
+
}>;
|
|
51
|
+
isError?: boolean;
|
|
52
|
+
}>;
|
|
53
|
+
export declare function register(server: McpServer, client: BudaClient): void;
|
|
54
|
+
//# sourceMappingURL=remittance_recipients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remittance_recipients.d.ts","sourceRoot":"","sources":["../../src/tools/remittance_recipients.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,UAAU,EAAgB,MAAM,cAAc,CAAC;AAGxD,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;CAoB1B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;CAiBzB,CAAC;AAaF,wBAAsB,8BAA8B,CAClD,IAAI,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACrC,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,CAoChF;AAED,wBAAsB,4BAA4B,CAChD,IAAI,EAAE;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACpB,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,CAgBhF;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAmBpE"}
|