@carrierllc/mcp 0.13.39 → 0.13.41
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/README.md +11 -1
- package/dist/{chunk-I3Z5WYDG.js → chunk-6OAZJBLA.js} +13 -6
- package/dist/{chunk-I3Z5WYDG.js.map → chunk-6OAZJBLA.js.map} +1 -1
- package/dist/cli.js +29 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.js +160 -65
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/plugin/carrier/skills/wallet/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
verifyStorefront,
|
|
81
81
|
withOcsListSummary,
|
|
82
82
|
withTemplateResellerId
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-6OAZJBLA.js";
|
|
84
84
|
import "./chunk-SHKKVIIA.js";
|
|
85
85
|
|
|
86
86
|
// src/index.ts
|
|
@@ -89,8 +89,95 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
89
89
|
|
|
90
90
|
// src/tools.ts
|
|
91
91
|
import { z } from "zod";
|
|
92
|
+
|
|
93
|
+
// src/durable-issuance.ts
|
|
94
|
+
async function issueInventory(ctx, args, extra) {
|
|
95
|
+
const key = args.request_key;
|
|
96
|
+
const error = (code, message, detail = {}) => ({ isError: true, content: [{ type: "text", text: JSON.stringify({ ...detail, code, message, request_key: key }) }] });
|
|
97
|
+
const token2 = await ctx.getApiToken?.(extra);
|
|
98
|
+
if (!token2) return error("CARRIER_API_AUTH_REQUIRED", "An authenticated Carrier API credential is required. No dispatch made.");
|
|
99
|
+
const body2 = {
|
|
100
|
+
packageTemplateId: args.packageTemplateId,
|
|
101
|
+
...args.account_for_subs !== void 0 ? { accountId: args.account_for_subs } : {},
|
|
102
|
+
...Object.fromEntries(["startDate", "endDate", "validityPeriod"].filter((k) => args[k] !== void 0).map((k) => [k, args[k]])),
|
|
103
|
+
...args.business_reference !== void 0 ? { businessReference: args.business_reference } : {}
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
const response = await fetch(`${ctx.env.CARRIER_API_BASE_URL ?? "https://api.carrier.llc"}/v1/subscribers/issue-from-inventory`, {
|
|
107
|
+
method: "POST",
|
|
108
|
+
redirect: "error",
|
|
109
|
+
headers: { "Authorization": `Bearer ${token2}`, "Content-Type": "application/json", "X-Idempotency-Key": String(key) },
|
|
110
|
+
body: JSON.stringify(body2)
|
|
111
|
+
});
|
|
112
|
+
const payload = await response.json();
|
|
113
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload) || response.ok && !payload.data) throw new Error("Malformed API response");
|
|
114
|
+
if (response.status >= 500 && payload.code !== "OUTCOME_UNKNOWN" && payload.upstream_dispatched !== false) {
|
|
115
|
+
return error("OUTCOME_UNKNOWN", "Issuance outcome is unknown. Preserve this request_key for reconciliation; do not issue with a new key.", { api_error: payload });
|
|
116
|
+
}
|
|
117
|
+
return { ...!response.ok ? { isError: true } : {}, content: [{ type: "text", text: JSON.stringify({ ...payload, request_key: key }) }] };
|
|
118
|
+
} catch {
|
|
119
|
+
return error("OUTCOME_UNKNOWN", "Issuance outcome is unknown. Preserve this request_key for reconciliation; do not issue with a new key.");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/tools.ts
|
|
92
124
|
import * as Sentry from "@sentry/cloudflare";
|
|
93
125
|
|
|
126
|
+
// src/ocs-scoping.ts
|
|
127
|
+
function positiveAccountId(raw) {
|
|
128
|
+
if (typeof raw !== "number" && (typeof raw !== "string" || !/^[1-9]\d*$/.test(raw))) return void 0;
|
|
129
|
+
const id = Number(raw);
|
|
130
|
+
return Number.isSafeInteger(id) && id > 0 ? id : void 0;
|
|
131
|
+
}
|
|
132
|
+
function tenantAccountIds(auth) {
|
|
133
|
+
if (auth.managed) {
|
|
134
|
+
const id = positiveAccountId(auth.accountId);
|
|
135
|
+
return id === void 0 ? [] : [id];
|
|
136
|
+
}
|
|
137
|
+
if (auth.restricted) return (auth.allowedAccountIds ?? []).filter((id) => positiveAccountId(id) !== void 0);
|
|
138
|
+
if (auth.preferredAccountId !== void 0) {
|
|
139
|
+
const id = positiveAccountId(auth.preferredAccountId);
|
|
140
|
+
return id === void 0 ? [] : [id];
|
|
141
|
+
}
|
|
142
|
+
return void 0;
|
|
143
|
+
}
|
|
144
|
+
function managedOwnAccountId(auth) {
|
|
145
|
+
const ids = tenantAccountIds(auth);
|
|
146
|
+
return ids === void 0 ? void 0 : ids[0] ?? -1;
|
|
147
|
+
}
|
|
148
|
+
function subscriberAccountId(data) {
|
|
149
|
+
if (!data || typeof data !== "object") return void 0;
|
|
150
|
+
const root = data;
|
|
151
|
+
const sub = root.subscriber && typeof root.subscriber === "object" ? root.subscriber : root;
|
|
152
|
+
const raw = sub.accountId ?? sub.account_id ?? sub.account;
|
|
153
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
154
|
+
return positiveAccountId(raw);
|
|
155
|
+
}
|
|
156
|
+
function isManagedSubscriberDenied(auth, subscriberData) {
|
|
157
|
+
const ids = tenantAccountIds(auth);
|
|
158
|
+
if (ids === void 0) return false;
|
|
159
|
+
const subAccountId = subscriberAccountId(subscriberData);
|
|
160
|
+
return subAccountId === void 0 || !ids.includes(subAccountId);
|
|
161
|
+
}
|
|
162
|
+
async function assertManagedIccidAccess(baseUrl2, auth, iccid) {
|
|
163
|
+
const ids = tenantAccountIds(auth);
|
|
164
|
+
if (ids === void 0) return { ok: true };
|
|
165
|
+
if (ids.length === 0) return { ok: false, error: "Subscriber not found" };
|
|
166
|
+
try {
|
|
167
|
+
const client2 = new OcsClient(baseUrl2, auth.token);
|
|
168
|
+
const data = await client2.call("getSingleSubscriber", { iccid });
|
|
169
|
+
if (isManagedSubscriberDenied(auth, data)) {
|
|
170
|
+
return { ok: false, error: "Subscriber not found" };
|
|
171
|
+
}
|
|
172
|
+
return { ok: true };
|
|
173
|
+
} catch (err9) {
|
|
174
|
+
return {
|
|
175
|
+
ok: false,
|
|
176
|
+
error: err9 instanceof Error ? err9.message : String(err9)
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
94
181
|
// ../../packages/carrier-ai/dist/index.js
|
|
95
182
|
import { AwsClient } from "aws4fetch";
|
|
96
183
|
var AI_TIER_POLICY = {
|
|
@@ -1211,8 +1298,19 @@ var DESTRUCTIVE_TOOLS = /* @__PURE__ */ new Set([
|
|
|
1211
1298
|
// S6 live-smoke gap fill (CAR-105)
|
|
1212
1299
|
"change_network_profile_of_location_zone"
|
|
1213
1300
|
]);
|
|
1301
|
+
function assignPackageRefusal(args) {
|
|
1302
|
+
const hasIccid = typeof args.iccid === "string" && args.iccid.trim().length > 0;
|
|
1303
|
+
const conflict = hasIccid && (args.account_for_subs !== void 0 || args.business_reference !== void 0);
|
|
1304
|
+
const invalidKey = !hasIccid && (typeof args.request_key !== "string" || !/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,199}$/.test(args.request_key));
|
|
1305
|
+
if (conflict || invalidKey) return { isError: true, content: [{ type: "text", text: JSON.stringify({
|
|
1306
|
+
code: conflict ? "INVALID_ASSIGN_PACKAGE_INPUT" : "IDEMPOTENCY_KEY_REQUIRED",
|
|
1307
|
+
message: conflict ? "iccid and inventory/business reference are mutually exclusive. No changes made." : "Inventory requires a stable request_key (1\u2013200 characters: letters, digits, underscore, dot, colon, hyphen). No changes made.",
|
|
1308
|
+
request_key: args.request_key
|
|
1309
|
+
}) }] };
|
|
1310
|
+
return void 0;
|
|
1311
|
+
}
|
|
1214
1312
|
function wrapHandler(toolName, ocsMethod, requiredScope, ctx, handler, options) {
|
|
1215
|
-
return async (args) => {
|
|
1313
|
+
return async (args, extra) => {
|
|
1216
1314
|
const start = Date.now();
|
|
1217
1315
|
const isDryRun = args.dry_run === true;
|
|
1218
1316
|
if (!ctx.props.scope.includes(requiredScope)) {
|
|
@@ -1256,6 +1354,11 @@ function wrapHandler(toolName, ocsMethod, requiredScope, ctx, handler, options)
|
|
|
1256
1354
|
]
|
|
1257
1355
|
};
|
|
1258
1356
|
}
|
|
1357
|
+
const refusal = options?.validateArgs?.(args);
|
|
1358
|
+
if (refusal) {
|
|
1359
|
+
ctx.audit({ tool_name: toolName, ocs_method: ocsMethod, status: "error", dry_run: isDryRun, duration_ms: 0 });
|
|
1360
|
+
return refusal;
|
|
1361
|
+
}
|
|
1259
1362
|
if (isDryRun && DESTRUCTIVE_TOOLS.has(toolName)) {
|
|
1260
1363
|
ctx.audit({
|
|
1261
1364
|
tool_name: toolName,
|
|
@@ -1276,8 +1379,9 @@ function wrapHandler(toolName, ocsMethod, requiredScope, ctx, handler, options)
|
|
|
1276
1379
|
}
|
|
1277
1380
|
let result2;
|
|
1278
1381
|
try {
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1382
|
+
const skipToken = typeof options?.skipUserToken === "function" ? options.skipUserToken(args) : options?.skipUserToken;
|
|
1383
|
+
const token2 = skipToken ? "" : await ctx.getUserToken(ctx.props.sub);
|
|
1384
|
+
result2 = extra === void 0 ? await handler(args, token2) : await handler(args, token2, extra);
|
|
1281
1385
|
} catch (err9) {
|
|
1282
1386
|
try {
|
|
1283
1387
|
Sentry.captureException(err9, {
|
|
@@ -1931,16 +2035,21 @@ function registerAllTools(server2, ctx) {
|
|
|
1931
2035
|
server2.registerTool(
|
|
1932
2036
|
"assign_package",
|
|
1933
2037
|
{
|
|
1934
|
-
title: "Assign Package
|
|
1935
|
-
description: "
|
|
1936
|
-
inputSchema: {
|
|
1937
|
-
iccid: z.string().describe("
|
|
1938
|
-
packageTemplateId: z.number().describe("The package template ID to assign"),
|
|
1939
|
-
account_for_subs: z.number().optional().describe(
|
|
1940
|
-
|
|
1941
|
-
),
|
|
2038
|
+
title: "Assign Package or Issue From Inventory",
|
|
2039
|
+
description: "Assign a one-time prepaid package to an existing subscriber using iccid + packageTemplateId. Inventory issuance uses authenticated Carrier API POST /v1/subscribers/issue-from-inventory with request_key as X-Idempotency-Key. API authorization and its durable ledger are authoritative. Keep the same key after unknown outcomes; never automatically issue with a new key. Do not send both iccid and account_for_subs. Use assign_recurring_package for auto-renew.",
|
|
2040
|
+
inputSchema: z.object({
|
|
2041
|
+
iccid: z.string().optional().describe("Existing subscriber ICCID"),
|
|
2042
|
+
packageTemplateId: z.number().int().positive().describe("The package template ID to assign"),
|
|
2043
|
+
account_for_subs: z.number().int().positive().optional().describe("Inventory account sent as API accountId"),
|
|
2044
|
+
request_key: z.string().max(200).regex(/^[A-Za-z0-9][A-Za-z0-9_.:-]*$/).optional().describe("Required stable inventory key; preserve after unknown outcomes"),
|
|
2045
|
+
startDate: z.string().optional(),
|
|
2046
|
+
endDate: z.string().optional(),
|
|
2047
|
+
validityPeriod: z.number().int().positive().optional(),
|
|
2048
|
+
business_reference: z.object({ kind: z.literal("storefront_order"), id: z.string().min(1), line: z.literal("esim"), verb: z.literal("issue") }).strict().optional().describe("API-authorized existing order reference; not proof of ownership"),
|
|
1942
2049
|
...DRY_RUN_FIELD
|
|
1943
|
-
},
|
|
2050
|
+
}).refine((d) => !((d.account_for_subs !== void 0 || d.business_reference !== void 0) && typeof d.iccid === "string" && d.iccid.trim().length > 0), {
|
|
2051
|
+
message: "iccid and account_for_subs are mutually exclusive \u2014 choose one path"
|
|
2052
|
+
}),
|
|
1944
2053
|
annotations: { destructiveHint: true }
|
|
1945
2054
|
},
|
|
1946
2055
|
wrapHandler(
|
|
@@ -1948,17 +2057,34 @@ function registerAllTools(server2, ctx) {
|
|
|
1948
2057
|
"affectPackageToSubscriber",
|
|
1949
2058
|
TOOL_SCOPES["assign_package"],
|
|
1950
2059
|
ctx,
|
|
1951
|
-
async (
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
}
|
|
1957
|
-
|
|
2060
|
+
async (args, token2, extra) => {
|
|
2061
|
+
const { iccid, packageTemplateId } = args;
|
|
2062
|
+
if (typeof iccid !== "string" || !iccid.trim()) return issueInventory(ctx, args, extra);
|
|
2063
|
+
const access = await assertManagedIccidAccess(
|
|
2064
|
+
ctx.env.CARRIER_OCS_BASE_URL,
|
|
2065
|
+
{ ...ctx.managedAuth, token: token2 },
|
|
2066
|
+
iccid
|
|
2067
|
+
);
|
|
2068
|
+
if (!access.ok) throw new Error(access.error);
|
|
1958
2069
|
return ocsCall(ctx.env, token2, "affectPackageToSubscriber", {
|
|
1959
2070
|
subscriber: { iccid },
|
|
1960
2071
|
packageTemplateId
|
|
1961
2072
|
});
|
|
2073
|
+
},
|
|
2074
|
+
{
|
|
2075
|
+
validateArgs: assignPackageRefusal,
|
|
2076
|
+
skipUserToken: (args) => typeof args.iccid !== "string" || !args.iccid.trim(),
|
|
2077
|
+
dryRunPayload: (args) => typeof args.iccid === "string" && args.iccid.trim() ? { subscriber: { iccid: args.iccid }, packageTemplateId: args.packageTemplateId } : {
|
|
2078
|
+
method: "POST",
|
|
2079
|
+
path: "/v1/subscribers/issue-from-inventory",
|
|
2080
|
+
headers: { "X-Idempotency-Key": args.request_key },
|
|
2081
|
+
body: {
|
|
2082
|
+
packageTemplateId: args.packageTemplateId,
|
|
2083
|
+
...args.account_for_subs !== void 0 ? { accountId: args.account_for_subs } : {},
|
|
2084
|
+
...Object.fromEntries(["startDate", "endDate", "validityPeriod"].filter((k) => args[k] !== void 0).map((k) => [k, args[k]])),
|
|
2085
|
+
...args.business_reference !== void 0 ? { businessReference: args.business_reference } : {}
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
1962
2088
|
}
|
|
1963
2089
|
)
|
|
1964
2090
|
);
|
|
@@ -6419,6 +6545,9 @@ function denyUnlessScoped(props2, toolName, scopes) {
|
|
|
6419
6545
|
|
|
6420
6546
|
// src/wallet-tools.ts
|
|
6421
6547
|
var PACKS = [
|
|
6548
|
+
{ id: "pack_25", eurCents: 2500, bonusPct: 0 },
|
|
6549
|
+
{ id: "pack_50", eurCents: 5e3, bonusPct: 0 },
|
|
6550
|
+
{ id: "pack_100", eurCents: 1e4, bonusPct: 0 },
|
|
6422
6551
|
{ id: "pack_500", eurCents: 5e4, bonusPct: 0 },
|
|
6423
6552
|
{ id: "pack_1000", eurCents: 1e5, bonusPct: 3 },
|
|
6424
6553
|
{ id: "pack_2500", eurCents: 25e4, bonusPct: 6 },
|
|
@@ -6673,10 +6802,10 @@ function registerWalletTools(server2, ctx) {
|
|
|
6673
6802
|
"wallet_topup_checkout",
|
|
6674
6803
|
{
|
|
6675
6804
|
title: "Wallet Top-up Checkout",
|
|
6676
|
-
description: "Create a Stripe Checkout link so a human can top up the Carrier prepaid wallet by card. This tool charges nothing itself: it returns a hosted URL, and the wallet is credited (pack amount + bonus) only after someone completes the payment in a browser. Params: `pack` (optional \u2014 pack id `pack_500`/`pack_1000`/`pack_2500`/`pack_5000`, or an exact EUR-cents amount matching a catalog pack; omit to list the packs and their bonuses without creating a session). Returns: { pack_id, pack_eur_cents, bonus_eur_cents, checkout_session_id, checkout_url } \u2014 amounts in EUR cents. Do NOT use this when the wallet must be funded now with no human in the loop \u2014 use `wallet_auto_topup`, which charges the saved card immediately. Do NOT use this to move money in OCS \u2014 `modify_account_balance` and `modify_subscriber_balance` are unrelated ledgers.",
|
|
6805
|
+
description: "Create a Stripe Checkout link so a human can top up the Carrier prepaid wallet by card. This tool charges nothing itself: it returns a hosted URL, and the wallet is credited (pack amount + bonus) only after someone completes the payment in a browser. Params: `pack` (optional \u2014 pack id `pack_25`/`pack_50`/`pack_100`/`pack_500`/`pack_1000`/`pack_2500`/`pack_5000`, or an exact EUR-cents amount matching a catalog pack; omit to list the packs and their bonuses without creating a session). Returns: { pack_id, pack_eur_cents, bonus_eur_cents, checkout_session_id, checkout_url } \u2014 amounts in EUR cents. Do NOT use this when the wallet must be funded now with no human in the loop \u2014 use `wallet_auto_topup`, which charges the saved card immediately. Do NOT use this to move money in OCS \u2014 `modify_account_balance` and `modify_subscriber_balance` are unrelated ledgers.",
|
|
6677
6806
|
inputSchema: {
|
|
6678
6807
|
pack: z7.string().optional().describe(
|
|
6679
|
-
"Pack id (pack_500/pack_1000/pack_2500/pack_5000) or exact EUR-cents amount. Omit to list packs."
|
|
6808
|
+
"Pack id (pack_25/pack_50/pack_100/pack_500/pack_1000/pack_2500/pack_5000) or exact EUR-cents amount. Omit to list packs."
|
|
6680
6809
|
)
|
|
6681
6810
|
},
|
|
6682
6811
|
/**
|
|
@@ -10586,45 +10715,6 @@ function buildExamples(toolName) {
|
|
|
10586
10715
|
// src/list-recent-ocs-events.ts
|
|
10587
10716
|
import { z as z16 } from "zod";
|
|
10588
10717
|
|
|
10589
|
-
// src/ocs-scoping.ts
|
|
10590
|
-
function managedOwnAccountId(auth) {
|
|
10591
|
-
if (!auth.managed || auth.accountId === void 0) return void 0;
|
|
10592
|
-
const n = Number(auth.accountId);
|
|
10593
|
-
return Number.isFinite(n) ? n : void 0;
|
|
10594
|
-
}
|
|
10595
|
-
function subscriberAccountId(data) {
|
|
10596
|
-
if (!data || typeof data !== "object") return void 0;
|
|
10597
|
-
const root = data;
|
|
10598
|
-
const sub = root.subscriber && typeof root.subscriber === "object" ? root.subscriber : root;
|
|
10599
|
-
const raw = sub.accountId ?? sub.account_id ?? sub.account;
|
|
10600
|
-
if (raw === void 0 || raw === null) return void 0;
|
|
10601
|
-
const n = Number(raw);
|
|
10602
|
-
return Number.isFinite(n) ? n : void 0;
|
|
10603
|
-
}
|
|
10604
|
-
function isManagedSubscriberDenied(auth, subscriberData) {
|
|
10605
|
-
const ownId = managedOwnAccountId(auth);
|
|
10606
|
-
if (ownId === void 0) return false;
|
|
10607
|
-
const subAccountId = subscriberAccountId(subscriberData);
|
|
10608
|
-
if (subAccountId === void 0) return true;
|
|
10609
|
-
return subAccountId !== ownId;
|
|
10610
|
-
}
|
|
10611
|
-
async function assertManagedIccidAccess(baseUrl2, auth, iccid) {
|
|
10612
|
-
if (managedOwnAccountId(auth) === void 0) return { ok: true };
|
|
10613
|
-
try {
|
|
10614
|
-
const client2 = new OcsClient(baseUrl2, auth.token);
|
|
10615
|
-
const data = await client2.call("getSingleSubscriber", { iccid });
|
|
10616
|
-
if (isManagedSubscriberDenied(auth, data)) {
|
|
10617
|
-
return { ok: false, error: "Subscriber not found" };
|
|
10618
|
-
}
|
|
10619
|
-
return { ok: true };
|
|
10620
|
-
} catch (err9) {
|
|
10621
|
-
return {
|
|
10622
|
-
ok: false,
|
|
10623
|
-
error: err9 instanceof Error ? err9.message : String(err9)
|
|
10624
|
-
};
|
|
10625
|
-
}
|
|
10626
|
-
}
|
|
10627
|
-
|
|
10628
10718
|
// ../../packages/ocs-spec/src/ocs-event-buffer-read.ts
|
|
10629
10719
|
var LIFECYCLE_RESELLER_ID2 = 1170;
|
|
10630
10720
|
function ocsEventRingBufferIccidFromDigitsReference(raw) {
|
|
@@ -12857,13 +12947,14 @@ function registerUiAgentGenericTools(server2, ctx, runtime) {
|
|
|
12857
12947
|
// src/index.ts
|
|
12858
12948
|
var baseUrl = process.env.CARRIER_OCS_BASE_URL ?? process.env.ESIMVAULT_BASE_URL ?? "https://ocs.esimvault.cloud";
|
|
12859
12949
|
var token = process.env.CARRIER_OCS_API_TOKEN ?? process.env.ESIMVAULT_API_TOKEN;
|
|
12860
|
-
if (!token) {
|
|
12950
|
+
if (!token && !process.env.CARRIER_API_TOKEN) {
|
|
12861
12951
|
console.error(
|
|
12862
|
-
"ERROR:
|
|
12952
|
+
"ERROR: Set CARRIER_API_TOKEN for durable inventory or CARRIER_OCS_API_TOKEN for explicit OCS tools."
|
|
12863
12953
|
);
|
|
12864
12954
|
process.exit(1);
|
|
12865
12955
|
}
|
|
12866
12956
|
var stdioEnv = {
|
|
12957
|
+
CARRIER_API_BASE_URL: process.env.CARRIER_API_BASE_URL ?? "https://api.carrier.llc",
|
|
12867
12958
|
CARRIER_OCS_BASE_URL: baseUrl,
|
|
12868
12959
|
// Empty on purpose. rotate_credentials reads this and throws a clear
|
|
12869
12960
|
// message rather than pretending a local install can rotate the vault.
|
|
@@ -12931,13 +13022,17 @@ var props = {
|
|
|
12931
13022
|
};
|
|
12932
13023
|
var audit = (_row) => {
|
|
12933
13024
|
};
|
|
12934
|
-
var getUserToken = async (_sub) =>
|
|
13025
|
+
var getUserToken = async (_sub) => {
|
|
13026
|
+
if (!token) throw new Error("CARRIER_OCS_API_TOKEN is required for explicit OCS tools");
|
|
13027
|
+
return token;
|
|
13028
|
+
};
|
|
12935
13029
|
var toolCtx = {
|
|
12936
13030
|
env: stdioEnv,
|
|
12937
13031
|
props,
|
|
12938
13032
|
managedAuth: {},
|
|
12939
13033
|
audit,
|
|
12940
|
-
getUserToken
|
|
13034
|
+
getUserToken,
|
|
13035
|
+
getApiToken: async () => process.env.CARRIER_API_TOKEN || void 0
|
|
12941
13036
|
};
|
|
12942
13037
|
var server = new McpServer(
|
|
12943
13038
|
{ name: "carrier-mcp", version: CARRIER_VERSION },
|