@carrierllc/mcp 0.1.0 → 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.
Files changed (129) hide show
  1. package/dist/apps/app-state.d.ts +19 -0
  2. package/dist/apps/app-state.d.ts.map +1 -0
  3. package/dist/apps/app-state.js +28 -0
  4. package/dist/apps/app-state.js.map +1 -0
  5. package/dist/apps/balance-topup.d.ts +19 -0
  6. package/dist/apps/balance-topup.d.ts.map +1 -0
  7. package/dist/apps/balance-topup.js +121 -0
  8. package/dist/apps/balance-topup.js.map +1 -0
  9. package/dist/apps/fleet-health-app.d.ts +29 -0
  10. package/dist/apps/fleet-health-app.d.ts.map +1 -0
  11. package/dist/apps/fleet-health-app.js +152 -0
  12. package/dist/apps/fleet-health-app.js.map +1 -0
  13. package/dist/apps/index.d.ts +37 -0
  14. package/dist/apps/index.d.ts.map +1 -0
  15. package/dist/apps/index.js +42 -0
  16. package/dist/apps/index.js.map +1 -0
  17. package/dist/apps/provisioning-wizard.d.ts +11 -0
  18. package/dist/apps/provisioning-wizard.d.ts.map +1 -0
  19. package/dist/apps/provisioning-wizard.js +345 -0
  20. package/dist/apps/provisioning-wizard.js.map +1 -0
  21. package/dist/audit.d.ts +31 -0
  22. package/dist/audit.d.ts.map +1 -0
  23. package/dist/audit.js +42 -0
  24. package/dist/audit.js.map +1 -0
  25. package/dist/billing-thresholds.d.ts +71 -0
  26. package/dist/billing-thresholds.d.ts.map +1 -0
  27. package/dist/billing-thresholds.js +238 -0
  28. package/dist/billing-thresholds.js.map +1 -0
  29. package/dist/billing.d.ts +95 -0
  30. package/dist/billing.d.ts.map +1 -0
  31. package/dist/billing.js +239 -0
  32. package/dist/billing.js.map +1 -0
  33. package/dist/clerk.d.ts +125 -0
  34. package/dist/clerk.d.ts.map +1 -0
  35. package/dist/clerk.js +389 -0
  36. package/dist/clerk.js.map +1 -0
  37. package/dist/client.d.ts +12 -15
  38. package/dist/client.d.ts.map +1 -1
  39. package/dist/client.js +48 -55
  40. package/dist/client.js.map +1 -1
  41. package/dist/credits.d.ts +165 -0
  42. package/dist/credits.d.ts.map +1 -0
  43. package/dist/credits.js +483 -0
  44. package/dist/credits.js.map +1 -0
  45. package/dist/index.d.ts +6 -11
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +74 -23
  48. package/dist/index.js.map +1 -1
  49. package/dist/intelligence.d.ts +2 -8
  50. package/dist/intelligence.d.ts.map +1 -1
  51. package/dist/intelligence.js +321 -154
  52. package/dist/intelligence.js.map +1 -1
  53. package/dist/list-recent-ocs-events.d.ts +48 -0
  54. package/dist/list-recent-ocs-events.d.ts.map +1 -0
  55. package/dist/list-recent-ocs-events.js +160 -0
  56. package/dist/list-recent-ocs-events.js.map +1 -0
  57. package/dist/manus-client.d.ts +429 -0
  58. package/dist/manus-client.d.ts.map +1 -0
  59. package/dist/manus-client.js +401 -0
  60. package/dist/manus-client.js.map +1 -0
  61. package/dist/manus-common.d.ts +5 -0
  62. package/dist/manus-common.d.ts.map +1 -0
  63. package/dist/manus-common.js +5 -0
  64. package/dist/manus-common.js.map +1 -0
  65. package/dist/manus-schedule.d.ts +74 -0
  66. package/dist/manus-schedule.d.ts.map +1 -0
  67. package/dist/manus-schedule.js +213 -0
  68. package/dist/manus-schedule.js.map +1 -0
  69. package/dist/manus-usage.d.ts +32 -0
  70. package/dist/manus-usage.d.ts.map +1 -0
  71. package/dist/manus-usage.js +120 -0
  72. package/dist/manus-usage.js.map +1 -0
  73. package/dist/manus-webhook.d.ts +60 -0
  74. package/dist/manus-webhook.d.ts.map +1 -0
  75. package/dist/manus-webhook.js +361 -0
  76. package/dist/manus-webhook.js.map +1 -0
  77. package/dist/pricing-tools.d.ts +26 -0
  78. package/dist/pricing-tools.d.ts.map +1 -0
  79. package/dist/pricing-tools.js +428 -0
  80. package/dist/pricing-tools.js.map +1 -0
  81. package/dist/projects-tools.d.ts +39 -0
  82. package/dist/projects-tools.d.ts.map +1 -0
  83. package/dist/projects-tools.js +545 -0
  84. package/dist/projects-tools.js.map +1 -0
  85. package/dist/prompts.d.ts +1 -0
  86. package/dist/prompts.d.ts.map +1 -1
  87. package/dist/prompts.js +1 -0
  88. package/dist/prompts.js.map +1 -1
  89. package/dist/stripe-connect-tools.d.ts +33 -0
  90. package/dist/stripe-connect-tools.d.ts.map +1 -0
  91. package/dist/stripe-connect-tools.js +504 -0
  92. package/dist/stripe-connect-tools.js.map +1 -0
  93. package/dist/timing-safe-equal.d.ts +5 -0
  94. package/dist/timing-safe-equal.d.ts.map +1 -0
  95. package/dist/timing-safe-equal.js +13 -0
  96. package/dist/timing-safe-equal.js.map +1 -0
  97. package/dist/tools-backlog.d.ts +28 -0
  98. package/dist/tools-backlog.d.ts.map +1 -0
  99. package/dist/tools-backlog.js +315 -0
  100. package/dist/tools-backlog.js.map +1 -0
  101. package/dist/tools-carrier-ask.d.ts +138 -0
  102. package/dist/tools-carrier-ask.d.ts.map +1 -0
  103. package/dist/tools-carrier-ask.js +913 -0
  104. package/dist/tools-carrier-ask.js.map +1 -0
  105. package/dist/tools-pricing.d.ts +18 -0
  106. package/dist/tools-pricing.d.ts.map +1 -0
  107. package/dist/tools-pricing.js +172 -0
  108. package/dist/tools-pricing.js.map +1 -0
  109. package/dist/tools-ui-agent-ask.d.ts +29 -0
  110. package/dist/tools-ui-agent-ask.d.ts.map +1 -0
  111. package/dist/tools-ui-agent-ask.js +272 -0
  112. package/dist/tools-ui-agent-ask.js.map +1 -0
  113. package/dist/tools-ui-agent-schedule.d.ts +29 -0
  114. package/dist/tools-ui-agent-schedule.d.ts.map +1 -0
  115. package/dist/tools-ui-agent-schedule.js +517 -0
  116. package/dist/tools-ui-agent-schedule.js.map +1 -0
  117. package/dist/tools-ui-agent.d.ts +40 -0
  118. package/dist/tools-ui-agent.d.ts.map +1 -0
  119. package/dist/tools-ui-agent.js +508 -0
  120. package/dist/tools-ui-agent.js.map +1 -0
  121. package/dist/tools.d.ts +44 -13
  122. package/dist/tools.d.ts.map +1 -1
  123. package/dist/tools.js +794 -201
  124. package/dist/tools.js.map +1 -1
  125. package/dist/types.d.ts +291 -0
  126. package/dist/types.d.ts.map +1 -0
  127. package/dist/types.js +5 -0
  128. package/dist/types.js.map +1 -0
  129. package/package.json +14 -8
