@usethrottle/mcp 0.1.1 → 0.2.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/dist/contract-index.json +1 -1
- package/dist/docs-index.json +1 -1
- package/dist/lib.cjs +1702 -0
- package/dist/lib.cjs.map +1 -0
- package/dist/lib.d.cts +165 -0
- package/dist/lib.d.ts +165 -0
- package/dist/lib.js +1668 -0
- package/dist/lib.js.map +1 -0
- package/dist/mcp.js +311 -26
- package/dist/mcp.js.map +1 -1
- package/package.json +11 -1
package/dist/mcp.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { readFileSync } from "fs";
|
|
5
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
5
|
|
|
7
6
|
// ../errors/dist/index.js
|
|
@@ -504,6 +503,116 @@ var ACTIONS = [
|
|
|
504
503
|
requests: [{ method: "GET", path: "/api/v1/invoices/aging" }],
|
|
505
504
|
channels: ["mcp", "zapier", "make", "n8n"]
|
|
506
505
|
},
|
|
506
|
+
// --------------------------------------------------------------- discounts
|
|
507
|
+
{
|
|
508
|
+
id: "search_discounts",
|
|
509
|
+
title: "Search discounts",
|
|
510
|
+
description: "List discount codes with optional filters \u2014 type, active state, and creation date range.",
|
|
511
|
+
kind: "read",
|
|
512
|
+
scopes: ["discounts:read"],
|
|
513
|
+
input: [
|
|
514
|
+
{ name: "q", type: "string", required: false, description: "Free-text search." },
|
|
515
|
+
{ name: "code", type: "string", required: false, description: "Exact code match." },
|
|
516
|
+
{
|
|
517
|
+
name: "type",
|
|
518
|
+
type: "string",
|
|
519
|
+
required: false,
|
|
520
|
+
description: "Filter by discount type.",
|
|
521
|
+
enum: ["percentage", "fixed_amount"]
|
|
522
|
+
},
|
|
523
|
+
{ name: "isActive", type: "boolean", required: false, description: "Filter by active state." },
|
|
524
|
+
{ name: "createdAfter", type: "string", required: false, description: "ISO 8601 date lower bound." },
|
|
525
|
+
{ name: "createdBefore", type: "string", required: false, description: "ISO 8601 date upper bound." },
|
|
526
|
+
{ name: "limit", type: "number", required: false, description: "Page size." },
|
|
527
|
+
{ name: "cursor", type: "string", required: false, description: "Pagination cursor." }
|
|
528
|
+
],
|
|
529
|
+
requests: [{ method: "GET", path: "/api/v1/discounts" }],
|
|
530
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
id: "get_discount",
|
|
534
|
+
title: "Get one discount",
|
|
535
|
+
description: "Read a single discount code: value, conditions, usage limits and redemption count.",
|
|
536
|
+
kind: "read",
|
|
537
|
+
scopes: ["discounts:read"],
|
|
538
|
+
input: [{ name: "id", type: "string", required: true, description: "Discount id." }],
|
|
539
|
+
requests: [{ method: "GET", path: "/api/v1/discounts/:id" }],
|
|
540
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
541
|
+
},
|
|
542
|
+
// ---------------------------------------------------------------- payments
|
|
543
|
+
{
|
|
544
|
+
id: "search_payments",
|
|
545
|
+
title: "Search payments",
|
|
546
|
+
description: "List payments with optional filters \u2014 method, status, order, amount range, or a Net-N overdue bucket. Today payments are only reachable nested inside get_order; this is the standalone entry point.",
|
|
547
|
+
kind: "read",
|
|
548
|
+
scopes: ["payments:read"],
|
|
549
|
+
input: [
|
|
550
|
+
{ name: "method", type: "string", required: false, description: "Filter by payment method." },
|
|
551
|
+
{ name: "status", type: "string", required: false, description: "Filter by payment status." },
|
|
552
|
+
{ name: "orderId", type: "string", required: false, description: "Filter to one order." },
|
|
553
|
+
{
|
|
554
|
+
name: "aging",
|
|
555
|
+
type: "string",
|
|
556
|
+
required: false,
|
|
557
|
+
description: "Overdue bucket filter, Net-N payments only.",
|
|
558
|
+
enum: ["0_30", "31_60", "61_90", "90_plus"]
|
|
559
|
+
},
|
|
560
|
+
{ name: "dueFrom", type: "string", required: false, description: "Due-date range start, YYYY-MM-DD." },
|
|
561
|
+
{ name: "dueTo", type: "string", required: false, description: "Due-date range end, YYYY-MM-DD." },
|
|
562
|
+
{ name: "amountMin", type: "number", required: false, description: "Minimum amount, minor units." },
|
|
563
|
+
{ name: "amountMax", type: "number", required: false, description: "Maximum amount, minor units." },
|
|
564
|
+
{ name: "limit", type: "number", required: false, description: "Page size." },
|
|
565
|
+
{ name: "cursor", type: "string", required: false, description: "Pagination cursor." }
|
|
566
|
+
],
|
|
567
|
+
requests: [{ method: "GET", path: "/api/v1/payments" }],
|
|
568
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
id: "get_payment",
|
|
572
|
+
title: "Get one payment with its transactions",
|
|
573
|
+
description: "Read a single payment plus its full transaction history (authorize/capture/refund/void attempts).",
|
|
574
|
+
kind: "read",
|
|
575
|
+
scopes: ["payments:read"],
|
|
576
|
+
input: [{ name: "id", type: "string", required: true, description: "Payment id." }],
|
|
577
|
+
requests: [
|
|
578
|
+
{ method: "GET", path: "/api/v1/payments/:id" },
|
|
579
|
+
{ method: "GET", path: "/api/v1/payments/:id/transactions" }
|
|
580
|
+
],
|
|
581
|
+
channels: ["mcp"],
|
|
582
|
+
guardrails: [
|
|
583
|
+
"The transactions sub-read needs its own read of the same payment scope; report it as unavailable rather than failing the whole call if the underlying request errors."
|
|
584
|
+
]
|
|
585
|
+
},
|
|
586
|
+
// ---------------------------------------------------------------- invoices
|
|
587
|
+
{
|
|
588
|
+
id: "get_invoice",
|
|
589
|
+
title: "Get one invoice",
|
|
590
|
+
description: "Read a single issued invoice: line items, totals, status and the billing snapshot at issue time.",
|
|
591
|
+
kind: "read",
|
|
592
|
+
scopes: ["invoices:read"],
|
|
593
|
+
input: [{ name: "id", type: "string", required: true, description: "Invoice id." }],
|
|
594
|
+
requests: [{ method: "GET", path: "/api/v1/invoices/:id" }],
|
|
595
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
596
|
+
},
|
|
597
|
+
// ------------------------------------------------------------------ carts
|
|
598
|
+
{
|
|
599
|
+
id: "list_abandoned_carts",
|
|
600
|
+
title: "List abandoned carts",
|
|
601
|
+
description: "Carts that were started but never finalized, with recovery status \u2014 the abandoned-cart recovery list.",
|
|
602
|
+
kind: "read",
|
|
603
|
+
scopes: ["carts:read"],
|
|
604
|
+
input: [
|
|
605
|
+
{ name: "sinceDays", type: "number", required: false, description: "How many days back to look." },
|
|
606
|
+
{ name: "limit", type: "number", required: false, description: "Page size." },
|
|
607
|
+
{ name: "cursor", type: "string", required: false, description: "Pagination cursor." }
|
|
608
|
+
],
|
|
609
|
+
requests: [
|
|
610
|
+
{ method: "GET", path: "/api/v1/abandoned-carts" },
|
|
611
|
+
{ method: "GET", path: "/api/v1/abandoned-carts/summary" }
|
|
612
|
+
],
|
|
613
|
+
channels: ["mcp", "zapier", "make", "n8n"],
|
|
614
|
+
guardrails: ["Report the summary as unavailable rather than failing the whole call if that sub-read errors."]
|
|
615
|
+
},
|
|
507
616
|
// ---------------------------------------------------------------- debugging
|
|
508
617
|
{
|
|
509
618
|
id: "search_events",
|
|
@@ -526,7 +635,7 @@ var ACTIONS = [
|
|
|
526
635
|
title: "List webhook deliveries",
|
|
527
636
|
description: "Recent outbound webhook deliveries, filterable by endpoint and status.",
|
|
528
637
|
kind: "read",
|
|
529
|
-
scopes: ["
|
|
638
|
+
scopes: ["webhook_deliveries:read"],
|
|
530
639
|
input: [
|
|
531
640
|
{ name: "endpointId", type: "string", required: false, description: "Filter by endpoint." },
|
|
532
641
|
{ name: "status", type: "string", required: false, description: "Filter by delivery status." },
|
|
@@ -540,7 +649,7 @@ var ACTIONS = [
|
|
|
540
649
|
title: "Get one webhook delivery",
|
|
541
650
|
description: "Full delivery record: the signed payload we sent, the response we got back, and every attempt.",
|
|
542
651
|
kind: "read",
|
|
543
|
-
scopes: ["
|
|
652
|
+
scopes: ["webhook_deliveries:read"],
|
|
544
653
|
input: [{ name: "id", type: "string", required: true, description: "Delivery id." }],
|
|
545
654
|
requests: [{ method: "GET", path: "/api/v1/webhook-deliveries/:id" }],
|
|
546
655
|
channels: ["mcp", "n8n"]
|
|
@@ -570,6 +679,46 @@ var ACTIONS = [
|
|
|
570
679
|
"Report which sections were unavailable rather than failing the call when a sub-read is unscoped."
|
|
571
680
|
]
|
|
572
681
|
},
|
|
682
|
+
// ------------------------------------------------------------- extensions
|
|
683
|
+
{
|
|
684
|
+
id: "list_extension_installations",
|
|
685
|
+
title: "List installed extensions",
|
|
686
|
+
description: "Extensions installed on this application, with status and configuration.",
|
|
687
|
+
kind: "read",
|
|
688
|
+
scopes: ["extensions:read"],
|
|
689
|
+
input: [
|
|
690
|
+
{
|
|
691
|
+
name: "status",
|
|
692
|
+
type: "string",
|
|
693
|
+
required: false,
|
|
694
|
+
description: "Filter by installation status.",
|
|
695
|
+
enum: ["active", "suspended", "uninstalled"]
|
|
696
|
+
},
|
|
697
|
+
{ name: "limit", type: "number", required: false, description: "Page size." },
|
|
698
|
+
{ name: "cursor", type: "string", required: false, description: "Pagination cursor." }
|
|
699
|
+
],
|
|
700
|
+
requests: [{ method: "GET", path: "/api/v1/installations" }],
|
|
701
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
702
|
+
},
|
|
703
|
+
// ------------------------------------------------------------- connectors
|
|
704
|
+
{
|
|
705
|
+
id: "get_connector_routing",
|
|
706
|
+
title: "Payment routing and decline rules",
|
|
707
|
+
description: "Read the payment-routing cascade, active routing connectors, and card/other decline rules \u2014 what determines which processor handles a payment and what happens on a decline.",
|
|
708
|
+
kind: "read",
|
|
709
|
+
scopes: ["connectors:read"],
|
|
710
|
+
input: [],
|
|
711
|
+
requests: [
|
|
712
|
+
{ method: "GET", path: "/api/v1/payment-routing" },
|
|
713
|
+
{ method: "GET", path: "/api/v1/routing-connectors" },
|
|
714
|
+
{ method: "GET", path: "/api/v1/card-decline" },
|
|
715
|
+
{ method: "GET", path: "/api/v1/other-decline" }
|
|
716
|
+
],
|
|
717
|
+
channels: ["mcp"],
|
|
718
|
+
guardrails: [
|
|
719
|
+
"Every sub-read proxies live to the payment provider's routing API and none are guaranteed to succeed together; report any that fail as unavailable rather than failing the whole call."
|
|
720
|
+
]
|
|
721
|
+
},
|
|
573
722
|
{
|
|
574
723
|
id: "get_integration_status",
|
|
575
724
|
title: "Integration readiness",
|
|
@@ -588,6 +737,29 @@ var ACTIONS = [
|
|
|
588
737
|
'Each section needs its own scope (connectors:read, webhooks:read). Report a section as "not readable with this credential" instead of failing.'
|
|
589
738
|
]
|
|
590
739
|
},
|
|
740
|
+
// --------------------------------------------------------------- workspace
|
|
741
|
+
{
|
|
742
|
+
id: "get_workspace_settings",
|
|
743
|
+
title: "Get workspace settings",
|
|
744
|
+
description: "Read this workspace's identity and settings: name, slug, branding, onboarding state, and the default Net-N payment terms.",
|
|
745
|
+
kind: "read",
|
|
746
|
+
scopes: ["merchant:read"],
|
|
747
|
+
input: [],
|
|
748
|
+
requests: [{ method: "GET", path: "/api/v1/merchants/me" }],
|
|
749
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
id: "get_audit_log",
|
|
753
|
+
title: "Get the workspace audit log",
|
|
754
|
+
description: "Recent admin actions taken on this workspace \u2014 invites, billing changes, key rotation, suspensions.",
|
|
755
|
+
kind: "read",
|
|
756
|
+
scopes: ["audit_logs:read"],
|
|
757
|
+
input: [
|
|
758
|
+
{ name: "limit", type: "number", required: false, description: "Maximum entries (1-200).", default: 100 }
|
|
759
|
+
],
|
|
760
|
+
requests: [{ method: "GET", path: "/api/v1/audit-log" }],
|
|
761
|
+
channels: ["mcp", "zapier", "make", "n8n"]
|
|
762
|
+
},
|
|
591
763
|
{
|
|
592
764
|
id: "get_business_summary",
|
|
593
765
|
title: "Business summary",
|
|
@@ -657,9 +829,9 @@ var ACTIONS = [
|
|
|
657
829
|
scopes: ["quotes:write"],
|
|
658
830
|
input: [
|
|
659
831
|
{ name: "customerId", type: "string", required: true, description: "Customer the quote is for." },
|
|
660
|
-
{ name: "
|
|
832
|
+
{ name: "items", type: "array", required: true, description: "Quote line items: { name, unitPrice, quantity }." },
|
|
661
833
|
{ name: "expiresAt", type: "string", required: false, description: "ISO 8601 expiry." },
|
|
662
|
-
{ name: "netN", type: "number", required: false, description: "Payment terms in days." },
|
|
834
|
+
{ name: "netN", type: "number", required: false, description: "Payment terms in days. Omit for pay-in-full." },
|
|
663
835
|
{ name: "notes", type: "string", required: false, description: "Buyer-visible notes." }
|
|
664
836
|
],
|
|
665
837
|
requests: [{ method: "POST", path: "/api/v1/quotes" }],
|
|
@@ -750,7 +922,7 @@ var ACTIONS = [
|
|
|
750
922
|
title: "Replay a webhook delivery",
|
|
751
923
|
description: "Re-send a past webhook delivery to its endpoint \u2014 useful after fixing a broken handler.",
|
|
752
924
|
kind: "write",
|
|
753
|
-
scopes: ["
|
|
925
|
+
scopes: ["webhook_deliveries:write"],
|
|
754
926
|
input: [{ name: "id", type: "string", required: true, description: "Delivery id." }],
|
|
755
927
|
requests: [{ method: "POST", path: "/api/v1/webhook-deliveries/:id/replay" }],
|
|
756
928
|
channels: ["mcp", "n8n"],
|
|
@@ -1141,6 +1313,54 @@ var HANDLERS = {
|
|
|
1141
1313
|
// ---------------------------------------------------------------- invoices
|
|
1142
1314
|
list_invoices: async (ctx, args) => ctx.client.list("/api/v1/invoices", { status: args.status, ...page(args) }),
|
|
1143
1315
|
receivables_aging: async (ctx) => ctx.client.get("/api/v1/invoices/aging"),
|
|
1316
|
+
// --------------------------------------------------------------- discounts
|
|
1317
|
+
search_discounts: async (ctx, args) => ctx.client.list("/api/v1/discounts", {
|
|
1318
|
+
q: args.q,
|
|
1319
|
+
code: args.code,
|
|
1320
|
+
type: args.type,
|
|
1321
|
+
isActive: args.isActive,
|
|
1322
|
+
createdAfter: args.createdAfter,
|
|
1323
|
+
createdBefore: args.createdBefore,
|
|
1324
|
+
...page(args)
|
|
1325
|
+
}),
|
|
1326
|
+
get_discount: async (ctx, args) => ctx.client.get(`/api/v1/discounts/${String(args.id)}`),
|
|
1327
|
+
// ---------------------------------------------------------------- payments
|
|
1328
|
+
search_payments: async (ctx, args) => ctx.client.list("/api/v1/payments", {
|
|
1329
|
+
method: args.method,
|
|
1330
|
+
status: args.status,
|
|
1331
|
+
// The route only accepts these as snake_case query params -- confirmed
|
|
1332
|
+
// by reading its querystring schema directly, not assumed from the
|
|
1333
|
+
// platform's usual camelCase convention.
|
|
1334
|
+
order_id: args.orderId,
|
|
1335
|
+
aging: args.aging,
|
|
1336
|
+
due_from: args.dueFrom,
|
|
1337
|
+
due_to: args.dueTo,
|
|
1338
|
+
amount_min: args.amountMin,
|
|
1339
|
+
amount_max: args.amountMax,
|
|
1340
|
+
...page(args)
|
|
1341
|
+
}),
|
|
1342
|
+
get_payment: async (ctx, args) => {
|
|
1343
|
+
const id = String(args.id);
|
|
1344
|
+
const payment = await ctx.client.get(`/api/v1/payments/${id}`);
|
|
1345
|
+
const transactions = await optional(() => ctx.client.list(`/api/v1/payments/${id}/transactions`));
|
|
1346
|
+
return {
|
|
1347
|
+
payment,
|
|
1348
|
+
transactions: transactions.ok ? transactions.value.data : transactions.unavailable
|
|
1349
|
+
};
|
|
1350
|
+
},
|
|
1351
|
+
// ---------------------------------------------------------------- invoices
|
|
1352
|
+
get_invoice: async (ctx, args) => ctx.client.get(`/api/v1/invoices/${String(args.id)}`),
|
|
1353
|
+
// ------------------------------------------------------------------ carts
|
|
1354
|
+
list_abandoned_carts: async (ctx, args) => {
|
|
1355
|
+
const [carts, summary] = await Promise.all([
|
|
1356
|
+
optional(() => ctx.client.list("/api/v1/abandoned-carts", { ...page(args) })),
|
|
1357
|
+
optional(() => ctx.client.get("/api/v1/abandoned-carts/summary", { sinceDays: args.sinceDays }))
|
|
1358
|
+
]);
|
|
1359
|
+
return {
|
|
1360
|
+
carts: carts.ok ? carts.value.data : carts.unavailable,
|
|
1361
|
+
summary: summary.ok ? summary.value : summary.unavailable
|
|
1362
|
+
};
|
|
1363
|
+
},
|
|
1144
1364
|
// --------------------------------------------------------------- debugging
|
|
1145
1365
|
search_events: async (ctx, args) => ctx.client.list("/api/v1/events", {
|
|
1146
1366
|
type: args.type,
|
|
@@ -1154,6 +1374,13 @@ var HANDLERS = {
|
|
|
1154
1374
|
limit: args.limit
|
|
1155
1375
|
}),
|
|
1156
1376
|
get_webhook_delivery: async (ctx, args) => ctx.client.get(`/api/v1/webhook-deliveries/${String(args.id)}`),
|
|
1377
|
+
send_test_webhook: async (ctx, args) => ctx.client.post(`/api/v1/webhook-endpoints/${String(args.id)}/test`, {
|
|
1378
|
+
body: { eventType: args.eventType },
|
|
1379
|
+
idempotencyKey: `mcp-send-test-webhook-${String(args.id)}-${Date.now()}`
|
|
1380
|
+
}),
|
|
1381
|
+
replay_webhook_delivery: async (ctx, args) => ctx.client.post(`/api/v1/webhook-deliveries/${String(args.id)}/replay`, {
|
|
1382
|
+
idempotencyKey: `mcp-replay-webhook-delivery-${String(args.id)}-${Date.now()}`
|
|
1383
|
+
}),
|
|
1157
1384
|
explain_checkout_failure: async (ctx, args) => {
|
|
1158
1385
|
const id = String(args.id);
|
|
1159
1386
|
const session = await optional(() => ctx.client.get(`/api/v1/checkout-sessions/${id}`));
|
|
@@ -1198,7 +1425,11 @@ var HANDLERS = {
|
|
|
1198
1425
|
idempotencyKey: `mcp-seed-customer-${stamp}`
|
|
1199
1426
|
});
|
|
1200
1427
|
const cart = await ctx.client.post("/api/v1/carts", {
|
|
1201
|
-
|
|
1428
|
+
// Unlike /api/v1/customers, cart creation requires applicationId
|
|
1429
|
+
// explicitly in the body (it's cross-checked against the caller's own
|
|
1430
|
+
// authenticated application, not inferred) -- omitting it is a real
|
|
1431
|
+
// 400 missing_application_id from the live API, not a hypothetical.
|
|
1432
|
+
body: { applicationId: ctx.identity.application?.id, customerId: customer?.id },
|
|
1202
1433
|
idempotencyKey: `mcp-seed-cart-${stamp}`
|
|
1203
1434
|
});
|
|
1204
1435
|
const requested = Array.isArray(args.lineItems) && args.lineItems.length > 0 ? args.lineItems : [{ name: "Seed widget", unitPrice: 2500, quantity: 2 }];
|
|
@@ -1223,8 +1454,54 @@ var HANDLERS = {
|
|
|
1223
1454
|
note: "Seeded a finalized DRAFT order. No payment was captured \u2014 that needs a browser-tokenised payment method, which a server-side key cannot produce."
|
|
1224
1455
|
};
|
|
1225
1456
|
},
|
|
1457
|
+
// -------------------------------------------------------------- money/mail
|
|
1458
|
+
manage_subscription: async (ctx, args) => {
|
|
1459
|
+
const id = String(args.id);
|
|
1460
|
+
const action = String(args.action);
|
|
1461
|
+
if (action !== "pause" && action !== "resume") {
|
|
1462
|
+
throw new Error(`manage_subscription: action must be "pause" or "resume", got "${action}".`);
|
|
1463
|
+
}
|
|
1464
|
+
return ctx.client.post(`/api/v1/subscriptions/${id}/${action}`, {
|
|
1465
|
+
idempotencyKey: `mcp-manage-subscription-${id}-${action}-${Date.now()}`
|
|
1466
|
+
});
|
|
1467
|
+
},
|
|
1468
|
+
create_quote: async (ctx, args) => (
|
|
1469
|
+
// The real route's body shape differs from this tool's flatter,
|
|
1470
|
+
// model-facing input: line items are "items" (not "lineItems"), Net-N
|
|
1471
|
+
// terms are nested under paymentTerms.netN with an explicit mode (not a
|
|
1472
|
+
// flat "netN"), and the buyer-visible note field is "buyerNote" (not
|
|
1473
|
+
// "notes"). Confirmed against packages/platform-api/src/validation/quotes.ts's
|
|
1474
|
+
// actual zod schema after a live call 400'd with unrecognized_keys.
|
|
1475
|
+
ctx.client.post("/api/v1/quotes", {
|
|
1476
|
+
body: {
|
|
1477
|
+
customerId: args.customerId,
|
|
1478
|
+
items: args.items,
|
|
1479
|
+
expiresAt: args.expiresAt,
|
|
1480
|
+
paymentTerms: args.netN !== void 0 ? { mode: "net_terms", netN: args.netN } : void 0,
|
|
1481
|
+
buyerNote: args.notes
|
|
1482
|
+
},
|
|
1483
|
+
idempotencyKey: `mcp-create-quote-${String(args.customerId)}-${Date.now()}`
|
|
1484
|
+
})
|
|
1485
|
+
),
|
|
1226
1486
|
get_business_summary: async (ctx, args) => ctx.client.get("/api/v1/analytics/business-summary", { period: args.period }),
|
|
1227
1487
|
get_attention_digest: async (ctx) => ctx.client.get("/api/v1/analytics/attention-digest"),
|
|
1488
|
+
// ------------------------------------------------------------- extensions
|
|
1489
|
+
list_extension_installations: async (ctx, args) => ctx.client.list("/api/v1/installations", { status: args.status, ...page(args) }),
|
|
1490
|
+
// ------------------------------------------------------------- connectors
|
|
1491
|
+
get_connector_routing: async (ctx) => {
|
|
1492
|
+
const [paymentRouting, routingConnectors, cardDecline, otherDecline] = await Promise.all([
|
|
1493
|
+
optional(() => ctx.client.get("/api/v1/payment-routing")),
|
|
1494
|
+
optional(() => ctx.client.get("/api/v1/routing-connectors")),
|
|
1495
|
+
optional(() => ctx.client.get("/api/v1/card-decline")),
|
|
1496
|
+
optional(() => ctx.client.get("/api/v1/other-decline"))
|
|
1497
|
+
]);
|
|
1498
|
+
return {
|
|
1499
|
+
paymentRouting: paymentRouting.ok ? paymentRouting.value : paymentRouting.unavailable,
|
|
1500
|
+
routingConnectors: routingConnectors.ok ? routingConnectors.value : routingConnectors.unavailable,
|
|
1501
|
+
cardDecline: cardDecline.ok ? cardDecline.value : cardDecline.unavailable,
|
|
1502
|
+
otherDecline: otherDecline.ok ? otherDecline.value : otherDecline.unavailable
|
|
1503
|
+
};
|
|
1504
|
+
},
|
|
1228
1505
|
get_integration_status: async (ctx) => {
|
|
1229
1506
|
const [connectors, endpoints, coverage] = await Promise.all([
|
|
1230
1507
|
optional(() => ctx.client.list("/api/v1/connectors")),
|
|
@@ -1239,7 +1516,10 @@ var HANDLERS = {
|
|
|
1239
1516
|
webhookEndpoints: endpoints.ok ? endpoints.value.data : endpoints.unavailable,
|
|
1240
1517
|
unsubscribedEvents: coverage.ok ? coverage.value : coverage.unavailable
|
|
1241
1518
|
};
|
|
1242
|
-
}
|
|
1519
|
+
},
|
|
1520
|
+
// --------------------------------------------------------------- workspace
|
|
1521
|
+
get_workspace_settings: async (ctx) => ctx.client.get("/api/v1/merchants/me"),
|
|
1522
|
+
get_audit_log: async (ctx, args) => ctx.client.list("/api/v1/audit-log", { limit: args.limit })
|
|
1243
1523
|
};
|
|
1244
1524
|
|
|
1245
1525
|
// src/input.ts
|
|
@@ -1275,7 +1555,7 @@ function applyModifiers(field, type) {
|
|
|
1275
1555
|
}
|
|
1276
1556
|
|
|
1277
1557
|
// src/server.ts
|
|
1278
|
-
var VERSION = true ? "0.
|
|
1558
|
+
var VERSION = true ? "0.2.0" : "0.0.0-dev";
|
|
1279
1559
|
function registerableActions(policy) {
|
|
1280
1560
|
const isProduction = policy.identity.environment.providerEnvironment === "production";
|
|
1281
1561
|
return actionsForChannel("mcp").filter((action) => {
|
|
@@ -1362,6 +1642,26 @@ function describeForModel(action) {
|
|
|
1362
1642
|
return parts.join(" ");
|
|
1363
1643
|
}
|
|
1364
1644
|
|
|
1645
|
+
// src/indexes.ts
|
|
1646
|
+
import { readFileSync } from "fs";
|
|
1647
|
+
function loadIndex(file, empty, label) {
|
|
1648
|
+
try {
|
|
1649
|
+
return JSON.parse(readFileSync(new URL(`./${file}`, import.meta.url), "utf8"));
|
|
1650
|
+
} catch {
|
|
1651
|
+
process.stderr.write(
|
|
1652
|
+
`throttle-mcp: ${label} index missing (${file}); that tool will return no results. Run "pnpm --filter @usethrottle/mcp build:indexes".
|
|
1653
|
+
`
|
|
1654
|
+
);
|
|
1655
|
+
return empty;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
function loadDocsIndex() {
|
|
1659
|
+
return loadIndex("docs-index.json", { generatedAt: "", entries: [] }, "docs");
|
|
1660
|
+
}
|
|
1661
|
+
function loadContractIndex() {
|
|
1662
|
+
return loadIndex("contract-index.json", { generatedAt: "", operations: [] }, "contract");
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1365
1665
|
// src/index.ts
|
|
1366
1666
|
var DEFAULT_API = "https://api.usethrottle.dev";
|
|
1367
1667
|
function fail(message) {
|
|
@@ -1413,17 +1713,6 @@ function parseArgs(argv) {
|
|
|
1413
1713
|
allowLiveWrites: args.includes("--allow-live-writes")
|
|
1414
1714
|
};
|
|
1415
1715
|
}
|
|
1416
|
-
function loadIndex(file, empty, label) {
|
|
1417
|
-
try {
|
|
1418
|
-
return JSON.parse(readFileSync(new URL(`./${file}`, import.meta.url), "utf8"));
|
|
1419
|
-
} catch {
|
|
1420
|
-
process.stderr.write(
|
|
1421
|
-
`throttle-mcp: ${label} index missing (${file}); that tool will return no results. Run "pnpm --filter @usethrottle/mcp build:indexes".
|
|
1422
|
-
`
|
|
1423
|
-
);
|
|
1424
|
-
return empty;
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
1716
|
async function main() {
|
|
1428
1717
|
const options = parseArgs(process.argv);
|
|
1429
1718
|
const client = new ThrottleClient({ apiKey: options.apiKey, apiBaseUrl: options.apiBaseUrl });
|
|
@@ -1436,12 +1725,8 @@ async function main() {
|
|
|
1436
1725
|
`could not identify the credential via GET /api/v1/whoami (${e?.code ?? "error"}: ${e?.message ?? String(error)}). Check the key and --api URL.`
|
|
1437
1726
|
);
|
|
1438
1727
|
}
|
|
1439
|
-
const docs =
|
|
1440
|
-
const contract =
|
|
1441
|
-
"contract-index.json",
|
|
1442
|
-
{ generatedAt: "", operations: [] },
|
|
1443
|
-
"contract"
|
|
1444
|
-
);
|
|
1728
|
+
const docs = loadDocsIndex();
|
|
1729
|
+
const contract = loadContractIndex();
|
|
1445
1730
|
const server = createServer({
|
|
1446
1731
|
identity,
|
|
1447
1732
|
client,
|