stables-mcp-server 1.4.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +70 -48
  2. package/build/index.js +3 -3
  3. package/build/index.js.map +1 -1
  4. package/build/lib/stables-client.d.ts +313 -136
  5. package/build/lib/stables-client.d.ts.map +1 -1
  6. package/build/lib/stables-client.js +107 -19
  7. package/build/lib/stables-client.js.map +1 -1
  8. package/build/tools/api-keys.d.ts.map +1 -1
  9. package/build/tools/api-keys.js +7 -3
  10. package/build/tools/api-keys.js.map +1 -1
  11. package/build/tools/customers.d.ts.map +1 -1
  12. package/build/tools/customers.js +239 -106
  13. package/build/tools/customers.js.map +1 -1
  14. package/build/tools/quotes.d.ts +5 -1
  15. package/build/tools/quotes.d.ts.map +1 -1
  16. package/build/tools/quotes.js +103 -59
  17. package/build/tools/quotes.js.map +1 -1
  18. package/build/tools/sandbox.d.ts +11 -0
  19. package/build/tools/sandbox.d.ts.map +1 -0
  20. package/build/tools/sandbox.js +78 -0
  21. package/build/tools/sandbox.js.map +1 -0
  22. package/build/tools/transfers.d.ts +4 -1
  23. package/build/tools/transfers.d.ts.map +1 -1
  24. package/build/tools/transfers.js +212 -112
  25. package/build/tools/transfers.js.map +1 -1
  26. package/build/tools/virtual-accounts.d.ts.map +1 -1
  27. package/build/tools/virtual-accounts.js +127 -84
  28. package/build/tools/virtual-accounts.js.map +1 -1
  29. package/build/tools/webhooks.d.ts.map +1 -1
  30. package/build/tools/webhooks.js +98 -24
  31. package/build/tools/webhooks.js.map +1 -1
  32. package/package.json +12 -4
  33. package/build/tools/notifications.d.ts +0 -8
  34. package/build/tools/notifications.d.ts.map +0 -1
  35. package/build/tools/notifications.js +0 -125
  36. package/build/tools/notifications.js.map +0 -1
@@ -1,66 +1,115 @@
1
1
  /**
2
2
  * Quote Tools for Stables MCP Server
3
- * Synced with OpenAPI spec from https://api.stables.money/docs
3
+ *
4
+ * Mirrors POST /api/v1/quotes and GET /api/v1/quotes/:id as of 2026-07-30. The
5
+ * request takes `source`/`destination` (was `from`/`to`), the response is the
6
+ * quote itself with no `{ quote }` wrapper, and `paymentMethodType` is gone —
7
+ * the payment network is now `destination.network`.
4
8
  */
5
9
  import { z } from "zod";