@@ -0,0 +1,483 @@
1
+ /**
2
+ * Carrier MCP — Credits System v2.0 (Pricing Evolution)
3
+ *
4
+ * Implements credit-based billing inspired by Stripe's Pricing Model Evolution Guide:
5
+ * - Monthly credit allotments per tier (Lovable pattern)
6
+ * - Auto-billed overages when base credits exhausted (Warp pattern)
7
+ * - Credit rollovers for irregular usage (Lovable pattern)
8
+ * - Daily free credits for acquisition (Browserbase/Lovable pattern)
9
+ * - Billing thresholds to prevent bill shock (Hex pattern)
10
+ * - Volume discounts for high-usage customers
11
+ *
12
+ * Storage layout (CARRIER_USERS KV):
13
+ * key: credits:<sub>:<yyyymm> value: CreditLedger
14
+ * key: credits:daily:<sub>:<yyyymmdd> value: DailyFreeCredits
15
+ * key: credits:config:<sub> value: CreditConfig (overrides, thresholds)
16
+ * key: credits:rollover:<sub> value: RolloverBalance
17
+ *
18
+ * Credit economy:
19
+ * 1 tool call = 1 credit (read scope)
20
+ * 1 tool call = 2 credits (write scope)
21
+ * 1 tool call = 5 credits (admin scope)
22
+ * Intelligence composites = 3 credits each
23
+ *
24
+ * Stripe integration:
25
+ * - Overages reported via Stripe Metered Billing (usage_records API)
26
+ * - Billing thresholds trigger Stripe invoice finalization
27
+ * - Credit grants created via Stripe Customer Balance Transactions
28
+ */
29
+ // ---------------------------------------------------------------------------
30
+ // Credit Constants
31
+ // ---------------------------------------------------------------------------
32
+ /** Monthly credit allotments per tier */
33
+ export const TIER_CREDIT_ALLOTMENTS = {
34
+ free: 5_000,
35
+ pro: 100_000,
36
+ enterprise: Infinity,
37
+ };
38
+ /** Daily free credits for all users (acquisition driver) */
39
+ export const DAILY_FREE_CREDITS = 50;
40
+ /** Maximum rollover credits (cap at 2x monthly allotment) */
41
+ export const ROLLOVER_CAP_MULTIPLIER = 2;
42
+ /** Credit cost per scope */
43
+ export const SCOPE_CREDIT_COSTS = {
44
+ read: 1,
45
+ write: 2,
46
+ admin: 5,
47
+ intelligence: 3,
48
+ };
49
+ /** Volume discount tiers (cumulative monthly usage) */
50
+ export const VOLUME_DISCOUNTS = [
51
+ { threshold: 50_000, discountPct: 0 },
52
+ { threshold: 100_000, discountPct: 10 },
53
+ { threshold: 250_000, discountPct: 15 },
54
+ { threshold: 500_000, discountPct: 20 },
55
+ { threshold: 1_000_000, discountPct: 25 },
56
+ ];
57
+ /** Default billing threshold (in cents) — triggers invoice at this spend level */
58
+ export const DEFAULT_BILLING_THRESHOLD_CENTS = 10_000; // $100
59
+ /** Overage price per credit (in cents) — Pro tier */
60
+ export const OVERAGE_PRICE_PER_CREDIT_CENTS = 0.1; // $0.001 per credit
61
+ // ---------------------------------------------------------------------------
62
+ // Credit Check
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Check if a user has sufficient credits for a tool call.
66
+ * Order of credit consumption:
67
+ * 1. Daily free credits (if available)
68
+ * 2. Monthly allotment (base + rollover)
69
+ * 3. Overage (if enabled for tier)
70
+ */
71
+ export async function checkCredits(env, sub, tier, scope) {
72
+ const cost = SCOPE_CREDIT_COSTS[scope];
73
+ const month = currentMonth();
74
+ const today = currentDay();
75
+ const resetAt = firstDayNextMonth();
76
+ // Enterprise always allowed
77
+ if (tier === "enterprise") {
78
+ return {
79
+ allowed: true,
80
+ credits_remaining: Infinity,
81
+ daily_free_remaining: Infinity,
82
+ overage_active: false,
83
+ overage_amount_cents: 0,
84
+ threshold_pct: 0,
85
+ tier,
86
+ volume_discount_pct: 0,
87
+ reset_at: resetAt,
88
+ };
89
+ }
90
+ // Load ledger
91
+ const ledger = await getLedger(env, sub, month, tier);
92
+ const dailyFree = await getDailyFreeCredits(env, sub, today);
93
+ const config = await getCreditConfig(env, sub, tier);
94
+ // Calculate remaining
95
+ const monthlyRemaining = Math.max(0, ledger.allotment - ledger.consumed);
96
+ const dailyFreeRemaining = Math.max(0, dailyFree.granted - dailyFree.consumed);
97
+ const totalRemaining = dailyFreeRemaining + monthlyRemaining;
98
+ // Check if allowed
99
+ const overageEnabled = config.overages_enabled && tier !== "free";
100
+ const allowed = totalRemaining >= cost || overageEnabled;
101
+ // Volume discount
102
+ const volumeDiscount = resolveVolumeDiscount(ledger.consumed);
103
+ // Threshold percentage
104
+ const thresholdPct = config.billing_threshold_cents > 0
105
+ ? Math.round((ledger.overage_billed_cents / config.billing_threshold_cents) * 100)
106
+ : 0;
107
+ return {
108
+ allowed,
109
+ credits_remaining: monthlyRemaining,
110
+ daily_free_remaining: dailyFreeRemaining,
111
+ overage_active: monthlyRemaining < cost && dailyFreeRemaining < cost && overageEnabled,
112
+ overage_amount_cents: ledger.overage_billed_cents,
113
+ threshold_pct: thresholdPct,
114
+ tier,
115
+ volume_discount_pct: volumeDiscount,
116
+ reset_at: resetAt,
117
+ };
118
+ }
119
+ // ---------------------------------------------------------------------------
120
+ // Credit Deduction
121
+ // ---------------------------------------------------------------------------
122
+ /**
123
+ * Deduct credits for a tool call. Fire-and-forget in the hot path.
124
+ *
125
+ * Consumption order:
126
+ * 1. Daily free credits first (lowest cost to user)
127
+ * 2. Monthly allotment
128
+ * 3. Overage (auto-billed, Pro+ only)
129
+ */
130
+ export function deductCredits(env, sub, tier, scope) {
131
+ void (async () => {
132
+ const cost = SCOPE_CREDIT_COSTS[scope];
133
+ const month = currentMonth();
134
+ const today = currentDay();
135
+ // Enterprise — no deduction needed
136
+ if (tier === "enterprise")
137
+ return;
138
+ // Try daily free credits first
139
+ const dailyFree = await getDailyFreeCredits(env, sub, today);
140
+ const dailyRemaining = dailyFree.granted - dailyFree.consumed;
141
+ if (dailyRemaining >= cost) {
142
+ // Deduct from daily free pool
143
+ await putDailyFreeCredits(env, sub, today, {
144
+ ...dailyFree,
145
+ consumed: dailyFree.consumed + cost,
146
+ });
147
+ return;
148
+ }
149
+ // Deduct from monthly allotment
150
+ const ledger = await getLedger(env, sub, month, tier);
151
+ const monthlyRemaining = ledger.allotment - ledger.consumed;
152
+ if (monthlyRemaining >= cost) {
153
+ await putLedger(env, sub, month, {
154
+ ...ledger,
155
+ consumed: ledger.consumed + cost,
156
+ updated_at: new Date().toISOString(),
157
+ });
158
+ return;
159
+ }
160
+ // Overage path (Pro+ only)
161
+ const config = await getCreditConfig(env, sub, tier);
162
+ if (!config.overages_enabled || tier === "free")
163
+ return;
164
+ const volumeDiscount = resolveVolumeDiscount(ledger.consumed);
165
+ const effectiveRate = OVERAGE_PRICE_PER_CREDIT_CENTS * (1 - volumeDiscount / 100);
166
+ const overageCostCents = Math.round(cost * effectiveRate * 100) / 100;
167
+ const updatedLedger = {
168
+ ...ledger,
169
+ consumed: ledger.consumed + cost,
170
+ overage: ledger.overage + cost,
171
+ overage_billed_cents: ledger.overage_billed_cents + overageCostCents,
172
+ updated_at: new Date().toISOString(),
173
+ };
174
+ // Check billing threshold
175
+ if (!ledger.threshold_triggered &&
176
+ updatedLedger.overage_billed_cents >= config.billing_threshold_cents) {
177
+ updatedLedger.threshold_triggered = true;
178
+ // Trigger Stripe invoice finalization (async, non-blocking)
179
+ void triggerBillingThreshold(env, sub, updatedLedger.overage_billed_cents);
180
+ }
181
+ await putLedger(env, sub, month, updatedLedger);
182
+ // Push overage to Stripe at every 100-credit boundary
183
+ if (updatedLedger.overage % 100 === 0) {
184
+ void pushOverageToStripe(env, sub, 100, effectiveRate).catch(() => { });
185
+ }
186
+ })();
187
+ }
188
+ // ---------------------------------------------------------------------------
189
+ // Credit Grant (Rollover)
190
+ // ---------------------------------------------------------------------------
191
+ /**
192
+ * Calculate and apply rollover credits from previous month.
193
+ * Called by the monthly cron job (scheduled handler).
194
+ *
195
+ * Rules:
196
+ * - Only Pro+ tiers get rollovers
197
+ * - Rollover = min(unused credits, allotment * ROLLOVER_CAP_MULTIPLIER)
198
+ * - Rollovers expire after 1 month (use-it-or-lose-it next cycle)
199
+ */
200
+ export async function applyMonthlyRollover(env, sub, tier) {
201
+ if (tier === "free")
202
+ return null;
203
+ const prevMonth = previousMonth();
204
+ const prevLedger = await getLedger(env, sub, prevMonth, tier);
205
+ const unused = Math.max(0, prevLedger.allotment - prevLedger.consumed);
206
+ if (unused === 0)
207
+ return null;
208
+ const maxRollover = TIER_CREDIT_ALLOTMENTS[tier] * ROLLOVER_CAP_MULTIPLIER;
209
+ const rolloverAmount = Math.min(unused, maxRollover);
210
+ const rollover = {
211
+ credits: rolloverAmount,
212
+ source_month: prevMonth,
213
+ expires_at: firstDayMonthAfterNext(),
214
+ };
215
+ await env.CARRIER_USERS.put(`credits:rollover:${sub}`, JSON.stringify(rollover), { expirationTtl: 62 * 24 * 60 * 60 });
216
+ // Apply to current month's ledger
217
+ const currentMo = currentMonth();
218
+ const currentLedger = await getLedger(env, sub, currentMo, tier);
219
+ await putLedger(env, sub, currentMo, {
220
+ ...currentLedger,
221
+ allotment: currentLedger.allotment + rolloverAmount,
222
+ rollover_applied: rolloverAmount,
223
+ updated_at: new Date().toISOString(),
224
+ });
225
+ return rollover;
226
+ }
227
+ // ---------------------------------------------------------------------------
228
+ // Volume Discounts
229
+ // ---------------------------------------------------------------------------
230
+ /**
231
+ * Resolve the applicable volume discount percentage based on cumulative usage.
232
+ */
233
+ export function resolveVolumeDiscount(consumed) {
234
+ let discount = 0;
235
+ for (const tier of VOLUME_DISCOUNTS) {
236
+ if (consumed >= tier.threshold) {
237
+ discount = tier.discountPct;
238
+ }
239
+ else {
240
+ break;
241
+ }
242
+ }
243
+ return discount;
244
+ }
245
+ // ---------------------------------------------------------------------------
246
+ // Billing Threshold
247
+ // ---------------------------------------------------------------------------
248
+ /**
249
+ * Trigger billing threshold — creates a Stripe invoice for accumulated overages.
250
+ * Prevents bill shock by invoicing incrementally (Hex pattern).
251
+ */
252
+ async function triggerBillingThreshold(env, sub, amountCents) {
253
+ const stripeKey = env.STRIPE_SECRET_KEY;
254
+ if (!stripeKey)
255
+ return;
256
+ const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);
257
+ if (!customerId)
258
+ return;
259
+ // Create an invoice item for the threshold amount
260
+ const body = new URLSearchParams({
261
+ customer: customerId,
262
+ amount: String(Math.round(amountCents)),
263
+ currency: "usd",
264
+ description: `Carrier MCP overage credits (threshold reached)`,
265
+ });
266
+ const resp = await fetch("https://api.stripe.com/v1/invoiceitems", {
267
+ method: "POST",
268
+ headers: {
269
+ Authorization: `Bearer ${stripeKey}`,
270
+ "Content-Type": "application/x-www-form-urlencoded",
271
+ },
272
+ body: body.toString(),
273
+ });
274
+ if (!resp.ok)
275
+ return;
276
+ // Create and finalize the invoice
277
+ const invoiceBody = new URLSearchParams({
278
+ customer: customerId,
279
+ auto_advance: "true", // Auto-finalize and attempt payment
280
+ "collection_method": "charge_automatically",
281
+ description: "Carrier MCP — Overage billing threshold invoice",
282
+ });
283
+ await fetch("https://api.stripe.com/v1/invoices", {
284
+ method: "POST",
285
+ headers: {
286
+ Authorization: `Bearer ${stripeKey}`,
287
+ "Content-Type": "application/x-www-form-urlencoded",
288
+ },
289
+ body: invoiceBody.toString(),
290
+ });
291
+ }
292
+ /**
293
+ * Push overage usage records to Stripe Metered Billing.
294
+ */
295
+ async function pushOverageToStripe(env, sub, quantity, ratePerCredit) {
296
+ const stripeKey = env.STRIPE_SECRET_KEY;
297
+ if (!stripeKey)
298
+ return;
299
+ const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);
300
+ if (!subItemId)
301
+ return;
302
+ const body = new URLSearchParams({
303
+ quantity: String(quantity),
304
+ timestamp: String(Math.floor(Date.now() / 1000)),
305
+ action: "increment",
306
+ });
307
+ await fetch(`https://api.stripe.com/v1/subscription_items/${subItemId}/usage_records`, {
308
+ method: "POST",
309
+ headers: {
310
+ Authorization: `Bearer ${stripeKey}`,
311
+ "Content-Type": "application/x-www-form-urlencoded",
312
+ },
313
+ body: body.toString(),
314
+ });
315
+ // Store rate for reconciliation
316
+ await env.CARRIER_USERS.put(`overage_rate:${sub}`, JSON.stringify({ rate_cents: ratePerCredit, updated_at: new Date().toISOString() }), { expirationTtl: 35 * 24 * 60 * 60 });
317
+ }
318
+ // ---------------------------------------------------------------------------
319
+ // KV Helpers
320
+ // ---------------------------------------------------------------------------
321
+ async function getLedger(env, sub, month, tier) {
322
+ const key = `credits:${sub}:${month}`;
323
+ const raw = await env.CARRIER_USERS.get(key, "json").catch(() => null);
324
+ if (raw && typeof raw === "object" && "allotment" in raw) {
325
+ return raw;
326
+ }
327
+ // Initialize new ledger for the month
328
+ const allotment = TIER_CREDIT_ALLOTMENTS[tier];
329
+ return {
330
+ allotment,
331
+ consumed: 0,
332
+ rollover_applied: 0,
333
+ overage: 0,
334
+ overage_billed_cents: 0,
335
+ threshold_triggered: false,
336
+ updated_at: new Date().toISOString(),
337
+ };
338
+ }
339
+ async function putLedger(env, sub, month, ledger) {
340
+ const key = `credits:${sub}:${month}`;
341
+ await env.CARRIER_USERS.put(key, JSON.stringify(ledger), {
342
+ expirationTtl: 65 * 24 * 60 * 60, // ~2 months
343
+ });
344
+ }
345
+ async function getDailyFreeCredits(env, sub, day) {
346
+ const key = `credits:daily:${sub}:${day}`;
347
+ const raw = await env.CARRIER_USERS.get(key, "json").catch(() => null);
348
+ if (raw && typeof raw === "object" && "granted" in raw) {
349
+ return raw;
350
+ }
351
+ // Initialize daily free credits
352
+ return {
353
+ granted: DAILY_FREE_CREDITS,
354
+ consumed: 0,
355
+ date: day,
356
+ };
357
+ }
358
+ async function putDailyFreeCredits(env, sub, day, credits) {
359
+ const key = `credits:daily:${sub}:${day}`;
360
+ await env.CARRIER_USERS.put(key, JSON.stringify(credits), {
361
+ expirationTtl: 2 * 24 * 60 * 60, // 2 days
362
+ });
363
+ }
364
+ async function getCreditConfig(env, sub, tier) {
365
+ const key = `credits:config:${sub}`;
366
+ const raw = await env.CARRIER_USERS.get(key, "json").catch(() => null);
367
+ if (raw && typeof raw === "object" && "billing_threshold_cents" in raw) {
368
+ return raw;
369
+ }
370
+ // Default config
371
+ return {
372
+ billing_threshold_cents: DEFAULT_BILLING_THRESHOLD_CENTS,
373
+ overages_enabled: tier !== "free",
374
+ rollovers_enabled: tier !== "free",
375
+ overage_rate_cents: OVERAGE_PRICE_PER_CREDIT_CENTS,
376
+ volume_discount_pct: 0,
377
+ notify_at_pct: [50, 80, 95, 100],
378
+ updated_at: new Date().toISOString(),
379
+ };
380
+ }
381
+ // ---------------------------------------------------------------------------
382
+ // Admin: Update Credit Config
383
+ // ---------------------------------------------------------------------------
384
+ /**
385
+ * Update a user's credit configuration (admin or self-service).
386
+ */
387
+ export async function updateCreditConfig(env, sub, updates) {
388
+ const tier = await resolveUserTier(env, sub);
389
+ const current = await getCreditConfig(env, sub, tier);
390
+ const updated = {
391
+ ...current,
392
+ ...updates,
393
+ updated_at: new Date().toISOString(),
394
+ };
395
+ const key = `credits:config:${sub}`;
396
+ await env.CARRIER_USERS.put(key, JSON.stringify(updated));
397
+ return updated;
398
+ }
399
+ /**
400
+ * Get credit usage summary for a user (used by billing UI).
401
+ */
402
+ export async function getCreditSummary(env, sub, tier) {
403
+ const month = currentMonth();
404
+ const today = currentDay();
405
+ const ledger = await getLedger(env, sub, month, tier);
406
+ const dailyFree = await getDailyFreeCredits(env, sub, today);
407
+ const config = await getCreditConfig(env, sub, tier);
408
+ const rolloverRaw = await env.CARRIER_USERS.get(`credits:rollover:${sub}`, "json").catch(() => null);
409
+ const rollover = rolloverRaw;
410
+ const volumeDiscount = resolveVolumeDiscount(ledger.consumed);
411
+ return { ledger, daily_free: dailyFree, config, rollover, volume_discount_pct: volumeDiscount };
412
+ }
413
+ // ---------------------------------------------------------------------------
414
+ // Stripe Credit Grants
415
+ // ---------------------------------------------------------------------------
416
+ /**
417
+ * Issue a credit grant to a customer via Stripe Customer Balance Transactions.
418
+ * Used for promotional credits, referral bonuses, and compensation.
419
+ */
420
+ export async function issueStripeCredits(env, sub, amountCents, description) {
421
+ const stripeKey = env.STRIPE_SECRET_KEY;
422
+ if (!stripeKey)
423
+ return false;
424
+ const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);
425
+ if (!customerId)
426
+ return false;
427
+ const body = new URLSearchParams({
428
+ amount: String(-Math.abs(amountCents)), // Negative = credit to customer
429
+ currency: "usd",
430
+ description,
431
+ });
432
+ const resp = await fetch(`https://api.stripe.com/v1/customers/${customerId}/balance_transactions`, {
433
+ method: "POST",
434
+ headers: {
435
+ Authorization: `Bearer ${stripeKey}`,
436
+ "Content-Type": "application/x-www-form-urlencoded",
437
+ },
438
+ body: body.toString(),
439
+ });
440
+ return resp.ok;
441
+ }
442
+ // ---------------------------------------------------------------------------
443
+ // Internal Helpers
444
+ // ---------------------------------------------------------------------------
445
+ async function resolveUserTier(env, sub) {
446
+ const raw = await env.CARRIER_USERS.get(`user:${sub}`, "json").catch(() => null);
447
+ if (raw && typeof raw === "object" && "tier" in raw) {
448
+ const t = raw.tier;
449
+ if (t === "pro" || t === "enterprise")
450
+ return t;
451
+ }
452
+ return "free";
453
+ }
454
+ function currentMonth() {
455
+ const now = new Date();
456
+ return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, "0")}`;
457
+ }
458
+ function currentDay() {
459
+ const now = new Date();
460
+ return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, "0")}${String(now.getUTCDate()).padStart(2, "0")}`;
461
+ }
462
+ function previousMonth() {
463
+ const now = new Date();
464
+ const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 1, 1));
465
+ return `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, "0")}`;
466
+ }
467
+ function firstDayNextMonth() {
468
+ const now = new Date();
469
+ const y = now.getUTCFullYear();
470
+ const m = now.getUTCMonth() + 1;
471
+ if (m === 12)
472
+ return new Date(Date.UTC(y + 1, 0, 1)).toISOString();
473
+ return new Date(Date.UTC(y, m, 1)).toISOString();
474
+ }
475
+ function firstDayMonthAfterNext() {
476
+ const now = new Date();
477
+ const y = now.getUTCFullYear();
478
+ const m = now.getUTCMonth() + 2;
479
+ if (m >= 12)
480
+ return new Date(Date.UTC(y + 1, m - 12, 1)).toISOString();
481
+ return new Date(Date.UTC(y, m, 1)).toISOString();
482
+ }
483
+ //# sourceMappingURL=credits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credits.js","sourceRoot":"","sources":["../src/credits.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,19 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @carrierllc/mcp — stdio entry point.
3
+ * Carrier MCP single-user stdio entry point (MCPB / DXT bundle target).
4
4
  *
