@avvio/payments 0.1.0 → 0.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 +190 -5
- package/ERRORS.md +120 -58
- package/QUICKSTART.md +162 -54
- package/README.md +136 -37
- package/index.d.ts +801 -82
- package/package.json +11 -5
- package/src/cli.js +204 -20
- package/src/client.js +576 -58
- package/src/mcp.js +279 -29
package/src/mcp.js
CHANGED
|
@@ -34,8 +34,16 @@ const TOOLS = [
|
|
|
34
34
|
name: 'list_corridors',
|
|
35
35
|
annotations: { readOnlyHint: true },
|
|
36
36
|
description:
|
|
37
|
-
'List every currency this organization can pay out to,
|
|
38
|
-
inputSchema: {
|
|
37
|
+
'List every currency this organization can pay out to, or pass one currency to use its exact approved provider routing. Read this instead of hardcoding a form — field names differ by corridor and can change.',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
properties: {
|
|
41
|
+
currency: {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Optional ISO code, e.g. MXN',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
39
47
|
},
|
|
40
48
|
{
|
|
41
49
|
name: 'get_requirements',
|
|
@@ -58,9 +66,15 @@ const TOOLS = [
|
|
|
58
66
|
inputSchema: {
|
|
59
67
|
type: 'object',
|
|
60
68
|
properties: {
|
|
61
|
-
amount: {
|
|
69
|
+
amount: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
description: 'Amount to send, e.g. "200.00"',
|
|
72
|
+
},
|
|
62
73
|
to: { type: 'string', description: 'Destination currency, e.g. MXN' },
|
|
63
|
-
from: {
|
|
74
|
+
from: {
|
|
75
|
+
type: 'string',
|
|
76
|
+
description: 'Source currency. Defaults to USD.',
|
|
77
|
+
},
|
|
64
78
|
},
|
|
65
79
|
required: ['amount', 'to'],
|
|
66
80
|
},
|
|
@@ -82,11 +96,13 @@ const TOOLS = [
|
|
|
82
96
|
},
|
|
83
97
|
externalId: {
|
|
84
98
|
type: 'string',
|
|
85
|
-
description:
|
|
99
|
+
description:
|
|
100
|
+
'Your own id for this beneficiary. Makes creation idempotent.',
|
|
86
101
|
},
|
|
87
102
|
details: {
|
|
88
103
|
type: 'object',
|
|
89
|
-
description:
|
|
104
|
+
description:
|
|
105
|
+
'Corridor fields from get_requirements, e.g. {"clabeNumber":"012..."}',
|
|
90
106
|
},
|
|
91
107
|
},
|
|
92
108
|
required: ['name', 'currency', 'details'],
|
|
@@ -102,6 +118,80 @@ const TOOLS = [
|
|
|
102
118
|
properties: { endUserId: { type: 'string' } },
|
|
103
119
|
},
|
|
104
120
|
},
|
|
121
|
+
{
|
|
122
|
+
name: 'get_beneficiary',
|
|
123
|
+
annotations: { readOnlyHint: true },
|
|
124
|
+
description:
|
|
125
|
+
'One beneficiary by the id this API returned, with their payment methods and each destinationAccountId.',
|
|
126
|
+
inputSchema: {
|
|
127
|
+
type: 'object',
|
|
128
|
+
properties: { recipientId: { type: 'string' } },
|
|
129
|
+
required: ['recipientId'],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'get_beneficiary_by_external_id',
|
|
134
|
+
annotations: { readOnlyHint: true },
|
|
135
|
+
description:
|
|
136
|
+
'One beneficiary by YOUR own id for them — the externalId you sent when you created them. Use this instead of listing everyone and filtering: it is unique per organization, so it returns exactly one or NOT_FOUND.',
|
|
137
|
+
inputSchema: {
|
|
138
|
+
type: 'object',
|
|
139
|
+
properties: {
|
|
140
|
+
externalId: {
|
|
141
|
+
type: 'string',
|
|
142
|
+
description: 'Your id for this beneficiary, e.g. "payroll-4471".',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
required: ['externalId'],
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'update_beneficiary',
|
|
150
|
+
annotations: { readOnlyHint: false },
|
|
151
|
+
description:
|
|
152
|
+
'Correct a beneficiary’s contact details: name, email, phone, country, individual/business. Only the fields you pass change. BANK DETAILS CANNOT BE EDITED — a wrong account is a new payment method, and the old one is deleted.',
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: 'object',
|
|
155
|
+
properties: {
|
|
156
|
+
recipientId: { type: 'string' },
|
|
157
|
+
name: { type: 'string' },
|
|
158
|
+
email: { type: 'string' },
|
|
159
|
+
phone: { type: 'string' },
|
|
160
|
+
country: { type: 'string', description: 'ISO-3166 alpha-2, e.g. MX' },
|
|
161
|
+
type: { type: 'string', enum: ['individual', 'business'] },
|
|
162
|
+
},
|
|
163
|
+
required: ['recipientId'],
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'delete_beneficiary_method',
|
|
168
|
+
annotations: { destructiveHint: true, readOnlyHint: false },
|
|
169
|
+
description:
|
|
170
|
+
'Remove one way of paying a beneficiary — an account that closed, or one entered wrong. Irreversible, and the destinationAccountId it carried stops being payable, so it requires confirm:true. The beneficiary and their other methods are untouched.',
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: 'object',
|
|
173
|
+
properties: {
|
|
174
|
+
recipientId: { type: 'string' },
|
|
175
|
+
methodId: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'From the beneficiary’s paymentMethods[].id.',
|
|
178
|
+
},
|
|
179
|
+
confirm: {
|
|
180
|
+
type: 'boolean',
|
|
181
|
+
description:
|
|
182
|
+
'Must be true. The account cannot be restored, only re-registered.',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
required: ['recipientId', 'methodId', 'confirm'],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
name: 'list_payment_reasons',
|
|
190
|
+
annotations: { readOnlyHint: true },
|
|
191
|
+
description:
|
|
192
|
+
'The stated payment reasons this organization may use. Some corridors require one on a payout; read this rather than inventing a value, because a rejected one is a 400 on a payout already promised to somebody.',
|
|
193
|
+
inputSchema: { type: 'object', properties: {} },
|
|
194
|
+
},
|
|
105
195
|
{
|
|
106
196
|
name: 'send_payout',
|
|
107
197
|
annotations: { destructiveHint: true, readOnlyHint: false },
|
|
@@ -124,6 +214,12 @@ const TOOLS = [
|
|
|
124
214
|
description:
|
|
125
215
|
'What you told the payer they would receive. The send is refused if the binding quote drifts more than 2% from it.',
|
|
126
216
|
},
|
|
217
|
+
amountLeg: {
|
|
218
|
+
type: 'string',
|
|
219
|
+
enum: ['source', 'destination', 'source_net'],
|
|
220
|
+
description:
|
|
221
|
+
"Which side `amount` describes. 'source' (default) takes the fees out of what you send. 'destination' pays the beneficiary that exact figure in THEIR currency and adds the fees to your debit. 'source_net' means the same but keeps the figure in the sender's currency — 'send them $200 worth' — converted at the market rate. The two locking modes need capabilities.exactOutput from list_corridors.",
|
|
222
|
+
},
|
|
127
223
|
idempotencyKey: {
|
|
128
224
|
type: 'string',
|
|
129
225
|
description:
|
|
@@ -131,18 +227,14 @@ const TOOLS = [
|
|
|
131
227
|
},
|
|
132
228
|
confirm: {
|
|
133
229
|
type: 'boolean',
|
|
134
|
-
description:
|
|
230
|
+
description:
|
|
231
|
+
'Must be true. Explicit acknowledgement that this moves money.',
|
|
135
232
|
},
|
|
136
233
|
},
|
|
137
234
|
// idempotencyKey is required because a timeout is the case this tool is
|
|
138
235
|
// most likely to hit, and retrying is what an agent does by reflex.
|
|
139
236
|
// Without a caller-supplied key that retry is a second payment.
|
|
140
|
-
required: [
|
|
141
|
-
'amount',
|
|
142
|
-
'destinationAccountId',
|
|
143
|
-
'confirm',
|
|
144
|
-
'idempotencyKey',
|
|
145
|
-
],
|
|
237
|
+
required: ['amount', 'destinationAccountId', 'confirm', 'idempotencyKey'],
|
|
146
238
|
},
|
|
147
239
|
},
|
|
148
240
|
{
|
|
@@ -173,16 +265,77 @@ const TOOLS = [
|
|
|
173
265
|
name: 'list_events',
|
|
174
266
|
annotations: { readOnlyHint: true },
|
|
175
267
|
description:
|
|
176
|
-
'The change feed: one row per
|
|
268
|
+
'The change feed: one row per transition, with a `sequence` cursor. This is the reconciliation primitive — carry `nextSince` back as `since` and you observe every revision. Each row\u2019s `data` is the webhook body for the same event (amounts, fee, reference). Payout, batch, approval and endpoint events share the feed; pass `type` to narrow it.',
|
|
177
269
|
inputSchema: {
|
|
178
270
|
type: 'object',
|
|
179
271
|
properties: {
|
|
180
|
-
since: {
|
|
272
|
+
since: {
|
|
273
|
+
type: 'string',
|
|
274
|
+
description: 'A `sequence` from a previous page. Digits only.',
|
|
275
|
+
},
|
|
181
276
|
limit: { type: 'number', description: '1-500, default 100.' },
|
|
182
|
-
payoutId: {
|
|
277
|
+
payoutId: {
|
|
278
|
+
type: 'string',
|
|
279
|
+
description: 'Only this payout\u2019s transitions.',
|
|
280
|
+
},
|
|
281
|
+
type: {
|
|
282
|
+
type: 'string',
|
|
283
|
+
description:
|
|
284
|
+
'Comma-separated event types, e.g. payout.completed,payout.failed,payout.returned. Unknown values are a 400.',
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: 'list_approvals',
|
|
291
|
+
annotations: { readOnlyHint: true },
|
|
292
|
+
description:
|
|
293
|
+
'Payouts and batch runs waiting on the organization\u2019s human approvers. send_payout answers 202 with `approvalId` when a policy holds it; this is that queue. Approving is a dashboard action — there is no tool for it, by design.',
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
status: { type: 'string', description: 'pending, approved, rejected, expired, executing, executed, execution_failed, execution_unknown.' },
|
|
298
|
+
limit: { type: 'number', description: '1-100, default 50.' },
|
|
183
299
|
},
|
|
184
300
|
},
|
|
185
301
|
},
|
|
302
|
+
{
|
|
303
|
+
name: 'get_approval',
|
|
304
|
+
annotations: { readOnlyHint: true },
|
|
305
|
+
description:
|
|
306
|
+
'One approval by the `approvalId` a 202 returned. Once `status` is `executed`, `payoutId` is the payout it became.',
|
|
307
|
+
inputSchema: {
|
|
308
|
+
type: 'object',
|
|
309
|
+
properties: { approvalId: { type: 'string' } },
|
|
310
|
+
required: ['approvalId'],
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: 'list_audit_events',
|
|
315
|
+
annotations: { readOnlyHint: true },
|
|
316
|
+
description:
|
|
317
|
+
'Who did what, from where, with which credential: every audited mutation on the organization, newest first, refused attempts included. Rows carry the key prefix, actor, IP, requestId, outcome and errorType. Page with `cursor` = the `nextCursor` from the last page.',
|
|
318
|
+
inputSchema: {
|
|
319
|
+
type: 'object',
|
|
320
|
+
properties: {
|
|
321
|
+
cursor: { type: 'string', description: 'A `nextCursor` from a previous page. Digits only.' },
|
|
322
|
+
limit: { type: 'number', description: '1-100, default 50.' },
|
|
323
|
+
action: { type: 'string', description: 'e.g. payout.create, payout_batch.confirm, recipient.delete, api_key.rotate.' },
|
|
324
|
+
resourceId: { type: 'string', description: 'Everything done to one payout, batch, approval, beneficiary, key or endpoint.' },
|
|
325
|
+
apiKey: { type: 'string', description: 'A key prefix.' },
|
|
326
|
+
actorUserId: { type: 'string' },
|
|
327
|
+
createdAfter: { type: 'string', description: 'Inclusive, ISO-8601 with a timezone.' },
|
|
328
|
+
createdBefore: { type: 'string', description: 'Inclusive, ISO-8601 with a timezone.' },
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
name: 'get_policy',
|
|
334
|
+
annotations: { readOnlyHint: true },
|
|
335
|
+
description:
|
|
336
|
+
'What this organization is bound by, read live. Call it FIRST: payout caps in USD (null = no cap), the approval threshold and how many approvers a held payout needs, which features are on (mass_payouts, developer), rate limits per minute, idempotency windows, the currencies that require purposeOfPayment, and fees.payout (the pre-quote fee schedule; null = only priced inside a quote). Plan sends against it instead of discovering a cap from a 422 or an approval from a 202.',
|
|
337
|
+
inputSchema: { type: 'object', properties: {} },
|
|
338
|
+
},
|
|
186
339
|
{
|
|
187
340
|
name: 'get_balance',
|
|
188
341
|
annotations: { readOnlyHint: true },
|
|
@@ -190,6 +343,24 @@ const TOOLS = [
|
|
|
190
343
|
'The organization\u2019s available balance. Check this before sending: an underfunded payout is refused, and the refusal is a 400 rather than a queued payment.',
|
|
191
344
|
inputSchema: { type: 'object', properties: {} },
|
|
192
345
|
},
|
|
346
|
+
{
|
|
347
|
+
name: 'list_balance_transactions',
|
|
348
|
+
annotations: { readOnlyHint: true },
|
|
349
|
+
description:
|
|
350
|
+
'Every change to the balance, newest first, each with `balanceAfter`: funding, payouts, returns, holds and their release, adjustments. Page with `cursor` = the `nextCursor` from the last page. An empty page means no rows yet, not an error.',
|
|
351
|
+
inputSchema: {
|
|
352
|
+
type: 'object',
|
|
353
|
+
properties: {
|
|
354
|
+
cursor: { type: 'string', description: 'A `nextCursor` from a previous page. Digits only.' },
|
|
355
|
+
limit: { type: 'number', description: '1-100, default 100.' },
|
|
356
|
+
type: { type: 'string', description: 'Comma-separated: funding, payout, payout_return, hold, hold_release, adjustment.' },
|
|
357
|
+
orderId: { type: 'string', description: 'Everything that moved for one payout.' },
|
|
358
|
+
currency: { type: 'string' },
|
|
359
|
+
createdAfter: { type: 'string', description: 'Inclusive, ISO-8601 with a timezone.' },
|
|
360
|
+
createdBefore: { type: 'string', description: 'Inclusive, ISO-8601 with a timezone.' },
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
193
364
|
{
|
|
194
365
|
name: 'get_funding',
|
|
195
366
|
annotations: { readOnlyHint: true },
|
|
@@ -209,11 +380,23 @@ const TOOLS = [
|
|
|
209
380
|
inputSchema: {
|
|
210
381
|
type: 'object',
|
|
211
382
|
properties: {
|
|
212
|
-
amount: {
|
|
213
|
-
|
|
214
|
-
|
|
383
|
+
amount: {
|
|
384
|
+
type: 'string',
|
|
385
|
+
description: 'Decimal string, e.g. "200.00".',
|
|
386
|
+
},
|
|
387
|
+
destinationCurrency: {
|
|
388
|
+
type: 'string',
|
|
389
|
+
description: 'ISO code, e.g. MXN',
|
|
390
|
+
},
|
|
391
|
+
endUserId: {
|
|
392
|
+
type: 'string',
|
|
393
|
+
description: 'Your id for the person being paid.',
|
|
394
|
+
},
|
|
215
395
|
reference: { type: 'string' },
|
|
216
|
-
expiresInMinutes: {
|
|
396
|
+
expiresInMinutes: {
|
|
397
|
+
type: 'number',
|
|
398
|
+
description: '1-10080, default 60.',
|
|
399
|
+
},
|
|
217
400
|
},
|
|
218
401
|
required: ['amount', 'destinationCurrency', 'endUserId'],
|
|
219
402
|
},
|
|
@@ -227,10 +410,14 @@ const TOOLS = [
|
|
|
227
410
|
type: 'object',
|
|
228
411
|
properties: {
|
|
229
412
|
payoutId: { type: 'string' },
|
|
230
|
-
transactionHash: {
|
|
413
|
+
transactionHash: {
|
|
414
|
+
type: 'string',
|
|
415
|
+
description: '0x-prefixed 32-byte hex.',
|
|
416
|
+
},
|
|
231
417
|
confirm: {
|
|
232
418
|
type: 'boolean',
|
|
233
|
-
description:
|
|
419
|
+
description:
|
|
420
|
+
'Must be true. This commits funds you have already sent.',
|
|
234
421
|
},
|
|
235
422
|
},
|
|
236
423
|
required: ['payoutId', 'transactionHash', 'confirm'],
|
|
@@ -258,15 +445,52 @@ const TOOLS = [
|
|
|
258
445
|
async function dispatch(client, name, args) {
|
|
259
446
|
switch (name) {
|
|
260
447
|
case 'list_corridors':
|
|
261
|
-
return client.corridors();
|
|
448
|
+
return client.corridors(args.currency);
|
|
262
449
|
case 'get_requirements':
|
|
263
450
|
return client.requirements(args.currency);
|
|
264
451
|
case 'quote':
|
|
265
|
-
return client.quote({
|
|
452
|
+
return client.quote({
|
|
453
|
+
amount: args.amount,
|
|
454
|
+
to: args.to,
|
|
455
|
+
from: args.from,
|
|
456
|
+
});
|
|
266
457
|
case 'create_beneficiary':
|
|
267
458
|
return client.createBeneficiary(args);
|
|
268
459
|
case 'list_beneficiaries':
|
|
269
460
|
return client.listBeneficiaries({ endUserId: args.endUserId });
|
|
461
|
+
case 'get_beneficiary':
|
|
462
|
+
return client.getBeneficiary(args.recipientId);
|
|
463
|
+
case 'get_beneficiary_by_external_id':
|
|
464
|
+
return client.getBeneficiaryByExternalId(args.externalId);
|
|
465
|
+
case 'update_beneficiary':
|
|
466
|
+
// An empty patch is a round trip that changes nothing and reads back as
|
|
467
|
+
// success — which an agent will report as "done". Name the editable
|
|
468
|
+
// fields instead, since the one it probably wanted is not among them.
|
|
469
|
+
if (
|
|
470
|
+
!['name', 'email', 'phone', 'country', 'type'].some(
|
|
471
|
+
(f) => args[f] !== undefined,
|
|
472
|
+
)
|
|
473
|
+
) {
|
|
474
|
+
throw new Error(
|
|
475
|
+
'update_beneficiary needs at least one of name, email, phone, country, type. Bank details are not editable: register a new payment method and delete the old one.',
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
return client.updateBeneficiary(args.recipientId, {
|
|
479
|
+
name: args.name,
|
|
480
|
+
email: args.email,
|
|
481
|
+
phone: args.phone,
|
|
482
|
+
country: args.country,
|
|
483
|
+
type: args.type,
|
|
484
|
+
});
|
|
485
|
+
case 'delete_beneficiary_method':
|
|
486
|
+
if (args.confirm !== true) {
|
|
487
|
+
throw new Error(
|
|
488
|
+
'delete_beneficiary_method is irreversible and requires confirm:true. The account can only be re-registered, not restored — check with whoever owns this beneficiary first.',
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
return client.deleteBeneficiaryMethod(args.recipientId, args.methodId);
|
|
492
|
+
case 'list_payment_reasons':
|
|
493
|
+
return client.paymentReasons();
|
|
270
494
|
case 'send_payout':
|
|
271
495
|
if (args.confirm !== true) {
|
|
272
496
|
throw new Error(
|
|
@@ -276,6 +500,7 @@ async function dispatch(client, name, args) {
|
|
|
276
500
|
return client.payout({
|
|
277
501
|
amount: args.amount,
|
|
278
502
|
destinationAccountId: args.destinationAccountId,
|
|
503
|
+
amountLeg: args.amountLeg,
|
|
279
504
|
purposeOfPayment: args.purposeOfPayment,
|
|
280
505
|
reference: args.reference,
|
|
281
506
|
expectDestinationAmount: args.expectDestinationAmount,
|
|
@@ -295,9 +520,37 @@ async function dispatch(client, name, args) {
|
|
|
295
520
|
since: args.since,
|
|
296
521
|
limit: args.limit,
|
|
297
522
|
payoutId: args.payoutId,
|
|
523
|
+
type: args.type,
|
|
298
524
|
});
|
|
525
|
+
case 'list_approvals':
|
|
526
|
+
return client.listApprovals({ status: args.status, limit: args.limit });
|
|
527
|
+
case 'get_approval':
|
|
528
|
+
return client.getApproval(args.approvalId);
|
|
529
|
+
case 'list_audit_events':
|
|
530
|
+
return client.listAuditEvents({
|
|
531
|
+
cursor: args.cursor,
|
|
532
|
+
limit: args.limit,
|
|
533
|
+
action: args.action,
|
|
534
|
+
resourceId: args.resourceId,
|
|
535
|
+
apiKey: args.apiKey,
|
|
536
|
+
actorUserId: args.actorUserId,
|
|
537
|
+
createdAfter: args.createdAfter,
|
|
538
|
+
createdBefore: args.createdBefore,
|
|
539
|
+
});
|
|
540
|
+
case 'get_policy':
|
|
541
|
+
return client.getPolicy();
|
|
299
542
|
case 'get_balance':
|
|
300
543
|
return client.balance();
|
|
544
|
+
case 'list_balance_transactions':
|
|
545
|
+
return client.listBalanceTransactions({
|
|
546
|
+
cursor: args.cursor,
|
|
547
|
+
limit: args.limit,
|
|
548
|
+
type: args.type,
|
|
549
|
+
orderId: args.orderId,
|
|
550
|
+
currency: args.currency,
|
|
551
|
+
createdAfter: args.createdAfter,
|
|
552
|
+
createdBefore: args.createdBefore,
|
|
553
|
+
});
|
|
301
554
|
case 'get_funding':
|
|
302
555
|
return client.getFunding(args.payoutId);
|
|
303
556
|
case 'create_payout_link':
|
|
@@ -353,8 +606,7 @@ function createServer({ makeClient = () => new PayoutsClient(), write } = {}) {
|
|
|
353
606
|
// Echo the client's version when they name one: this server's
|
|
354
607
|
// surface is stable across the versions that matter, and refusing
|
|
355
608
|
// over a version string helps nobody.
|
|
356
|
-
protocolVersion:
|
|
357
|
-
(params && params.protocolVersion) || '2025-06-18',
|
|
609
|
+
protocolVersion: (params && params.protocolVersion) || '2025-06-18',
|
|
358
610
|
capabilities: { tools: {} },
|
|
359
611
|
serverInfo: SERVER,
|
|
360
612
|
});
|
|
@@ -371,9 +623,7 @@ function createServer({ makeClient = () => new PayoutsClient(), write } = {}) {
|
|
|
371
623
|
try {
|
|
372
624
|
const out = await dispatch(clientOnce(), name, args);
|
|
373
625
|
return reply({
|
|
374
|
-
content: [
|
|
375
|
-
{ type: 'text', text: JSON.stringify(out, null, 2) },
|
|
376
|
-
],
|
|
626
|
+
content: [{ type: 'text', text: JSON.stringify(out, null, 2) }],
|
|
377
627
|
});
|
|
378
628
|
} catch (err) {
|
|
379
629
|
// Tool errors belong in the result with isError, not as protocol
|