10
+ const LIVE_NETWORKS = [
11
+ "arbitrum",
12
+ "avalanche",
13
+ "base",
14
+ "ethereum",
15
+ "optimism",
16
+ "polygon",
17
+ "solana",
18
+ "tron",
19
+ ];
20
+ function secondsUntil(iso) {
21
+ return Math.max(0, Math.floor((new Date(iso).getTime() - Date.now()) / 1000));
22
+ }
23
+ function describeAmount(side) {
24
+ return `${side.amount} ${side.currency}${side.network ? ` (${side.network})` : ""}`;
25
+ }
26
+ function feeLines(quote) {
27
+ const fees = quote.fees;
28
+ let out = `Total Fees: ${fees.total_fee.amount} ${fees.total_fee.currency}`;
29
+ if (fees.fx_fee)
30
+ out += `\n FX Fee: ${fees.fx_fee.amount} ${fees.fx_fee.currency}`;
31
+ if (fees.platform_fee)
32
+ out += `\n Platform Fee: ${fees.platform_fee.amount} ${fees.platform_fee.currency}`;
33
+ if (fees.payment_method_fee)
34
+ out += `\n Payment Method Fee: ${fees.payment_method_fee.amount} ${fees.payment_method_fee.currency}`;
35
+ if (fees.network_fee)
36
+ out += `\n Network Fee: ${fees.network_fee.amount} ${fees.network_fee.currency}`;
37
+ if (fees.integrator_fee)
38
+ out += `\n Integrator Fee: ${fees.integrator_fee.amount} ${fees.integrator_fee.currency}`;
39
+ return out;
40
+ }
6
41
  export function registerQuoteTools(server, client) {
7
42
  // Create Quote
8
- server.tool("create_quote", "Get a quote for currency exchange. Quotes show the exchange rate, fees, and amount the customer will receive. Quotes expire after 30 seconds. Currently supports crypto → fiat (off-ramp) with more types coming soon.", {
9
- customerId: z.string().optional().describe("The customer ID to associate this quote with. Required if the quote will be used to create a transfer."),
10
- fromCurrency: z.enum(["USDC", "USDT"]).describe("Source cryptocurrency (USDC or USDT)"),
11
- fromAmount: z.string().describe("Amount to convert (e.g., '125.75')"),
12
- fromNetwork: z.enum(["ethereum", "polygon"]).describe("Blockchain network for the source crypto"),
13
- toCurrency: z.string().describe("Destination currency code (e.g., 'EUR', 'USD', 'GBP')"),
14
- toCountry: z.string().describe("Destination country code (e.g., 'GR', 'US', 'GB')"),
15
- paymentMethodType: z.enum(["SWIFT", "LOCAL"]).describe("Payment method for fiat payouts - 'SWIFT' for international, 'LOCAL' for domestic rails"),
16
- }, async ({ customerId, fromCurrency, fromAmount, fromNetwork, toCurrency, toCountry, paymentMethodType }) => {
43
+ server.tool("create_quote", "Get a quote for a currency exchange: the rate, the fees, and what the customer receives. Quotes are short-lived, so create one immediately before the transfer. " +
44
+ "Off-ramp converts a stablecoin to fiat (source network required, destination country required); on-ramp converts fiat to a stablecoin (destination address required). " +
45
+ "Set preview to price without committing.", {
46
+ sourceCurrency: z
47
+ .string()
48
+ .describe("Source currency: a stablecoin for off-ramp (e.g. 'USDT'), fiat for on-ramp"),
49
+ sourceAmount: z.string().describe("Amount to convert, in major units (e.g. '125.75')"),
50
+ sourceNetwork: z
51
+ .enum(LIVE_NETWORKS)
52
+ .optional()
53
+ .describe("Blockchain network of the source. Required for off-ramp, omitted for on-ramp"),
54
+ destinationCurrency: z
55
+ .string()
56
+ .describe("Destination currency: fiat for off-ramp (e.g. 'EUR'), a stablecoin for on-ramp"),
57
+ destinationCountry: z
58
+ .string()
59
+ .optional()
60
+ .describe("Destination country, ISO 2-letter. Required for off-ramp"),
61
+ destinationNetwork: z
62
+ .string()
63
+ .optional()
64
+ .describe("Off-ramp: payment network, 'swift' or 'bank'. On-ramp: blockchain network. Replaces the old paymentMethodType"),
65
+ destinationAddress: z
66
+ .string()
67
+ .optional()
68
+ .describe("Destination wallet address. Required for on-ramp"),
69
+ preview: z
70
+ .boolean()
71
+ .optional()
72
+ .describe("Price the quote without persisting it — use to show an estimate"),
73
+ metadata: z.record(z.string()).optional().describe("Optional metadata"),
74
+ }, async (input) => {
17
75
  try {
18
- const response = await client.createQuote({
19
- customerId,
20
- from: {
21
- currency: fromCurrency,
22
- amount: fromAmount,
23
- network: fromNetwork,
76
+ const quote = await client.createQuote({
77
+ source: {
78
+ currency: input.sourceCurrency,
79
+ amount: input.sourceAmount,
80
+ ...(input.sourceNetwork && { network: input.sourceNetwork }),
24
81
  },
25
- to: {
26
- currency: toCurrency,
27
- country: toCountry,
28
- paymentMethodType,
82
+ destination: {
83
+ currency: input.destinationCurrency,
84
+ ...(input.destinationCountry && { country: input.destinationCountry }),
85
+ ...(input.destinationNetwork && { network: input.destinationNetwork }),
86
+ ...(input.destinationAddress && { address: input.destinationAddress }),
29
87
  },
88
+ ...(input.preview !== undefined && { preview: input.preview }),
89
+ ...(input.metadata && { metadata: input.metadata }),
30
90
  });
31
- const quote = response.quote;
32
- const expiresIn = Math.max(0, Math.floor((new Date(quote.expiresAt).getTime() - Date.now()) / 1000));
33
- let feeDetails = `Total Fees: ${quote.fees.totalFee.amount} ${quote.fees.totalFee.currency}`;
34
- if (quote.fees.fxFee)
35
- feeDetails += `\n FX Fee: ${quote.fees.fxFee.amount} ${quote.fees.fxFee.currency}`;
36
- if (quote.fees.platformFee)
37
- feeDetails += `\n Platform Fee: ${quote.fees.platformFee.amount} ${quote.fees.platformFee.currency}`;
38
- if (quote.fees.paymentMethodFee)
39
- feeDetails += `\n Payment Method Fee: ${quote.fees.paymentMethodFee.amount} ${quote.fees.paymentMethodFee.currency}`;
40
- if (quote.fees.networkFee)
41
- feeDetails += `\n Network Fee: ${quote.fees.networkFee.amount} ${quote.fees.networkFee.currency}`;
42
- if (quote.fees.integratorFee)
43
- feeDetails += `\n Integrator Fee: ${quote.fees.integratorFee.amount} ${quote.fees.integratorFee.currency}`;
44
91
  return {
45
92
  content: [
46
93
  {
47
94
  type: "text",
48
95
  text: `Quote created successfully!
49
96
 
50
- Quote ID: ${quote.quoteId}
97
+ Quote ID: ${quote.quote_id}
51
98
  Status: ${quote.status}
52
99
 
53
100
  Converting:
54
- From: ${quote.from.amount} ${quote.from.currency}${quote.from.network ? ` (${quote.from.network})` : ""}
55
- To: ${quote.to.amount} ${quote.to.currency} via ${quote.to.paymentMethodType}
101
+ From: ${describeAmount(quote.source)}
102
+ To: ${describeAmount(quote.destination)}
56
103
 
57
- Exchange Rate: ${quote.exchangeRate}
58
- ${feeDetails}
104
+ Exchange Rate: ${quote.exchange_rate}
105
+ ${feeLines(quote)}
59
106
 
60
- Expires in: ${expiresIn} seconds
61
- Expires at: ${quote.expiresAt}
107
+ Expires in: ${secondsUntil(quote.expires_at)} seconds
108
+ Expires at: ${quote.expires_at}
62
109
 
63
- To execute this quote, use 'create_transfer' with this quoteId and include bank details for off-ramp transfers.`,
110
+ ${quote.status === "preview"
111
+ ? "This is a preview and was not persisted. Create a real quote before transferring."
112
+ : "To execute it, call 'create_transfer' with this quote ID and the payout destination."}`,
64
113
  },
65
114
  ],
66
115
  };
@@ -82,24 +131,19 @@ To execute this quote, use 'create_transfer' with this quoteId and include bank
82
131
  quoteId: z.string().describe("The quote ID to look up"),
83
132
  }, async ({ quoteId }) => {
84
133
  try {
85
- const response = await client.getQuote(quoteId);
86
- const quote = response.quote;
87
- const isExpired = quote.status === "QUOTE_STATUS_EXPIRED" || new Date(quote.expiresAt) < new Date();
88
- const isUsed = quote.status === "QUOTE_STATUS_USED";
89
- const isCancelled = quote.status === "QUOTE_STATUS_CANCELLED";
90
- let statusMessage = "";
91
- if (isUsed) {
134
+ const quote = await client.getQuote(quoteId);
135
+ let statusMessage;
136
+ if (quote.status === "used") {
92
137
  statusMessage = "This quote has already been used to create a transfer.";
93
138
  }
94
- else if (isCancelled) {
139
+ else if (quote.status === "cancelled") {
95
140
  statusMessage = "This quote has been cancelled.";
96
141
  }
97
- else if (isExpired) {
142
+ else if (quote.status === "expired" || new Date(quote.expires_at) < new Date()) {
98
143
  statusMessage = "This quote has expired. Create a new quote to proceed.";
99
144
  }
100
145
  else {
101
- const expiresIn = Math.max(0, Math.floor((new Date(quote.expiresAt).getTime() - Date.now()) / 1000));
102
- statusMessage = `This quote is active and expires in ${expiresIn} seconds.`;
146
+ statusMessage = `This quote is active and expires in ${secondsUntil(quote.expires_at)} seconds.`;
103
147
  }
104
148
  return {
105
149
  content: [
@@ -107,18 +151,18 @@ To execute this quote, use 'create_transfer' with this quoteId and include bank
107
151
  type: "text",
108
152
  text: `Quote Details:
109
153
 
110
- Quote ID: ${quote.quoteId}
154
+ Quote ID: ${quote.quote_id}
111
155
  Status: ${quote.status}
112
156
 
113
157
  Converting:
114
- From: ${quote.from.amount} ${quote.from.currency}${quote.from.network ? ` (${quote.from.network})` : ""}
115
- To: ${quote.to.amount} ${quote.to.currency} via ${quote.to.paymentMethodType}
158
+ From: ${describeAmount(quote.source)}
159
+ To: ${describeAmount(quote.destination)}
116
160
 
117
- Exchange Rate: ${quote.exchangeRate}
118
- Total Fees: ${quote.fees.totalFee.amount} ${quote.fees.totalFee.currency}
161
+ Exchange Rate: ${quote.exchange_rate}
162
+ Total Fees: ${quote.fees.total_fee.amount} ${quote.fees.total_fee.currency}
119
163
 
120
- Created: ${quote.createdAt}
121
- Expires: ${quote.expiresAt}
164
+ Created: ${quote.created_at}
165
+ Expires: ${quote.expires_at}
122
166
 
123
167
  ${statusMessage}`,
124
168
  },
@@ -1 +1 @@
1
- {"version":3,"file":"quotes.js","sourceRoot":"","sources":["../../src/tools/quotes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,MAAwB;IAC5E,eAAe;IACf,MAAM,CAAC,IAAI,CACT,cAAc,EACd,wNAAwN,EACxN;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wGAAwG,CAAC;QACpJ,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,sCAAsC,CAAC;QACvF,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;QACrE,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,0CAA0C,CAAC;QACjG,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;QACxF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QACnF,iBAAiB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,yFAAyF,CAAC;KAClJ,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,EAAE;QACxG,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;gBACxC,UAAU;gBACV,IAAI,EAAE;oBACJ,QAAQ,EAAE,YAAY;oBACtB,MAAM,EAAE,UAAU;oBAClB,OAAO,EAAE,WAAW;iBACrB;gBACD,EAAE,EAAE;oBACF,QAAQ,EAAE,UAAU;oBACpB,OAAO,EAAE,SAAS;oBAClB,iBAAiB;iBAClB;aACF,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YAErG,IAAI,UAAU,GAAG,eAAe,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC7F,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK;gBAAE,UAAU,IAAI,eAAe,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC1G,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW;gBAAE,UAAU,IAAI,qBAAqB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;YAClI,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB;gBAAE,UAAU,IAAI,2BAA2B,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;YACvJ,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU;gBAAE,UAAU,IAAI,oBAAoB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC9H,IAAI,KAAK,CAAC,IAAI,CAAC,aAAa;gBAAE,UAAU,IAAI,uBAAuB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAE1I,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;YAER,KAAK,CAAC,OAAO;UACf,KAAK,CAAC,MAAM;;;UAGZ,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE;QACjG,KAAK,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,QAAQ,KAAK,CAAC,EAAE,CAAC,iBAAiB;;iBAE7D,KAAK,CAAC,YAAY;EACjC,UAAU;;cAEE,SAAS;cACT,KAAK,CAAC,SAAS;;gHAEmF;qBACnG;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;qBAC5F;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,YAAY;IACZ,MAAM,CAAC,IAAI,CACT,WAAW,EACX,kEAAkE,EAClE;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KACxD,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACpB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAE7B,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,KAAK,sBAAsB,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YACpG,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,mBAAmB,CAAC;YACpD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,KAAK,wBAAwB,CAAC;YAE9D,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,IAAI,MAAM,EAAE,CAAC;gBACX,aAAa,GAAG,wDAAwD,CAAC;YAC3E,CAAC;iBAAM,IAAI,WAAW,EAAE,CAAC;gBACvB,aAAa,GAAG,gCAAgC,CAAC;YACnD,CAAC;iBAAM,IAAI,SAAS,EAAE,CAAC;gBACrB,aAAa,GAAG,wDAAwD,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACN,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;gBACrG,aAAa,GAAG,uCAAuC,SAAS,WAAW,CAAC;YAC9E,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;YAER,KAAK,CAAC,OAAO;UACf,KAAK,CAAC,MAAM;;;UAGZ,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE;QACjG,KAAK,CAAC,EAAE,CAAC,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,QAAQ,KAAK,CAAC,EAAE,CAAC,iBAAiB;;iBAE7D,KAAK,CAAC,YAAY;cACrB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ;;WAE7D,KAAK,CAAC,SAAS;WACf,KAAK,CAAC,SAAS;;EAExB,aAAa,EAAE;qBACJ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;qBACzF;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"quotes.js","sourceRoot":"","sources":["../../src/tools/quotes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,aAAa,GAAG;IACpB,UAAU;IACV,WAAW;IACX,MAAM;IACN,UAAU;IACV,UAAU;IACV,SAAS;IACT,QAAQ;IACR,MAAM;CACE,CAAC;AAEX,SAAS,YAAY,CAAC,GAAW;IAC/B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,cAAc,CAAC,IAA4D;IAClF,OAAO,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACtF,CAAC;AAED,SAAS,QAAQ,CAAC,KAAY;IAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,GAAG,GAAG,eAAe,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC5E,IAAI,IAAI,CAAC,MAAM;QAAE,GAAG,IAAI,eAAe,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IACpF,IAAI,IAAI,CAAC,YAAY;QACnB,GAAG,IAAI,qBAAqB,IAAI,CAAC,YAAY,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;IACvF,IAAI,IAAI,CAAC,kBAAkB;QACzB,GAAG,IAAI,2BAA2B,IAAI,CAAC,kBAAkB,CAAC,MAAM,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC;IACzG,IAAI,IAAI,CAAC,WAAW;QAClB,GAAG,IAAI,oBAAoB,IAAI,CAAC,WAAW,CAAC,MAAM,IAAI,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;IACpF,IAAI,IAAI,CAAC,cAAc;QACrB,GAAG,IAAI,uBAAuB,IAAI,CAAC,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;IAC7F,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,MAAwB;IAC5E,eAAe;IACf,MAAM,CAAC,IAAI,CACT,cAAc,EACd,kKAAkK;QAChK,wKAAwK;QACxK,0CAA0C,EAC5C;QACE,cAAc,EAAE,CAAC;aACd,MAAM,EAAE;aACR,QAAQ,CAAC,4EAA4E,CAAC;QACzF,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QACtF,aAAa,EAAE,CAAC;aACb,IAAI,CAAC,aAAa,CAAC;aACnB,QAAQ,EAAE;aACV,QAAQ,CAAC,8EAA8E,CAAC;QAC3F,mBAAmB,EAAE,CAAC;aACnB,MAAM,EAAE;aACR,QAAQ,CAAC,gFAAgF,CAAC;QAC7F,kBAAkB,EAAE,CAAC;aAClB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;QACvE,kBAAkB,EAAE,CAAC;aAClB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CACP,+GAA+G,CAChH;QACH,kBAAkB,EAAE,CAAC;aAClB,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,kDAAkD,CAAC;QAC/D,OAAO,EAAE,CAAC;aACP,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,iEAAiE,CAAC;QAC9E,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KACxE,EACD,KAAK,EAAE,KAAK,EAAE,EAAE;QACd,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;gBACrC,MAAM,EAAE;oBACN,QAAQ,EAAE,KAAK,CAAC,cAAc;oBAC9B,MAAM,EAAE,KAAK,CAAC,YAAY;oBAC1B,GAAG,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,aAAa,EAAE,CAAC;iBAC7D;gBACD,WAAW,EAAE;oBACX,QAAQ,EAAE,KAAK,CAAC,mBAAmB;oBACnC,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,kBAAkB,EAAE,CAAC;oBACtE,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,kBAAkB,EAAE,CAAC;oBACtE,GAAG,CAAC,KAAK,CAAC,kBAAkB,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,kBAAkB,EAAE,CAAC;iBACvE;gBACD,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC9D,GAAG,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;aACpD,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;;YAER,KAAK,CAAC,QAAQ;UAChB,KAAK,CAAC,MAAM;;;UAGZ,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC;;iBAExB,KAAK,CAAC,aAAa;EAClC,QAAQ,CAAC,KAAK,CAAC;;cAEH,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC;cAC9B,KAAK,CAAC,UAAU;;EAG5B,KAAK,CAAC,MAAM,KAAK,SAAS;4BACxB,CAAC,CAAC,mFAAmF;4BACrF,CAAC,CAAC,sFACN,EAAE;qBACW;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,2BAA2B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;qBAC5F;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;IAEF,YAAY;IACZ,MAAM,CAAC,IAAI,CACT,WAAW,EACX,kEAAkE,EAClE;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KACxD,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACpB,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAE7C,IAAI,aAAqB,CAAC;YAC1B,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC5B,aAAa,GAAG,wDAAwD,CAAC;YAC3E,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACxC,aAAa,GAAG,gCAAgC,CAAC;YACnD,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;gBACjF,aAAa,GAAG,wDAAwD,CAAC;YAC3E,CAAC;iBAAM,CAAC;gBACN,aAAa,GAAG,uCAAuC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC;YACnG,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE;;YAER,KAAK,CAAC,QAAQ;UAChB,KAAK,CAAC,MAAM;;;UAGZ,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC;;iBAExB,KAAK,CAAC,aAAa;cACtB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ;;WAE/D,KAAK,CAAC,UAAU;WAChB,KAAK,CAAC,UAAU;;EAEzB,aAAa,EAAE;qBACJ;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,wBAAwB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE;qBACzF;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Sandbox simulation tools for the Stables MCP Server.
3
+ *
4
+ * These endpoints exist only on non-live deployments. Without them an agent
5
+ * cannot drive a deposit to a terminal state in test — a real bank payment would
6
+ * be required — so a test integration could never see a completed payout.
7
+ */
8
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
+ import { StablesApiClient } from "../lib/stables-client.js";
10
+ export declare function registerSandboxTools(server: McpServer, client: StablesApiClient): void;
11
+ //# sourceMappingURL=sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,QAuF/E"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Sandbox simulation tools for the Stables MCP Server.
3
+ *
4
+ * These endpoints exist only on non-live deployments. Without them an agent
5
+ * cannot drive a deposit to a terminal state in test — a real bank payment would
6
+ * be required — so a test integration could never see a completed payout.
7
+ */
8
+ import { z } from "zod";
9
+ export function registerSandboxTools(server, client) {
10
+ server.tool("simulate_route_deposit", "SANDBOX ONLY. Simulate a fiat deposit into a payment route so you can watch the conversion and payout complete without a real bank transfer. Fails on production.", {
11
+ customerId: z.string().describe("The customer ID"),
12
+ virtualAccountId: z.string().describe("The payment route (virtual account) ID"),
13
+ amount: z.string().describe("Deposit amount in major units (e.g. '500.00')"),
14
+ scenario: z
15
+ .enum(["create_only", "completed", "failed"])
16
+ .optional()
17
+ .describe("'completed' runs the deposit through to payout, 'failed' exercises the failure path, 'create_only' stops at the deposit"),
18
+ senderName: z.string().optional().describe("Name to attribute the deposit to"),
19
+ senderReference: z.string().optional().describe("Payment reference on the deposit"),
20
+ externalDepositId: z.string().optional().describe("Your own reference for this deposit"),
21
+ }, async ({ customerId, virtualAccountId, amount, scenario, senderName, senderReference, externalDepositId, }) => {
22
+ try {
23
+ const result = await client.simulateVirtualAccountDeposit(customerId, virtualAccountId, {
24
+ amount,
25
+ ...(scenario && { scenario }),
26
+ ...(senderName && { sender_name: senderName }),
27
+ ...(senderReference && { sender_reference: senderReference }),
28
+ ...(externalDepositId && { external_deposit_id: externalDepositId }),
29
+ });
30
+ return {
31
+ content: [
32
+ {
33
+ type: "text",
34
+ text: `Simulated deposit of ${amount} into route ${virtualAccountId}:\n\n${JSON.stringify(result, null, 2)}\n\nUse 'get_virtual_account_history' to see the deposit and its payout.`,
35
+ },
36
+ ],
37
+ };
38
+ }
39
+ catch (error) {
40
+ return {
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: `Failed to simulate the deposit: ${error instanceof Error ? error.message : "Unknown error"}\n\nThis endpoint exists only in sandbox — on production it will not be found.`,
45
+ },
46
+ ],
47
+ isError: true,
48
+ };
49
+ }
50
+ });
51
+ server.tool("simulate_transfer_deposit", "SANDBOX ONLY. Simulate the customer sending the crypto an off-ramp transfer is waiting on, so the transfer can progress to payout without an on-chain payment. Fails on production.", {
52
+ transferId: z.string().describe("The transfer awaiting funds"),
53
+ }, async ({ transferId }) => {
54
+ try {
55
+ const result = await client.simulateTransferDeposit(transferId);
56
+ return {
57
+ content: [
58
+ {
59
+ type: "text",
60
+ text: `Simulated the inbound deposit for transfer ${transferId}:\n\n${JSON.stringify(result, null, 2)}\n\nUse 'get_transfer' to follow the status.`,
61
+ },
62
+ ],
63
+ };
64
+ }
65
+ catch (error) {
66
+ return {
67
+ content: [
68
+ {
69
+ type: "text",
70
+ text: `Failed to simulate the transfer deposit: ${error instanceof Error ? error.message : "Unknown error"}\n\nThis endpoint exists only in sandbox — on production it will not be found.`,
71
+ },
72
+ ],
73
+ isError: true,
74
+ };
75
+ }
76
+ });
77
+ }
78
+ //# sourceMappingURL=sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sandbox.js","sourceRoot":"","sources":["../../src/tools/sandbox.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,9 @@
1
1
  /**
2
2
  * Transfer Tools for Stables MCP Server
3
- * Synced with OpenAPI spec from https://api.stables.money/docs
3
+ *
4
+ * Mirrors POST /api/v1/transfer as of 2026-07-30. The wire is snake_case and the
5
+ * payout target is a discriminated `destination`, not the old nested
6
+ * `paymentMethod.bankTransfer`.
4
7
  */
5
8
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
9
  import { StablesApiClient } from "../lib/stables-client.js";
@@ -1 +1 @@
1
- {"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["../../src/tools/transfers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,QAiQhF"}
1
+ {"version":3,"file":"transfers.d.ts","sourceRoot":"","sources":["../../src/tools/transfers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAuC,MAAM,0BAA0B,CAAC;AA2CjG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,gBAAgB,QAyUhF"}