5
- * Single-user stdio MCP server. Reads ESIMVAULT_API_TOKEN (or CARRIER_OCS_API_TOKEN)
6
- * and CARRIER_OCS_BASE_URL from env. No OAuth direct OCS access.
5
+ * Reads CARRIER_OCS_API_TOKEN from env; calls OCS directly with that token.
6
+ * No OAuth, no Workers for local Claude Desktop installs via the .mcpb bundle.
7
7
  *
8
- * Usage:
9
- * ESIMVAULT_API_TOKEN=<token> npx -y @carrierllc/mcp
8
+ * For multi-user deployments, use the remote OAuth endpoint at mcp.carrier.llc/mcp.
10
9
  *
11
- * MCP config (Claude Desktop / Cursor / Windsurf):
12
- * {
13
- * "command": "npx",
14
- * "args": ["-y", "@carrierllc/mcp"],
15
- * "env": { "ESIMVAULT_API_TOKEN": "YOUR_KEY" }
16
- * }
10
+ * Tool registry MUST mirror agent.ts exactly so that generate-docs / verify-fidelity
11
+ * produce the same tool list as the deployed Worker.
17
12
  */
18
13
  export {};
19
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/index.js CHANGED
@@ -1,43 +1,94 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @carrierllc/mcp — stdio entry point.
3
+ * Carrier MCP single-user stdio entry point (MCPB / DXT bundle target).
4
4
  *
