@carrierllc/mcp 0.9.1 → 0.9.2

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/cli.js CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  verifyStorefront,
40
40
  walletScreen,
41
41
  which
42
- } from "./chunk-V4CYEMLJ.js";
42
+ } from "./chunk-4XHSOF62.js";
43
43
  import {
44
44
  copyTree,
45
45
  exists,
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  subscriberIdParams,
38
38
  usageOverPeriodParams,
39
39
  verifyStorefront
40
- } from "./chunk-V4CYEMLJ.js";
40
+ } from "./chunk-4XHSOF62.js";
41
41
  import "./chunk-SHKKVIIA.js";
42
42
 
43
43
  // src/index.ts
@@ -234,12 +234,12 @@ function body(req) {
234
234
  ...req.tools ? { tools: req.tools, tool_choice: { type: "any" } } : {}
235
235
  };
236
236
  }
237
- function headersFor(req, accept) {
237
+ function headersFor(attribution, accept) {
238
238
  const headers = {
239
239
  "Content-Type": "application/json",
240
240
  Accept: accept
241
241
  };
242
- const meta = req.attribution ? requestMetadata(req.attribution) : null;
242
+ const meta = attribution ? requestMetadata(attribution) : null;
243
243
  if (meta) headers[REQUEST_METADATA_HEADER] = JSON.stringify(meta);
244
244
  return headers;
245
245
  }
@@ -261,27 +261,34 @@ async function fail(resp) {
261
261
  throw new BedrockError(text || `Bedrock returned HTTP ${resp.status}`, resp.status);
262
262
  }
263
263
  async function invokeTool(creds, req, signal) {
264
+ const json = await invokeModelRaw(
265
+ creds,
266
+ body(req),
267
+ { attribution: req.attribution, timeoutMs: req.timeoutMs },
268
+ signal
269
+ );
270
+ reportUsage(req, extractUsage(json));
271
+ const block = json.content?.find((b) => b.type === "tool_use");
272
+ return block?.name ? { name: block.name, input: block.input ?? {} } : null;
273
+ }
274
+ async function invokeModelRaw(creds, payload, opts = {}, signal) {
264
275
  const { aws, region, modelId } = client(creds);
265
276
  const controller = new AbortController();
266
- const timer = setTimeout(() => controller.abort(), req.timeoutMs ?? BEDROCK_TIMEOUT_MS);
277
+ const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? BEDROCK_TIMEOUT_MS);
267
278
  const onAbort = () => controller.abort();
268
279
  signal?.addEventListener("abort", onAbort, { once: true });
269
280
  try {
270
- const headers = headersFor(req, "application/json");
271
281
  const resp = await aws.fetch(
272
282
  `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`,
273
283
  {
274
284
  method: "POST",
275
- headers,
276
- body: JSON.stringify(body(req)),
285
+ headers: headersFor(opts.attribution, "application/json"),
286
+ body: JSON.stringify(payload),
277
287
  signal: controller.signal
278
288
  }
279
289
  );
280
290
  if (!resp.ok) await fail(resp);
281
- const json = await resp.json();
282
- reportUsage(req, extractUsage(json));
283
- const block = json.content?.find((b) => b.type === "tool_use");
284
- return block?.name ? { name: block.name, input: block.input ?? {} } : null;
291
+ return await resp.json();
285
292
  } finally {
286
293
  clearTimeout(timer);
287
294
  signal?.removeEventListener("abort", onAbort);
@@ -5528,6 +5535,21 @@ function computeExpiresAt(askedAt) {
5528
5535
  if (isNaN(asked)) return "";
5529
5536
  return new Date(asked + PENDING_ASK_TTL_SECONDS * 1e3).toISOString();
5530
5537
  }
5538
+ async function callerOwnsTask(ctx, taskId) {
5539
+ let raw;
5540
+ try {
5541
+ raw = await ctx.env.CARRIER_USERS.get(`steel_task:${taskId}`);
5542
+ } catch {
5543
+ return false;
5544
+ }
5545
+ if (!raw) return false;
5546
+ try {
5547
+ const task = JSON.parse(raw);
5548
+ return task.owner_sub !== void 0 && task.owner_sub === ctx.props.sub;
5549
+ } catch {
5550
+ return false;
5551
+ }
5552
+ }
5531
5553
  function registerUiAgentAskTools(server2, ctx) {
5532
5554
  server2.registerTool(
5533
5555
  "ui_agent_reply",
@@ -5577,7 +5599,7 @@ function registerUiAgentAskTools(server2, ctx) {
5577
5599
  }
5578
5600
  const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;
5579
5601
  const pendingRaw = await ctx.env.CARRIER_USERS.get(pendingKey);
5580
- if (pendingRaw === null) {
5602
+ if (pendingRaw === null || !await callerOwnsTask(ctx, task_id)) {
5581
5603
  return {
5582
5604
  isError: true,
5583
5605
  content: [
@@ -5719,6 +5741,8 @@ function registerUiAgentAskTools(server2, ctx) {
5719
5741
  if (!raw) return null;
5720
5742
  try {
5721
5743
  const parsed = JSON.parse(raw);
5744
+ const taskId = parsed.task_id ?? name.slice(PENDING_ASK_PREFIX.length);
5745
+ if (!await callerOwnsTask(ctx, taskId)) return null;
5722
5746
  return {
5723
5747
  ...parsed,
5724
5748
  expires_at: computeExpiresAt(parsed.asked_at)
@@ -6696,6 +6720,33 @@ async function resolveBillingSub(env, orgId) {
6696
6720
  return pointer ?? orgId;
6697
6721
  }
6698
6722
 
6723
+ // src/scope-guard.ts
6724
+ function denyUnlessScoped(props2, toolName, scopes) {
6725
+ const required = scopes[toolName];
6726
+ if (required === void 0) {
6727
+ return {
6728
+ isError: true,
6729
+ content: [
6730
+ {
6731
+ type: "text",
6732
+ text: `Scope denied: tool '${toolName}' declares no scope, so it cannot be authorised. This is a server-side omission \u2014 add it to the tool's scope table.`
6733
+ }
6734
+ ]
6735
+ };
6736
+ }
6737
+ const held = props2.scope ?? [];
6738
+ if (held.includes(required)) return null;
6739
+ return {
6740
+ isError: true,
6741
+ content: [
6742
+ {
6743
+ type: "text",
6744
+ text: `Scope denied: tool '${toolName}' requires '${required}' scope. Your token has: [${held.join(", ")}].`
6745
+ }
6746
+ ]
6747
+ };
6748
+ }
6749
+
6699
6750
  // src/wallet-tools.ts
6700
6751
  var PACKS = [
6701
6752
  { id: "pack_500", eurCents: 5e4, bonusPct: 0 },
@@ -6892,6 +6943,8 @@ function registerWalletTools(server2, ctx) {
6892
6943
  annotations: annotationsFor("wallet_balance", "read")
6893
6944
  },
6894
6945
  async () => {
6946
+ const denied = denyUnlessScoped(props2, "wallet_balance", WALLET_TOOL_SCOPES);
6947
+ if (denied) return denied;
6895
6948
  const orgId = defaultOrgId;
6896
6949
  const start = Date.now();
6897
6950
  try {
@@ -6934,6 +6987,8 @@ function registerWalletTools(server2, ctx) {
6934
6987
  annotations: annotationsFor("wallet_topup_checkout", "write")
6935
6988
  },
6936
6989
  async ({ pack }) => {
6990
+ const denied = denyUnlessScoped(props2, "wallet_topup_checkout", WALLET_TOOL_SCOPES);
6991
+ if (denied) return denied;
6937
6992
  const orgId = defaultOrgId;
6938
6993
  const start = Date.now();
6939
6994
  if (!pack) {
@@ -6993,6 +7048,8 @@ function registerWalletTools(server2, ctx) {
6993
7048
  annotations: annotationsFor("wallet_auto_topup", "write")
6994
7049
  },
6995
7050
  async ({ pack_cents }) => {
7051
+ const denied = denyUnlessScoped(props2, "wallet_auto_topup", WALLET_TOOL_SCOPES);
7052
+ if (denied) return denied;
6996
7053
  const orgId = defaultOrgId;
6997
7054
  const start = Date.now();
6998
7055
  try {
@@ -7103,6 +7160,8 @@ function registerStripeConnectTools(server2, ctx) {
7103
7160
  annotations: annotationsFor("stripe_connect_status", "read")
7104
7161
  },
7105
7162
  async ({ operator_id }) => {
7163
+ const denied = denyUnlessScoped(props2, "stripe_connect_status", STRIPE_CONNECT_TOOL_SCOPES);
7164
+ if (denied) return denied;
7106
7165
  if (operator_id !== void 0 && operator_id !== operatorId) {
7107
7166
  if (!isPlatformOperator(env, props2.org_id)) {
7108
7167
  return err2(
@@ -7163,6 +7222,8 @@ function registerStripeConnectTools(server2, ctx) {
7163
7222
  annotations: annotationsFor("stripe_connect_payouts", "read")
7164
7223
  },
7165
7224
  async ({ limit, status }) => {
7225
+ const denied = denyUnlessScoped(props2, "stripe_connect_payouts", STRIPE_CONNECT_TOOL_SCOPES);
7226
+ if (denied) return denied;
7166
7227
  const start = Date.now();
7167
7228
  try {
7168
7229
  const stripeKey = env.STRIPE_SECRET_KEY;
@@ -7198,6 +7259,8 @@ function registerStripeConnectTools(server2, ctx) {
7198
7259
  annotations: annotationsFor("stripe_connect_balance", "read")
7199
7260
  },
7200
7261
  async () => {
7262
+ const denied = denyUnlessScoped(props2, "stripe_connect_balance", STRIPE_CONNECT_TOOL_SCOPES);
7263
+ if (denied) return denied;
7201
7264
  const start = Date.now();
7202
7265
  try {
7203
7266
  const stripeKey = env.STRIPE_SECRET_KEY;
@@ -7240,6 +7303,8 @@ function registerStripeConnectTools(server2, ctx) {
7240
7303
  annotations: annotationsFor("stripe_connect_refund", "write")
7241
7304
  },
7242
7305
  async ({ charge_id, amount_cents, reason, confirm_token }) => {
7306
+ const denied = denyUnlessScoped(props2, "stripe_connect_refund", STRIPE_CONNECT_TOOL_SCOPES);
7307
+ if (denied) return denied;
7243
7308
  const start = Date.now();
7244
7309
  const toolName = "stripe_connect_refund";
7245
7310
  if (!confirm_token) {
@@ -7292,6 +7357,8 @@ Call again with confirm_token="${token2}" to execute. Token expires in 5 minutes
7292
7357
  annotations: annotationsFor("stripe_connect_dispute_list", "read")
7293
7358
  },
7294
7359
  async ({ limit, status }) => {
7360
+ const denied = denyUnlessScoped(props2, "stripe_connect_dispute_list", STRIPE_CONNECT_TOOL_SCOPES);
7361
+ if (denied) return denied;
7295
7362
  const start = Date.now();
7296
7363
  try {
7297
7364
  const stripeKey = env.STRIPE_SECRET_KEY;
@@ -7330,6 +7397,13 @@ Call again with confirm_token="${token2}" to execute. Token expires in 5 minutes
7330
7397
  annotations: annotationsFor("radar_review_list", "read")
7331
7398
  },
7332
7399
  async ({ open_only, limit }) => {
7400
+ const denied = denyUnlessScoped(props2, "radar_review_list", STRIPE_CONNECT_TOOL_SCOPES);
7401
+ if (denied) return denied;
7402
+ if (!isPlatformOperator(env, props2.org_id)) {
7403
+ return err2(
7404
+ "This tool acts on Carrier's platform Stripe account and is restricted to Carrier's own organization."
7405
+ );
7406
+ }
7333
7407
  const start = Date.now();
7334
7408
  try {
7335
7409
  const stripeKey = env.STRIPE_SECRET_KEY;
@@ -7366,6 +7440,13 @@ Call again with confirm_token="${token2}" to execute. Token expires in 5 minutes
7366
7440
  annotations: annotationsFor("radar_review_approve", "admin")
7367
7441
  },
7368
7442
  async ({ review_id, confirm_token }) => {
7443
+ const denied = denyUnlessScoped(props2, "radar_review_approve", STRIPE_CONNECT_TOOL_SCOPES);
7444
+ if (denied) return denied;
7445
+ if (!isPlatformOperator(env, props2.org_id)) {
7446
+ return err2(
7447
+ "This tool acts on Carrier's platform Stripe account and is restricted to Carrier's own organization."
7448
+ );
7449
+ }
7369
7450
  const toolName = "radar_review_approve";
7370
7451
  const start = Date.now();
7371
7452
  if (!confirm_token) {
@@ -7415,6 +7496,13 @@ Call again with confirm_token="${token2}" to execute. Expires in 5 minutes.`
7415
7496
  annotations: annotationsFor("radar_review_decline", "admin")
7416
7497
  },
7417
7498
  async ({ review_id, confirm_token }) => {
7499
+ const denied = denyUnlessScoped(props2, "radar_review_decline", STRIPE_CONNECT_TOOL_SCOPES);
7500
+ if (denied) return denied;
7501
+ if (!isPlatformOperator(env, props2.org_id)) {
7502
+ return err2(
7503
+ "This tool acts on Carrier's platform Stripe account and is restricted to Carrier's own organization."
7504
+ );
7505
+ }
7418
7506
  const toolName = "radar_review_decline";
7419
7507
  const start = Date.now();
7420
7508
  if (!confirm_token) {
@@ -7465,6 +7553,13 @@ Expires in 5 minutes.`
7465
7553
  annotations: annotationsFor("radar_value_list_add", "admin")
7466
7554
  },
7467
7555
  async ({ value_list_id, value, confirm_token }) => {
7556
+ const denied = denyUnlessScoped(props2, "radar_value_list_add", STRIPE_CONNECT_TOOL_SCOPES);
7557
+ if (denied) return denied;
7558
+ if (!isPlatformOperator(env, props2.org_id)) {
7559
+ return err2(
7560
+ "This tool acts on Carrier's platform Stripe account and is restricted to Carrier's own organization."
7561
+ );
7562
+ }
7468
7563
  const toolName = "radar_value_list_add";
7469
7564
  const start = Date.now();
7470
7565
  if (!confirm_token) {
@@ -7514,6 +7609,13 @@ Expires in 5 minutes.`
7514
7609
  annotations: annotationsFor("radar_rule_toggle", "admin")
7515
7610
  },
7516
7611
  async ({ rule_id, enabled }) => {
7612
+ const denied = denyUnlessScoped(props2, "radar_rule_toggle", STRIPE_CONNECT_TOOL_SCOPES);
7613
+ if (denied) return denied;
7614
+ if (!isPlatformOperator(env, props2.org_id)) {
7615
+ return err2(
7616
+ "This tool acts on Carrier's platform Stripe account and is restricted to Carrier's own organization."
7617
+ );
7618
+ }
7517
7619
  return ok2(
7518
7620
  `Stripe Radar does not expose rule enable/disable via the public API.
7519
7621
  To ${enabled ? "enable" : "disable"} rule ${rule_id}:
@@ -10014,7 +10116,82 @@ function buildExamples(toolName) {
10014
10116
  // src/list-recent-ocs-events.ts
10015
10117
  import { z as z12 } from "zod";
10016
10118
 
10119
+ // src/ocs-scoping.ts
10120
+ function managedOwnAccountId(auth) {
10121
+ if (!auth.managed || auth.accountId === void 0) return void 0;
10122
+ const n = Number(auth.accountId);
10123
+ return Number.isFinite(n) ? n : void 0;
10124
+ }
10125
+ function subscriberAccountId(data) {
10126
+ if (!data || typeof data !== "object") return void 0;
10127
+ const root = data;
10128
+ const sub = root.subscriber && typeof root.subscriber === "object" ? root.subscriber : root;
10129
+ const raw = sub.accountId ?? sub.account_id ?? sub.account;
10130
+ if (raw === void 0 || raw === null) return void 0;
10131
+ const n = Number(raw);
10132
+ return Number.isFinite(n) ? n : void 0;
10133
+ }
10134
+ function isManagedSubscriberDenied(auth, subscriberData) {
10135
+ const ownId = managedOwnAccountId(auth);
10136
+ if (ownId === void 0) return false;
10137
+ const subAccountId = subscriberAccountId(subscriberData);
10138
+ if (subAccountId === void 0) return true;
10139
+ return subAccountId !== ownId;
10140
+ }
10141
+ async function assertManagedIccidAccess(baseUrl2, auth, iccid) {
10142
+ if (managedOwnAccountId(auth) === void 0) return { ok: true };
10143
+ try {
10144
+ const client2 = new OcsClient(baseUrl2, auth.token);
10145
+ const data = await client2.call("getSingleSubscriber", { iccid });
10146
+ if (isManagedSubscriberDenied(auth, data)) {
10147
+ return { ok: false, error: "Subscriber not found" };
10148
+ }
10149
+ return { ok: true };
10150
+ } catch (err7) {
10151
+ return {
10152
+ ok: false,
10153
+ error: err7 instanceof Error ? err7.message : String(err7)
10154
+ };
10155
+ }
10156
+ }
10157
+
10017
10158
  // ../../packages/ocs-spec/src/ocs-event-buffer-read.ts
10159
+ function ocsEventRingBufferIccidFromDigitsReference(raw) {
10160
+ const digits = raw.replace(/\D/g, "");
10161
+ if (digits.length === 0) {
10162
+ throw new Error("reference must contain at least one digit");
10163
+ }
10164
+ if (digits.length > 20) {
10165
+ return digits.slice(-20);
10166
+ }
10167
+ if (digits.length >= 19) {
10168
+ return digits;
10169
+ }
10170
+ return digits.padStart(19, "0");
10171
+ }
10172
+ function msisdnFieldFromSubscriberPayload(data) {
10173
+ if (!data || typeof data !== "object") return null;
10174
+ const r = data;
10175
+ const v = r["msisdn"] ?? r["MSISDN"];
10176
+ if (v === void 0 || v === null) return null;
10177
+ if (typeof v === "string") return /\d/.test(v) ? v : null;
10178
+ if (typeof v === "number") return String(v);
10179
+ return null;
10180
+ }
10181
+ function mergeOcsEventOutputsNewestFirst(parts, limit) {
10182
+ const seen = /* @__PURE__ */ new Set();
10183
+ const out = [];
10184
+ const combined = [...parts].flat().sort(
10185
+ (x, y) => x.timestamp < y.timestamp ? 1 : x.timestamp > y.timestamp ? -1 : x.event_id.localeCompare(y.event_id)
10186
+ );
10187
+ for (const e of combined) {
10188
+ if (seen.has(e.event_id)) continue;
10189
+ seen.add(e.event_id);
10190
+ out.push(e);
10191
+ if (out.length >= limit) break;
10192
+ }
10193
+ return out;
10194
+ }
10018
10195
  async function listRecentOcsEvents(iccid, limit, eventTypes, since, kv) {
10019
10196
  const routingRaw = await kv.get(`iccid:${iccid}`, "json");
10020
10197
  const resellerId = routingRaw?.reseller_id ?? 0;
@@ -10097,7 +10274,8 @@ var listRecentOcsEventsSchema = {
10097
10274
  async function listRecentOcsEvents2(iccid, limit, eventTypes, since, kv) {
10098
10275
  return listRecentOcsEvents(iccid, limit, eventTypes, since, kv);
10099
10276
  }
10100
- function registerListRecentOcsEventsTool(server2, env) {
10277
+ function registerListRecentOcsEventsTool(server2, ctx) {
10278
+ const env = ctx.env;
10101
10279
  server2.registerTool(
10102
10280
  "list_recent_ocs_events",
10103
10281
  {
@@ -10113,6 +10291,19 @@ function registerListRecentOcsEventsTool(server2, env) {
10113
10291
  async (args) => {
10114
10292
  const { iccid, limit, event_types, since } = args;
10115
10293
  try {
10294
+ if (managedOwnAccountId(ctx.managedAuth) !== void 0) {
10295
+ const access = await assertManagedIccidAccess(
10296
+ env.CARRIER_OCS_BASE_URL,
10297
+ { token: await ctx.getUserToken(ctx.props.sub), ...ctx.managedAuth },
10298
+ iccid
10299
+ );
10300
+ if (!access.ok) {
10301
+ return {
10302
+ isError: true,
10303
+ content: [{ type: "text", text: access.error }]
10304
+ };
10305
+ }
10306
+ }
10116
10307
  const result2 = await listRecentOcsEvents2(
10117
10308
  iccid,
10118
10309
  limit,
@@ -10230,6 +10421,20 @@ function ok5(payload) {
10230
10421
  function err5(message) {
10231
10422
  return { isError: true, content: [{ type: "text", text: message }] };
10232
10423
  }
10424
+ async function ownershipToken(ctx) {
10425
+ if (managedOwnAccountId(ctx.managedAuth) === void 0) return null;
10426
+ return ctx.getUserToken(ctx.props.sub);
10427
+ }
10428
+ async function ownsEvent(ctx, token2, iccid) {
10429
+ if (token2 === null) return true;
10430
+ if (!iccid) return false;
10431
+ const access = await assertManagedIccidAccess(
10432
+ ctx.env.CARRIER_OCS_BASE_URL,
10433
+ { token: token2, ...ctx.managedAuth },
10434
+ iccid
10435
+ );
10436
+ return access.ok;
10437
+ }
10233
10438
  function registerDepletionEventsTool(server2, ctx) {
10234
10439
  server2.registerTool(
10235
10440
  "subscriber_depletion_events",
@@ -10259,6 +10464,14 @@ function registerDepletionEventsTool(server2, ctx) {
10259
10464
  );
10260
10465
  }
10261
10466
  const { subscriberId, since } = args;
10467
+ let scopeToken;
10468
+ try {
10469
+ scopeToken = await ownershipToken(ctx);
10470
+ } catch (e) {
10471
+ return err5(
10472
+ `Could not resolve the OCS credential needed to scope this read: ${e instanceof Error ? e.message : String(e)}`
10473
+ );
10474
+ }
10262
10475
  if (subscriberId) {
10263
10476
  const raw = await kv.get(`bundle-depleted:${subscriberId}`, "text");
10264
10477
  if (!raw) {
@@ -10280,6 +10493,14 @@ function registerDepletionEventsTool(server2, ctx) {
10280
10493
  note: "Stored depletion entry was invalid JSON and was ignored."
10281
10494
  });
10282
10495
  }
10496
+ if (!await ownsEvent(ctx, scopeToken, event.iccid)) {
10497
+ return ok5({
10498
+ subscriber_id: subscriberId,
10499
+ depleted: false,
10500
+ event: null,
10501
+ note: "No bundle depletion event found in the last 7 days."
10502
+ });
10503
+ }
10283
10504
  if (since && event.depletedAt < since) {
10284
10505
  return ok5({
10285
10506
  subscriber_id: subscriberId,
@@ -10316,6 +10537,7 @@ function registerDepletionEventsTool(server2, ctx) {
10316
10537
  try {
10317
10538
  const ev = JSON.parse(raw);
10318
10539
  if (since && ev.depletedAt < since) return;
10540
+ if (!await ownsEvent(ctx, scopeToken, ev.iccid)) return;
10319
10541
  events.push({
10320
10542
  subscriber_id: ev.subscriberId,
10321
10543
  iccid: ev.iccid,
@@ -10353,19 +10575,46 @@ function registerCountryHistoryTool(server2, ctx) {
10353
10575
  },
10354
10576
  wrapHandler(
10355
10577
  "subscriber_country_history",
10356
- "[country-history:kv]",
10578
+ "getSingleSubscriber",
10357
10579
  "read",
10358
10580
  ctx,
10359
- async ({ subscriberId, limit }) => {
10581
+ async ({ subscriberId, limit }, token2) => {
10360
10582
  const effectiveLimit = limit ?? 20;
10361
- const result2 = await listRecentOcsEvents2(
10583
+ const client2 = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token2);
10584
+ const subscriberPayload = await client2.call("getSingleSubscriber", {
10585
+ iccid: subscriberId
10586
+ });
10587
+ let syntheticRingIccid = null;
10588
+ const msisdnRaw = msisdnFieldFromSubscriberPayload(subscriberPayload);
10589
+ if (msisdnRaw) {
10590
+ try {
10591
+ const k = ocsEventRingBufferIccidFromDigitsReference(msisdnRaw);
10592
+ if (k !== subscriberId) syntheticRingIccid = k;
10593
+ } catch {
10594
+ syntheticRingIccid = null;
10595
+ }
10596
+ }
10597
+ const primary = await listRecentOcsEvents(
10362
10598
  subscriberId,
10363
10599
  effectiveLimit,
10364
10600
  ["country.entered"],
10365
10601
  void 0,
10366
10602
  ctx.env.OCS_EVENT_ROUTING
10367
10603
  );
10368
- const countryEvents = result2.events;
10604
+ let countryEvents = primary.events;
10605
+ if (syntheticRingIccid) {
10606
+ const secondary = await listRecentOcsEvents(
10607
+ syntheticRingIccid,
10608
+ effectiveLimit,
10609
+ ["country.entered"],
10610
+ void 0,
10611
+ ctx.env.OCS_EVENT_ROUTING
10612
+ );
10613
+ countryEvents = mergeOcsEventOutputsNewestFirst(
10614
+ [primary.events, secondary.events],
10615
+ effectiveLimit
10616
+ );
10617
+ }
10369
10618
  return {
10370
10619
  content: [
10371
10620
  {
@@ -10383,7 +10632,7 @@ function registerCountryHistoryTool(server2, ctx) {
10383
10632
  source: e.data["source"] ?? "relay-lu"
10384
10633
  })),
10385
10634
  total_country_events: countryEvents.length,
10386
- total_in_buffer: result2.total_in_buffer,
10635
+ total_in_buffer: primary.total_in_buffer,
10387
10636
  note: countryEvents.length === 0 ? "No cross-border events recorded in the 24h ring-buffer for this subscriber." : void 0
10388
10637
  },
10389
10638
  null,
@@ -11949,7 +12198,13 @@ var props = {
11949
12198
  var audit = (_row) => {
11950
12199
  };
11951
12200
  var getUserToken = async (_sub) => token;
11952
- var toolCtx = { env: stdioEnv, props, audit, getUserToken };
12201
+ var toolCtx = {
12202
+ env: stdioEnv,
12203
+ props,
12204
+ managedAuth: {},
12205
+ audit,
12206
+ getUserToken
12207
+ };
11953
12208
  var server = new McpServer(
11954
12209
  { name: "carrier-mcp", version: CARRIER_VERSION },
11955
12210
  {
@@ -11961,7 +12216,7 @@ registerAllTools(server, toolCtx);
11961
12216
  registerIntelligenceTools(server, toolCtx);
11962
12217
  registerAllBacklogTools(server, toolCtx);
11963
12218
  registerAllCarrierAskTools(server, toolCtx);
11964
- registerListRecentOcsEventsTool(server, stdioEnv);
12219
+ registerListRecentOcsEventsTool(server, toolCtx);
11965
12220
  registerRateLimitStatusTool(server, toolCtx);
11966
12221
  registerCountryHistoryTool(server, toolCtx);
11967
12222
  registerDepletionEventsTool(server, toolCtx);