@sly_ai/mcp-server 0.1.0 → 0.1.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.
@@ -0,0 +1,1301 @@
1
+ import {
2
+ tools
3
+ } from "./chunk-YDZJAN2U.js";
4
+
5
+ // src/server-factory.ts
6
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
+ import {
8
+ CallToolRequestSchema,
9
+ ListToolsRequestSchema
10
+ } from "@modelcontextprotocol/sdk/types.js";
11
+ import { Sly } from "@sly_ai/sdk";
12
+ function createMcpServer(sly, apiUrl, apiKey, keys, urls) {
13
+ const ctx = {
14
+ sly,
15
+ apiUrl,
16
+ apiKey,
17
+ environment: apiKey.startsWith("pk_live_") ? "production" : "sandbox",
18
+ keys: keys || {},
19
+ urls: urls || {}
20
+ };
21
+ const server = new Server(
22
+ {
23
+ name: "@sly/mcp-server",
24
+ version: "0.1.0"
25
+ },
26
+ {
27
+ capabilities: {
28
+ tools: {}
29
+ },
30
+ instructions: [
31
+ "This is the Sly payment platform MCP server.",
32
+ `"Accounts" in this system are merchant or entity records within the tenant's own payment ledger \u2014 NOT user accounts on external services.`,
33
+ "Creating, updating, and listing accounts are standard data-management operations authorized by the tenant's API key.",
34
+ "These tools manage the tenant's own internal data. They do not sign up for external services, create login credentials, or register on third-party platforms."
35
+ ].join(" ")
36
+ }
37
+ );
38
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
39
+ return { tools };
40
+ });
41
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
42
+ const { name, arguments: args } = request.params;
43
+ try {
44
+ switch (name) {
45
+ case "get_settlement_quote": {
46
+ const quote = await ctx.sly.getSettlementQuote(args);
47
+ return {
48
+ content: [
49
+ {
50
+ type: "text",
51
+ text: JSON.stringify(quote, null, 2)
52
+ }
53
+ ]
54
+ };
55
+ }
56
+ case "create_settlement": {
57
+ const settlement = await ctx.sly.createSettlement(args);
58
+ return {
59
+ content: [
60
+ {
61
+ type: "text",
62
+ text: JSON.stringify(settlement, null, 2)
63
+ }
64
+ ]
65
+ };
66
+ }
67
+ case "get_settlement_status": {
68
+ const { settlementId } = args;
69
+ const settlement = await ctx.sly.getSettlement(settlementId);
70
+ return {
71
+ content: [
72
+ {
73
+ type: "text",
74
+ text: JSON.stringify(settlement, null, 2)
75
+ }
76
+ ]
77
+ };
78
+ }
79
+ // ======================================================================
80
+ // UCP Tools
81
+ // ======================================================================
82
+ case "ucp_discover": {
83
+ const { merchantUrl } = args;
84
+ const profile = await ctx.sly.ucp.discover(merchantUrl);
85
+ return {
86
+ content: [
87
+ {
88
+ type: "text",
89
+ text: JSON.stringify(profile, null, 2)
90
+ }
91
+ ]
92
+ };
93
+ }
94
+ case "ucp_create_checkout": {
95
+ const {
96
+ currency,
97
+ line_items,
98
+ buyer,
99
+ shipping_address,
100
+ payment_config,
101
+ payment_instruments,
102
+ checkout_type,
103
+ metadata,
104
+ agent_id
105
+ } = args;
106
+ const body = { currency, line_items, buyer, shipping_address, payment_config, metadata };
107
+ if (payment_instruments) body.payment_instruments = payment_instruments;
108
+ if (checkout_type) body.checkout_type = checkout_type;
109
+ if (agent_id) body.agent_id = agent_id;
110
+ const result = await ctx.sly.request("/v1/ucp/checkouts", {
111
+ method: "POST",
112
+ body: JSON.stringify(body)
113
+ });
114
+ return {
115
+ content: [
116
+ {
117
+ type: "text",
118
+ text: JSON.stringify(result, null, 2)
119
+ }
120
+ ]
121
+ };
122
+ }
123
+ case "ucp_get_checkout": {
124
+ const { checkoutId } = args;
125
+ const result = await ctx.sly.request(`/v1/ucp/checkouts/${checkoutId}`);
126
+ return {
127
+ content: [
128
+ {
129
+ type: "text",
130
+ text: JSON.stringify(result, null, 2)
131
+ }
132
+ ]
133
+ };
134
+ }
135
+ case "ucp_list_checkouts": {
136
+ const params = new URLSearchParams();
137
+ if (args && args.status) params.set("status", args.status);
138
+ if (args && args.agent_id) params.set("agent_id", args.agent_id);
139
+ if (args && args.page) params.set("page", String(args.page));
140
+ if (args && args.limit) params.set("limit", String(args.limit));
141
+ const query = params.toString();
142
+ const result = await ctx.sly.request(`/v1/ucp/checkouts${query ? `?${query}` : ""}`);
143
+ return {
144
+ content: [
145
+ {
146
+ type: "text",
147
+ text: JSON.stringify(result, null, 2)
148
+ }
149
+ ]
150
+ };
151
+ }
152
+ case "ucp_update_checkout": {
153
+ const { checkoutId, ...updates } = args;
154
+ const result = await ctx.sly.request(`/v1/ucp/checkouts/${checkoutId}`, {
155
+ method: "PUT",
156
+ body: JSON.stringify(updates)
157
+ });
158
+ return {
159
+ content: [
160
+ {
161
+ type: "text",
162
+ text: JSON.stringify(result, null, 2)
163
+ }
164
+ ]
165
+ };
166
+ }
167
+ case "ucp_complete_checkout": {
168
+ const { checkoutId } = args;
169
+ const result = await ctx.sly.request(`/v1/ucp/checkouts/${checkoutId}/complete`, {
170
+ method: "POST"
171
+ });
172
+ return {
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: JSON.stringify(result, null, 2)
177
+ }
178
+ ]
179
+ };
180
+ }
181
+ case "ucp_cancel_checkout": {
182
+ const { checkoutId } = args;
183
+ const result = await ctx.sly.request(`/v1/ucp/checkouts/${checkoutId}/cancel`, {
184
+ method: "POST"
185
+ });
186
+ return {
187
+ content: [
188
+ {
189
+ type: "text",
190
+ text: JSON.stringify(result, null, 2)
191
+ }
192
+ ]
193
+ };
194
+ }
195
+ case "ucp_add_payment_instrument": {
196
+ const { checkoutId, id: instrumentId, handler, type: instrumentType, last4, brand, metadata } = args;
197
+ const result = await ctx.sly.request(`/v1/ucp/checkouts/${checkoutId}/instruments`, {
198
+ method: "POST",
199
+ body: JSON.stringify({ id: instrumentId, handler, type: instrumentType, last4, brand, metadata })
200
+ });
201
+ return {
202
+ content: [
203
+ {
204
+ type: "text",
205
+ text: JSON.stringify(result, null, 2)
206
+ }
207
+ ]
208
+ };
209
+ }
210
+ case "ucp_batch_checkout": {
211
+ const { checkouts } = args;
212
+ const batchRes = await fetch(`${ctx.apiUrl}/v1/ucp/checkouts/batch`, {
213
+ method: "POST",
214
+ headers: {
215
+ "Authorization": `Bearer ${ctx.apiKey}`,
216
+ "Content-Type": "application/json",
217
+ "X-Environment": ctx.apiKey.startsWith("pk_live_") ? "live" : "test"
218
+ },
219
+ body: JSON.stringify({
220
+ checkouts,
221
+ auto_complete: true
222
+ })
223
+ });
224
+ const batchJson = await batchRes.json();
225
+ const batchData = batchJson?.data || batchJson;
226
+ return {
227
+ content: [
228
+ {
229
+ type: "text",
230
+ text: JSON.stringify(batchData, null, 2)
231
+ }
232
+ ]
233
+ };
234
+ }
235
+ case "ucp_batch_complete": {
236
+ const { checkout_ids, default_payment_instrument } = args;
237
+ const batchRes = await fetch(`${ctx.apiUrl}/v1/ucp/checkouts/batch-complete`, {
238
+ method: "POST",
239
+ headers: {
240
+ "Authorization": `Bearer ${ctx.apiKey}`,
241
+ "Content-Type": "application/json",
242
+ "X-Environment": ctx.apiKey.startsWith("pk_live_") ? "live" : "test"
243
+ },
244
+ body: JSON.stringify({ checkout_ids, default_payment_instrument })
245
+ });
246
+ const batchJson = await batchRes.json();
247
+ const batchData = batchJson?.data || batchJson;
248
+ return {
249
+ content: [
250
+ {
251
+ type: "text",
252
+ text: JSON.stringify(batchData, null, 2)
253
+ }
254
+ ]
255
+ };
256
+ }
257
+ case "ucp_list_orders": {
258
+ const params = new URLSearchParams();
259
+ if (args && args.status) params.set("status", args.status);
260
+ if (args && args.agent_id) params.set("agent_id", args.agent_id);
261
+ if (args && args.page) params.set("page", String(args.page));
262
+ if (args && args.limit) params.set("limit", String(args.limit));
263
+ const query = params.toString();
264
+ const result = await ctx.sly.request(`/v1/ucp/orders${query ? `?${query}` : ""}`);
265
+ return {
266
+ content: [
267
+ {
268
+ type: "text",
269
+ text: JSON.stringify(result, null, 2)
270
+ }
271
+ ]
272
+ };
273
+ }
274
+ case "ucp_get_order": {
275
+ const { orderId } = args;
276
+ const result = await ctx.sly.request(`/v1/ucp/orders/${orderId}`);
277
+ return {
278
+ content: [
279
+ {
280
+ type: "text",
281
+ text: JSON.stringify(result, null, 2)
282
+ }
283
+ ]
284
+ };
285
+ }
286
+ case "ucp_update_order_status": {
287
+ const { orderId, status } = args;
288
+ const result = await ctx.sly.request(`/v1/ucp/orders/${orderId}/status`, {
289
+ method: "PUT",
290
+ body: JSON.stringify({ status })
291
+ });
292
+ return {
293
+ content: [
294
+ {
295
+ type: "text",
296
+ text: JSON.stringify(result, null, 2)
297
+ }
298
+ ]
299
+ };
300
+ }
301
+ case "ucp_cancel_order": {
302
+ const { orderId, reason } = args;
303
+ const result = await ctx.sly.request(`/v1/ucp/orders/${orderId}/cancel`, {
304
+ method: "POST",
305
+ body: JSON.stringify({ reason })
306
+ });
307
+ return {
308
+ content: [
309
+ {
310
+ type: "text",
311
+ text: JSON.stringify(result, null, 2)
312
+ }
313
+ ]
314
+ };
315
+ }
316
+ case "ucp_add_fulfillment_event": {
317
+ const { orderId, type: eventType, description, tracking_number, carrier } = args;
318
+ const result = await ctx.sly.request(`/v1/ucp/orders/${orderId}/events`, {
319
+ method: "POST",
320
+ body: JSON.stringify({ type: eventType, description, tracking_number, carrier })
321
+ });
322
+ return {
323
+ content: [
324
+ {
325
+ type: "text",
326
+ text: JSON.stringify(result, null, 2)
327
+ }
328
+ ]
329
+ };
330
+ }
331
+ // ======================================================================
332
+ // Merchant Catalog Tools
333
+ // ======================================================================
334
+ case "list_merchants": {
335
+ const params = new URLSearchParams();
336
+ if (args && args.type) params.set("type", args.type);
337
+ if (args && args.country) params.set("country", args.country);
338
+ if (args && args.search) params.set("search", args.search);
339
+ if (args && args.limit) params.set("limit", String(args.limit));
340
+ const query = params.toString();
341
+ const result = await ctx.sly.request(`/v1/ucp/merchants${query ? `?${query}` : ""}`);
342
+ return {
343
+ content: [
344
+ {
345
+ type: "text",
346
+ text: JSON.stringify(result, null, 2)
347
+ }
348
+ ]
349
+ };
350
+ }
351
+ case "get_merchant": {
352
+ const { merchantId } = args;
353
+ const result = await ctx.sly.request(`/v1/ucp/merchants/${merchantId}`);
354
+ return {
355
+ content: [
356
+ {
357
+ type: "text",
358
+ text: JSON.stringify(result, null, 2)
359
+ }
360
+ ]
361
+ };
362
+ }
363
+ // ======================================================================
364
+ // Agent Management Tools
365
+ // ======================================================================
366
+ case "list_accounts": {
367
+ const params = new URLSearchParams();
368
+ if (args && args.type) params.set("type", args.type);
369
+ if (args && args.status) params.set("status", args.status);
370
+ const query = params.toString();
371
+ const result = await ctx.sly.request(`/v1/accounts${query ? `?${query}` : ""}`);
372
+ return {
373
+ content: [
374
+ {
375
+ type: "text",
376
+ text: JSON.stringify(result, null, 2)
377
+ }
378
+ ]
379
+ };
380
+ }
381
+ case "create_account": {
382
+ const { type, name: accountName, email, metadata } = args;
383
+ const body = { type, name: accountName };
384
+ if (email) body.email = email;
385
+ if (metadata) body.metadata = metadata;
386
+ const result = await ctx.sly.request("/v1/accounts", {
387
+ method: "POST",
388
+ body: JSON.stringify(body)
389
+ });
390
+ return {
391
+ content: [
392
+ {
393
+ type: "text",
394
+ text: JSON.stringify(result, null, 2)
395
+ }
396
+ ]
397
+ };
398
+ }
399
+ case "update_account": {
400
+ const {
401
+ accountId,
402
+ name: accountName,
403
+ email,
404
+ metadata
405
+ } = args;
406
+ const body = {};
407
+ if (accountName !== void 0) body.name = accountName;
408
+ if (email !== void 0) body.email = email;
409
+ if (metadata !== void 0) body.metadata = metadata;
410
+ const result = await ctx.sly.request(`/v1/accounts/${accountId}`, {
411
+ method: "PATCH",
412
+ body: JSON.stringify(body)
413
+ });
414
+ return {
415
+ content: [
416
+ {
417
+ type: "text",
418
+ text: JSON.stringify(result, null, 2)
419
+ }
420
+ ]
421
+ };
422
+ }
423
+ case "get_tenant_info": {
424
+ const result = await ctx.sly.request("/v1/context/whoami");
425
+ return {
426
+ content: [
427
+ {
428
+ type: "text",
429
+ text: JSON.stringify(result, null, 2)
430
+ }
431
+ ]
432
+ };
433
+ }
434
+ case "create_agent": {
435
+ const { accountId, name: agentName, description } = args;
436
+ const result = await ctx.sly.request("/v1/agents", {
437
+ method: "POST",
438
+ body: JSON.stringify({
439
+ accountId,
440
+ name: agentName,
441
+ description
442
+ })
443
+ });
444
+ return {
445
+ content: [
446
+ {
447
+ type: "text",
448
+ text: JSON.stringify(result, null, 2)
449
+ }
450
+ ]
451
+ };
452
+ }
453
+ case "verify_agent": {
454
+ const { agentId, tier } = args;
455
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/verify`, {
456
+ method: "POST",
457
+ body: JSON.stringify({ tier })
458
+ });
459
+ return {
460
+ content: [
461
+ {
462
+ type: "text",
463
+ text: JSON.stringify(result, null, 2)
464
+ }
465
+ ]
466
+ };
467
+ }
468
+ case "get_agent": {
469
+ const { agentId } = args;
470
+ const result = await ctx.sly.request(`/v1/agents/${agentId}`);
471
+ return {
472
+ content: [
473
+ {
474
+ type: "text",
475
+ text: JSON.stringify(result, null, 2)
476
+ }
477
+ ]
478
+ };
479
+ }
480
+ case "get_agent_limits": {
481
+ const { agentId } = args;
482
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/limits`);
483
+ return {
484
+ content: [
485
+ {
486
+ type: "text",
487
+ text: JSON.stringify(result, null, 2)
488
+ }
489
+ ]
490
+ };
491
+ }
492
+ case "get_agent_transactions": {
493
+ const { agentId, limit: txLimit, offset: txOffset, from, to } = args;
494
+ const params = new URLSearchParams();
495
+ if (txLimit) params.set("limit", String(txLimit));
496
+ if (txOffset) params.set("offset", String(txOffset));
497
+ if (from) params.set("from", from);
498
+ if (to) params.set("to", to);
499
+ const query = params.toString();
500
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/transactions${query ? `?${query}` : ""}`);
501
+ return {
502
+ content: [
503
+ {
504
+ type: "text",
505
+ text: JSON.stringify(result, null, 2)
506
+ }
507
+ ]
508
+ };
509
+ }
510
+ case "delete_agent": {
511
+ const { agentId } = args;
512
+ const result = await ctx.sly.request(`/v1/agents/${agentId}`, {
513
+ method: "DELETE"
514
+ });
515
+ return {
516
+ content: [
517
+ {
518
+ type: "text",
519
+ text: JSON.stringify(result, null, 2)
520
+ }
521
+ ]
522
+ };
523
+ }
524
+ // ======================================================================
525
+ // AP2 Mandate Tools
526
+ // ======================================================================
527
+ case "ap2_cancel_mandate": {
528
+ const { mandateId } = args;
529
+ const result = await ctx.sly.request(`/v1/ap2/mandates/${mandateId}/cancel`, {
530
+ method: "PATCH",
531
+ body: JSON.stringify({})
532
+ });
533
+ return {
534
+ content: [
535
+ {
536
+ type: "text",
537
+ text: JSON.stringify(result, null, 2)
538
+ }
539
+ ]
540
+ };
541
+ }
542
+ case "ap2_create_mandate": {
543
+ const {
544
+ mandate_id,
545
+ agent_id,
546
+ account_id,
547
+ authorized_amount,
548
+ currency,
549
+ mandate_type,
550
+ description,
551
+ expires_at,
552
+ metadata,
553
+ mandate_data
554
+ } = args;
555
+ const result = await ctx.sly.ap2.createMandate({
556
+ mandate_id,
557
+ agent_id,
558
+ account_id,
559
+ authorized_amount,
560
+ currency,
561
+ mandate_type: mandate_type || "payment",
562
+ mandate_data: mandate_data || (description ? { description } : void 0),
563
+ metadata,
564
+ expires_at
565
+ });
566
+ return {
567
+ content: [
568
+ {
569
+ type: "text",
570
+ text: JSON.stringify(result, null, 2)
571
+ }
572
+ ]
573
+ };
574
+ }
575
+ case "ap2_get_mandate": {
576
+ const { mandateId } = args;
577
+ const result = await ctx.sly.ap2.getMandate(mandateId);
578
+ return {
579
+ content: [
580
+ {
581
+ type: "text",
582
+ text: JSON.stringify(result, null, 2)
583
+ }
584
+ ]
585
+ };
586
+ }
587
+ case "ap2_execute_mandate": {
588
+ const { mandateId, amount, currency, description, order_ids } = args;
589
+ const result = await ctx.sly.ap2.executeMandate(mandateId, {
590
+ amount,
591
+ currency,
592
+ description,
593
+ order_ids
594
+ });
595
+ return {
596
+ content: [
597
+ {
598
+ type: "text",
599
+ text: JSON.stringify(result, null, 2)
600
+ }
601
+ ]
602
+ };
603
+ }
604
+ case "ap2_list_mandates": {
605
+ const { status, agent_id, account_id, limit } = args || {};
606
+ const result = await ctx.sly.ap2.listMandates({
607
+ status,
608
+ agent_id,
609
+ account_id,
610
+ limit
611
+ });
612
+ return {
613
+ content: [
614
+ {
615
+ type: "text",
616
+ text: JSON.stringify(result, null, 2)
617
+ }
618
+ ]
619
+ };
620
+ }
621
+ case "ap2_update_mandate": {
622
+ const { mandateId, ...updateFields } = args;
623
+ const result = await ctx.sly.request(`/v1/ap2/mandates/${mandateId}`, {
624
+ method: "PATCH",
625
+ body: JSON.stringify(updateFields)
626
+ });
627
+ return {
628
+ content: [
629
+ {
630
+ type: "text",
631
+ text: JSON.stringify(result, null, 2)
632
+ }
633
+ ]
634
+ };
635
+ }
636
+ // ======================================================================
637
+ // ACP Checkout Tools
638
+ // ======================================================================
639
+ case "acp_create_checkout": {
640
+ const {
641
+ checkout_id,
642
+ agent_id,
643
+ account_id,
644
+ merchant_id,
645
+ items,
646
+ tax_amount,
647
+ shipping_amount,
648
+ payment_method,
649
+ checkout_data
650
+ } = args;
651
+ const result = await ctx.sly.acp.createCheckout({
652
+ checkout_id,
653
+ agent_id,
654
+ account_id: account_id || "",
655
+ merchant_id,
656
+ items,
657
+ tax_amount,
658
+ shipping_amount,
659
+ payment_method,
660
+ checkout_data
661
+ });
662
+ return {
663
+ content: [
664
+ {
665
+ type: "text",
666
+ text: JSON.stringify(result, null, 2)
667
+ }
668
+ ]
669
+ };
670
+ }
671
+ case "acp_get_checkout": {
672
+ const { checkoutId } = args;
673
+ const result = await ctx.sly.acp.getCheckout(checkoutId);
674
+ return {
675
+ content: [
676
+ {
677
+ type: "text",
678
+ text: JSON.stringify(result, null, 2)
679
+ }
680
+ ]
681
+ };
682
+ }
683
+ case "acp_complete_checkout": {
684
+ const { checkoutId, shared_payment_token, payment_method } = args;
685
+ const token = shared_payment_token || `spt_test_${Date.now()}`;
686
+ const result = await ctx.sly.acp.completeCheckout(checkoutId, {
687
+ shared_payment_token: token,
688
+ payment_method
689
+ });
690
+ return {
691
+ content: [
692
+ {
693
+ type: "text",
694
+ text: JSON.stringify(result, null, 2)
695
+ }
696
+ ]
697
+ };
698
+ }
699
+ case "acp_list_checkouts": {
700
+ const { status, agent_id, merchant_id, limit } = args || {};
701
+ const result = await ctx.sly.acp.listCheckouts({
702
+ status,
703
+ agent_id,
704
+ merchant_id,
705
+ limit
706
+ });
707
+ return {
708
+ content: [
709
+ {
710
+ type: "text",
711
+ text: JSON.stringify(result, null, 2)
712
+ }
713
+ ]
714
+ };
715
+ }
716
+ case "acp_batch_checkout": {
717
+ const { checkouts } = args;
718
+ const batchRes = await fetch(`${ctx.apiUrl}/v1/acp/checkouts/batch`, {
719
+ method: "POST",
720
+ headers: {
721
+ "Authorization": `Bearer ${ctx.apiKey}`,
722
+ "Content-Type": "application/json",
723
+ "X-Environment": ctx.apiKey.startsWith("pk_live_") ? "live" : "test"
724
+ },
725
+ body: JSON.stringify({ checkouts })
726
+ });
727
+ const batchJson = await batchRes.json();
728
+ const batchData = batchJson?.data || batchJson;
729
+ return {
730
+ content: [
731
+ {
732
+ type: "text",
733
+ text: JSON.stringify(batchData, null, 2)
734
+ }
735
+ ]
736
+ };
737
+ }
738
+ // ======================================================================
739
+ // Wallet Management Tools
740
+ // ======================================================================
741
+ case "list_wallets": {
742
+ const params = new URLSearchParams();
743
+ if (args && args.owner_account_id) params.set("owner_account_id", args.owner_account_id);
744
+ if (args && args.managed_by_agent_id) params.set("managed_by_agent_id", args.managed_by_agent_id);
745
+ if (args && args.status) params.set("status", args.status);
746
+ if (args && args.page) params.set("page", String(args.page));
747
+ if (args && args.limit) params.set("limit", String(args.limit));
748
+ const query = params.toString();
749
+ const result = await ctx.sly.request(`/v1/wallets${query ? `?${query}` : ""}`);
750
+ return {
751
+ content: [
752
+ {
753
+ type: "text",
754
+ text: JSON.stringify(result, null, 2)
755
+ }
756
+ ]
757
+ };
758
+ }
759
+ case "create_wallet": {
760
+ const {
761
+ accountId,
762
+ name: walletName,
763
+ currency,
764
+ walletType,
765
+ blockchain,
766
+ initialBalance,
767
+ managedByAgentId,
768
+ purpose
769
+ } = args;
770
+ const result = await ctx.sly.request("/v1/wallets", {
771
+ method: "POST",
772
+ body: JSON.stringify({
773
+ accountId,
774
+ name: walletName,
775
+ currency,
776
+ walletType,
777
+ blockchain,
778
+ initialBalance,
779
+ managedByAgentId,
780
+ purpose
781
+ })
782
+ });
783
+ return {
784
+ content: [
785
+ {
786
+ type: "text",
787
+ text: JSON.stringify(result, null, 2)
788
+ }
789
+ ]
790
+ };
791
+ }
792
+ case "get_wallet": {
793
+ const { walletId } = args;
794
+ const result = await ctx.sly.request(`/v1/wallets/${walletId}`);
795
+ return {
796
+ content: [
797
+ {
798
+ type: "text",
799
+ text: JSON.stringify(result, null, 2)
800
+ }
801
+ ]
802
+ };
803
+ }
804
+ case "get_wallet_balance": {
805
+ const { walletId } = args;
806
+ const result = await ctx.sly.request(`/v1/wallets/${walletId}/balance`);
807
+ return {
808
+ content: [
809
+ {
810
+ type: "text",
811
+ text: JSON.stringify(result, null, 2)
812
+ }
813
+ ]
814
+ };
815
+ }
816
+ case "wallet_deposit": {
817
+ const { walletId, amount, fromAccountId, reference } = args;
818
+ const result = await ctx.sly.request(`/v1/wallets/${walletId}/deposit`, {
819
+ method: "POST",
820
+ body: JSON.stringify({ amount, fromAccountId, reference })
821
+ });
822
+ return {
823
+ content: [
824
+ {
825
+ type: "text",
826
+ text: JSON.stringify(result, null, 2)
827
+ }
828
+ ]
829
+ };
830
+ }
831
+ case "wallet_withdraw": {
832
+ const { walletId, amount, destinationAccountId, reference } = args;
833
+ const result = await ctx.sly.request(`/v1/wallets/${walletId}/withdraw`, {
834
+ method: "POST",
835
+ body: JSON.stringify({ amount, destinationAccountId, reference })
836
+ });
837
+ return {
838
+ content: [
839
+ {
840
+ type: "text",
841
+ text: JSON.stringify(result, null, 2)
842
+ }
843
+ ]
844
+ };
845
+ }
846
+ case "wallet_test_fund": {
847
+ const { walletId, amount, currency, reference } = args;
848
+ const result = await ctx.sly.request(`/v1/wallets/${walletId}/test-fund`, {
849
+ method: "POST",
850
+ body: JSON.stringify({ amount, currency, reference })
851
+ });
852
+ return {
853
+ content: [
854
+ {
855
+ type: "text",
856
+ text: JSON.stringify(result, null, 2)
857
+ }
858
+ ]
859
+ };
860
+ }
861
+ // ======================================================================
862
+ // Agent Wallet Policy Tools (Epic 18)
863
+ // ======================================================================
864
+ case "agent_wallet_evaluate_policy": {
865
+ const { agentId, amount, currency, action_type, contract_type, counterparty_agent_id, counterparty_address } = args;
866
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/policy/evaluate`, {
867
+ method: "POST",
868
+ body: JSON.stringify({
869
+ amount,
870
+ currency: currency || "USDC",
871
+ action_type: action_type || "negotiation_check",
872
+ contract_type,
873
+ counterparty_agent_id,
874
+ counterparty_address
875
+ })
876
+ });
877
+ return {
878
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
879
+ };
880
+ }
881
+ case "agent_wallet_get_exposures": {
882
+ const { agentId } = args;
883
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/exposures`);
884
+ return {
885
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
886
+ };
887
+ }
888
+ case "agent_wallet_get_evaluations": {
889
+ const { agentId, page, limit } = args;
890
+ const params = new URLSearchParams();
891
+ if (page) params.set("page", String(page));
892
+ if (limit) params.set("limit", String(limit));
893
+ const qs = params.toString();
894
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/policy/evaluations${qs ? `?${qs}` : ""}`);
895
+ return {
896
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
897
+ };
898
+ }
899
+ case "agent_wallet_get": {
900
+ const { agentId } = args;
901
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet`);
902
+ return {
903
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
904
+ };
905
+ }
906
+ case "agent_wallet_freeze": {
907
+ const { agentId } = args;
908
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/freeze`, {
909
+ method: "POST"
910
+ });
911
+ return {
912
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
913
+ };
914
+ }
915
+ case "agent_wallet_unfreeze": {
916
+ const { agentId } = args;
917
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/unfreeze`, {
918
+ method: "POST"
919
+ });
920
+ return {
921
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
922
+ };
923
+ }
924
+ case "agent_wallet_set_policy": {
925
+ const { agentId, ...policyFields } = args;
926
+ const result = await ctx.sly.request(`/v1/agents/${agentId}/wallet/policy`, {
927
+ method: "PUT",
928
+ body: JSON.stringify(policyFields)
929
+ });
930
+ return {
931
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
932
+ };
933
+ }
934
+ // ======================================================================
935
+ // x402 Micropayment Tools
936
+ // ======================================================================
937
+ case "x402_create_endpoint": {
938
+ const {
939
+ name: endpointName,
940
+ path,
941
+ method,
942
+ description,
943
+ accountId,
944
+ basePrice,
945
+ currency,
946
+ volumeDiscounts,
947
+ webhookUrl
948
+ } = args;
949
+ const result = await ctx.sly.request("/v1/x402/endpoints", {
950
+ method: "POST",
951
+ body: JSON.stringify({
952
+ name: endpointName,
953
+ path,
954
+ method,
955
+ description,
956
+ accountId,
957
+ basePrice,
958
+ currency,
959
+ volumeDiscounts,
960
+ webhookUrl
961
+ })
962
+ });
963
+ return {
964
+ content: [
965
+ {
966
+ type: "text",
967
+ text: JSON.stringify(result, null, 2)
968
+ }
969
+ ]
970
+ };
971
+ }
972
+ case "x402_list_endpoints": {
973
+ const params = new URLSearchParams();
974
+ if (args && args.status) params.set("status", args.status);
975
+ if (args && args.account_id) params.set("account_id", args.account_id);
976
+ if (args && args.page) params.set("page", String(args.page));
977
+ if (args && args.limit) params.set("limit", String(args.limit));
978
+ const query = params.toString();
979
+ const result = await ctx.sly.request(`/v1/x402/endpoints${query ? `?${query}` : ""}`);
980
+ return {
981
+ content: [
982
+ {
983
+ type: "text",
984
+ text: JSON.stringify(result, null, 2)
985
+ }
986
+ ]
987
+ };
988
+ }
989
+ case "x402_get_endpoint": {
990
+ const { endpointId } = args;
991
+ const result = await ctx.sly.request(`/v1/x402/endpoints/${endpointId}`);
992
+ return {
993
+ content: [
994
+ {
995
+ type: "text",
996
+ text: JSON.stringify(result, null, 2)
997
+ }
998
+ ]
999
+ };
1000
+ }
1001
+ case "x402_pay": {
1002
+ const { endpointId, walletId, amount, currency, method: httpMethod, path: endpointPath } = args;
1003
+ const requestId = crypto.randomUUID();
1004
+ const result = await ctx.sly.request("/v1/x402/pay", {
1005
+ method: "POST",
1006
+ body: JSON.stringify({
1007
+ endpointId,
1008
+ requestId,
1009
+ amount,
1010
+ currency,
1011
+ walletId,
1012
+ method: httpMethod,
1013
+ path: endpointPath,
1014
+ timestamp: Math.floor(Date.now() / 1e3)
1015
+ })
1016
+ });
1017
+ return {
1018
+ content: [
1019
+ {
1020
+ type: "text",
1021
+ text: JSON.stringify(result, null, 2)
1022
+ }
1023
+ ]
1024
+ };
1025
+ }
1026
+ case "x402_verify": {
1027
+ const { jwt, requestId, transferId } = args;
1028
+ const result = await ctx.sly.request("/v1/x402/verify", {
1029
+ method: "POST",
1030
+ body: JSON.stringify({ jwt, requestId, transferId })
1031
+ });
1032
+ return {
1033
+ content: [
1034
+ {
1035
+ type: "text",
1036
+ text: JSON.stringify(result, null, 2)
1037
+ }
1038
+ ]
1039
+ };
1040
+ }
1041
+ // ====================================================================
1042
+ // A2A Tools
1043
+ // ====================================================================
1044
+ case "a2a_discover_agent": {
1045
+ const { url } = args;
1046
+ const result = await ctx.sly.request("/v1/a2a/discover", {
1047
+ method: "POST",
1048
+ body: JSON.stringify({ url })
1049
+ });
1050
+ return {
1051
+ content: [
1052
+ {
1053
+ type: "text",
1054
+ text: JSON.stringify(result, null, 2)
1055
+ }
1056
+ ]
1057
+ };
1058
+ }
1059
+ case "a2a_send_task": {
1060
+ const { agent_id, remote_url, message, context_id } = args;
1061
+ const result = await ctx.sly.request("/v1/a2a/tasks", {
1062
+ method: "POST",
1063
+ body: JSON.stringify({
1064
+ agent_id,
1065
+ remote_url,
1066
+ message: {
1067
+ parts: [{ text: message }]
1068
+ },
1069
+ context_id
1070
+ })
1071
+ });
1072
+ return {
1073
+ content: [
1074
+ {
1075
+ type: "text",
1076
+ text: JSON.stringify(result, null, 2)
1077
+ }
1078
+ ]
1079
+ };
1080
+ }
1081
+ case "a2a_get_task": {
1082
+ const { task_id } = args;
1083
+ const result = await ctx.sly.request(`/v1/a2a/tasks/${task_id}`, {
1084
+ method: "GET"
1085
+ });
1086
+ return {
1087
+ content: [
1088
+ {
1089
+ type: "text",
1090
+ text: JSON.stringify(result, null, 2)
1091
+ }
1092
+ ]
1093
+ };
1094
+ }
1095
+ case "a2a_list_tasks": {
1096
+ const { agent_id, state, direction, limit, page } = args;
1097
+ const params = new URLSearchParams();
1098
+ if (agent_id) params.set("agent_id", agent_id);
1099
+ if (state) params.set("state", state);
1100
+ if (direction) params.set("direction", direction);
1101
+ if (limit) params.set("limit", String(limit));
1102
+ if (page) params.set("page", String(page));
1103
+ const query = params.toString();
1104
+ const result = await ctx.sly.request(`/v1/a2a/tasks${query ? `?${query}` : ""}`, {
1105
+ method: "GET"
1106
+ });
1107
+ return {
1108
+ content: [
1109
+ {
1110
+ type: "text",
1111
+ text: JSON.stringify(result, null, 2)
1112
+ }
1113
+ ]
1114
+ };
1115
+ }
1116
+ // ======================================================================
1117
+ // MPP Tools
1118
+ // ======================================================================
1119
+ case "mpp_pay": {
1120
+ const { service_url, amount, currency, intent, agent_id, wallet_id } = args;
1121
+ const result = await ctx.sly.request("/v1/mpp/pay", {
1122
+ method: "POST",
1123
+ body: JSON.stringify({ service_url, amount, currency, intent, agent_id, wallet_id })
1124
+ });
1125
+ return {
1126
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1127
+ };
1128
+ }
1129
+ case "mpp_open_session": {
1130
+ const { service_url, deposit_amount, max_budget, agent_id, wallet_id, currency } = args;
1131
+ const result = await ctx.sly.request("/v1/mpp/sessions", {
1132
+ method: "POST",
1133
+ body: JSON.stringify({ service_url, deposit_amount, max_budget, agent_id, wallet_id, currency })
1134
+ });
1135
+ return {
1136
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1137
+ };
1138
+ }
1139
+ case "mpp_get_session": {
1140
+ const { session_id } = args;
1141
+ const result = await ctx.sly.request(`/v1/mpp/sessions/${session_id}`);
1142
+ return {
1143
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1144
+ };
1145
+ }
1146
+ case "mpp_list_sessions": {
1147
+ const { agent_id, status, limit, offset } = args;
1148
+ const params = new URLSearchParams();
1149
+ if (agent_id) params.set("agent_id", agent_id);
1150
+ if (status) params.set("status", status);
1151
+ if (limit) params.set("limit", String(limit));
1152
+ if (offset) params.set("offset", String(offset));
1153
+ const query = params.toString();
1154
+ const result = await ctx.sly.request(`/v1/mpp/sessions${query ? `?${query}` : ""}`);
1155
+ return {
1156
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1157
+ };
1158
+ }
1159
+ case "mpp_close_session": {
1160
+ const { session_id } = args;
1161
+ const result = await ctx.sly.request(`/v1/mpp/sessions/${session_id}/close`, {
1162
+ method: "POST"
1163
+ });
1164
+ return {
1165
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1166
+ };
1167
+ }
1168
+ case "mpp_list_transfers": {
1169
+ const { service_url, session_id, limit, offset } = args;
1170
+ const params = new URLSearchParams();
1171
+ if (service_url) params.set("service_url", service_url);
1172
+ if (session_id) params.set("session_id", session_id);
1173
+ if (limit) params.set("limit", String(limit));
1174
+ if (offset) params.set("offset", String(offset));
1175
+ const query = params.toString();
1176
+ const result = await ctx.sly.request(`/v1/mpp/transfers${query ? `?${query}` : ""}`);
1177
+ return {
1178
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1179
+ };
1180
+ }
1181
+ case "mpp_verify_receipt": {
1182
+ const { receipt_id } = args;
1183
+ const result = await ctx.sly.request("/v1/mpp/receipts/verify", {
1184
+ method: "POST",
1185
+ body: JSON.stringify({ receipt_id })
1186
+ });
1187
+ return {
1188
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1189
+ };
1190
+ }
1191
+ // ====================================================================
1192
+ // Support Tools (Intercom Fin)
1193
+ // ====================================================================
1194
+ case "explain_rejection": {
1195
+ const { error_code, transaction_id, agent_id } = args;
1196
+ const params = new URLSearchParams();
1197
+ if (error_code) params.set("error_code", error_code);
1198
+ if (transaction_id) params.set("transaction_id", transaction_id);
1199
+ if (agent_id) params.set("agent_id", agent_id);
1200
+ const query = params.toString();
1201
+ const result = await ctx.sly.request(`/v1/support/explain-rejection${query ? `?${query}` : ""}`, {
1202
+ method: "GET"
1203
+ });
1204
+ return {
1205
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1206
+ };
1207
+ }
1208
+ case "request_limit_increase": {
1209
+ const { agent_id, limit_type, requested_amount, reason, duration } = args;
1210
+ const body = { agent_id, limit_type, requested_amount, reason };
1211
+ if (duration) body.duration = duration;
1212
+ const result = await ctx.sly.request("/v1/support/limit-requests", {
1213
+ method: "POST",
1214
+ body: JSON.stringify(body)
1215
+ });
1216
+ return {
1217
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1218
+ };
1219
+ }
1220
+ case "open_dispute": {
1221
+ const { transaction_id, reason, description, requested_resolution } = args;
1222
+ const body = {
1223
+ transferId: transaction_id,
1224
+ reason,
1225
+ description
1226
+ };
1227
+ if (requested_resolution) body.requestedResolution = requested_resolution;
1228
+ const result = await ctx.sly.request("/v1/disputes", {
1229
+ method: "POST",
1230
+ body: JSON.stringify(body)
1231
+ });
1232
+ return {
1233
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1234
+ };
1235
+ }
1236
+ case "escalate_to_human": {
1237
+ const { agent_id, reason, summary, priority } = args;
1238
+ const body = { reason, summary };
1239
+ if (agent_id) body.agent_id = agent_id;
1240
+ if (priority) body.priority = priority;
1241
+ const result = await ctx.sly.request("/v1/support/escalations", {
1242
+ method: "POST",
1243
+ body: JSON.stringify(body)
1244
+ });
1245
+ return {
1246
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
1247
+ };
1248
+ }
1249
+ // ======================================================================
1250
+ // Environment Management Tools
1251
+ // ======================================================================
1252
+ case "get_environment": {
1253
+ const masked = ctx.apiKey.slice(0, 12) + "***";
1254
+ return {
1255
+ content: [{
1256
+ type: "text",
1257
+ text: JSON.stringify({ environment: ctx.environment, apiKeyPrefix: masked, availableEnvironments: Object.keys(ctx.keys) }, null, 2)
1258
+ }]
1259
+ };
1260
+ }
1261
+ case "switch_environment": {
1262
+ const { environment: targetEnv } = args;
1263
+ if (targetEnv === ctx.environment) {
1264
+ return { content: [{ type: "text", text: JSON.stringify({ message: `Already in ${targetEnv} environment`, environment: ctx.environment, apiKeyPrefix: ctx.apiKey.slice(0, 12) + "***" }, null, 2) }] };
1265
+ }
1266
+ const targetKey = ctx.keys[targetEnv];
1267
+ if (!targetKey) {
1268
+ const hint = targetEnv === "production" ? "Set SLY_API_KEY_LIVE in your MCP server config (.mcp.json)" : "Set SLY_API_KEY in your MCP server config (.mcp.json)";
1269
+ return { content: [{ type: "text", text: `Error: No API key configured for "${targetEnv}" environment. ${hint}` }], isError: true };
1270
+ }
1271
+ const targetUrl = ctx.urls[targetEnv] || ctx.apiUrl;
1272
+ ctx.sly = new Sly({ apiKey: targetKey, apiUrl: targetUrl });
1273
+ ctx.apiKey = targetKey;
1274
+ ctx.apiUrl = targetUrl;
1275
+ ctx.environment = targetEnv;
1276
+ return { content: [{ type: "text", text: JSON.stringify({ message: `Switched to ${targetEnv} environment`, environment: ctx.environment, apiKeyPrefix: ctx.apiKey.slice(0, 12) + "***" }, null, 2) }] };
1277
+ }
1278
+ default:
1279
+ throw new Error(`Unknown tool: ${name}`);
1280
+ }
1281
+ } catch (error) {
1282
+ const details = error.details || error.errors || "";
1283
+ const detailsStr = details ? `
1284
+ Details: ${JSON.stringify(details, null, 2)}` : "";
1285
+ return {
1286
+ content: [
1287
+ {
1288
+ type: "text",
1289
+ text: `Error: ${error.message}${detailsStr}`
1290
+ }
1291
+ ],
1292
+ isError: true
1293
+ };
1294
+ }
1295
+ });
1296
+ return server;
1297
+ }
1298
+
1299
+ export {
1300
+ createMcpServer
1301
+ };
package/dist/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createMcpServer
4
- } from "./chunk-OHTORKDB.js";
4
+ } from "./chunk-2I7VXMKG.js";
5
5
  import {
6
6
  tools
7
7
  } from "./chunk-YDZJAN2U.js";
8
8
 
9
9
  // src/index.ts
10
10
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
- import { Sly, getEnvironmentConfig } from "@sly/sdk";
11
+ import { Sly, getEnvironmentConfig } from "@sly_ai/sdk";
12
12
  var SLY_API_KEY = process.env.SLY_API_KEY;
13
13
  var SLY_API_KEY_LIVE = process.env.SLY_API_KEY_LIVE;
14
14
  var SLY_ENVIRONMENT = process.env.SLY_ENVIRONMENT || "sandbox";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createMcpServer
3
- } from "./chunk-OHTORKDB.js";
3
+ } from "./chunk-2I7VXMKG.js";
4
4
  import "./chunk-YDZJAN2U.js";
5
5
  export {
6
6
  createMcpServer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sly_ai/mcp-server",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Model Context Protocol (MCP) server for Sly - enables Claude Desktop integration and remote HTTP access",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "start": "node dist/index.js"
32
32
  },
33
33
  "dependencies": {
34
- "@sly/sdk": "workspace:*",
34
+ "@sly_ai/sdk": "^0.1.0",
35
35
  "@modelcontextprotocol/sdk": "^1.0.4"
36
36
  },
37
37
  "devDependencies": {
package/src/index.ts CHANGED
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
18
- import { Sly, getEnvironmentConfig } from '@sly/sdk';
18
+ import { Sly, getEnvironmentConfig } from '@sly_ai/sdk';
19
19
  import { createMcpServer } from './server-factory.js';
20
20
 
21
21
  // Re-export for external consumers (e.g., apps/api remote MCP endpoint)
@@ -10,7 +10,7 @@ import {
10
10
  CallToolRequestSchema,
11
11
  ListToolsRequestSchema,
12
12
  } from '@modelcontextprotocol/sdk/types.js';
13
- import { Sly } from '@sly/sdk';
13
+ import { Sly } from '@sly_ai/sdk';
14
14
  import { tools } from './tools.js';
15
15
 
16
16
  /**