5
- * Single-user stdio MCP server. Reads ESIMVAULT_API_TOKEN (or CARRIER_OCS_API_TOKEN)
6
- * and CARRIER_OCS_BASE_URL from env. No OAuth direct OCS access.
5
+ * Reads CARRIER_OCS_API_TOKEN from env; calls OCS directly with that token.
6
+ * No OAuth, no Workers for local Claude Desktop installs via the .mcpb bundle.
7
7
  *
8
- * Usage:
9
- * ESIMVAULT_API_TOKEN=<token> npx -y @carrierllc/mcp
8
+ * For multi-user deployments, use the remote OAuth endpoint at mcp.carrier.llc/mcp.
10
9
  *
11
- * MCP config (Claude Desktop / Cursor / Windsurf):
12
- * {
13
- * "command": "npx",
14
- * "args": ["-y", "@carrierllc/mcp"],
15
- * "env": { "ESIMVAULT_API_TOKEN": "YOUR_KEY" }
16
- * }
10
+ * Tool registry MUST mirror agent.ts exactly so that generate-docs / verify-fidelity
11
+ * produce the same tool list as the deployed Worker.
17
12
  */
18
13
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
19
14
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
20
- import { OcsClient } from "./client.js";
21
15
  import { registerAllTools } from "./tools.js";
22
- import { registerAllIntelligenceTools } from "./intelligence.js";
16
+ import { registerIntelligenceTools } from "./intelligence.js";
17
+ import { registerAllBacklogTools } from "./tools-backlog.js";
18
+ import { registerAllCarrierAskTools } from "./tools-carrier-ask.js";
19
+ import { registerListRecentOcsEventsTool } from "./list-recent-ocs-events.js";
20
+ import { registerAllApps } from "./apps/index.js";
23
21
  import { registerAllPrompts } from "./prompts.js";
22
+ import { registerAllPricingTools } from "./tools-pricing.js";
23
+ import { registerScheduleAndUsageTools } from "./tools-ui-agent-schedule.js";
24
+ import { registerAllUiAgentTools } from "./tools-ui-agent.js";
25
+ import { registerUiAgentAskTools } from "./tools-ui-agent-ask.js";
26
+ import { registerStripeConnectTools } from "./stripe-connect-tools.js";
24
27
  const baseUrl = process.env.CARRIER_OCS_BASE_URL ??
25
28
  process.env.ESIMVAULT_BASE_URL ??
26
29
  "https://ocs.esimvault.cloud";
27
- const token = process.env.ESIMVAULT_API_TOKEN ??
28
- process.env.CARRIER_OCS_API_TOKEN;
30
+ const token = process.env.CARRIER_OCS_API_TOKEN ?? process.env.ESIMVAULT_API_TOKEN;
29
31
  if (!token) {
30
- process.stderr.write("ERROR: ESIMVAULT_API_TOKEN (or CARRIER_OCS_API_TOKEN) must be set.\n" +
31
- "Get a key at https://mcp.carrier.llc\n");
32
+ console.error("ERROR: CARRIER_OCS_API_TOKEN (or legacy ESIMVAULT_API_TOKEN) must be set.");
32
33
  process.exit(1);
33
34
  }
34
- const client = new OcsClient(baseUrl, token);
35
- const server = new McpServer({ name: "carrier-mcp", version: "0.1.0" }, {
36
- instructions: "Carrier MCP direct eSIMVault OCS access via stdio. 51 tools for MVNO/eSIM fleet management. " +
37
- "43 OCS tools (read/write/admin) + 8 intelligence composites + 5 prompts.",
35
+ // Minimal env shim stdio mode never touches KV/R2/AE/secrets at runtime.
36
+ // CF-only bindings (OAUTH_KV, OCS_EVENT_ROUTING, ASSETS, CARRIER_USERS, DOWNLOADS)
37
+ // are stubbed so that tool *registration* succeeds; their handlers would error if
38
+ // actually invoked in stdio mode (acceptable these tools require the Workers runtime).
39
+ const stdioEnv = {
40
+ CARRIER_OCS_BASE_URL: baseUrl,
41
+ CARRIER_TOKEN_ENCRYPTION_KEY: "",
42
+ SENTRY_DSN: "",
43
+ CLERK_PUBLISHABLE_KEY: "",
44
+ CLERK_SECRET_KEY: "",
45
+ CLERK_WEBHOOK_SECRET: "",
46
+ AUDIT_LOG: { writeDataPoint: (_) => undefined },
47
+ OAUTH_KV: null,
48
+ OCS_EVENT_ROUTING: null,
49
+ ASSETS: null,
50
+ CARRIER_USERS: null,
51
+ DOWNLOADS: null,
52
+ MANUS_API_KEY: "",
53
+ STRIPE_SECRET_KEY: "",
54
+ };
55
+ const props = {
56
+ sub: "stdio@local",
57
+ reseller_id: 0,
58
+ reseller_name: "stdio",
59
+ tier: "enterprise",
60
+ scope: ["read", "write", "admin"],
61
+ };
62
+ const audit = (_row) => {
63
+ // no-op in stdio mode
64
+ };
65
+ const getUserToken = async (_sub) => token;
66
+ const toolCtx = { env: stdioEnv, props, audit, getUserToken };
67
+ const server = new McpServer({ name: "carrier-mcp", version: "0.2.0" }, {
68
+ instructions: "Carrier MCP — single-user stdio mode. Full tool registry (mirrors the deployed Worker).",
38
69
  });
39
- registerAllTools(server, client);
40
- registerAllIntelligenceTools(server, client);
70
+ // v1: 43 OCS API wrappers
71
+ registerAllTools(server, toolCtx);
72
+ // v1 intelligence: 8 AI composite tools
73
+ registerIntelligenceTools(server, toolCtx);
74
+ // v1.1 backlog: 8 confirmed-live OCS methods
75
+ registerAllBacklogTools(server, toolCtx);
76
+ // NL router: carrier_ask + carrier_ask_describe
77
+ registerAllCarrierAskTools(server, toolCtx);
78
+ // OCS event ring-buffer tool
79
+ registerListRecentOcsEventsTool(server, stdioEnv);
80
+ // v1.2 MCP Apps (fleet-health, provisioning-wizard, balance-topup)
81
+ registerAllApps(server, toolCtx);
82
+ // Pricing + projects tools
83
+ registerAllPricingTools(server, toolCtx);
84
+ // UI agent schedule + usage tools
85
+ registerScheduleAndUsageTools(server, toolCtx);
86
+ // UI agent write tools
87
+ registerAllUiAgentTools(server, toolCtx);
88
+ // UI agent ask/reply tools
89
+ registerUiAgentAskTools(server, toolCtx);
90
+ // Stripe Connect + Radar tools
91
+ registerStripeConnectTools(server, { env: stdioEnv, props });
41
92
  registerAllPrompts(server);
42
93
  const transport = new StdioServerTransport();
43
94
  await server.connect(transport);