@carrierllc/mcp 0.2.14 → 0.2.16
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/index.js +26 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/tools.ts","../src/client.ts","../src/billing.ts","../src/intelligence.ts","../../../packages/ocs-spec/ocs-methods.json","../../../packages/ocs-spec/src/mcc-iso.ts","../../../packages/ocs-spec/src/index.ts","../src/tools-backlog.ts","../src/tools-carrier-ask.ts","../src/list-recent-ocs-events.ts","../src/apps/fleet-health-app.ts","../src/apps/provisioning-wizard.ts","../src/apps/app-state.ts","../src/apps/balance-topup.ts","../src/apps/index.ts","../src/prompts.ts","../src/tools-pricing.ts","../src/credits.ts","../src/billing-thresholds.ts","../src/pricing-tools.ts","../src/projects-tools.ts","../src/tools-ui-agent-schedule.ts","../src/manus-common.ts","../src/manus-schedule.ts","../src/manus-usage.ts","../src/tools-ui-agent.ts","../src/clerk.ts","../src/tools-ui-agent-ask.ts","../src/manus-webhook.ts","../src/manus-client.ts","../src/stripe-connect-tools.ts","../src/audit.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Carrier MCP — single-user stdio entry point (MCPB / DXT bundle target).\n *\n * Reads CARRIER_OCS_API_TOKEN from env; calls OCS directly with that token.\n * No OAuth, no Workers — for local Claude Desktop installs via the .mcpb bundle.\n *\n * For multi-user deployments, use the remote OAuth endpoint at mcp.carrier.llc/mcp.\n *\n * Tool registry MUST mirror agent.ts exactly so that generate-docs / verify-fidelity\n * produce the same tool list as the deployed Worker.\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { registerAllTools } from \"./tools.js\";\nimport { registerIntelligenceTools } from \"./intelligence.js\";\nimport { registerAllBacklogTools } from \"./tools-backlog.js\";\nimport { registerAllCarrierAskTools } from \"./tools-carrier-ask.js\";\nimport { registerListRecentOcsEventsTool } from \"./list-recent-ocs-events.js\";\nimport { registerAllApps } from \"./apps/index.js\";\nimport { registerAllPrompts } from \"./prompts.js\";\nimport { registerAllPricingTools } from \"./tools-pricing.js\";\nimport { registerScheduleAndUsageTools } from \"./tools-ui-agent-schedule.js\";\nimport { registerAllUiAgentTools } from \"./tools-ui-agent.js\";\nimport { registerUiAgentAskTools } from \"./tools-ui-agent-ask.js\";\nimport { registerStripeConnectTools } from \"./stripe-connect-tools.js\";\nimport type { CarrierProps, AuditRow, Env } from \"./types.js\";\n\nconst baseUrl =\n process.env.CARRIER_OCS_BASE_URL ??\n process.env.ESIMVAULT_BASE_URL ??\n \"https://ocs.esimvault.cloud\";\nconst token =\n process.env.CARRIER_OCS_API_TOKEN ?? process.env.ESIMVAULT_API_TOKEN;\n\nif (!token) {\n console.error(\n \"ERROR: CARRIER_OCS_API_TOKEN (or legacy ESIMVAULT_API_TOKEN) must be set.\",\n );\n process.exit(1);\n}\n\n// Minimal env shim — stdio mode never touches KV/R2/AE/secrets at runtime.\n// CF-only bindings (OAUTH_KV, OCS_EVENT_ROUTING, ASSETS, CARRIER_USERS, DOWNLOADS)\n// are stubbed so that tool *registration* succeeds; their handlers would error if\n// actually invoked in stdio mode (acceptable — these tools require the Workers runtime).\nconst stdioEnv = {\n CARRIER_OCS_BASE_URL: baseUrl,\n CARRIER_TOKEN_ENCRYPTION_KEY: \"\",\n SENTRY_DSN: \"\",\n CLERK_PUBLISHABLE_KEY: \"\",\n CLERK_SECRET_KEY: \"\",\n CLERK_WEBHOOK_SECRET: \"\",\n AUDIT_LOG: { writeDataPoint: (_: unknown) => undefined },\n OAUTH_KV: null,\n OCS_EVENT_ROUTING: null,\n ASSETS: null,\n CARRIER_USERS: null,\n DOWNLOADS: null,\n MANUS_API_KEY: \"\",\n STRIPE_SECRET_KEY: \"\",\n} as unknown as Env;\n\nconst props: CarrierProps = {\n sub: \"stdio@local\",\n reseller_id: 0,\n reseller_name: \"stdio\",\n tier: \"enterprise\",\n scope: [\"read\", \"write\", \"admin\"],\n};\n\nconst audit = (_row: AuditRow): void => {\n // no-op in stdio mode\n};\n\nconst getUserToken = async (_sub: string): Promise<string> => token;\n\nconst toolCtx = { env: stdioEnv, props, audit, getUserToken };\n\nconst server = new McpServer(\n { name: \"carrier-mcp\", version: \"0.2.4\" },\n {\n instructions:\n \"Carrier MCP — single-user stdio mode. Full tool registry (mirrors the deployed Worker).\",\n },\n);\n\n// v1: 43 OCS API wrappers\nregisterAllTools(server, toolCtx);\n// v1 intelligence: 8 AI composite tools\nregisterIntelligenceTools(server, toolCtx);\n// v1.1 backlog: 8 confirmed-live OCS methods\nregisterAllBacklogTools(server, toolCtx);\n// NL router: carrier_ask + carrier_ask_describe\nregisterAllCarrierAskTools(server, toolCtx);\n// OCS event ring-buffer tool\nregisterListRecentOcsEventsTool(server, stdioEnv);\n// v1.2 MCP Apps (fleet-health, provisioning-wizard, balance-topup)\nregisterAllApps(server, toolCtx);\n// Pricing + projects tools\nregisterAllPricingTools(server, toolCtx);\n// UI agent schedule + usage tools\nregisterScheduleAndUsageTools(server, toolCtx);\n// UI agent write tools\nregisterAllUiAgentTools(server, toolCtx);\n// UI agent ask/reply tools\nregisterUiAgentAskTools(server, toolCtx);\n// Stripe Connect + Radar tools\nregisterStripeConnectTools(server, { env: stdioEnv, props });\nregisterAllPrompts(server);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","/**\n * Carrier MCP — OCS tool registrations (43 tools).\n *\n * All 43 OCS v1 methods are exposed as MCP tools. Each is wrapped with:\n * - Scope enforcement (read / write / admin)\n * - Dry-run short-circuit for destructive tools (no OCS call)\n * - Sentry error capture\n * - Audit hook into Analytics Engine\n * - Per-user token resolution via getUserToken(sub)\n *\n * Scope assignments live in TOOL_SCOPES below; must match packages/ocs-spec/ocs-methods.json.\n *\n * PR #10 schema fixes applied:\n * Fix #1: getSimProviderStatus — ICCID → simId lookup → bare integer\n * Fix #2: hlrGetBitrate — ICCID → IMSI lookup → { imsi }\n * Fix #3: hlrSetBitrate — ICCID → IMSI + bitrate → limit rename → { imsi, limit }\n * Fix #4: subscriberUsageOverPeriod — { subscriber: { iccid }, period: { start, end } }\n * Fix #5: subscriberNetworkEventsOverPeriod — same nested shape\n * Fix #6: modifySubscriberStatus — { subscriber, newStatus }\n * Fix #7: modifySubscriberBalance — { subscriber, amount } or { subscriber, setBalance }\n * Fix #8: changeSimStatus — ICCID → simId + simStatus → newStatus\n * Fix #9: modifySubscriberContactInfo — firstName+lastName → name, email→mail, phone→phone\n * Fix #10: setSubscriberTrafficRestrictions — typed booleans, not JSON string\n * Fix #11: sendMtSms — ICCID→IMSI, message→text, sender→senderId\n * Fix #12: listSponsor — bare integer (resellerId)\n * Fix #13: listSteeringList — bare integer (resellerId)\n * Fix #14: getCustomerTariff — bare integer + response key listTariffRule\n * Fix #15: listDetailedLocationZone — bare integer (resellerId)\n * Fix #16: modifySubscriberSteeringList — { subscriber, steeringListId }\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport * as Sentry from \"@sentry/cloudflare\";\nimport { OcsClient, OcsApiError } from \"./client.js\";\nimport type { Env, CarrierProps, AuditRow, ToolScope } from \"./types.js\";\nimport { checkCallQuota, recordUsage, UPGRADE_URL } from \"./billing.js\";\n\nexport interface ToolContext {\n env: Env;\n props: CarrierProps;\n audit: (row: AuditRow) => void;\n getUserToken: (sub: string) => Promise<string>;\n}\n\n// Scope metadata per tool — all 43 tools declared here.\n// Must stay in sync with ocs-methods.json from packages/ocs-spec.\nexport const TOOL_SCOPES: Record<string, ToolScope> = {\n // --- read ---\n list_reseller_accounts: \"read\",\n get_reseller_info: \"read\",\n esim_status_per_account: \"read\",\n list_sponsors: \"read\",\n list_steering_lists: \"read\",\n get_subscriber: \"read\",\n list_subscribers: \"read\",\n get_sim_provider_status: \"read\",\n get_subscriber_location: \"read\",\n hlr_get_bitrate: \"read\",\n list_subscriber_packages: \"read\",\n list_package_templates: \"read\",\n list_location_zones: \"read\",\n list_detailed_location_zones: \"read\",\n list_destination_prefixes: \"read\",\n subscriber_usage: \"read\",\n subscriber_network_events: \"read\",\n subscriber_active_period: \"read\",\n get_tariff: \"read\",\n list_network_profiles: \"read\",\n // --- intelligence composites ---\n detect_country_entry: \"read\",\n // --- write ---\n modify_subscriber_balance: \"write\",\n modify_subscriber_status: \"write\",\n modify_subscriber_contact_info: \"write\",\n set_subscriber_traffic_restrictions: \"write\",\n modify_subscriber_steering_list: \"write\",\n move_subscriber_range_to_account: \"write\",\n hlr_set_bitrate: \"write\",\n assign_package: \"write\",\n assign_recurring_package: \"write\",\n modify_package_limits: \"write\",\n modify_package_expiry: \"write\",\n modify_package_status: \"write\",\n stop_resume_recurring_package: \"write\",\n create_package_template: \"write\",\n create_location_zone: \"write\",\n // --- admin ---\n modify_account_balance: \"admin\", // corrected per ocs-spec PR #6\n change_sim_status: \"admin\",\n delete_subscriber_package: \"admin\",\n clean_all_packages: \"admin\",\n modify_template_core: \"admin\",\n modify_template_recurring: \"admin\",\n modify_template_throttling: \"admin\",\n send_sms: \"admin\",\n};\n\nexport const DESTRUCTIVE_TOOLS = new Set([\n \"modify_account_balance\",\n \"modify_subscriber_balance\",\n \"modify_subscriber_status\",\n \"change_sim_status\",\n \"modify_subscriber_contact_info\",\n \"set_subscriber_traffic_restrictions\",\n \"modify_subscriber_steering_list\",\n \"move_subscriber_range_to_account\",\n \"hlr_set_bitrate\",\n \"assign_package\",\n \"assign_recurring_package\",\n \"modify_package_limits\",\n \"modify_package_expiry\",\n \"modify_package_status\",\n \"stop_resume_recurring_package\",\n \"delete_subscriber_package\",\n \"clean_all_packages\",\n \"modify_template_core\",\n \"modify_template_recurring\",\n \"modify_template_throttling\",\n \"create_package_template\",\n \"create_location_zone\",\n \"send_sms\",\n // v1.1 backlog — same dry_run contract as v1 write/admin tools (tools-backlog.ts)\n \"affect_subscriber_phone_number\",\n \"modify_subscriber_mobile_plan\",\n \"modify_subscriber_package_active_period\",\n \"modify_subscriber_voip_plan\",\n \"push_steering_to_subscriber\",\n \"reset_subscriber_gz_counter\",\n]);\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Wraps a tool handler with scope enforcement, dry-run short-circuit,\n * Sentry capture, and audit logging.\n */\nexport function wrapHandler<T extends Record<string, unknown>>(\n toolName: string,\n ocsMethod: string,\n requiredScope: ToolScope,\n ctx: ToolContext,\n handler: (args: T, token: string) => Promise<ToolResult>,\n) {\n return async (args: T & { dry_run?: boolean }): Promise<ToolResult> => {\n const start = Date.now();\n const isDryRun = args.dry_run === true;\n\n // Scope enforcement\n if (!ctx.props.scope.includes(requiredScope)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Scope denied: tool '${toolName}' requires '${requiredScope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Billing quota check (Phase 7 — v1.1)\n // Enterprise is unlimited; free/pro are gate-checked against KV counter.\n const quota = await checkCallQuota(ctx.env, ctx.props.sub, ctx.props.tier);\n if (!quota.allowed) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"quota_exceeded\",\n dry_run: isDryRun,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: [\n `Quota exceeded: your ${quota.tier} plan has reached the safety limit of 100,000 regular tool calls/month.`,\n `This limit exists to prevent runaway automation. Resets ${quota.resetAt}.`,\n `Upgrade to Pro for unlimited calls at ${UPGRADE_URL}`,\n ].join(\" \"),\n },\n ],\n };\n }\n\n // Dry-run short-circuit for destructive tools\n if (isDryRun && DESTRUCTIVE_TOOLS.has(toolName)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"dry_run\",\n dry_run: true,\n duration_ms: 0,\n });\n return {\n content: [\n {\n type: \"text\",\n text: `[dry_run=true] Would execute '${toolName}' (OCS method '${ocsMethod}') with args: ${JSON.stringify(args)}. No changes made.`,\n },\n ],\n };\n }\n\n let result: ToolResult;\n try {\n const token = await ctx.getUserToken(ctx.props.sub);\n result = await handler(args, token);\n } catch (err) {\n try {\n Sentry.captureException(err, {\n tags: {\n tool: toolName,\n feature: \"mcp\",\n reseller_id: String(ctx.props.reseller_id),\n },\n });\n } catch {\n // Sentry may not be initialised in tests — swallow.\n }\n const message = err instanceof Error ? err.message : String(err);\n const ocsCode = err instanceof OcsApiError ? err.code : undefined;\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"error\",\n dry_run: isDryRun,\n duration_ms: Date.now() - start,\n ...(ocsCode !== undefined ? { ocs_status_code: ocsCode } : {}),\n });\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${message}` }],\n };\n }\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: result.isError ? \"error\" : \"ok\",\n dry_run: isDryRun,\n duration_ms: Date.now() - start,\n });\n\n // Record usage on successful (non-error, non-dry-run) calls.\n // Fire-and-forget — never blocks the response.\n if (!result.isError && !isDryRun) {\n recordUsage(ctx.env, ctx.props.sub, ctx.props.tier);\n }\n\n return result;\n };\n}\n\n// ---------------------------------------------------------------------------\n// OCS call helper — accepts explicit token (no module-level singleton).\n// Fix: params broadened to accept bare scalar for methods that expect it\n// (listSponsor, listSteeringList, getCustomerTariff, listDetailedLocationZone,\n// getSimProviderStatus).\n// ---------------------------------------------------------------------------\nasync function ocsCall<T = Record<string, unknown>>(\n env: Env,\n token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<ToolResult> {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call<T>(method, params);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Request-scoped subscriber lookup cache (ICCID → subscriber record).\n// Prevents N+1 lookups when tools need simId or IMSI from the same subscriber.\n// Fix #1, #2, #3, #8, #11 depend on this resolver.\n// ---------------------------------------------------------------------------\ntype SubscriberRecord = Record<string, unknown>;\n\nexport async function resolveSubscriberByIccid(\n env: Env,\n token: string,\n iccid: string,\n cache: Map<string, SubscriberRecord>,\n): Promise<SubscriberRecord> {\n const hit = cache.get(iccid);\n if (hit) return hit;\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const record = await client.call<SubscriberRecord>(\"getSingleSubscriber\", { iccid });\n cache.set(iccid, record);\n return record;\n}\n\n// ---------------------------------------------------------------------------\n// Fetch the token owner's reseller ID via getResellerInfo.\n// Used for bare-integer OCS methods: listSponsor, listSteeringList,\n// getCustomerTariff, listDetailedLocationZone.\n// Fix #12, #13, #14, #15.\n// ---------------------------------------------------------------------------\nexport async function getDefaultResellerId(env: Env, token: string): Promise<number> {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const info = await client.call<{ id?: number }>(\"getResellerInfo\", {});\n const id = info?.id;\n if (typeof id !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return id;\n}\n\n// Shorthand: build the destructive-tool annotation + dry_run schema field\nconst DRY_RUN_FIELD = {\n dry_run: z\n .boolean()\n .optional()\n .describe(\n \"If true, do not call OCS — return the would-be request for confirmation\",\n ),\n};\n\nexport function registerAllTools(server: McpServer, ctx: ToolContext): void {\n // =========================================================================\n // 1. RESELLER TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_reseller_accounts\",\n {\n title: \"List Reseller Accounts\",\n description:\n \"Use this to enumerate all accounts (sub-resellers or customer accounts) under a reseller. \" +\n \"Returns each account's name, ID, current balance, package-only flag, and account type. \" +\n \"Params: `resellerId` (integer, optional — omit to list accounts under the token owner's reseller). \" +\n \"Returns: array of account records, each containing `accountId`, `name`, `balance`, `type`. \" +\n \"Do NOT use this to fetch a single subscriber's details — use `get_subscriber` instead. \" +\n \"Do NOT use this to check eSIM activation counts — use `esim_status_per_account` for that.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Filter to a specific reseller by ID (omit for token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_reseller_accounts\",\n \"listResellerAccount\",\n TOOL_SCOPES[\"list_reseller_accounts\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.resellerId = resellerId;\n return ocsCall(ctx.env, token, \"listResellerAccount\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_account_balance\",\n {\n title: \"Modify Account Balance\",\n description:\n \"Use this to adjust or set the monetary balance on a reseller account. \" +\n \"'adapt' mode adds (positive amount) or subtracts (negative amount) from the current balance; \" +\n \"'set' mode replaces the balance with the exact amount. Every change is logged as a transaction. \" +\n \"Params: `accountId` (integer account ID from `list_reseller_accounts`), `amount` (number), \" +\n \"`mode` ('adapt' | 'set'). \" +\n \"Returns: updated account balance record with the transaction ID. \" +\n \"Do NOT use this to modify a subscriber's personal balance — use `modify_subscriber_balance` instead. \" +\n \"Always call `list_reseller_accounts` first to confirm the target accountId before executing.\",\n inputSchema: {\n accountId: z.number().describe(\"The account ID to modify\"),\n amount: z.number().describe(\"Amount to add (adapt) or set to (set)\"),\n mode: z\n .enum([\"adapt\", \"set\"])\n .describe(\"'adapt' adds/subtracts, 'set' replaces the balance\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_account_balance\",\n \"modifyAccountBalance\",\n TOOL_SCOPES[\"modify_account_balance\"]!,\n ctx,\n async ({ accountId, amount, mode }, token) => {\n const params: Record<string, unknown> = { accountId };\n if (mode === \"adapt\") params.adaptBalance = amount;\n else params.setBalance = amount;\n return ocsCall(ctx.env, token, \"modifyAccountBalance\", params);\n },\n ),\n );\n\n server.registerTool(\n \"get_reseller_info\",\n {\n title: \"Get Reseller Info\",\n description:\n \"Use this to retrieve full details for a reseller: main info, traffic configuration, \" +\n \"charging info, contact info, and active pricing plans. \" +\n \"Params: `resellerId` (integer, optional — omit to return the token owner's reseller). \" +\n \"Returns: reseller object with `id`, `name`, `balance`, `pricingPlan`, `contactInfo`, and more. \" +\n \"Do NOT use this to list all accounts under a reseller — use `list_reseller_accounts` for that.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit for token owner)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_reseller_info\",\n \"getResellerInfo\",\n TOOL_SCOPES[\"get_reseller_info\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.resellerId = resellerId;\n return ocsCall(ctx.env, token, \"getResellerInfo\", params);\n },\n ),\n );\n\n server.registerTool(\n \"esim_status_per_account\",\n {\n title: \"eSIM Status Per Account\",\n description:\n \"Use this to get eSIM status counts broken down by account: active, suspended, inventory \" +\n \"(not yet activated), and other states. Good for fleet health dashboards and capacity planning. \" +\n \"OCS requires either `accountId` OR `resellerId`. If both omitted, the token owner's reseller is resolved automatically. \" +\n \"Params: `accountId` (integer, optional — for a single account), `resellerId` (integer, optional — for all accounts under a specific reseller). \" +\n \"Returns: array of per-account objects with `accountId`, `active`, `suspended`, `inventory`, `other`. \" +\n \"Do NOT use this to check a single subscriber's status — use `get_subscriber` for that. \" +\n \"Do NOT use this for billing or balance checks — use `list_reseller_accounts` for balances.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter to a specific account\"),\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"esim_status_per_account\",\n \"esimStatusPerAccount\",\n TOOL_SCOPES[\"esim_status_per_account\"]!,\n ctx,\n async ({ accountId, resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) {\n params.accountId = accountId;\n } else {\n params.resellerId = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n }\n return ocsCall(ctx.env, token, \"esimStatusPerAccount\", params);\n },\n ),\n );\n\n // Fix #12: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_sponsors\",\n {\n title: \"List Sponsors\",\n description:\n \"Use this to list all sponsor networks (eSIM sponsor carriers) available to this reseller. \" +\n \"A sponsor defines which physical network infrastructure backs a given eSIM profile. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of sponsor records with `sponsorId`, `name`, and coverage metadata. \" +\n \"Do NOT use this to list steering lists or network profiles — those are separate concepts. \" +\n \"Use `list_steering_lists` to see operator preference configurations.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_sponsors\",\n \"listSponsor\",\n TOOL_SCOPES[\"list_sponsors\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listSponsor\", id);\n },\n ),\n );\n\n // Fix #13: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_steering_lists\",\n {\n title: \"List Steering Lists\",\n description:\n \"Use this to retrieve all network steering lists configured for this reseller. \" +\n \"A steering list is a named configuration of excluded and priority mobile operators that \" +\n \"controls which networks an eSIM prefers to roam onto — the primary mechanism for network \" +\n \"quality optimisation and cost control. Call this before `modify_subscriber_steering_list` \" +\n \"to obtain valid steering list IDs. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of steering list records with `steeringListId`, `name`, and configured operators. \" +\n \"Do NOT use this to assign a steering list to a subscriber — use `modify_subscriber_steering_list`. \" +\n \"Do NOT use this to push a steering change to a device — use `push_steering_to_subscriber` after assignment.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_steering_lists\",\n \"listSteeringList\",\n TOOL_SCOPES[\"list_steering_lists\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listSteeringList\", id);\n },\n ),\n );\n\n // =========================================================================\n // 2. SUBSCRIBER TOOLS\n // =========================================================================\n\n server.registerTool(\n \"get_subscriber\",\n {\n title: \"Get Single Subscriber\",\n description:\n \"Use this as the primary lookup for a single subscriber by ICCID or MSISDN. \" +\n \"Returns the complete subscriber record: status, balance, assigned account, contact info, \" +\n \"IMSI, simId, steering list, active pricing plan, and traffic restriction flags. \" +\n \"Params: `iccid` (20-digit ICC identifier, optional) OR `msisdn` (E.164 phone number, optional) — \" +\n \"provide at least one. \" +\n \"Optional: `with_gz_counter` (boolean) — when true, includes `greenZoneCounter` in the response: \" +\n \"{ subscriberId, volumeOnGZ (bytes consumed on reseller whitelist hosts/IPs after bundle depletion), \" +\n \"lastResetDate, lastUpdateDate }. Omit or set false to skip the GZ counter (default). \" +\n \"Returns: full subscriber object. Key fields: `status` (ACTIVE/SUSPENDED/TERMINATED), \" +\n \"`balance`, `imsi`, `simId`, `steeringListId`. \" +\n \"Do NOT use this for bulk lookups — use `list_subscribers` with filters for that.\",\n inputSchema: {\n iccid: z.string().optional().describe(\"The ICCID of the subscriber\"),\n msisdn: z\n .string()\n .optional()\n .describe(\"The MSISDN (phone number) of the subscriber\"),\n with_gz_counter: z\n .boolean()\n .optional()\n .describe(\n \"When true, include greenZoneCounter { subscriberId, volumeOnGZ (bytes), lastResetDate, lastUpdateDate } — tracks bytes consumed on reseller whitelist hosts/IPs after bundle depletion\",\n ),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber\",\n \"getSingleSubscriber\",\n TOOL_SCOPES[\"get_subscriber\"]!,\n ctx,\n async ({ iccid, msisdn, with_gz_counter }, token) => {\n const params: Record<string, unknown> = {};\n if (iccid) params.iccid = iccid;\n if (msisdn) params.msisdn = msisdn;\n if (with_gz_counter === true) params.withGzCounter = true;\n return ocsCall(ctx.env, token, \"getSingleSubscriber\", params);\n },\n ),\n );\n\n server.registerTool(\n \"list_subscribers\",\n {\n title: \"List Subscribers\",\n description:\n \"Use this to list subscribers with optional filters and pagination. Good for fleet enumeration, \" +\n \"bulk status checks, and finding subscribers by account or status. \" +\n \"OCS REQUIRES at least one search key — provide exactly one of: `imsi`, `iccid`, `activationCode`, \" +\n \"`accountId`, or `msisdn`. Calling with no key will be rejected before reaching OCS. \" +\n \"Params: `imsi` (string), `iccid` (string), `activationCode` (string), `accountId` (integer), \" +\n \"`msisdn` (string), `status` (string, e.g. 'ACTIVE'/'SUSPENDED'), `offset` (integer, pagination — default 0), \" +\n \"`limit` (integer, max results — always set to avoid unbounded fetches; recommended max 100 per call). \" +\n \"Returns: array of subscriber summary records with ICCID, status, and account. \" +\n \"Do NOT use this to fetch full details for a specific subscriber — use `get_subscriber` for that.\",\n inputSchema: z\n .object({\n imsi: z.string().optional().describe(\"Filter by IMSI\"),\n iccid: z.string().optional().describe(\"Filter by ICCID\"),\n activationCode: z\n .string()\n .optional()\n .describe(\"Filter by activation code\"),\n accountId: z.number().optional().describe(\"Filter by account ID\"),\n msisdn: z.string().optional().describe(\"Filter by MSISDN\"),\n status: z.string().optional().describe(\"Filter by status\"),\n offset: z.number().optional().describe(\"Pagination offset\"),\n limit: z.number().optional().describe(\"Max results to return\"),\n })\n .refine(\n (d) =>\n d.imsi !== undefined ||\n d.iccid !== undefined ||\n d.activationCode !== undefined ||\n d.accountId !== undefined ||\n d.msisdn !== undefined,\n {\n message:\n \"Provide at least one of: imsi, iccid, activationCode, accountId, msisdn\",\n },\n ),\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_subscribers\",\n \"listSubscriber\",\n TOOL_SCOPES[\"list_subscribers\"]!,\n ctx,\n async (args, token) => {\n // OCS listSubscriber does not accept `limit` — strip it before forwarding.\n // We keep `limit` in the inputSchema as a UX hint so callers can express intent.\n const params: Record<string, unknown> = {};\n if (args.imsi) params.imsi = args.imsi;\n if (args.iccid) params.iccid = args.iccid;\n if (args.activationCode) params.activationCode = args.activationCode;\n if (args.accountId !== undefined) params.accountId = args.accountId;\n if (args.msisdn) params.msisdn = args.msisdn;\n if (args.status) params.status = args.status;\n if (args.offset !== undefined) params.offset = args.offset;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const raw = await client.call<unknown>(\"listSubscriber\", params);\n const limit = args.limit;\n const payload =\n Array.isArray(raw) && typeof limit === \"number\" && limit >= 0\n ? raw.slice(0, limit)\n : raw;\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n },\n ),\n );\n\n // Fix #7: OCS expects { subscriber, amount } or { subscriber, setBalance } not { iccid, adaptBalance|setBalance }\n server.registerTool(\n \"modify_subscriber_balance\",\n {\n title: \"Modify Subscriber Balance\",\n description:\n \"Use this to adjust or set the monetary balance for an individual subscriber. \" +\n \"'adapt' mode adds (positive) or subtracts (negative) from the current balance; \" +\n \"'set' mode replaces the balance with the exact amount provided. \" +\n \"Params: `iccid` (subscriber identifier), `amount` (number), `mode` ('adapt' | 'set'). \" +\n \"Returns: updated subscriber balance. \" +\n \"Do NOT use this to modify an account-level balance — use `modify_account_balance` for that. \" +\n \"Always call `get_subscriber` first to capture the current balance before adjusting.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n amount: z.number().describe(\"Amount to add (adapt) or set to (set)\"),\n mode: z\n .enum([\"adapt\", \"set\"])\n .describe(\"'adapt' adds/subtracts, 'set' replaces\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_balance\",\n \"modifySubscriberBalance\",\n TOOL_SCOPES[\"modify_subscriber_balance\"]!,\n ctx,\n async ({ iccid, amount, mode }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n if (mode === \"adapt\") params.amount = amount;\n else params.setBalance = amount;\n return ocsCall(ctx.env, token, \"modifySubscriberBalance\", params);\n },\n ),\n );\n\n // Fix #6: OCS expects { subscriber, newStatus } not { iccid, status }\n server.registerTool(\n \"modify_subscriber_status\",\n {\n title: \"Modify Subscriber Status\",\n description:\n \"Use this to change the OCS lifecycle status of a subscriber. \" +\n \"Common transitions: ACTIVE → SUSPENDED (pause without losing packages), \" +\n \"SUSPENDED → ACTIVE (reactivate), ACTIVE/SUSPENDED → TERMINATED (irreversible). \" +\n \"WARNING: TERMINATED status is permanent — the subscriber record cannot be reactivated. \" +\n \"⚠ Setting status to END_OF_LIFE is irreversible. The subscriber becomes read-only (OCS error 17 on subsequent mutations). Confirm before calling. \" +\n \"Params: `iccid` (subscriber identifier), `status` (new status string, e.g. 'ACTIVE', \" +\n \"'SUSPENDED', 'TERMINATED', 'END_OF_LIFE'). \" +\n \"Returns: updated subscriber record with the new status. \" +\n \"Do NOT use this to disable the SIM card at the network level — use `change_sim_status` for that. \" +\n \"Always call `get_subscriber` first to confirm current status before modifying.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n status: z.string().describe(\"New status value\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_status\",\n \"modifySubscriberStatus\",\n TOOL_SCOPES[\"modify_subscriber_status\"]!,\n ctx,\n async ({ iccid, status }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberStatus\", {\n subscriber: iccid,\n newStatus: status,\n }),\n ),\n );\n\n // Fix #8: OCS expects { simId, newStatus } not { iccid, simStatus }.\n // Resolve ICCID → simId via getSingleSubscriber, then send { simId, newStatus }.\n server.registerTool(\n \"change_sim_status\",\n {\n title: \"Change SIM Status\",\n description:\n \"Use this to change the physical SIM/eSIM card status at the SIM provider level, \" +\n \"independent of the OCS subscriber lifecycle status. \" +\n \"Statuses: ENABLED (normal operation), DISABLED (blocked at network level, subscriber cannot connect), \" +\n \"DELETED (irrecoverably removes the SIM profile — use only to decommission). \" +\n \"WARNING: DELETED is irreversible. Always use `dry_run=true` first. \" +\n \"Internally resolves ICCID → numeric simId via a getSingleSubscriber call before forwarding to OCS. \" +\n \"Params: `iccid` (subscriber identifier), `simStatus` ('ENABLED' | 'DISABLED' | 'DELETED'). \" +\n \"Returns: updated SIM record with new status. \" +\n \"Do NOT use this to change the subscriber's OCS lifecycle status — use `modify_subscriber_status`. \" +\n \"Do NOT confuse DISABLED (reversible) with DELETED (irreversible).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n simStatus: z.string().describe(\"New SIM status (e.g. ENABLED, DISABLED, DELETED)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"change_sim_status\",\n \"changeSimStatus\",\n TOOL_SCOPES[\"change_sim_status\"]!,\n ctx,\n async ({ iccid, simStatus }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const simId = Number(sub.simId ?? sub.sim_id ?? sub.id);\n if (simId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve simId for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"changeSimStatus\", {\n simId: Number(simId),\n newStatus: simStatus,\n });\n },\n ),\n );\n\n // Fix #1: OCS expects bare Long (simId integer) not { iccid }.\n // Resolve ICCID → simId via getSingleSubscriber, then send bare integer.\n server.registerTool(\n \"get_sim_provider_status\",\n {\n title: \"Get SIM Provider Status\",\n description:\n \"Use this to check the physical SIM/eSIM card status at the SIM provider level \" +\n \"(ENABLED, DISABLED, DELETED) — distinct from the OCS subscriber status. \" +\n \"Useful when `get_subscriber` shows ACTIVE but connectivity is broken; the SIM may be \" +\n \"DISABLED at the provider level. Internally resolves ICCID → numeric simId. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: provider status object with `simStatus`, `activationDate`, `lastStatusChange`. \" +\n \"Do NOT use this to change the SIM status — use `change_sim_status` for that.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_sim_provider_status\",\n \"getSimProviderStatus\",\n TOOL_SCOPES[\"get_sim_provider_status\"]!,\n ctx,\n async ({ iccid }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const simId = Number(sub.simId ?? sub.sim_id ?? sub.id);\n if (simId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve simId for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"getSimProviderStatus\", Number(simId));\n },\n ),\n );\n\n server.registerTool(\n \"get_subscriber_location\",\n {\n title: \"Get Subscriber Location\",\n description:\n \"Returns last-known location from subscriber's most recent cell tower usage. Complementary to GeoSense get_subscriber_location_by_cell_id — use this when you have the subscriber id, use the cell-id variant when you have raw cell parameters.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber_location\",\n \"getSubscriberLocation\",\n TOOL_SCOPES[\"get_subscriber_location\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"getSubscriberLocation\", { iccid }),\n ),\n );\n\n // Fix #9: OCS expects { subscriber, name, company, phone, mail }\n // not { iccid, firstName, lastName, email, phoneNumber }\n server.registerTool(\n \"modify_subscriber_contact_info\",\n {\n title: \"Modify Subscriber Contact Info\",\n description:\n \"Use this to update the contact details stored on a subscriber record in OCS. \" +\n \"Only the fields you provide are updated — omitted fields are left unchanged. \" +\n \"Params: `iccid` (subscriber identifier), `firstName` (optional), `lastName` (optional), \" +\n \"`company` (optional), `email` (optional), `phoneNumber` (optional). \" +\n \"Returns: updated subscriber contact record. \" +\n \"Do NOT use this to change subscriber status, balance, or traffic flags — those have dedicated tools.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n firstName: z.string().optional().describe(\"First name\"),\n lastName: z.string().optional().describe(\"Last name\"),\n company: z.string().optional().describe(\"Company name\"),\n email: z.string().optional().describe(\"Email address\"),\n phoneNumber: z.string().optional().describe(\"Phone number\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_contact_info\",\n \"modifySubscriberContactInfo\",\n TOOL_SCOPES[\"modify_subscriber_contact_info\"]!,\n ctx,\n async ({ iccid, firstName, lastName, company, email, phoneNumber }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n const nameParts = [firstName, lastName].filter(Boolean);\n if (nameParts.length > 0) params.name = nameParts.join(\" \");\n if (company !== undefined) params.company = company;\n if (phoneNumber !== undefined) params.phone = phoneNumber;\n if (email !== undefined) params.mail = email;\n return ocsCall(ctx.env, token, \"modifySubscriberContactInfo\", params);\n },\n ),\n );\n\n // Fix #10: OCS expects { subscriber, mtcAllowed, smsMoAllowed, dataAllowed, mocAllowed }\n // Drop JSON-string antipattern; use typed booleans directly.\n server.registerTool(\n \"set_subscriber_traffic_restrictions\",\n {\n title: \"Set Traffic Restrictions\",\n description:\n \"Use this to enable or disable individual traffic types for a subscriber: mobile data, \" +\n \"voice calls (mobile-originated and mobile-terminated), and SMS. Omit any flag to leave \" +\n \"it unchanged. Changes take effect immediately at the OCS level. \" +\n \"Params: `iccid` (subscriber identifier), `dataAllowed` (boolean, controls data traffic), \" +\n \"`mocAllowed` (boolean, controls outbound calls), `mtcAllowed` (boolean, controls inbound calls), \" +\n \"`smsMoAllowed` (boolean, controls outbound SMS). \" +\n \"Returns: updated traffic restriction record for the subscriber. \" +\n \"Do NOT use this to throttle bandwidth — use `hlr_set_bitrate` for speed limiting. \" +\n \"Do NOT use this to suspend the subscriber entirely — use `modify_subscriber_status` (SUSPENDED) instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n mtcAllowed: z.boolean().optional().describe(\"Allow mobile-terminated calls\"),\n smsMoAllowed: z.boolean().optional().describe(\"Allow SMS mobile-originated\"),\n dataAllowed: z.boolean().optional().describe(\"Allow data traffic\"),\n mocAllowed: z.boolean().optional().describe(\"Allow mobile-originated calls\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"set_subscriber_traffic_restrictions\",\n \"setSubscriberTrafficRestrictions\",\n TOOL_SCOPES[\"set_subscriber_traffic_restrictions\"]!,\n ctx,\n async ({ iccid, mtcAllowed, smsMoAllowed, dataAllowed, mocAllowed }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n if (mtcAllowed !== undefined) params.mtcAllowed = mtcAllowed;\n if (smsMoAllowed !== undefined) params.smsMoAllowed = smsMoAllowed;\n if (dataAllowed !== undefined) params.dataAllowed = dataAllowed;\n if (mocAllowed !== undefined) params.mocAllowed = mocAllowed;\n return ocsCall(ctx.env, token, \"setSubscriberTrafficRestrictions\", params);\n },\n ),\n );\n\n // Fix #16: OCS expects { subscriber, steeringListId } not { iccid, steeringListId }\n server.registerTool(\n \"modify_subscriber_steering_list\",\n {\n title: \"Modify Subscriber Steering List\",\n description:\n \"Use this to assign or remove a network steering list on a specific subscriber, controlling \" +\n \"which mobile operators the subscriber's eSIM prefers to connect to. Steering lists are \" +\n \"managed separately — call `list_steering_lists` to get valid IDs. \" +\n \"This operates at the SUBSCRIBER level only. After assigning, call `push_steering_to_subscriber` \" +\n \"to push the change to the physical device immediately; without that call the device continues \" +\n \"using the old operator preference list until next re-registration. \" +\n \"Params: `iccid` (subscriber identifier), `steeringListId` (integer from `list_steering_lists`, \" +\n \"or null/0 to remove the current steering list). \" +\n \"Returns: updated subscriber record confirming the new steeringListId. \" +\n \"Do NOT use this for account-level steering (no MCP tool yet — gap G-03, awaiting eSIMVault input).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n steeringListId: z.number().describe(\"The steering list ID to assign\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_steering_list\",\n \"modifySubscriberSteeringList\",\n TOOL_SCOPES[\"modify_subscriber_steering_list\"]!,\n ctx,\n async ({ iccid, steeringListId }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberSteeringList\", {\n subscriber: iccid,\n steeringListId,\n }),\n ),\n );\n\n server.registerTool(\n \"move_subscriber_range_to_account\",\n {\n title: \"Move Subscribers to Account\",\n description:\n \"Use this to move a contiguous ICCID range of subscribers to a different account. \" +\n \"Useful for bulk subscriber migrations between accounts or during account restructuring. \" +\n \"Params: `iccidFrom` (start ICCID of range, inclusive), `iccidTo` (end ICCID of range, inclusive), \" +\n \"`accountId` (target account ID from `list_reseller_accounts`). \" +\n \"Returns: OCS confirmation of the range move with affected subscriber count. \" +\n \"Do NOT use this for a single subscriber move — provide identical iccidFrom and iccidTo. \" +\n \"Always call `list_subscribers` on the range first to verify the correct subscribers are included.\",\n inputSchema: {\n iccidFrom: z.string().describe(\"Start ICCID of range\"),\n iccidTo: z.string().describe(\"End ICCID of range\"),\n accountId: z.number().describe(\"Target account ID\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"move_subscriber_range_to_account\",\n \"moveSubscriberRangeToAccount\",\n TOOL_SCOPES[\"move_subscriber_range_to_account\"]!,\n ctx,\n async ({ iccidFrom, iccidTo, accountId }, token) =>\n ocsCall(ctx.env, token, \"moveSubscriberRangeToAccount\", {\n iccidFrom,\n iccidTo,\n accountId,\n }),\n ),\n );\n\n // Fix #3: OCS expects { imsi, limit } not { iccid, bitrate }.\n // Resolve ICCID → IMSI via getSingleSubscriber; rename bitrate → limit.\n // B2.4: added bitrate_string string-enum alternative; refine ensures at least one of (bitrate, bitrate_string).\n server.registerTool(\n \"hlr_set_bitrate\",\n {\n title: \"Set HLR Bitrate\",\n description:\n \"Use this to set a hard bandwidth cap for a subscriber at the HLR (Home Location Register) level. \" +\n \"This is a network-level throttle applied regardless of package allowance — use it to enforce \" +\n \"fair-use speed limits or to throttle heavy users without suspending service. \" +\n \"Provide at least one of `bitrate` (numeric bps) or `bitrate_string` (OCS string enum); \" +\n \"when both are provided, `bitrate_string` is used. \" +\n \"String enum values: KB_32, KB_64, KB_128, KB_256, KB_384, KB_512, KB_1024, KB_2048, KB_3072, \" +\n \"KB_5120, KB_7680, KB_10240, KB_20480, KB_51200, KB_102400, UNLIMITED. \" +\n \"Numeric equivalents: 256000 (256 kbps throttle), 1000000 (1 Mbps), 0 (remove limit). \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup. \" +\n \"Params: `iccid` (subscriber identifier), `bitrate` (integer, bits-per-second) OR \" +\n \"`bitrate_string` (string enum from the list above). \" +\n \"Returns: HLR confirmation with the applied bitrate. \" +\n \"Do NOT use this to block data entirely — use `set_subscriber_traffic_restrictions` with `dataAllowed=false`. \" +\n \"Do NOT use this to change throttling thresholds on a package template — use `modify_template_throttling`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n bitrate: z.number().optional().describe(\"Max bitrate in bps (numeric form; use 0 to remove limit)\"),\n bitrate_string: z\n .enum([\n \"KB_32\", \"KB_64\", \"KB_128\", \"KB_256\", \"KB_384\", \"KB_512\",\n \"KB_1024\", \"KB_2048\", \"KB_3072\", \"KB_5120\", \"KB_7680\",\n \"KB_10240\", \"KB_20480\", \"KB_51200\", \"KB_102400\", \"UNLIMITED\",\n ])\n .optional()\n .describe(\"Max bitrate as OCS string enum (alternative to numeric `bitrate`)\"),\n dry_run: z\n .boolean()\n .optional()\n .describe(\"If true, do not call OCS — return the would-be request for confirmation\"),\n })\n .refine(\n (d) => d.bitrate !== undefined || d.bitrate_string !== undefined,\n { message: \"Provide at least one of `bitrate` (number) or `bitrate_string` (string enum)\" },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"hlr_set_bitrate\",\n \"hlrSetBitrate\",\n TOOL_SCOPES[\"hlr_set_bitrate\"]!,\n ctx,\n async ({ iccid, bitrate, bitrate_string }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n const limit = bitrate_string !== undefined ? bitrate_string : bitrate;\n return ocsCall(ctx.env, token, \"hlrSetBitrate\", { imsi, limit });\n },\n ),\n );\n\n // Fix #2: OCS expects { imsi } not { iccid }.\n // Resolve ICCID → IMSI via getSingleSubscriber.\n server.registerTool(\n \"hlr_get_bitrate\",\n {\n title: \"Get HLR Bitrate\",\n description:\n \"Use this to read the current HLR-level bandwidth cap applied to a subscriber. \" +\n \"A non-zero value means the subscriber is throttled to that speed regardless of package allowance. \" +\n \"A zero or null response means no HLR-level cap is in effect. \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: object with `bitrate` (integer, bits-per-second) or null if no limit is set. \" +\n \"Do NOT use this to check package data allowance limits — use `list_subscriber_packages` for that.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"hlr_get_bitrate\",\n \"hlrGetBitrate\",\n TOOL_SCOPES[\"hlr_get_bitrate\"]!,\n ctx,\n async ({ iccid }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"hlrGetBitrate\", { imsi });\n },\n ),\n );\n\n // =========================================================================\n // 3. PACKAGE TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_subscriber_packages\",\n {\n title: \"List Subscriber Packages\",\n description:\n \"Use this to retrieve all prepaid packages currently assigned to a subscriber. \" +\n \"Returns each package's allowance (data/voice/SMS), consumed usage, expiry date, status, and packageId. \" +\n \"Always call this before any package modification tool (`modify_package_limits`, \" +\n \"`modify_package_expiry`, `modify_package_status`, `delete_subscriber_package`) to confirm \" +\n \"the correct packageId and current state. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: array of package records with `packageId`, `name`, `status`, `dataLimit`, `dataUsed`, \" +\n \"`expirationDate`, `recurring` flag. \" +\n \"Do NOT use this to browse the product catalog — use `list_package_templates` for that.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_subscriber_packages\",\n \"listSubscriberPrepaidPackages\",\n TOOL_SCOPES[\"list_subscriber_packages\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n ),\n );\n\n server.registerTool(\n \"assign_package\",\n {\n title: \"Assign Package to Subscriber\",\n description:\n \"Use this to assign a one-time prepaid data/voice package to a subscriber from an existing template. \" +\n \"The package is active immediately (or at first usage, depending on template settings). \" +\n \"Params: `iccid` (subscriber identifier), `packageTemplateId` (integer from `list_package_templates`), \" +\n \"`account_for_subs` (integer, optional — when provided instead of resolving a subscriber, OCS auto-selects \" +\n \"a free eSIM from that account and assigns the package; this is the bulk auto-provisioning path). \" +\n \"Returns: created package record with `packageId`, `startDate`, `endDate`, and allowances. \" +\n \"Do NOT use this for packages that should auto-renew — use `assign_recurring_package` instead. \" +\n \"Do NOT use this to provision a new subscriber end-to-end — consider `provision_esim_wizard` \" +\n \"for a guided flow with dry-run preview.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageTemplateId: z\n .number()\n .describe(\"The package template ID to assign\"),\n account_for_subs: z\n .number()\n .optional()\n .describe(\n \"Account ID — when provided, OCS auto-selects a free eSIM from this account for bulk provisioning\",\n ),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"assign_package\",\n \"affectPackageToSubscriber\",\n TOOL_SCOPES[\"assign_package\"]!,\n ctx,\n async ({ iccid, packageTemplateId, account_for_subs }, token) => {\n // accountForSubs is an alternative to subscriber per OCS — never send both.\n if (account_for_subs !== undefined) {\n return ocsCall(ctx.env, token, \"affectPackageToSubscriber\", {\n packageTemplateId,\n accountForSubs: account_for_subs,\n });\n }\n // Fix #17: OCS affectPackageToSubscriber expects integer subscriberId, not ICCID string.\n // Resolve ICCID → numeric id via getSingleSubscriber before calling OCS.\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const subscriberId = sub.id ?? sub.subscriberId;\n if (subscriberId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve subscriberId for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"affectPackageToSubscriber\", {\n subscriber: Number(subscriberId),\n packageTemplateId,\n });\n },\n ),\n );\n\n server.registerTool(\n \"assign_recurring_package\",\n {\n title: \"Assign Recurring Package\",\n description:\n \"Use this to assign an auto-renewing prepaid package to a subscriber. The package renews \" +\n \"automatically based on the template's periodicity settings, reducing churn from manual renewal. \" +\n \"Params: `iccid` (subscriber identifier), `packageTemplateId` (integer from `list_package_templates` \" +\n \"— must be a template configured with recurring/periodicity settings), \" +\n \"`activation_at_first_use` (boolean, optional — when true, package activates on the subscriber's \" +\n \"first network usage rather than immediately; mutually exclusive with `start_time_utc`), \" +\n \"`start_time_utc` (ISO 8601 UTC datetime, optional — schedules a specific activation start; \" +\n \"mutually exclusive with `activation_at_first_use`). \" +\n \"Returns: created recurring package record with `packageId` and renewal schedule. \" +\n \"Do NOT use this for one-time packages — use `assign_package` instead. \" +\n \"To pause or cancel auto-renewal without deleting the package, use `stop_resume_recurring_package`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageTemplateId: z.number().describe(\"The package template ID\"),\n activation_at_first_use: z\n .boolean()\n .optional()\n .describe(\n \"When true, package activates on first network usage (mutually exclusive with start_time_utc)\",\n ),\n start_time_utc: z\n .string()\n .optional()\n .describe(\n \"Scheduled activation datetime in ISO 8601 UTC format (mutually exclusive with activation_at_first_use)\",\n ),\n dry_run: z\n .boolean()\n .optional()\n .describe(\"If true, do not call OCS — return the would-be request for confirmation\"),\n })\n .refine(\n (d) => !(d.activation_at_first_use === true && d.start_time_utc !== undefined),\n {\n message:\n \"activation_at_first_use and start_time_utc are mutually exclusive — choose one\",\n },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"assign_recurring_package\",\n \"affectRecurringPackageToSubscriber\",\n TOOL_SCOPES[\"assign_recurring_package\"]!,\n ctx,\n async ({ iccid, packageTemplateId, activation_at_first_use, start_time_utc }, token) => {\n // Fix #18: OCS affectRecurringPackageToSubscriber expects integer subscriberId, not ICCID string.\n // Resolve ICCID → numeric id via getSingleSubscriber before calling OCS.\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const subscriberId = sub.id ?? sub.subscriberId;\n if (subscriberId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve subscriberId for ICCID ${iccid}` }],\n };\n }\n const params: Record<string, unknown> = {\n subscriber: Number(subscriberId),\n packageTemplateId,\n };\n if (activation_at_first_use === true) params.activationAtFirstUse = true;\n if (start_time_utc !== undefined) params.startTimeUTC = start_time_utc;\n return ocsCall(ctx.env, token, \"affectRecurringPackageToSubscriber\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_package_limits\",\n {\n title: \"Modify Package Limits\",\n description:\n \"Use this to change the data, voice, or SMS allowance ceilings on an already-assigned subscriber package. \" +\n \"Useful for mid-cycle top-ups or corrections without assigning a new package. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`limits` (JSON string with the limit fields to change, e.g. {\\\"dataLimit\\\": 5368709120}). \" +\n \"Returns: updated package record with new limits. \" +\n \"Do NOT use this to change the package template (affecting future subscribers) — use `modify_template_core`. \" +\n \"Do NOT use this to change expiry — use `modify_package_expiry`. \" +\n \"Always call `list_subscriber_packages` first to confirm the correct packageId.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n limits: z.string().describe(\"New limits as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_limits\",\n \"modifySubscriberPrepaidPackageLimits\",\n TOOL_SCOPES[\"modify_package_limits\"]!,\n ctx,\n async ({ iccid, packageId, limits }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageLimits\", {\n iccid,\n packageId,\n ...(JSON.parse(limits) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_package_expiry\",\n {\n title: \"Modify Package Expiry Date\",\n description:\n \"Use this to extend or shorten the expiry date of an active prepaid package on a subscriber. \" +\n \"Useful when a subscriber's trip is longer than expected or for promotional extensions. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`expirationDate` (ISO 8601 date string, e.g. '2026-06-01' or '2026-06-01T23:59:59' — absolute date), \" +\n \"`validity_days` (integer, optional — number of days from now; passed to OCS as `newValidityDuration`; \" +\n \"provide either `expirationDate` OR `validity_days`, not both). \" +\n \"Returns: updated package record with the new expiry date. \" +\n \"Do NOT use this to change when a package becomes active — use `modify_subscriber_package_active_period`. \" +\n \"Do NOT use this to change data allowances — use `modify_package_limits`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n expirationDate: z\n .string()\n .optional()\n .describe(\"New expiry date (ISO 8601 format, absolute)\"),\n validity_days: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Number of days from now until expiry (alternative to expirationDate)\"),\n ...DRY_RUN_FIELD,\n })\n .refine(\n (d) => d.expirationDate !== undefined || d.validity_days !== undefined,\n {\n message:\n \"Provide at least one of `expirationDate` (absolute) or `validity_days` (relative)\",\n },\n )\n .refine(\n (d) => !(d.expirationDate !== undefined && d.validity_days !== undefined),\n {\n message:\n \"`expirationDate` and `validity_days` are mutually exclusive — choose one\",\n },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_expiry\",\n \"modifySubscriberPrepaidPackageExpDate\",\n TOOL_SCOPES[\"modify_package_expiry\"]!,\n ctx,\n async ({ iccid, packageId, expirationDate, validity_days }, token) => {\n const params: Record<string, unknown> = { iccid, packageId };\n if (expirationDate !== undefined) params.expirationDate = expirationDate;\n if (validity_days !== undefined) params.newValidityDuration = validity_days;\n return ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageExpDate\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_package_status\",\n {\n title: \"Modify Package Status\",\n description:\n \"Use this to activate or deactivate a specific prepaid package on a subscriber without \" +\n \"removing it. A deactivated package retains its allowances and can be reactivated later. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`status` (new package status string, e.g. 'ACTIVE', 'INACTIVE'). \" +\n \"Returns: updated package record with the new status. \" +\n \"Do NOT use this to delete a package — use `delete_subscriber_package` for permanent removal. \" +\n \"Do NOT use this to change the subscriber's overall account status — use `modify_subscriber_status`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n status: z.string().describe(\"New package status\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_status\",\n \"modifySubscriberPrepaidPackageStatus\",\n TOOL_SCOPES[\"modify_package_status\"]!,\n ctx,\n async ({ iccid, packageId, status }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageStatus\", {\n iccid,\n packageId,\n status,\n }),\n ),\n );\n\n server.registerTool(\n \"stop_resume_recurring_package\",\n {\n title: \"Stop/Resume Recurring Package\",\n description:\n \"Use this to pause or restart the auto-renewal cycle of a recurring package without removing it. \" +\n \"'stop' halts future renewals (subscriber keeps current period until expiry); \" +\n \"'resume' re-enables auto-renewal from the next renewal date. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`action` ('stop' | 'resume'). \" +\n \"Returns: updated recurring package record with new renewal state. \" +\n \"Do NOT use this to permanently delete a recurring package — use `delete_subscriber_package`. \" +\n \"Do NOT confuse this with `modify_package_status` (which activates/deactivates a package for usage).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The recurring package ID\"),\n action: z\n .enum([\"stop\", \"resume\"])\n .describe(\"Whether to stop or resume\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"stop_resume_recurring_package\",\n \"stopResumeSubsRecurringPackage\",\n TOOL_SCOPES[\"stop_resume_recurring_package\"]!,\n ctx,\n async ({ iccid, packageId, action }, token) =>\n ocsCall(ctx.env, token, \"stopResumeSubsRecurringPackage\", {\n iccid,\n packageId,\n action,\n }),\n ),\n );\n\n server.registerTool(\n \"delete_subscriber_package\",\n {\n title: \"Delete Subscriber Package\",\n description:\n \"Use this to permanently remove a single prepaid package from a subscriber. \" +\n \"This is irreversible — the package record and any unused allowance are deleted. \" +\n \"Always call `list_subscriber_packages` first to confirm the correct packageId and snapshot \" +\n \"the current state. Use `dry_run=true` on the first call. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`). \" +\n \"Returns: OCS confirmation of deletion. \" +\n \"Do NOT use this to remove ALL packages at once — use `clean_all_packages` for that (requires separate confirm). \" +\n \"Do NOT use this to pause a package — use `modify_package_status` to deactivate it instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The package ID to delete\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"delete_subscriber_package\",\n \"deleteSubscriberPackage\",\n TOOL_SCOPES[\"delete_subscriber_package\"]!,\n ctx,\n async ({ iccid, packageId }, token) =>\n ocsCall(ctx.env, token, \"deleteSubscriberPackage\", { iccid, packageId }),\n ),\n );\n\n server.registerTool(\n \"clean_all_packages\",\n {\n title: \"Clean All Subscriber Packages\",\n description:\n \"DANGEROUS: Removes ALL prepaid packages from a subscriber in a single irreversible operation. \" +\n \"There is no undo. Typical use: resetting a subscriber to zero before re-provisioning a new package series. \" +\n \"REQUIRED workflow: (1) call `list_subscriber_packages` to snapshot what will be deleted; \" +\n \"(2) call this tool with `dry_run=true` to preview; (3) get explicit user confirmation; \" +\n \"(4) call again with `dry_run=false`. \" +\n \"Params: `iccid` (subscriber identifier), `dry_run` (boolean — MUST be true on first call). \" +\n \"Returns: list of packages that were (or would be) deleted. \" +\n \"Do NOT use this to remove a single package — use `delete_subscriber_package` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"clean_all_packages\",\n \"cleanSubscriberAllPackages\",\n TOOL_SCOPES[\"clean_all_packages\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"cleanSubscriberAllPackages\", { iccid }),\n ),\n );\n\n // =========================================================================\n // 4. PACKAGE TEMPLATE TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_package_templates\",\n {\n title: \"List Package Templates\",\n description:\n \"Use this to browse the product catalog of prepaid package templates available for assignment. \" +\n \"Returns each template's name, data/voice/SMS limits, pricing, validity period, location zone, \" +\n \"and recurring configuration. Call this before `assign_package` or `assign_recurring_package` \" +\n \"to obtain valid `packageTemplateId` values. \" +\n \"Params: `accountId` (integer, optional — filter templates visible to a specific account). \" +\n \"Returns: array of template records with `templateId`, `name`, `dataLimit`, `price`, \" +\n \"`validityDays`, `locationZoneId`, `recurring`. \" +\n \"Do NOT use this to list packages assigned to a specific subscriber — use `list_subscriber_packages`.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter templates by account ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_package_templates\",\n \"listPrepaidPackageTemplate\",\n TOOL_SCOPES[\"list_package_templates\"]!,\n ctx,\n async ({ accountId }, token) => {\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) params.accountId = accountId;\n return ocsCall(ctx.env, token, \"listPrepaidPackageTemplate\", params);\n },\n ),\n );\n\n server.registerTool(\n \"create_package_template\",\n {\n title: \"Create Package Template\",\n description:\n \"Use this to create a new prepaid package template in the product catalog. Templates define \" +\n \"allowances, pricing, location zones, validity, and throttling thresholds that are reused each \" +\n \"time the template is assigned to a subscriber. \" +\n \"Params: `template` (full template configuration as a JSON string — fields include `name`, \" +\n \"`dataLimit` in bytes, `price`, `validityDays`, `locationZoneId`, `recurring`, `throttlingActive`). \" +\n \"Returns: created template record with the new `templateId`. \" +\n \"Do NOT use this to modify an existing template — use `modify_template_core`. \" +\n \"After creation, call `list_package_templates` to confirm the template is visible.\",\n inputSchema: {\n template: z\n .string()\n .describe(\"Full template configuration as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"create_package_template\",\n \"createPrepaidPackageTemplate\",\n TOOL_SCOPES[\"create_package_template\"]!,\n ctx,\n async ({ template }, token) =>\n ocsCall(\n ctx.env,\n token,\n \"createPrepaidPackageTemplate\",\n JSON.parse(template) as Record<string, unknown>,\n ),\n ),\n );\n\n server.registerTool(\n \"modify_template_core\",\n {\n title: \"Modify Template Core Settings\",\n description:\n \"Use this to change the core fields of an existing package template: name, data/voice/SMS limits, \" +\n \"pricing, validity period, and location zone. Changes affect future package assignments from this \" +\n \"template but do NOT retroactively change packages already assigned to subscribers. \" +\n \"Params: `templateId` (integer from `list_package_templates`), `changes` (JSON string with fields \" +\n \"to modify, e.g. {\\\"name\\\": \\\"Europe 5GB\\\", \\\"dataLimit\\\": 5368709120}). \" +\n \"Returns: updated template record. \" +\n \"Do NOT use this to modify throttling thresholds — use `modify_template_throttling`. \" +\n \"Do NOT use this to modify recurring/renewal settings — use `modify_template_recurring`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z.string().describe(\"Core fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_core\",\n \"modifyPPTCore\",\n TOOL_SCOPES[\"modify_template_core\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTCore\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_template_recurring\",\n {\n title: \"Modify Template Recurring Settings\",\n description:\n \"Use this to change the auto-renewal configuration of a package template: periodicity \" +\n \"(daily/weekly/monthly), occurrence count, and renewal trigger conditions. Changes affect \" +\n \"future assignments and existing recurring packages assigned from this template. \" +\n \"Params: `templateId` (integer from `list_package_templates`), `changes` (JSON string with \" +\n \"recurring fields, e.g. {\\\"periodicity\\\": \\\"monthly\\\", \\\"occurrences\\\": 12}). \" +\n \"Returns: updated template record with new recurring settings. \" +\n \"Do NOT use this to stop an individual subscriber's recurring renewal — use `stop_resume_recurring_package`. \" +\n \"Do NOT use this to change core template fields like data limits — use `modify_template_core`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z\n .string()\n .describe(\"Recurring fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_recurring\",\n \"modifyPPTRecurring\",\n TOOL_SCOPES[\"modify_template_recurring\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTRecurring\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_template_throttling\",\n {\n title: \"Modify Template Throttling\",\n description:\n \"Use this to change the bandwidth throttling thresholds on a package template. \" +\n \"WARNING: changes apply immediately to ALL existing subscriber packages created from this template, \" +\n \"not just future ones. Setting a lower threshold will NOT retroactively throttle subscribers \" +\n \"already below the new threshold (the system does not re-check existing usage). \" +\n \"Params: `templateId` (integer), `changes` (JSON string with throttling fields, e.g. \" +\n \"{\\\"throttlingActive\\\": true, \\\"firstThresholdPercent\\\": 80, \\\"firstThresholdLimitKbps\\\": 1024, \" +\n \"\\\"errorAction\\\": \\\"continue_unthrottled\\\"}). \" +\n \"Returns: updated template record with new throttling configuration. \" +\n \"Do NOT use this to throttle a single subscriber — use `hlr_set_bitrate` instead. \" +\n \"Do NOT use this to change core package limits — use `modify_template_core`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z\n .string()\n .describe(\"Throttling fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_throttling\",\n \"modifyPPTThrottling\",\n TOOL_SCOPES[\"modify_template_throttling\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTThrottling\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"list_location_zones\",\n {\n title: \"List Location Zone Elements\",\n description:\n \"Use this to list countries and networks within a specific location zone. \" +\n \"WARNING: this method has a known Jackson deserialization bug in the upstream OCS API that \" +\n \"may return malformed responses. Prefer `list_detailed_location_zones` for reliable results. \" +\n \"Params: `locationZoneId` (integer, optional — filter to a specific zone). \" +\n \"Returns: array of zone element records with country and operator entries. \" +\n \"Do NOT use this for reliable zone data — use `list_detailed_location_zones` instead. \" +\n \"Do NOT use this to create zones — use `create_location_zone`.\",\n inputSchema: {\n locationZoneId: z.number().optional().describe(\"Filter by zone ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_location_zones\",\n \"listLocationZoneElement\",\n TOOL_SCOPES[\"list_location_zones\"]!,\n ctx,\n async ({ locationZoneId }, token) => {\n const params: Record<string, unknown> = {};\n if (locationZoneId !== undefined) params.locationZoneId = locationZoneId;\n return ocsCall(ctx.env, token, \"listLocationZoneElement\", params);\n },\n ),\n );\n\n // Fix #15: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_detailed_location_zones\",\n {\n title: \"List Detailed Location Zones\",\n description:\n \"Use this as the preferred way to list location zones with full detail: included countries, \" +\n \"operator networks, zone IDs, and names. This is the working alternative to `list_location_zones` \" +\n \"which has a known upstream deserialization bug. Use `locationZoneId` values from this response \" +\n \"when creating or editing package templates. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of zone objects each containing `locationZoneId`, `name`, `countries`, and `operators`. \" +\n \"Do NOT use `list_location_zones` when you need reliable data — always use this tool instead.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_detailed_location_zones\",\n \"listDetailedLocationZone\",\n TOOL_SCOPES[\"list_detailed_location_zones\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listDetailedLocationZone\", id);\n },\n ),\n );\n\n server.registerTool(\n \"list_destination_prefixes\",\n {\n title: \"List Destination List Prefixes\",\n description:\n \"Use this to list the phone number prefixes (country dialling codes) within a specific \" +\n \"named destination list. Destination lists control which countries a subscriber may call on \" +\n \"voice/SMS packages. You must already know the `destinationListId` to use this tool. \" +\n \"Params: `destinationListId` (integer, optional — omit to list all known prefixes). \" +\n \"Returns: array of prefix records with country code and E.164 prefix. \" +\n \"Do NOT use this to discover the destination list catalog — use `list_destination_lists` for that. \" +\n \"For data-only eSIM products without MOC voice, destination lists are irrelevant.\",\n inputSchema: {\n destinationListId: z\n .number()\n .optional()\n .describe(\"Filter by destination list ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_destination_prefixes\",\n \"listDestinationListPrefix\",\n TOOL_SCOPES[\"list_destination_prefixes\"]!,\n ctx,\n async ({ destinationListId }, token) => {\n const params: Record<string, unknown> = {};\n if (destinationListId !== undefined)\n params.destinationListId = destinationListId;\n return ocsCall(ctx.env, token, \"listDestinationListPrefix\", params);\n },\n ),\n );\n\n server.registerTool(\n \"create_location_zone\",\n {\n title: \"Create Location Zone\",\n description:\n \"Use this to create a new location zone — a named collection of countries and operators \" +\n \"that defines where a package can be used. Location zones are required when creating package \" +\n \"templates. Use `list_network_profiles` to find valid operator identifiers to include. \" +\n \"Params: `zone` (full zone configuration as a JSON string — fields include `name`, `countries` \" +\n \"(array of ISO country codes), `operators` (array of MCC-MNC strings)). \" +\n \"Returns: created zone record with the new `locationZoneId`. \" +\n \"Do NOT use this to modify an existing zone — no edit tool exists yet (gap G-19, pending eSIMVault). \" +\n \"After creation, verify with `list_detailed_location_zones`.\",\n inputSchema: {\n zone: z.string().describe(\"Zone configuration as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"create_location_zone\",\n \"createLocationZone\",\n TOOL_SCOPES[\"create_location_zone\"]!,\n ctx,\n async ({ zone }, token) =>\n ocsCall(\n ctx.env,\n token,\n \"createLocationZone\",\n JSON.parse(zone) as Record<string, unknown>,\n ),\n ),\n );\n\n // =========================================================================\n // 5. STATISTICS TOOLS\n // =========================================================================\n\n // Fix #4: OCS expects { subscriber: { iccid }, period: { start, end } }\n // not { iccid, startDate, endDate }\n server.registerTool(\n \"subscriber_usage\",\n {\n title: \"Subscriber Usage Over Period\",\n description:\n \"Use this to retrieve daily data, voice, and SMS usage for a subscriber over a date range. \" +\n \"Hard limit: maximum 7 days per query — do not exceed or OCS will return an error. \" +\n \"Params: `iccid` (subscriber identifier), `startDate` (YYYY-MM-DD, inclusive), \" +\n \"`endDate` (YYYY-MM-DD, inclusive, max 7 days from start). \" +\n \"Returns: array of daily usage records. Each record contains a `usageType` integer code: \" +\n \"1=MOC (mobile-originated call), 15=MTC (mobile-terminated call), \" +\n \"21=MO-SMS (outbound SMS), 22=MT-SMS (inbound SMS), \" +\n \"33=Data, 40=MOC VoIP, 41=MTC VoIP. \" +\n \"Do NOT use this for event-level network activity — use `subscriber_network_events` for attach/detach events. \" +\n \"Do NOT use this to check current package allowances — use `list_subscriber_packages`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n startDate: z.string().describe(\"Start date (YYYY-MM-DD, inclusive)\"),\n endDate: z\n .string()\n .describe(\n \"End date (YYYY-MM-DD, inclusive, max 7 days from start)\",\n ),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_usage\",\n \"subscriberUsageOverPeriod\",\n TOOL_SCOPES[\"subscriber_usage\"]!,\n ctx,\n async ({ iccid, startDate, endDate }, token) =>\n ocsCall(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: startDate, end: endDate },\n }),\n ),\n );\n\n // Fix #5: same nested shape as subscriberUsageOverPeriod\n server.registerTool(\n \"subscriber_network_events\",\n {\n title: \"Subscriber Network Events\",\n description:\n \"Use this to retrieve timestamped network events for a subscriber: attach, detach, location \" +\n \"updates, and handovers between operators. Useful for connectivity troubleshooting, roaming \" +\n \"activity verification, and fraud pattern detection. Max 7 days per query. \" +\n \"Params: `iccid` (subscriber identifier), `startDate` (YYYY-MM-DD, inclusive), \" +\n \"`endDate` (YYYY-MM-DD, inclusive, max 7 days from start). \" +\n \"Returns: array of event records with `timestamp`, `eventType`, `country`, `operator`, `mccMnc`. \" +\n \"Do NOT use this for daily usage volumes — use `subscriber_usage` for data/voice/SMS byte counts. \" +\n \"For real-time events (last 24h), prefer `list_recent_ocs_events` which reads from the ring buffer.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n startDate: z.string().describe(\"Start date (YYYY-MM-DD, inclusive)\"),\n endDate: z.string().describe(\"End date (YYYY-MM-DD, inclusive)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_network_events\",\n \"subscriberNetworkEventsOverPeriod\",\n TOOL_SCOPES[\"subscriber_network_events\"]!,\n ctx,\n async ({ iccid, startDate, endDate }, token) =>\n ocsCall(ctx.env, token, \"subscriberNetworkEventsOverPeriod\", {\n subscriber: { iccid },\n period: { start: startDate, end: endDate },\n }),\n ),\n );\n\n server.registerTool(\n \"subscriber_active_period\",\n {\n title: \"Get Subscriber Active Period\",\n description:\n \"Use this to retrieve the lifetime activity window for a subscriber: the date of first usage \" +\n \"and the date of last usage. Useful for churn analysis, dormancy detection, and subscriber \" +\n \"lifetime value calculations. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: object with `firstUseDate` and `lastUseDate` (ISO 8601 strings). \" +\n \"Do NOT use this to check current package status — use `list_subscriber_packages`. \" +\n \"Do NOT use this for detailed daily usage patterns — use `subscriber_usage`.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_active_period\",\n \"getSubscriberActivePeriod\",\n TOOL_SCOPES[\"subscriber_active_period\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"getSubscriberActivePeriod\", { iccid }),\n ),\n );\n\n // =========================================================================\n // 6. MISC TOOLS (tariff, SMS, network profiles)\n // =========================================================================\n\n // Fix #14: OCS expects bare integer (resellerId); response key is listTariffRule.\n server.registerTool(\n \"get_tariff\",\n {\n title: \"Get Customer Tariff\",\n description:\n \"Use this to retrieve the complete tariff table for a reseller: per-country, per-traffic-type \" +\n \"(data/voice/SMS) wholesale rates. Useful for cost analysis, margin calculations, and identifying \" +\n \"expensive roaming countries before steering decisions. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of tariff rules, each with `country`, `trafficType`, `rate`, and `currency`. \" +\n \"Response key in OCS is `listTariffRule`. \" +\n \"Do NOT use this to assign a pricing plan to a subscriber — use `modify_subscriber_mobile_plan`. \" +\n \"This shows the RESELLER's wholesale cost, not what end-users are charged.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_tariff\",\n \"getCustomerTariff\",\n TOOL_SCOPES[\"get_tariff\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"getCustomerTariff\", id);\n },\n ),\n );\n\n // Fix #11: OCS expects { imsi, msisdn, text, senderId? }\n // not { iccid, msisdn, message, sender }\n // Resolve ICCID → IMSI; rename message → text, sender → senderId.\n server.registerTool(\n \"send_sms\",\n {\n title: \"Send MT SMS\",\n description:\n \"Use this to send a mobile-terminated (MT) SMS to a subscriber. Useful for service notifications, \" +\n \"package expiry alerts, and support messages sent programmatically from the platform. \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup before forwarding to OCS. \" +\n \"Params: `iccid` (subscriber identifier), `msisdn` (E.164 phone number of the subscriber), \" +\n \"`message` (SMS text content, max 160 chars for single SMS in GSM-7 encoding), \" +\n \"`sender` (optional sender ID or phone number displayed on the device). \" +\n \"⚠ Messages containing non-GSM-7 characters (any emoji, é, ñ, Chinese, Arabic, Hebrew, etc.) \" +\n \"trigger UCS-2 encoding which limits a single SMS to 70 characters instead of 160. \" +\n \"Plan for multi-part splits accordingly. \" +\n \"Returns: OCS delivery confirmation. \" +\n \"Do NOT use this for bulk SMS campaigns — this sends one message per call and is rate-limited. \" +\n \"Requires admin scope.\",\n inputSchema: {\n iccid: z.string().describe(\"The target subscriber ICCID\"),\n msisdn: z.string().describe(\"The target MSISDN\"),\n message: z.string().describe(\"SMS text content\"),\n sender: z.string().optional().describe(\"Sender ID/number (senderId in OCS)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"send_sms\",\n \"sendMtSms\",\n TOOL_SCOPES[\"send_sms\"]!,\n ctx,\n async ({ iccid, msisdn, message, sender }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n const params: Record<string, unknown> = { imsi, msisdn, text: message };\n if (sender) params.senderId = sender;\n return ocsCall(ctx.env, token, \"sendMtSms\", params);\n },\n ),\n );\n\n server.registerTool(\n \"list_network_profiles\",\n {\n title: \"List Network Profiles\",\n description:\n \"Use this to list all network profiles available to this reseller. A network profile defines \" +\n \"the roaming configuration and operator partnerships for eSIM provisioning. Use profile IDs \" +\n \"when creating location zones or configuring steering lists. \" +\n \"Params: none. \" +\n \"Returns: array of profile records with `profileId`, `name`, and coverage metadata. \" +\n \"Do NOT use this to list operator steering configurations — use `list_steering_lists` for that.\",\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_network_profiles\",\n \"listNetworkProfile\",\n TOOL_SCOPES[\"list_network_profiles\"]!,\n ctx,\n async (_args, token) => ocsCall(ctx.env, token, \"listNetworkProfile\"),\n ),\n );\n}\n","/**\n * eSIMVault OCS API client.\n * All requests are POST to /v1?token=<api_key> with JSON body { methodName: <params> }.\n * Responses: { status: { code, msg }, methodName: { ...data } }.\n *\n * params may be a plain object OR a bare scalar (number/string) for OCS methods that\n * expect a primitive as the request value rather than a nested object (e.g. listSponsor,\n * listSteeringList, getCustomerTariff, listDetailedLocationZone, getSimProviderStatus).\n */\n\nexport interface OcsStatus {\n code: number;\n msg: string;\n}\n\nexport interface OcsResponse<T = Record<string, unknown>> {\n status: OcsStatus;\n [method: string]: T | OcsStatus;\n}\n\nexport class OcsApiError extends Error {\n constructor(\n public readonly code: number,\n message: string,\n public readonly method: string,\n ) {\n super(`[${method}] OCS error ${code}: ${message}`);\n this.name = \"OcsApiError\";\n }\n}\n\nexport class OcsClient {\n private readonly baseUrl: string;\n private readonly token: string;\n\n constructor(baseUrl: string, token: string) {\n this.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n this.token = token;\n }\n\n async call<T = Record<string, unknown>>(\n method: string,\n params: Record<string, unknown> | number | string = {},\n ): Promise<T> {\n const url = `${this.baseUrl}/v1?token=${this.token}`;\n const body = JSON.stringify({ [method]: params });\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n\n if (!res.ok) {\n throw new OcsApiError(res.status, `HTTP ${res.status} ${res.statusText}`, method);\n }\n\n const json = (await res.json()) as OcsResponse<T>;\n\n if (json.status?.code !== 0) {\n throw new OcsApiError(json.status?.code ?? -1, json.status?.msg ?? \"Unknown error\", method);\n }\n\n // getCustomerTariff response is keyed as \"listTariffRule\" not \"getCustomerTariff\"\n if (method === \"getCustomerTariff\" && json[\"listTariffRule\"] !== undefined) {\n return json[\"listTariffRule\"] as T;\n }\n\n // GeoSense: live OCS returns coordinates under \"subscriberLocation\", not the method name\n if (method === \"getSubscriberLocationByCellId\") {\n const byMethod = json[method] as T | undefined;\n if (byMethod !== undefined) {\n return byMethod;\n }\n if (json[\"subscriberLocation\"] !== undefined) {\n return json[\"subscriberLocation\"] as T;\n }\n }\n\n // Return the method-specific payload\n return (json[method] as T) ?? (json as unknown as T);\n }\n}\n\nlet _client: OcsClient | null = null;\n\nexport function getClient(): OcsClient {\n if (!_client) {\n const baseUrl = process.env.ESIMVAULT_BASE_URL;\n const token = process.env.ESIMVAULT_API_TOKEN;\n if (!baseUrl || !token) {\n throw new Error(\n \"Missing ESIMVAULT_BASE_URL or ESIMVAULT_API_TOKEN environment variables. \" +\n \"Set them before starting the MCP server.\",\n );\n }\n _client = new OcsClient(baseUrl, token);\n }\n return _client;\n}\n\n/**\n * Fetch the token owner's reseller ID via getResellerInfo.\n * Used as a fallback when bare-integer methods are called without an explicit resellerId.\n */\nexport async function getDefaultResellerId(): Promise<number> {\n const info = await getClient().call<{ id?: number }>(\"getResellerInfo\", {});\n const id = info?.id;\n if (typeof id !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return id;\n}\n","/**\n * Carrier MCP — Billing v2.0 (Phase 15 — Clerk Billing GA Migration)\n *\n * Tier model:\n * free — 5,000 tool calls/mo, read scope only, no Stripe product\n * pro — 50,000 tool calls/mo, read+write+intelligence, $49/mo\n * enterprise — unlimited tool calls, read+write+admin, $499/mo, custom rate limits, SSO\n *\n * Storage layout (CARRIER_USERS KV):\n * key: user:<sub> value: UserRecord (tier field drives all gate checks)\n * key: usage:<sub>:<yyyymm> value: JSON { calls: number } (TTL: 35 days)\n *\n * Analytics Engine (carrier_mcp_audit dataset) is the source of truth for usage\n * rollups — KV counter is a fast hot path for quota checks.\n *\n * BILLING_PRIMARY feature flag (Doppler carrier/prd):\n * \"clerk\" → Clerk Billing is authoritative; KV is a cache/fallback.\n * Portal redirects to Clerk-hosted billing page.\n * Stripe webhook still runs (dual-write period; kept for 1 billing cycle).\n * \"stripe\" → (default) Direct Stripe path; Clerk plan claim is a session-layer overlay.\n *\n * IMPORTANT: This module NEVER charges a card. It only:\n * 1. Gates tool calls based on tier + call count.\n * 2. Records usage records to Stripe Metered Billing (for Pro overages, Stripe-primary only).\n * 3. Redirects users to the appropriate Billing Portal (Clerk or Stripe).\n */\n\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const TIER_CALL_LIMITS: Record<Tier, number> = {\n free: 5_000,\n pro: 50_000,\n enterprise: Infinity,\n};\n\nexport const UPGRADE_URL = \"https://mcp.carrier.llc/upgrade\";\n\nexport type Tier = \"free\" | \"pro\" | \"enterprise\";\nexport type ScopeToken = \"read\" | \"write\" | \"admin\";\n\n// Intelligence scope is a virtual scope — Pro users can call intelligence tools\n// because those tools are registered under \"read\" or \"write\" scope internally.\nexport const TIER_SCOPES: Record<Tier, ScopeToken[]> = {\n free: [\"read\"],\n pro: [\"read\", \"write\"],\n enterprise: [\"read\", \"write\", \"admin\"],\n};\n\n// ---------------------------------------------------------------------------\n// Phase 15 — BILLING_PRIMARY feature flag\n// ---------------------------------------------------------------------------\n\n/**\n * \"clerk\" → Clerk Billing is the authoritative source.\n * \"stripe\" → (default) Direct Stripe path; Clerk plan claim is a session overlay only.\n *\n * Cutover recommendation: flip to \"clerk\" after one full billing cycle of\n * dual-write validation confirming KV ↔ Clerk plan parity for all active subscribers.\n */\nexport type BillingPrimary = \"clerk\" | \"stripe\";\n\nexport function getBillingPrimary(env: Env): BillingPrimary {\n const raw = (env as Env & { BILLING_PRIMARY?: string }).BILLING_PRIMARY;\n return raw === \"clerk\" ? \"clerk\" : \"stripe\";\n}\n\n// ---------------------------------------------------------------------------\n// getUserTier\n// ---------------------------------------------------------------------------\n\n/**\n * Read the tier stored in the user's KV record.\n * Falls back to \"free\" if the record is missing or malformed.\n * When BILLING_PRIMARY=clerk this becomes a cache/fallback only.\n */\nexport async function getUserTier(env: Env, sub: string): Promise<Tier> {\n // stdio mode: no CF Workers KV available — treat as free tier (callers will gate).\n if (!env.CARRIER_USERS) return \"free\";\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(\n () => null,\n );\n if (\n raw &&\n typeof raw === \"object\" &&\n \"tier\" in raw &&\n (raw as { tier: string }).tier in TIER_CALL_LIMITS\n ) {\n return (raw as { tier: Tier }).tier;\n }\n return \"free\";\n}\n\n/**\n * Phase 15 — Resolve the effective tier.\n *\n * BILLING_PRIMARY=clerk: Clerk session plan claim is primary; KV is the fallback.\n * BILLING_PRIMARY=stripe (default): KV is canonical; Clerk plan is an overlay\n * (used to catch Clerk-driven downgrades like plan cancellations).\n *\n * In both modes: clerkPlan ?? fallbackTier — the function is the same; the\n * caller decides which value to pass as fallbackTier based on BILLING_PRIMARY.\n */\nexport function resolveTierFromClerk(\n clerkPlan: Tier | undefined,\n fallbackTier: Tier,\n): Tier {\n return clerkPlan ?? fallbackTier;\n}\n\n// ---------------------------------------------------------------------------\n// Portal URL resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Phase 15 — Build the Clerk-hosted billing portal URL.\n * Activated as primary when BILLING_PRIMARY=clerk.\n */\nexport function buildClerkBillingPortalUrl(env: Env, returnUrl: string): string {\n const base =\n env.CLERK_BILLING_PORTAL_URL ?? \"https://accounts.carrier.llc/user/billing\";\n const url = new URL(base);\n url.searchParams.set(\"redirect_url\", returnUrl);\n return url.toString();\n}\n\n/**\n * Phase 15 — Resolve the billing portal URL based on BILLING_PRIMARY.\n * This is the single entry point for all portal redirects (oauth/index.ts,\n * console billing routes, etc.).\n *\n * BILLING_PRIMARY=clerk → Clerk-hosted portal (buildClerkBillingPortalUrl)\n * BILLING_PRIMARY=stripe → Stripe portal (createBillingPortalSession) with\n * Clerk portal as fallback when Stripe is unconfigured\n */\nexport async function resolveBillingPortalUrl(\n env: Env,\n sub: string,\n returnUrl: string,\n): Promise<string | null> {\n const primary = getBillingPrimary(env);\n\n if (primary === \"clerk\") {\n return buildClerkBillingPortalUrl(env, returnUrl);\n }\n\n // BILLING_PRIMARY=stripe — try Stripe first, fall back to Clerk portal\n const stripePortalUrl = await createBillingPortalSession(env, sub, returnUrl);\n if (stripePortalUrl) return stripePortalUrl;\n\n return buildClerkBillingPortalUrl(env, returnUrl);\n}\n\n// ---------------------------------------------------------------------------\n// getScopeForTier\n// ---------------------------------------------------------------------------\n\nexport function getScopeForTier(tier: Tier): ScopeToken[] {\n return TIER_SCOPES[tier];\n}\n\n// ---------------------------------------------------------------------------\n// checkCallQuota\n// ---------------------------------------------------------------------------\n\nexport interface QuotaResult {\n allowed: boolean;\n remaining: number;\n resetAt: string; // ISO 8601 first day of next month\n tier: Tier;\n}\n\n/**\n * Returns current-month usage from KV hot counter.\n * Enterprise users always get allowed=true / remaining=Infinity.\n */\nexport async function checkCallQuota(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<QuotaResult> {\n const limit = TIER_CALL_LIMITS[tier];\n const resetAt = firstDayNextMonth();\n\n if (tier === \"enterprise\") {\n return { allowed: true, remaining: Infinity, resetAt, tier };\n }\n\n // stdio mode: no CF Workers KV available — allow unbounded calls locally.\n if (!env.CARRIER_USERS) {\n return { allowed: true, remaining: Infinity, resetAt, tier };\n }\n\n const month = currentMonth();\n const usageKey = `usage:${sub}:${month}`;\n const raw = await env.CARRIER_USERS.get(usageKey, \"json\").catch(() => null);\n const calls: number =\n raw && typeof raw === \"object\" && \"calls\" in raw\n ? Number((raw as { calls: number }).calls)\n : 0;\n\n const remaining = Math.max(0, limit - calls);\n return {\n allowed: calls < limit,\n remaining,\n resetAt,\n tier,\n };\n}\n\n// ---------------------------------------------------------------------------\n// recordUsage\n// ---------------------------------------------------------------------------\n\nexport function recordUsage(env: Env, sub: string, tier: Tier): void {\n // stdio mode: no CF Workers KV available — telemetry is a no-op locally.\n // Without this guard the async IIFE below crashes the Node process with\n // \"Cannot read properties of null (reading 'get')\" after returning the\n // tool result, breaking subsequent JSON-RPC calls over stdin.\n if (!env.CARRIER_USERS) return;\n\n (async () => {\n const month = currentMonth();\n const usageKey = `usage:${sub}:${month}`;\n\n const raw = await env.CARRIER_USERS.get(usageKey, \"json\").catch(() => null);\n const prev: number =\n raw && typeof raw === \"object\" && \"calls\" in raw\n ? Number((raw as { calls: number }).calls)\n : 0;\n const next = prev + 1;\n\n await env.CARRIER_USERS.put(\n usageKey,\n JSON.stringify({ calls: next, updated_at: new Date().toISOString() }),\n { expirationTtl: 35 * 24 * 60 * 60 },\n );\n\n // Push Stripe usage record only when Stripe is the primary billing source.\n // When BILLING_PRIMARY=clerk, Clerk Billing handles metering natively.\n if (tier === \"pro\" && next % 100 === 0 && getBillingPrimary(env) === \"stripe\") {\n await pushStripeUsageRecord(env, sub, 100).catch(() => {\n // Non-fatal — nightly rollup will reconcile.\n });\n }\n })();\n}\n\n// ---------------------------------------------------------------------------\n// pushStripeUsageRecord (internal — Stripe-primary mode only)\n// ---------------------------------------------------------------------------\n\nasync function pushStripeUsageRecord(\n env: Env,\n sub: string,\n quantity: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string })\n .STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n if (!env.CARRIER_USERS) return;\n\n const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);\n if (!subItemId) return;\n\n const body = new URLSearchParams({\n quantity: String(quantity),\n timestamp: String(Math.floor(Date.now() / 1000)),\n action: \"increment\",\n });\n\n await fetch(\n `https://api.stripe.com/v1/subscription_items/${subItemId}/usage_records`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// createBillingPortalSession (Stripe — kept for dual-write period)\n// ---------------------------------------------------------------------------\n\n/**\n * Create a Stripe Billing Portal session URL for the given customer.\n * Used by /oauth/billing route when BILLING_PRIMARY=stripe.\n * Kept during the dual-write period; will be removed after Clerk-primary cutover.\n *\n * Returns null if Stripe is not configured or the user has no Stripe customer record.\n */\nexport async function createBillingPortalSession(\n env: Env,\n sub: string,\n returnUrl: string,\n): Promise<string | null> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string })\n .STRIPE_SECRET_KEY;\n if (!stripeKey) return null;\n if (!env.CARRIER_USERS) return null;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return null;\n\n const body = new URLSearchParams({\n customer: customerId,\n return_url: returnUrl,\n });\n\n const resp = await fetch(\n \"https://api.stripe.com/v1/billing_portal/sessions\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n if (!resp.ok) return null;\n const data = (await resp.json()) as { url?: string };\n return data.url ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction currentMonth(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction firstDayNextMonth(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 1;\n if (m === 12) {\n return new Date(Date.UTC(y + 1, 0, 1)).toISOString();\n }\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { mccToIso } from \"@carrier/ocs-spec\";\nimport { OcsClient } from \"./client.js\";\nimport { getDefaultResellerId, type ToolContext } from \"./tools.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function safeCall<T = Record<string, unknown>>(\n env: { CARRIER_OCS_BASE_URL: string },\n token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const data = await client.call<T>(method, params);\n return { data, error: null };\n } catch (err) {\n return { data: null, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\n/**\n * OCS listSubscriber requires one of: accountId/activationCode/imsiPrefix/iccidPrefix/msisdnPrefix.\n * 'status' is NOT a valid filter. Fan out across reseller accounts when none provided.\n */\nasync function fetchActiveSubscribers(\n env: { CARRIER_OCS_BASE_URL: string },\n token: string,\n accountId: number | undefined,\n resellerId: number,\n): Promise<{ data: Record<string, unknown>[] | null; error: string | null }> {\n let accountIds: number[];\n if (accountId !== undefined) {\n accountIds = [accountId];\n } else {\n const accountsResult = await safeCall<{ reseller?: Array<{ account?: Array<{ id: number }> }> }>(\n env,\n token,\n \"listResellerAccount\",\n { resellerId },\n );\n if (accountsResult.error) return { data: null, error: accountsResult.error };\n const reseller = accountsResult.data?.reseller ?? [];\n accountIds = reseller.flatMap((r) => (r.account ?? []).map((a) => a.id));\n if (accountIds.length === 0) return { data: [], error: null };\n }\n\n const aggregated: Record<string, unknown>[] = [];\n for (const acctId of accountIds) {\n const subResult = await safeCall<Record<string, unknown> | Record<string, unknown>[]>(\n env,\n token,\n \"listSubscriber\",\n { accountId: acctId },\n );\n if (subResult.error) return { data: null, error: subResult.error };\n const raw = subResult.data;\n const list = Array.isArray(raw)\n ? raw\n : ((raw as { subscriberList?: Record<string, unknown>[] } | null)?.subscriberList ?? []);\n aggregated.push(...list);\n }\n\n const active = aggregated.filter((s) => String(s.status ?? \"\").toUpperCase() === \"ACTIVE\");\n return { data: active, error: null };\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i]}`;\n}\n\nfunction daysUntil(dateStr: string): number {\n const now = new Date();\n const target = new Date(dateStr);\n return Math.ceil((target.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));\n}\n\nfunction toISODate(d: Date): string {\n return d.toISOString().split(\"T\")[0];\n}\n\ntype ToolResult = { content: Array<{ type: \"text\"; text: string }>; isError?: boolean };\n\nfunction result(text: string, isError = false): ToolResult {\n return { content: [{ type: \"text\" as const, text }], ...(isError ? { isError: true } : {}) };\n}\n\n// ---------------------------------------------------------------------------\n// 1. DIAGNOSE SUBSCRIBER — \"why is this subscriber offline?\"\n// ---------------------------------------------------------------------------\n\nexport function registerIntelligenceTools(server: McpServer, ctx: ToolContext) {\n server.registerTool(\"diagnose_subscriber\", {\n title: \"Diagnose Subscriber Issues\",\n description:\n \"Smart diagnostic that chains multiple API calls to analyze why a subscriber \" +\n \"may be offline, throttled, or having connectivity issues. Returns a structured \" +\n \"diagnosis with root cause analysis and recommended actions.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to diagnose\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const findings: string[] = [];\n const actions: string[] = [];\n let severity: \"critical\" | \"warning\" | \"info\" | \"healthy\" = \"healthy\";\n\n // 1. Get subscriber details\n const sub = await safeCall<Record<string, unknown>>(ctx.env, token, \"getSingleSubscriber\", { iccid });\n if (sub.error) return result(`Failed to fetch subscriber: ${sub.error}`, true);\n if (!sub.data) return result(\"Subscriber not found\", true);\n\n const status = String(sub.data.status ?? \"\").toUpperCase();\n const balance = Number(sub.data.balance ?? 0);\n\n // Check OCS status\n if (status !== \"ACTIVE\") {\n findings.push(`OCS status is ${status} (not ACTIVE)`);\n actions.push(`Reactivate subscriber via modify_subscriber_status`);\n severity = \"critical\";\n }\n\n // Check balance\n if (balance <= 0) {\n findings.push(`Balance is ${balance} — subscriber may be blocked from usage`);\n actions.push(`Top up balance via modify_subscriber_balance`);\n if (severity !== \"critical\") severity = \"warning\";\n }\n\n // 2. Check SIM provider status — OCS expects bare simId (Long), resolve from subscriber record\n const simId = sub.data.simId ?? sub.data.sim_id ?? sub.data.id;\n const sim = simId !== undefined\n ? await safeCall<Record<string, unknown>>(ctx.env, token, \"getSimProviderStatus\", Number(simId))\n : { data: null, error: null };\n if (sim.data) {\n const simStatus = String(sim.data.simStatus ?? sim.data.status ?? \"\").toUpperCase();\n if (simStatus && ![\"ENABLED\", \"ACTIVE\", \"ACTIVATED\"].includes(simStatus)) {\n findings.push(`SIM provider status is ${simStatus} — SIM may be disabled at network level`);\n actions.push(`Enable SIM via change_sim_status`);\n severity = \"critical\";\n }\n }\n\n // 3. Check packages\n const pkgs = await safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid });\n if (pkgs.data && Array.isArray(pkgs.data)) {\n const activePkgs = pkgs.data.filter((p: Record<string, unknown>) =>\n String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n if (activePkgs.length === 0) {\n findings.push(\"No active packages — subscriber has no data/voice/SMS allowance\");\n actions.push(\"Assign a package via assign_package\");\n severity = \"critical\";\n } else {\n // Check for depleted packages\n for (const pkg of activePkgs) {\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n if (dataLimit > 0 && dataUsed >= dataLimit) {\n findings.push(\n `Package \"${pkg.name ?? pkg.packageTemplateId}\" data depleted: ` +\n `${formatBytes(dataUsed)} / ${formatBytes(dataLimit)}`\n );\n actions.push(\"Assign additional package or increase limits via modify_package_limits\");\n if (severity !== \"critical\") severity = \"warning\";\n }\n\n // Check expiry\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n if (expiry) {\n const days = daysUntil(expiry);\n if (days < 0) {\n findings.push(`Package \"${pkg.name ?? pkg.packageTemplateId}\" expired ${Math.abs(days)} days ago`);\n actions.push(\"Remove expired package and assign a new one\");\n if (severity !== \"critical\") severity = \"warning\";\n } else if (days <= 3) {\n findings.push(`Package \"${pkg.name ?? pkg.packageTemplateId}\" expires in ${days} day(s)`);\n actions.push(\"Consider renewing or assigning a recurring package\");\n if (severity === \"healthy\") severity = \"info\";\n }\n }\n }\n }\n }\n\n // 4. Check recent network events (last 2 days)\n const now = new Date();\n const twoDaysAgo = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000);\n const events = await safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberNetworkEventsOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(twoDaysAgo), end: toISODate(now) },\n });\n if (events.data && Array.isArray(events.data)) {\n if (events.data.length === 0) {\n findings.push(\"No network events in last 48 hours — device may be powered off or out of coverage\");\n if (severity === \"healthy\") severity = \"warning\";\n } else {\n const lastEvent = events.data[events.data.length - 1];\n const lastType = String(lastEvent.eventType ?? lastEvent.type ?? \"unknown\");\n findings.push(`Last network event: ${lastType} at ${lastEvent.timestamp ?? lastEvent.date ?? \"unknown\"}`);\n }\n }\n\n // 5. Check HLR bitrate — OCS expects { imsi }, resolve from subscriber record\n const imsiForBitrate = typeof sub.data.imsi === \"string\" ? sub.data.imsi : null;\n const bitrate = imsiForBitrate\n ? await safeCall<Record<string, unknown>>(ctx.env, token, \"hlrGetBitrate\", { imsi: imsiForBitrate })\n : { data: null, error: null };\n if (bitrate.data) {\n const rate = Number(bitrate.data.bitrate ?? bitrate.data.maxBitrate ?? 0);\n if (rate > 0 && rate < 1000000) {\n findings.push(`HLR bitrate throttled to ${(rate / 1000).toFixed(0)} kbps`);\n actions.push(\"Increase bitrate via hlr_set_bitrate if throttling is unintended\");\n if (severity === \"healthy\") severity = \"info\";\n }\n }\n\n // Build report\n if (findings.length === 0) {\n findings.push(\"No issues detected — subscriber appears healthy\");\n }\n\n const report = [\n `# Subscriber Diagnosis: ${iccid}`,\n ``,\n `## Severity: ${severity.toUpperCase()}`,\n ``,\n `## Findings`,\n ...findings.map((f, i) => `${i + 1}. ${f}`),\n ``,\n ...(actions.length > 0 ? [\n `## Recommended Actions`,\n ...actions.map((a, i) => `${i + 1}. ${a}`),\n ] : []),\n ``,\n `## Raw Status`,\n `- OCS Status: ${status}`,\n `- Balance: ${balance}`,\n `- Active Packages: ${pkgs.data && Array.isArray(pkgs.data) ? pkgs.data.filter((p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\").length : \"unknown\"}`,\n ].join(\"\\n\");\n\n return result(report);\n });\n\n // ---------------------------------------------------------------------------\n // 2. FLEET HEALTH — single-call fleet overview\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"fleet_health\", {\n title: \"Fleet Health Dashboard\",\n description:\n \"Aggregates eSIM status counts, low-balance accounts, and provides a \" +\n \"fleet-wide health summary in a single call. Identifies accounts that \" +\n \"need attention.\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account (omit for all)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n // OCS requires resellerId for both calls; resolve once from token owner.\n const resellerId = await getDefaultResellerId(ctx.env, token).catch(() => undefined);\n const [statusResult, accountsResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"esimStatusPerAccount\",\n accountId !== undefined\n ? { accountId }\n : resellerId !== undefined\n ? { resellerId }\n : {},\n ),\n safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"listResellerAccount\",\n resellerId !== undefined ? { resellerId } : {},\n ),\n ]);\n\n const sections: string[] = [\"# Fleet Health Dashboard\\n\"];\n\n // OCS responses are wrapped: esimStatusPerAccount → { account: [{sponsor:[{esim:{status:[...]}}]}] },\n // listResellerAccount → { reseller: [{account:[...]}] }. Unwrap to flat per-account arrays.\n const statusRaw = statusResult.data as { account?: Record<string, unknown>[] } | Record<string, unknown>[] | null;\n const statusAccounts: Record<string, unknown>[] = Array.isArray(statusRaw)\n ? statusRaw\n : (statusRaw?.account ?? []);\n const statusOk = statusResult.data !== null && (statusAccounts.length > 0 || statusResult.error === null);\n\n // OCS eSIM status shape: { statusNum: 0|1|2|3, statusStr: \"Free\"|\"Activated\"|\"Suspended\"|\"Released\", count }\n // statusNum canonical: 0=Free (inventory, not yet activated), 1=Activated, 2=Suspended, 3=Released/other.\n const countByState = (account: Record<string, unknown>): { active: number; suspended: number; inventory: number; other: number } => {\n const sponsors = (account.sponsor as Array<Record<string, unknown>> | undefined) ?? [];\n let active = 0, suspended = 0, inventory = 0, other = 0;\n for (const sp of sponsors) {\n const esim = (sp.esim as Record<string, unknown> | undefined) ?? {};\n const statuses = (esim.status as Array<Record<string, unknown>> | undefined) ?? [];\n for (const s of statuses) {\n const count = Number(s.count ?? 0);\n const num = s.statusNum;\n if (typeof num === \"number\") {\n if (num === 1) active += count;\n else if (num === 2) suspended += count;\n else if (num === 0) inventory += count;\n else other += count;\n continue;\n }\n const str = String(s.statusStr ?? s.name ?? \"\").toUpperCase();\n if (str === \"ACTIVATED\" || str === \"ACTIVE\") active += count;\n else if (str === \"SUSPENDED\") suspended += count;\n else if (str === \"FREE\" || str === \"INVENTORY\" || str === \"NOT_ACTIVATED\" || str === \"AVAILABLE\") inventory += count;\n else other += count;\n }\n }\n return { active, suspended, inventory, other };\n };\n\n let totalActive = 0, totalSuspended = 0, totalInventory = 0, totalOther = 0;\n\n if (statusOk) {\n for (const account of statusAccounts) {\n const hasSponsors = Array.isArray(account.sponsor);\n if (hasSponsors) {\n const c = countByState(account);\n totalActive += c.active;\n totalSuspended += c.suspended;\n totalInventory += c.inventory;\n totalOther += c.other;\n } else {\n totalActive += Number(account.active ?? 0);\n totalSuspended += Number(account.suspended ?? 0);\n totalInventory += Number(account.inventory ?? account.notActivated ?? 0);\n totalOther += Number(account.other ?? account.terminated ?? 0);\n }\n }\n\n const total = totalActive + totalSuspended + totalInventory + totalOther;\n const utilization = total > 0 ? ((totalActive / total) * 100).toFixed(1) : \"0\";\n\n sections.push(`## eSIM Fleet Status`);\n if (total === 0) {\n sections.push(`No eSIMs provisioned across ${statusAccounts.length} account(s).`);\n } else {\n sections.push(`| Metric | Count | % |`);\n sections.push(`|--------|-------|---|`);\n sections.push(`| Active | ${totalActive} | ${((totalActive / total) * 100).toFixed(1)}% |`);\n sections.push(`| Suspended | ${totalSuspended} | ${((totalSuspended / total) * 100).toFixed(1)}% |`);\n sections.push(`| Inventory | ${totalInventory} | ${((totalInventory / total) * 100).toFixed(1)}% |`);\n sections.push(`| Other | ${totalOther} | ${((totalOther / total) * 100).toFixed(1)}% |`);\n sections.push(`| **Total** | **${total}** | |`);\n sections.push(`\\n**Fleet Utilization: ${utilization}%**`);\n\n if (totalSuspended > totalActive * 0.1) {\n sections.push(`\\nHigh suspension rate (${totalSuspended} suspended vs ${totalActive} active)`);\n }\n }\n } else {\n sections.push(`## eSIM Fleet Status`);\n sections.push(`Unavailable: ${statusResult.error ?? \"esimStatusPerAccount returned no data\"}`);\n }\n\n // Account balances + health flags — unwrap { reseller: [{account: [...]}] }\n const accountsRaw = accountsResult.data as\n | { reseller?: Array<{ account?: Record<string, unknown>[] }> }\n | Record<string, unknown>[]\n | null;\n const accounts: Record<string, unknown>[] = Array.isArray(accountsRaw)\n ? accountsRaw\n : (accountsRaw?.reseller ?? []).flatMap((r) => r.account ?? []);\n const accountsOk = accountsResult.data !== null && (accounts.length > 0 || accountsResult.error === null);\n\n if (accountsOk) {\n const lowBalance = accounts.filter(\n (a) => Number(a.balance ?? 0) < 10,\n );\n const packageOnlyZero = accounts.filter(\n (a) => Boolean(a.packageOnly) && Number(a.balance ?? 0) <= 0,\n );\n\n sections.push(`\\n## Account Summary`);\n sections.push(`- Total accounts: ${accounts.length}`);\n sections.push(`- Low balance (< 10): ${lowBalance.length}`);\n sections.push(`- Package-only with 0 balance: ${packageOnlyZero.length}`);\n\n if (lowBalance.length > 0) {\n sections.push(`\\n### Low Balance Accounts (< 10)`);\n sections.push(`| Account | Balance | packageOnly |`);\n sections.push(`|---------|---------|-------------|`);\n for (const a of lowBalance) {\n sections.push(`| ${a.name ?? a.accountId ?? \"?\"} | ${Number(a.balance ?? 0).toFixed(2)} | ${a.packageOnly ? \"yes\" : \"no\"} |`);\n }\n }\n\n // Health verdict\n const critical = packageOnlyZero.length;\n const warning = lowBalance.length - critical;\n const healthy = accounts.length - lowBalance.length;\n sections.push(`\\n## Fleet Health Verdict`);\n sections.push(`- Healthy: ${healthy}`);\n sections.push(`- Warning (low balance, not package-only-zero): ${Math.max(warning, 0)}`);\n sections.push(`- Critical (package-only and 0 balance): ${critical}`);\n if (accounts.length === 0) {\n sections.push(`\\nNo accounts found under this reseller.`);\n } else if (critical > 0) {\n sections.push(`\\nAction: top up package-only accounts at 0 balance to keep packages assignable.`);\n } else if (lowBalance.length === 0) {\n sections.push(`\\nAll accounts healthy.`);\n }\n } else {\n sections.push(`\\n## Account Summary`);\n sections.push(`Unavailable: ${accountsResult.error ?? \"listResellerAccount returned no data\"}`);\n }\n\n // Surface aggregated errors if both upstream calls failed\n if (!statusOk && !accountsOk) {\n sections.push(`\\n## Errors`);\n if (statusResult.error) sections.push(`- esimStatusPerAccount: ${statusResult.error}`);\n if (accountsResult.error) sections.push(`- listResellerAccount: ${accountsResult.error}`);\n return result(sections.join(\"\\n\"), true);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 3. USAGE ANOMALY DETECTION\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"detect_usage_anomalies\", {\n title: \"Detect Usage Anomalies\",\n description:\n \"Analyzes a subscriber's recent usage patterns over the last 7 days to detect \" +\n \"anomalies: sudden spikes, unusual off-hours activity, or consumption rates that \" +\n \"would exhaust the package before expiry.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to analyze\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [usageResult, pkgResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n ]);\n\n if (usageResult.error) return result(`Failed to fetch usage: ${usageResult.error}`, true);\n\n const sections: string[] = [`# Usage Anomaly Report: ${iccid}\\n`];\n const anomalies: string[] = [];\n\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length > 0) {\n // Extract daily data volumes\n const dailyData: { date: string; bytes: number }[] = [];\n\n for (const entry of usageResult.data) {\n const bytes = Number(entry.dataBytes ?? entry.dataVolume ?? entry.totalData ?? 0);\n const date = String(entry.date ?? entry.day ?? \"?\");\n dailyData.push({ date, bytes });\n }\n\n if (dailyData.length >= 2) {\n // Calculate stats\n const volumes = dailyData.map(d => d.bytes);\n const mean = volumes.reduce((a, b) => a + b, 0) / volumes.length;\n const stdDev = Math.sqrt(volumes.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / volumes.length);\n\n sections.push(`## Daily Usage (Last 7 Days)`);\n sections.push(`| Date | Data | vs Average |`);\n sections.push(`|------|------|-----------|`);\n\n for (const d of dailyData) {\n const deviation = mean > 0 ? ((d.bytes - mean) / mean * 100).toFixed(0) : \"0\";\n const flag = d.bytes > mean + 2 * stdDev ? \" SPIKE\" :\n d.bytes > mean + stdDev ? \" HIGH\" : \"\";\n sections.push(`| ${d.date} | ${formatBytes(d.bytes)} | ${deviation}%${flag} |`);\n\n if (d.bytes > mean + 2 * stdDev) {\n anomalies.push(`Spike on ${d.date}: ${formatBytes(d.bytes)} (${deviation}% above average)`);\n }\n }\n\n sections.push(`\\n**Average daily usage: ${formatBytes(mean)}**`);\n sections.push(`**Std deviation: ${formatBytes(stdDev)}**`);\n\n // Burn rate analysis against active packages\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n for (const pkg of activePkgs) {\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const remaining = dataLimit - dataUsed;\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n\n if (remaining > 0 && expiry && mean > 0) {\n const daysLeft = daysUntil(expiry);\n const daysToExhaust = remaining / mean;\n\n sections.push(`\\n## Burn Rate: ${pkg.name ?? pkg.packageTemplateId}`);\n sections.push(`- Remaining: ${formatBytes(remaining)} of ${formatBytes(dataLimit)}`);\n sections.push(`- Days until expiry: ${daysLeft}`);\n sections.push(`- At current rate, data exhausts in: ${daysToExhaust.toFixed(1)} days`);\n\n if (daysToExhaust < daysLeft * 0.5) {\n anomalies.push(\n `Package \"${pkg.name ?? pkg.packageTemplateId}\" will run out ` +\n `${(daysLeft - daysToExhaust).toFixed(0)} days before expiry at current consumption`\n );\n }\n }\n }\n }\n }\n } else {\n sections.push(\"No usage data available for the last 7 days.\");\n }\n\n if (anomalies.length > 0) {\n sections.push(`\\n## Anomalies Detected`);\n anomalies.forEach((a, i) => sections.push(`${i + 1}. ${a}`));\n } else {\n sections.push(`\\n## No anomalies detected — usage appears normal.`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 4. PACKAGE OPTIMIZER — recommend better-fit packages\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"optimize_package\", {\n title: \"Package Optimization Advisor\",\n description:\n \"Compares a subscriber's actual usage against their current package and all \" +\n \"available templates. Recommends better-fit packages to reduce waste or prevent \" +\n \"overages. Calculates potential savings.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to optimize\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [usageResult, pkgResult, templatesResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listPrepaidPackageTemplate\", {}),\n ]);\n\n const sections: string[] = [`# Package Optimization: ${iccid}\\n`];\n\n // Calculate average daily usage\n let avgDailyData = 0;\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length > 0) {\n const totalData = usageResult.data.reduce(\n (sum: number, e: Record<string, unknown>) =>\n sum + Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0),\n 0\n );\n avgDailyData = totalData / usageResult.data.length;\n sections.push(`## Current Usage Pattern`);\n sections.push(`- Average daily data: ${formatBytes(avgDailyData)}`);\n sections.push(`- Projected monthly: ${formatBytes(avgDailyData * 30)}`);\n }\n\n // Current packages\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n if (activePkgs.length > 0) {\n sections.push(`\\n## Current Active Packages`);\n for (const pkg of activePkgs) {\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const utilization = dataLimit > 0 ? ((dataUsed / dataLimit) * 100).toFixed(1) : \"N/A\";\n const price = Number(pkg.price ?? pkg.cost ?? 0);\n\n sections.push(`\\n### ${pkg.name ?? pkg.packageTemplateId}`);\n sections.push(`- Data: ${formatBytes(dataUsed)} / ${formatBytes(dataLimit)} (${utilization}% used)`);\n if (price > 0) sections.push(`- Price: ${price.toFixed(2)}`);\n\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n if (expiry) sections.push(`- Expires: ${expiry} (${daysUntil(expiry)} days)`);\n\n // Flag waste\n if (dataLimit > 0 && Number(utilization) < 30) {\n sections.push(`- LOW UTILIZATION — subscriber is using less than 30% of allowance`);\n } else if (Number(utilization) > 90) {\n sections.push(`- NEAR LIMIT — subscriber at risk of running out`);\n }\n }\n }\n }\n\n // Recommend templates\n if (templatesResult.data && Array.isArray(templatesResult.data) && avgDailyData > 0) {\n // Score templates by fit\n const scored = templatesResult.data\n .map((t: Record<string, unknown>) => {\n const limit = Number(t.dataLimit ?? t.dataAllowance ?? 0);\n const validity = Number(t.validityDays ?? t.duration ?? 30);\n const price = Number(t.price ?? t.cost ?? 0);\n const projectedUsage = avgDailyData * validity;\n\n // Fit score: penalize both waste (too much data) and shortage (too little)\n const ratio = limit > 0 ? projectedUsage / limit : 0;\n const fitScore = 1 - Math.abs(1 - ratio); // 1.0 = perfect fit, 0 = terrible\n const costPerGB = limit > 0 && price > 0 ? price / (limit / (1024 * 1024 * 1024)) : Infinity;\n\n const name = String(t.name ?? t.templateId ?? \"?\");\n return { name, limit, validity, price, projectedUsage, fitScore, costPerGB, ratio };\n })\n .filter((t) => t.fitScore > 0.3 && t.limit > 0)\n .sort((a, b) => b.fitScore - a.fitScore)\n .slice(0, 5);\n\n if (scored.length > 0) {\n sections.push(`\\n## Recommended Packages (by usage fit)`);\n sections.push(`| Template | Data | Validity | Price | Fit | Projected Use |`);\n sections.push(`|----------|------|----------|-------|-----|--------------|`);\n\n for (const t of scored) {\n const fitLabel = t.fitScore > 0.8 ? \"GREAT\" : t.fitScore > 0.6 ? \"GOOD\" : \"OK\";\n sections.push(\n `| ${t.name} | ${formatBytes(t.limit)} | ` +\n `${t.validity}d | ${t.price > 0 ? t.price.toFixed(2) : \"?\"} | ` +\n `${fitLabel} (${(t.fitScore * 100).toFixed(0)}%) | ${formatBytes(t.projectedUsage)} |`\n );\n }\n }\n } else if (avgDailyData === 0) {\n sections.push(`\\n*No usage data available — cannot recommend packages without usage history.*`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 5. CHURN RISK SCORING\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"churn_risk\", {\n title: \"Churn Risk Assessment\",\n description:\n \"Analyzes a subscriber's usage trends, package status, balance, and activity \" +\n \"to produce a churn risk score (0-100) with contributing factors and retention \" +\n \"recommendations.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to assess\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [subResult, usageResult, pkgResult, activeResult] = await Promise.all([\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSingleSubscriber\", { iccid }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberActivePeriod\", { iccid }),\n ]);\n\n let riskScore = 0;\n const factors: { factor: string; impact: number; detail: string }[] = [];\n\n // Factor 1: Usage trend (declining usage = higher risk)\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length >= 3) {\n const volumes = usageResult.data.map(\n (e: Record<string, unknown>) => Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0)\n );\n const firstHalf = volumes.slice(0, Math.floor(volumes.length / 2));\n const secondHalf = volumes.slice(Math.floor(volumes.length / 2));\n const avgFirst = firstHalf.reduce((a: number, b: number) => a + b, 0) / firstHalf.length;\n const avgSecond = secondHalf.reduce((a: number, b: number) => a + b, 0) / secondHalf.length;\n\n if (avgFirst > 0) {\n const trend = (avgSecond - avgFirst) / avgFirst;\n if (trend < -0.5) {\n const impact = 30;\n riskScore += impact;\n factors.push({ factor: \"Declining usage\", impact, detail: `Usage dropped ${Math.abs(trend * 100).toFixed(0)}% week-over-week` });\n } else if (trend < -0.2) {\n const impact = 15;\n riskScore += impact;\n factors.push({ factor: \"Moderately declining usage\", impact, detail: `Usage dropped ${Math.abs(trend * 100).toFixed(0)}%` });\n }\n }\n } else if (!usageResult.data || (Array.isArray(usageResult.data) && usageResult.data.length === 0)) {\n riskScore += 25;\n factors.push({ factor: \"No recent usage\", impact: 25, detail: \"Zero data activity in last 7 days\" });\n }\n\n // Factor 2: Package status\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n if (activePkgs.length === 0) {\n riskScore += 20;\n factors.push({ factor: \"No active packages\", impact: 20, detail: \"Subscriber has no active data packages\" });\n } else {\n // Check if all packages are near expiry\n const allExpiringSoon = activePkgs.every((p: Record<string, unknown>) => {\n const expiry = String(p.expirationDate ?? p.endDate ?? \"\");\n return expiry && daysUntil(expiry) <= 5;\n });\n if (allExpiringSoon) {\n riskScore += 15;\n factors.push({ factor: \"All packages expiring soon\", impact: 15, detail: \"No package renewal in sight\" });\n }\n\n // Check if no recurring packages\n const hasRecurring = activePkgs.some(\n (p: Record<string, unknown>) => p.recurring === true || p.isRecurring === true\n );\n if (!hasRecurring) {\n riskScore += 10;\n factors.push({ factor: \"No recurring packages\", impact: 10, detail: \"Manual renewal required — higher churn risk\" });\n }\n }\n }\n\n // Factor 3: Balance\n if (subResult.data) {\n const balance = Number(subResult.data.balance ?? 0);\n if (balance <= 0) {\n riskScore += 15;\n factors.push({ factor: \"Zero balance\", impact: 15, detail: \"Cannot purchase new packages\" });\n }\n }\n\n // Factor 4: Subscriber age (newer = higher risk)\n if (activeResult.data) {\n const firstUse = String(activeResult.data.firstUseDate ?? activeResult.data.activationDate ?? \"\");\n if (firstUse) {\n const daysSinceFirst = Math.abs(daysUntil(firstUse));\n if (daysSinceFirst < 30) {\n riskScore += 10;\n factors.push({ factor: \"New subscriber\", impact: 10, detail: `Only ${daysSinceFirst} days since first use` });\n }\n }\n }\n\n // Cap at 100\n riskScore = Math.min(riskScore, 100);\n\n // Risk level\n const level = riskScore >= 70 ? \"HIGH\" : riskScore >= 40 ? \"MEDIUM\" : \"LOW\";\n\n // Build report\n const sections = [\n `# Churn Risk Assessment: ${iccid}`,\n ``,\n `## Risk Score: ${riskScore}/100 (${level})`,\n ``,\n `${\"█\".repeat(Math.floor(riskScore / 5))}${\"░\".repeat(20 - Math.floor(riskScore / 5))}`,\n ``,\n ];\n\n if (factors.length > 0) {\n sections.push(`## Contributing Factors`);\n sections.push(`| Factor | Impact | Detail |`);\n sections.push(`|--------|--------|--------|`);\n factors.sort((a, b) => b.impact - a.impact);\n for (const f of factors) {\n sections.push(`| ${f.factor} | +${f.impact} | ${f.detail} |`);\n }\n }\n\n // Retention recommendations\n sections.push(`\\n## Retention Recommendations`);\n if (riskScore >= 70) {\n sections.push(\"1. **Immediate outreach** — contact subscriber with special offer\");\n sections.push(\"2. Assign a complimentary small data package to re-engage\");\n sections.push(\"3. Set up a recurring package to reduce renewal friction\");\n } else if (riskScore >= 40) {\n sections.push(\"1. Monitor usage for next 7 days\");\n sections.push(\"2. Consider proactive package renewal notification (via send_sms)\");\n sections.push(\"3. Ensure package fits usage pattern (run optimize_package)\");\n } else {\n sections.push(\"1. No immediate action required\");\n sections.push(\"2. Continue monitoring via regular fleet_health checks\");\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 6. NETWORK COVERAGE AUDIT — \"am I on the right networks?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"audit_network_coverage\", {\n title: \"Network Coverage Audit\",\n description:\n \"Analyzes which networks your subscribers are actually connecting to in a given \" +\n \"country or across all countries. Compares against your steering lists to identify \" +\n \"mismatches — subscribers roaming on expensive or non-preferred networks. \" +\n \"Use this to answer: 'Am I using the right networks in country X?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n limit: z.number().optional().describe(\"Max subscribers to sample (default 50)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId, limit: sampleLimit }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const maxSample = sampleLimit ?? 50;\n\n // OCS listSubscriber requires accountId. Fan out across accounts.\n const resellerId = await getDefaultResellerId(ctx.env, token);\n const [subsResult, steeringResult] = await Promise.all([\n fetchActiveSubscribers(ctx.env, token, accountId, resellerId),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSteeringList\", resellerId),\n ]);\n\n if (subsResult.error) return result(`Failed to fetch subscribers: ${subsResult.error}`, true);\n\n const sections: string[] = [`# Network Coverage Audit\\n`];\n\n // Build steering list lookup\n const steeringMap = new Map<number, Record<string, unknown>>();\n if (steeringResult.data && Array.isArray(steeringResult.data)) {\n for (const sl of steeringResult.data) {\n steeringMap.set(Number(sl.steeringListId ?? sl.id), sl);\n }\n sections.push(`## Steering Lists: ${steeringMap.size} configured`);\n }\n\n // Sample subscriber locations and networks\n const countryStats = new Map<string, {\n count: number;\n networks: Map<string, number>;\n subscribers: string[];\n }>();\n\n if (subsResult.data && Array.isArray(subsResult.data)) {\n const subs = subsResult.data.slice(0, maxSample);\n sections.push(`## Sampling ${subs.length} active subscribers\\n`);\n\n // Fetch locations in batches of 10\n const batchSize = 10;\n\n for (let i = 0; i < subs.length; i += batchSize) {\n const batch = subs.slice(i, i + batchSize);\n const locations = await Promise.all(\n batch.map((s: Record<string, unknown>) =>\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", {\n iccid: String(s.iccid ?? \"\"),\n })\n )\n );\n\n for (let j = 0; j < batch.length; j++) {\n const loc = locations[j];\n if (loc.data) {\n const country = String(loc.data.country ?? loc.data.countryCode ?? \"Unknown\");\n const network = String(loc.data.network ?? loc.data.operator ?? loc.data.mccMnc ?? \"Unknown\");\n const iccid = String(batch[j].iccid ?? \"\");\n\n if (!countryStats.has(country)) {\n countryStats.set(country, { count: 0, networks: new Map(), subscribers: [] });\n }\n const stat = countryStats.get(country)!;\n stat.count++;\n stat.networks.set(network, (stat.networks.get(network) ?? 0) + 1);\n stat.subscribers.push(iccid);\n }\n }\n }\n }\n\n // Report by country\n if (countryStats.size > 0) {\n sections.push(`## Network Distribution by Country`);\n\n const sorted = [...countryStats.entries()].sort((a, b) => b[1].count - a[1].count);\n\n for (const [country, stat] of sorted) {\n sections.push(`\\n### ${country} (${stat.count} subscribers)`);\n sections.push(`| Network | Subscribers | % |`);\n sections.push(`|---------|------------|---|`);\n\n const networksSorted = [...stat.networks.entries()].sort((a, b) => b[1] - a[1]);\n for (const [network, count] of networksSorted) {\n sections.push(`| ${network} | ${count} | ${((count / stat.count) * 100).toFixed(0)}% |`);\n }\n\n if (networksSorted.length > 3) {\n sections.push(`\\n${networksSorted.length} different networks in ${country} — possible steering fragmentation`);\n }\n }\n } else {\n sections.push(\"No location data available for sampled subscribers.\");\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 7. MARKETING INTELLIGENCE — \"which countries should I target?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"marketing_intelligence\", {\n title: \"Marketing Intelligence Report\",\n description:\n \"Analyzes your subscriber base to identify high-growth markets, underserved regions, \" +\n \"and revenue concentration. Answers: 'Which countries should I target with marketing?' \" +\n \"and 'Where are my most valuable subscribers?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) params.accountId = accountId;\n\n const [subsResult, templatesResult, resellerId] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriber\", params),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listPrepaidPackageTemplate\", {}),\n getDefaultResellerId(ctx.env, token),\n ]);\n const zonesResult = await safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"listDetailedLocationZone\",\n resellerId,\n );\n\n const sections: string[] = [`# Marketing Intelligence Report\\n`];\n\n // Subscriber distribution by location\n if (subsResult.data && Array.isArray(subsResult.data)) {\n const total = subsResult.data.length;\n sections.push(`## Fleet Size: ${total} subscribers sampled\\n`);\n\n // Get locations for a sample\n const sample = subsResult.data.slice(0, 100);\n const countryData = new Map<string, {\n subscribers: number;\n activePackages: number;\n totalBalance: number;\n }>();\n\n const batchSize = 10;\n for (let i = 0; i < sample.length; i += batchSize) {\n const batch = sample.slice(i, i + batchSize);\n const locations = await Promise.all(\n batch.map((s: Record<string, unknown>) =>\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", {\n iccid: String(s.iccid ?? \"\"),\n })\n )\n );\n\n for (let j = 0; j < batch.length; j++) {\n const loc = locations[j];\n const sub = batch[j];\n const country = loc.data\n ? String(loc.data.country ?? loc.data.countryCode ?? \"Unknown\")\n : \"Unknown\";\n\n if (!countryData.has(country)) {\n countryData.set(country, { subscribers: 0, activePackages: 0, totalBalance: 0 });\n }\n const cd = countryData.get(country)!;\n cd.subscribers++;\n cd.totalBalance += Number(sub.balance ?? 0);\n }\n }\n\n if (countryData.size > 0) {\n const sorted = [...countryData.entries()].sort((a, b) => b[1].subscribers - a[1].subscribers);\n\n sections.push(`## Subscriber Concentration by Country`);\n sections.push(`| Country | Subscribers | % of Fleet | Avg Balance |`);\n sections.push(`|---------|-----------|------------|-------------|`);\n\n for (const [country, data] of sorted) {\n const pct = ((data.subscribers / sample.length) * 100).toFixed(1);\n const avgBal = (data.totalBalance / data.subscribers).toFixed(2);\n sections.push(`| ${country} | ${data.subscribers} | ${pct}% | ${avgBal} |`);\n }\n\n // Insights\n sections.push(`\\n## Market Insights`);\n\n // Top market\n const topMarket = sorted[0];\n if (topMarket) {\n sections.push(`- **Strongest market**: ${topMarket[0]} (${topMarket[1].subscribers} subscribers)`);\n if (topMarket[1].subscribers / sample.length > 0.5) {\n sections.push(` Revenue concentration risk — >50% of fleet in one market`);\n }\n }\n\n // High-value markets (high avg balance)\n const highValue = sorted\n .filter(([, d]) => d.subscribers >= 3)\n .sort((a, b) => (b[1].totalBalance / b[1].subscribers) - (a[1].totalBalance / a[1].subscribers))\n .slice(0, 3);\n\n if (highValue.length > 0) {\n sections.push(`\\n### High-Value Markets (by avg balance)`);\n for (const [country, data] of highValue) {\n sections.push(`- **${country}**: avg balance ${(data.totalBalance / data.subscribers).toFixed(2)} (${data.subscribers} subs)`);\n }\n }\n\n // Underserved (1-2 subscribers — early traction)\n const emerging = sorted.filter(([, d]) => d.subscribers >= 1 && d.subscribers <= 3);\n if (emerging.length > 0) {\n sections.push(`\\n### Emerging Markets (early traction, 1-3 subscribers)`);\n sections.push(`These markets show initial demand — consider targeted campaigns:`);\n for (const [country, data] of emerging) {\n sections.push(`- ${country}: ${data.subscribers} subscriber(s)`);\n }\n }\n }\n }\n\n // Available coverage vs actual usage\n if (zonesResult.data && Array.isArray(zonesResult.data)) {\n sections.push(`\\n## Coverage Catalog`);\n sections.push(`- Location zones available: ${zonesResult.data.length}`);\n }\n\n if (templatesResult.data && Array.isArray(templatesResult.data)) {\n sections.push(`- Package templates available: ${templatesResult.data.length}`);\n\n // Price analysis\n const prices = templatesResult.data\n .map((t: Record<string, unknown>) => Number(t.price ?? t.cost ?? 0))\n .filter((p: number) => p > 0);\n\n if (prices.length > 0) {\n const avgPrice = prices.reduce((a: number, b: number) => a + b, 0) / prices.length;\n const minPrice = Math.min(...prices);\n const maxPrice = Math.max(...prices);\n sections.push(`\\n### Pricing Range`);\n sections.push(`- Min: ${minPrice.toFixed(2)} | Avg: ${avgPrice.toFixed(2)} | Max: ${maxPrice.toFixed(2)}`);\n }\n }\n\n sections.push(`\\n## Recommended Actions`);\n sections.push(`1. Run \\`audit_network_coverage\\` to verify network quality in top markets`);\n sections.push(`2. Run \\`high_cost_subscribers\\` to identify margin pressure`);\n sections.push(`3. Consider creating regional package templates for emerging markets`);\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 8. HIGH COST SUBSCRIBERS — \"who's costing me money?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"high_cost_subscribers\", {\n title: \"High Cost Subscriber Report\",\n description:\n \"Identifies subscribers with disproportionately high data consumption relative \" +\n \"to their package value. Finds subscribers burning through data at rates that \" +\n \"erode margins. Answers: 'Which subscribers are costing me money?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n limit: z.number().optional().describe(\"Max subscribers to analyze (default 100)\"),\n thresholdPct: z.number().optional().describe(\"Usage % threshold to flag (default 80)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId, limit: maxLimit, thresholdPct }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const sampleSize = maxLimit ?? 100;\n const threshold = thresholdPct ?? 80;\n\n // OCS listSubscriber requires accountId. Fan out across accounts.\n const resellerId = await getDefaultResellerId(ctx.env, token);\n const subsResult = await fetchActiveSubscribers(ctx.env, token, accountId, resellerId);\n if (subsResult.error) return result(`Failed to fetch subscribers: ${subsResult.error}`, true);\n if (!subsResult.data || subsResult.data.length === 0) return result(\"No subscribers found\", true);\n\n const sections: string[] = [`# High Cost Subscriber Report\\n`];\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n type SubscriberCost = {\n iccid: string;\n dailyAvgBytes: number;\n packageDataLimit: number;\n packagePrice: number;\n utilizationPct: number;\n costPerGB: number;\n daysToExhaust: number;\n country: string;\n };\n\n const highCostSubs: SubscriberCost[] = [];\n\n // Analyze in batches\n const batchSize = 5;\n const subs = subsResult.data.slice(0, sampleSize);\n\n for (let i = 0; i < subs.length; i += batchSize) {\n const batch = subs.slice(i, i + batchSize);\n\n await Promise.all(\n batch.map(async (sub: Record<string, unknown>) => {\n const iccid = String(sub.iccid ?? \"\");\n\n const [usage, pkgs, loc] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", { iccid }),\n ]);\n\n // Calculate daily avg\n let dailyAvgBytes = 0;\n if (usage.data && Array.isArray(usage.data) && usage.data.length > 0) {\n const totalBytes = usage.data.reduce(\n (sum: number, e: Record<string, unknown>) =>\n sum + Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0),\n 0\n );\n dailyAvgBytes = totalBytes / usage.data.length;\n }\n\n // Get active package info\n if (pkgs.data && Array.isArray(pkgs.data)) {\n const activePkg = pkgs.data.find(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n if (activePkg && dailyAvgBytes > 0) {\n const dataLimit = Number(activePkg.dataLimit ?? activePkg.dataAllowance ?? 0);\n const dataUsed = Number(activePkg.dataUsed ?? activePkg.dataConsumed ?? 0);\n const price = Number(activePkg.price ?? activePkg.cost ?? 0);\n const utilizationPct = dataLimit > 0 ? (dataUsed / dataLimit) * 100 : 0;\n const remaining = dataLimit - dataUsed;\n const daysToExhaust = dailyAvgBytes > 0 ? remaining / dailyAvgBytes : Infinity;\n const costPerGB = price > 0 && dataUsed > 0\n ? price / (dataUsed / (1024 * 1024 * 1024))\n : 0;\n\n const country = loc.data\n ? String(loc.data.country ?? loc.data.countryCode ?? \"?\")\n : \"?\";\n\n if (utilizationPct >= threshold || daysToExhaust < 3) {\n highCostSubs.push({\n iccid,\n dailyAvgBytes,\n packageDataLimit: dataLimit,\n packagePrice: price,\n utilizationPct,\n costPerGB,\n daysToExhaust,\n country,\n });\n }\n }\n }\n })\n );\n }\n\n // Sort by utilization (highest first)\n highCostSubs.sort((a, b) => b.utilizationPct - a.utilizationPct);\n\n sections.push(`Analyzed ${subs.length} active subscribers (threshold: ${threshold}% usage)\\n`);\n\n if (highCostSubs.length === 0) {\n sections.push(`No subscribers above ${threshold}% package utilization. Fleet margins look healthy.`);\n } else {\n sections.push(`## ${highCostSubs.length} High-Cost Subscribers Found\\n`);\n sections.push(`| ICCID | Country | Daily Avg | Usage % | Days Left | Cost/GB |`);\n sections.push(`|-------|---------|-----------|---------|-----------|---------|`);\n\n let totalDailyBytes = 0;\n for (const s of highCostSubs) {\n totalDailyBytes += s.dailyAvgBytes;\n sections.push(\n `| ${s.iccid.slice(-8)}... | ${s.country} | ${formatBytes(s.dailyAvgBytes)} | ` +\n `${s.utilizationPct.toFixed(0)}% | ${s.daysToExhaust === Infinity ? \"inf\" : s.daysToExhaust.toFixed(1)} | ` +\n `${s.costPerGB > 0 ? s.costPerGB.toFixed(2) : \"?\"} |`\n );\n }\n\n sections.push(`\\n## Summary`);\n sections.push(`- High-cost subscribers: ${highCostSubs.length} / ${subs.length} (${((highCostSubs.length / subs.length) * 100).toFixed(1)}%)`);\n sections.push(`- Combined daily data burn: ${formatBytes(totalDailyBytes)}`);\n\n // Country breakdown\n const byCountry = new Map<string, number>();\n for (const s of highCostSubs) {\n byCountry.set(s.country, (byCountry.get(s.country) ?? 0) + 1);\n }\n const countrySorted = [...byCountry.entries()].sort((a, b) => b[1] - a[1]);\n if (countrySorted.length > 0) {\n sections.push(`\\n### By Country`);\n for (const [country, count] of countrySorted) {\n sections.push(`- ${country}: ${count} high-cost subscriber(s)`);\n }\n }\n\n sections.push(`\\n## Recommended Actions`);\n sections.push(`1. Review tariff rates for top countries via \\`get_tariff\\``);\n sections.push(`2. Consider throttling heavy users via \\`hlr_set_bitrate\\``);\n sections.push(`3. Run \\`optimize_package\\` on flagged ICCIDs to find better-fit plans`);\n sections.push(`4. Negotiate better wholesale rates for high-volume countries`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n // ---------------------------------------------------------------------------\n // 9. DETECT COUNTRY ENTRY — cheap MCC-based location change detection\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"detect_country_entry\", {\n title: \"Detect Country Entry\",\n description:\n \"Detects when a subscriber has entered a new country by reading \" +\n \"networkInfo.lastMcc from getSingleSubscriber (one cheap OCS call — \" +\n \"avoids the per-call cost of getSubscriberLocationByCellId). Resolves \" +\n \"MCC → ISO 3166-1 alpha-2 and optionally diffs against a caller-supplied \" +\n \"expectedCountry to return countryChanged. Designed for downstream \" +\n \"country-entry upsell workflows (e.g. mango.talk SMS/push offers). \" +\n \"COST NOTE: This tool makes exactly one OCS call per invocation. \" +\n \"Consumers running polling crons MUST enforce their own rate floor — \" +\n \"this layer provides no throttle.\",\n inputSchema: {\n subscriber: z\n .union([\n z.object({ subscriberId: z.number() }).describe(\"Internal subscriber ID\"),\n z.object({ imsi: z.string() }).describe(\"IMSI\"),\n z.object({ iccid: z.string() }).describe(\"ICCID\"),\n z.object({ msisdn: z.string() }).describe(\"MSISDN / phone number\"),\n z.object({ multiImsi: z.string() }).describe(\"Multi-IMSI identifier\"),\n z.object({ activationCode: z.string() }).describe(\"eSIM activation code\"),\n ])\n .describe(\"Subscriber identifier (use exactly one field)\"),\n expectedCountry: z\n .string()\n .length(2)\n .transform((code) => code.toUpperCase())\n .optional()\n .describe(\n \"Caller\\u2019s last-known ISO 3166-1 alpha-2 country for this subscriber \" +\n \"(e.g. \\\"RU\\\"). When provided, countryChanged is included in the response.\",\n ),\n },\n annotations: { readOnlyHint: true },\n }, async ({ subscriber, expectedCountry }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n\n // getSingleSubscriber accepts any of subscriberId | imsi | iccid | msisdn |\n // multiImsi | activationCode — pass the discriminated union value directly.\n const sub = await safeCall<Record<string, unknown>>(\n ctx.env,\n token,\n \"getSingleSubscriber\",\n subscriber as Record<string, unknown>,\n );\n\n if (sub.error) return result(`Failed to fetch subscriber: ${sub.error}`, true);\n if (!sub.data) return result(\"Subscriber not found\", true);\n\n const subscriberId =\n sub.data.subscriberId ??\n sub.data.id ??\n (\"subscriberId\" in subscriber\n ? (subscriber as { subscriberId: number }).subscriberId\n : undefined);\n\n const networkInfo = sub.data.networkInfo as Record<string, unknown> | null | undefined;\n\n if (networkInfo === null || networkInfo === undefined || typeof networkInfo !== \"object\") {\n return result(\n JSON.stringify({ status: \"no_location_data\", subscriberId: subscriberId ?? null }),\n );\n }\n\n const lastMcc =\n networkInfo.lastMcc != null ? Number(networkInfo.lastMcc) : null;\n const lastMnc =\n networkInfo.lastMnc != null ? Number(networkInfo.lastMnc) : null;\n const lastSeenAtUtc =\n networkInfo.time != null ? String(networkInfo.time) : null;\n\n if (lastMcc === null || isNaN(lastMcc)) {\n return result(\n JSON.stringify({ status: \"no_location_data\", subscriberId: subscriberId ?? null }),\n );\n }\n\n const currentCountry = mccToIso(lastMcc);\n const mccUnresolved = currentCountry === null;\n\n const response: Record<string, unknown> = {\n subscriberId: subscriberId ?? null,\n currentCountry,\n currentMcc: lastMcc,\n currentMnc: lastMnc,\n lastSeenAtUtc,\n ...(mccUnresolved ? { mccUnresolved: true } : {}),\n };\n\n if (expectedCountry !== undefined) {\n response.expectedCountry = expectedCountry;\n // null = cannot determine (MCC unresolved); true/false = definitive diff\n response.countryChanged = currentCountry !== null\n ? currentCountry !== expectedCountry\n : null;\n }\n\n return result(JSON.stringify(response, null, 2));\n });\n\n}\n","{\n \"version\": \"1.0.0\",\n \"captured_at\": \"2026-05-10T20:55:08.779899+00:00\",\n \"sources\": {\n \"live_docs_url\": \"https://docs.esimvault.cloud/ocs-api\",\n \"server_source_repo\": \"auroracapital/esimmcp.com\",\n \"server_source_commit\": \"8793971\",\n \"server_source_branch\": \"feat/intelligence-tools@e200c42 merged to main via restore-mcp-to-main PR#31\",\n \"notes\": \"Live docs SPA rendered via Kapture (2026-05-10). Server is a strict subset of live docs (43/52 methods). Zero server→live drift confirmed. 9 live-only methods are v1.1 backlog.\"\n },\n \"v1_methods\": [\n {\n \"name\": \"list_reseller_accounts\",\n \"ocs_method\": \"listResellerAccount\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all accounts across all resellers\",\n \"params\": {\n \"resellerId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_reseller_info\",\n \"ocs_method\": \"getResellerInfo\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"Retrieve reseller details\",\n \"params\": {\n \"resellerId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"esim_status_per_account\",\n \"ocs_method\": \"esimStatusPerAccount\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"eSIM status breakdown per account\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_sponsors\",\n \"ocs_method\": \"listSponsor\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all sponsor networks\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_steering_lists\",\n \"ocs_method\": \"listSteeringList\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all network steering lists\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_account_balance\",\n \"ocs_method\": \"modifyAccountBalance\",\n \"category\": \"reseller\",\n \"scope\": \"admin\",\n \"description\": \"Adjust or set reseller account balance\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": true },\n \"amount\": { \"type\": \"number\", \"required\": true },\n \"mode\": { \"type\": \"enum[adapt,set]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber\",\n \"ocs_method\": \"getSingleSubscriber\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get full subscriber details by ICCID or MSISDN\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": false },\n \"msisdn\": { \"type\": \"string\", \"required\": false },\n \"with_gz_counter\": { \"type\": \"boolean\", \"required\": false, \"ocs_field\": \"withGzCounter\", \"description\": \"When true, include greenZoneCounter { subscriberId, volumeOnGZ (bytes), lastResetDate, lastUpdateDate } in response\" }\n },\n \"response\": {\n \"greenZoneCounter\": { \"type\": \"object\", \"present_when\": \"with_gz_counter=true\", \"fields\": { \"subscriberId\": \"number\", \"volumeOnGZ\": \"number (bytes)\", \"lastResetDate\": \"string (ISO8601)\", \"lastUpdateDate\": \"string (ISO8601)\" } }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_subscribers\",\n \"ocs_method\": \"listSubscriber\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"List subscribers with optional filters\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false },\n \"status\": { \"type\": \"string\", \"required\": false },\n \"offset\": { \"type\": \"number\", \"required\": false },\n \"limit\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_balance\",\n \"ocs_method\": \"modifySubscriberBalance\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Adjust or set subscriber balance\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"amount\": { \"type\": \"number\", \"required\": true },\n \"mode\": { \"type\": \"enum[adapt,set]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_status\",\n \"ocs_method\": \"modifySubscriberStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change subscriber OCS status\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"status\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"change_sim_status\",\n \"ocs_method\": \"changeSimStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change SIM status at provider level\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"simStatus\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_sim_provider_status\",\n \"ocs_method\": \"getSimProviderStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Check SIM provider-level status\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber_location\",\n \"ocs_method\": \"getSubscriberLocation\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get last known subscriber location\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_contact_info\",\n \"ocs_method\": \"modifySubscriberContactInfo\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Update subscriber contact info\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"firstName\": { \"type\": \"string\", \"required\": false },\n \"lastName\": { \"type\": \"string\", \"required\": false },\n \"email\": { \"type\": \"string\", \"required\": false },\n \"phoneNumber\": { \"type\": \"string\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"set_subscriber_traffic_restrictions\",\n \"ocs_method\": \"setSubscriberTrafficRestrictions\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Configure traffic restrictions for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"restrictions\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_steering_list\",\n \"ocs_method\": \"modifySubscriberSteeringList\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change network steering list for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"steeringListId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"move_subscriber_range_to_account\",\n \"ocs_method\": \"moveSubscriberRangeToAccount\",\n \"category\": \"subscriber\",\n \"scope\": \"admin\",\n \"description\": \"Move subscriber range to another account\",\n \"params\": {\n \"iccidFrom\": { \"type\": \"string\", \"required\": true },\n \"iccidTo\": { \"type\": \"string\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"hlr_set_bitrate\",\n \"ocs_method\": \"hlrSetBitrate\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Set HLR bitrate for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"bitrate\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"hlr_get_bitrate\",\n \"ocs_method\": \"hlrGetBitrate\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get HLR bitrate for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_subscriber_packages\",\n \"ocs_method\": \"listSubscriberPrepaidPackages\",\n \"category\": \"packages\",\n \"scope\": \"read\",\n \"description\": \"List all prepaid packages assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"assign_package\",\n \"ocs_method\": \"affectPackageToSubscriber\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Assign prepaid package template to subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageTemplateId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"assign_recurring_package\",\n \"ocs_method\": \"affectRecurringPackageToSubscriber\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Assign recurring prepaid package to subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageTemplateId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_limits\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageLimits\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Change data/voice/SMS limits on active package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"limits\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_expiry\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageExpDate\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Change expiration date of active package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"expirationDate\": { \"type\": \"string(ISO8601)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_status\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageStatus\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Activate or deactivate a subscriber package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"status\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"stop_resume_recurring_package\",\n \"ocs_method\": \"stopResumeSubsRecurringPackage\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Stop or resume recurring package auto-renewal\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"action\": { \"type\": \"enum[stop,resume]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"delete_subscriber_package\",\n \"ocs_method\": \"deleteSubscriberPackage\",\n \"category\": \"packages\",\n \"scope\": \"admin\",\n \"description\": \"Remove a package from a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"clean_all_packages\",\n \"ocs_method\": \"cleanSubscriberAllPackages\",\n \"category\": \"packages\",\n \"scope\": \"admin\",\n \"description\": \"Remove ALL packages from a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_package_templates\",\n \"ocs_method\": \"listPrepaidPackageTemplate\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List all prepaid package templates\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"create_package_template\",\n \"ocs_method\": \"createPrepaidPackageTemplate\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Create a new prepaid package template\",\n \"params\": {\n \"template\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_core\",\n \"ocs_method\": \"modifyPPTCore\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify core settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_recurring\",\n \"ocs_method\": \"modifyPPTRecurring\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify recurring settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_throttling\",\n \"ocs_method\": \"modifyPPTThrottling\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify throttling settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_location_zones\",\n \"ocs_method\": \"listLocationZoneElement\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List countries/networks in a location zone\",\n \"params\": {\n \"locationZoneId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_detailed_location_zones\",\n \"ocs_method\": \"listDetailedLocationZone\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"Get detailed location zone definitions\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_destination_prefixes\",\n \"ocs_method\": \"listDestinationListPrefix\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List phone number prefixes in destination lists\",\n \"params\": {\n \"destinationListId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"create_location_zone\",\n \"ocs_method\": \"createLocationZone\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Create a new location zone\",\n \"params\": {\n \"zone\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_usage\",\n \"ocs_method\": \"subscriberUsageOverPeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get daily usage for a subscriber (max 7 days)\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_network_events\",\n \"ocs_method\": \"subscriberNetworkEventsOverPeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get network events for a subscriber (max 7 days)\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_active_period\",\n \"ocs_method\": \"getSubscriberActivePeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get subscriber active period\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_tariff\",\n \"ocs_method\": \"getCustomerTariff\",\n \"category\": \"tariff\",\n \"scope\": \"read\",\n \"description\": \"Retrieve customer tariff/pricing table\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"send_sms\",\n \"ocs_method\": \"sendMtSms\",\n \"category\": \"messaging\",\n \"scope\": \"write\",\n \"description\": \"Send MT SMS to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"msisdn\": { \"type\": \"string\", \"required\": true },\n \"message\": { \"type\": \"string\", \"required\": true },\n \"sender\": { \"type\": \"string\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_network_profiles\",\n \"ocs_method\": \"listNetworkProfile\",\n \"category\": \"network\",\n \"scope\": \"read\",\n \"description\": \"List all available network profiles\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n }\n ],\n \"v1_intelligence_methods\": [\n {\n \"name\": \"diagnose_subscriber\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"AI diagnostic: chains 5 OCS calls to diagnose connectivity issues\",\n \"wraps\": [\"getSingleSubscriber\", \"getSimProviderStatus\", \"listSubscriberPrepaidPackages\", \"subscriberNetworkEventsOverPeriod\", \"hlrGetBitrate\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"fleet_health\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Single-call fleet overview: accounts, eSIM counts, low-balance alerts\",\n \"wraps\": [\"listResellerAccount\", \"esimStatusPerAccount\", \"listSubscriberPrepaidPackages\"],\n \"params\": {},\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"detect_usage_anomalies\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Detect abnormal usage patterns across subscribers\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"optimize_package\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Package optimization: match subscriber usage to best template\",\n \"wraps\": [\"getSingleSubscriber\", \"listSubscriberPrepaidPackages\", \"subscriberUsageOverPeriod\", \"listPrepaidPackageTemplate\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"churn_risk\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Identify subscribers at risk of churn based on usage patterns\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\", \"getSubscriberActivePeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"audit_network_coverage\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Audit network coverage and steering effectiveness\",\n \"wraps\": [\"listDetailedLocationZone\", \"listSteeringList\", \"getSubscriberLocation\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"marketing_intelligence\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Marketing insights: segment analysis, upsell opportunities\",\n \"wraps\": [\"listResellerAccount\", \"esimStatusPerAccount\", \"listPrepaidPackageTemplate\", \"subscriberUsageOverPeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"high_cost_subscribers\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Identify highest-cost subscribers for cost optimization\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\", \"getCustomerTariff\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n }\n ],\n \"v1_1_backlog\": [\n {\n \"name\": \"affect_subscriber_phone_number\",\n \"ocs_method\": \"affectSubscriberFakePhoneNumber / affectSubscriberRealPhoneNumber\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Assign a fake or real MSISDN to a subscriber — single MCP tool wraps both OCS methods via phone_type param\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"phone_number\": { \"type\": \"string(E.164)\", \"required\": true },\n \"phone_type\": { \"type\": \"enum[fake,real]\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber_location_by_cell_id\",\n \"ocs_method\": \"getSubscriberLocationByCellId\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"status\": \"implemented\",\n \"description\": \"Resolve a cell tower tuple (radioType + MCC + MNC + LAC + optional cellId) to lat/lon via Bridge4IP GeoSense. No subscriber identifier required — caller supplies cell params directly.\",\n \"params\": {\n \"radio_type\": { \"type\": \"enum[2G,3G,4G,5G,NB-IoT]\", \"required\": true },\n \"mcc\": { \"type\": \"integer\", \"required\": true },\n \"mnc\": { \"type\": \"integer\", \"required\": true },\n \"lac\": { \"type\": \"integer\", \"required\": true },\n \"cell_id\": { \"type\": \"integer\", \"required\": false },\n \"signal_strength\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {\n \"latitude\": { \"type\": \"number\" },\n \"longitude\": { \"type\": \"number\" },\n \"accuracy\": { \"type\": \"integer\", \"notes\": \"median error in meters at 50% confidence\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_destination_lists\",\n \"ocs_method\": \"listDetailedDestinationList\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"status\": \"implemented\",\n \"description\": \"List all destination lists with full detail (prefix sets for voice/SMS routing control)\",\n \"params\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_mobile_plan\",\n \"ocs_method\": \"modifySubscriberMobilePlan\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the mobile plan assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"mobile_plan_id\": { \"type\": \"number\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_package_active_period\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageActivePeriod\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the active period (start/end dates) of a prepaid package on a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"package_id\": { \"type\": \"number\", \"required\": true },\n \"start_date\": { \"type\": \"string(ISO8601)\", \"required\": false },\n \"end_date\": { \"type\": \"string(ISO8601)\", \"required\": false }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_voip_plan\",\n \"ocs_method\": \"modifySubscriberVoipPlan\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the VoIP plan assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"voip_plan_id\": { \"type\": \"number\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"push_steering_to_subscriber\",\n \"ocs_method\": \"pushSteeringToSubs\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Push the current steering list configuration down to the subscriber's SIM — required after modifying steering to take effect\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"reset_subscriber_gz_counter\",\n \"ocs_method\": \"resetSubsGzCounter\",\n \"category\": \"subscriber\",\n \"scope\": \"admin\",\n \"status\": \"implemented\",\n \"description\": \"Reset the Green Zone (Greenzone) volume counter for a subscriber — tracks bytes consumed on reseller whitelist after bundle depletion. Irreversible, use only for reprovisioning or billing disputes.\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"resolve_cell_location\",\n \"ocs_method\": \"getSubscriberLocationByCellId\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"status\": \"stubbed\",\n \"audit_pr\": \"feat/ocs-feature-audit\",\n \"audit_stub_id\": \"S-03\",\n \"description\": \"Resolve a raw cell tower tuple (radioType + MCC + MNC + LAC + optional cellId) to lat/lon via Bridge4IP GeoSense. Does NOT require a subscriber identifier — caller supplies cell params directly. Lower-level primitive than get_subscriber_location_by_cell_id. Needed for Relay LU webhook consumer.\",\n \"params\": {\n \"radio_type\": { \"type\": \"enum[2G,3G,4G,5G,NB-IoT]\", \"required\": true },\n \"mcc\": { \"type\": \"integer\", \"required\": true },\n \"mnc\": { \"type\": \"integer\", \"required\": true },\n \"lac\": { \"type\": \"integer\", \"required\": true },\n \"cell_id\": { \"type\": \"integer\", \"required\": false },\n \"signal_strength\": { \"type\": \"integer\", \"required\": false }\n },\n \"response\": {\n \"latitude\": { \"type\": \"number\" },\n \"longitude\": { \"type\": \"number\" },\n \"accuracy\": { \"type\": \"integer\", \"notes\": \"median error in meters at 50% confidence\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"blocked_by\": \"confirm Relay LU payload shape with Bridge4IP NOC\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"carrier_webhook_config\",\n \"ocs_method\": \"getResellerInfo\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"status\": \"stubbed\",\n \"audit_pr\": \"feat/ocs-feature-audit\",\n \"audit_stub_id\": \"S-04\",\n \"description\": \"Read-only view of Bridge4IP webhook and relay flag state from getResellerInfo.trafficInfo. Surfaces relayLU, relayGy, relayCallSms, relayVoIP booleans + notification webhook types. Relay LU is the key flag for event-driven country-change detection (vs polling). Relay endpoint config is OCS portal UI-only.\",\n \"params\": {\n \"reseller_id\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {\n \"relay_lu\": { \"type\": \"boolean\", \"notes\": \"Update Location relay active — closest to country-change signal\" },\n \"relay_gy\": { \"type\": \"boolean\", \"notes\": \"Mobile data usage relay active\" },\n \"relay_voip\": { \"type\": \"boolean\", \"notes\": \"VoIP usage relay active\" },\n \"relay_calls_sms\": { \"type\": \"boolean\", \"notes\": \"Calls + SMS relay active\" },\n \"notification_webhooks\": { \"type\": \"array\", \"notes\": \"Active notification types: prepaid_usage, low_credit, esim_status, recurring_packages\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": true\n }\n ],\n \"v1_app_methods\": [\n {\n \"name\": \"fleet_health_app\",\n \"category\": \"apps\",\n \"scope\": \"read\",\n \"description\": \"MCP App: Fleet Health Dashboard — rendered chart UI wrapping the fleet_health composite. Read-only, no destructive ops.\",\n \"min_tier\": \"free\",\n \"destructive\": false,\n \"ui_resource_uri\": \"ui://fleet-health-dashboard\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"provision_esim_wizard\",\n \"category\": \"apps\",\n \"scope\": \"write\",\n \"description\": \"MCP App: eSIM Provisioning Wizard — 3-step wizard UI. Destructive on step 3 (confirm). Pro tier minimum.\",\n \"min_tier\": \"pro\",\n \"destructive\": true,\n \"destructive_step\": 3,\n \"ui_resource_uri\": \"ui://esim-provisioning-wizard\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"balance_topup_form\",\n \"category\": \"apps\",\n \"scope\": \"admin\",\n \"description\": \"MCP App: Balance Top-up Form — single-field destructive form with dry_run preview. Enterprise only, MFA-gated.\",\n \"min_tier\": \"enterprise\",\n \"destructive\": true,\n \"mfa_gated\": true,\n \"ui_resource_uri\": \"ui://balance-topup-form\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n }\n ]\n}\n","/**\n * ITU-T E.212 Mobile Country Code (MCC) → ISO 3166-1 alpha-2 mapping.\n *\n * Source: ITU-T E.212 (11/2019) + Wikipedia \"Mobile country code\" article.\n * Used by detect_country_entry intelligence composite and mango.talk country-watch cron.\n */\nexport const MCC_TO_ISO: Record<number, string> = {\n // Europe\n 202: \"GR\", // Greece\n 204: \"NL\", // Netherlands\n 206: \"BE\", // Belgium\n 208: \"FR\", // France\n 212: \"MC\", // Monaco\n 213: \"AD\", // Andorra\n 214: \"ES\", // Spain\n 216: \"HU\", // Hungary\n 218: \"BA\", // Bosnia and Herzegovina\n 219: \"HR\", // Croatia\n 220: \"RS\", // Serbia\n 221: \"XK\", // Kosovo\n 222: \"IT\", // Italy\n 225: \"VA\", // Vatican City\n 226: \"RO\", // Romania\n 228: \"CH\", // Switzerland\n 230: \"CZ\", // Czech Republic\n 231: \"SK\", // Slovakia\n 232: \"AT\", // Austria\n 234: \"GB\", // United Kingdom\n 235: \"GB\", // United Kingdom\n 238: \"DK\", // Denmark\n 240: \"SE\", // Sweden\n 242: \"NO\", // Norway\n 244: \"FI\", // Finland\n 246: \"LT\", // Lithuania\n 247: \"LV\", // Latvia\n 248: \"EE\", // Estonia\n 250: \"RU\", // Russia\n 255: \"UA\", // Ukraine\n 257: \"BY\", // Belarus\n 259: \"MD\", // Moldova\n 260: \"PL\", // Poland\n 262: \"DE\", // Germany\n 266: \"GI\", // Gibraltar\n 268: \"PT\", // Portugal\n 270: \"LU\", // Luxembourg\n 272: \"IE\", // Ireland\n 274: \"IS\", // Iceland\n 276: \"AL\", // Albania\n 278: \"MT\", // Malta\n 280: \"CY\", // Cyprus\n 282: \"GE\", // Georgia\n 283: \"AM\", // Armenia\n 284: \"BG\", // Bulgaria\n 286: \"TR\", // Turkey\n 288: \"FO\", // Faroe Islands\n 289: \"GE\", // Abkhazia (Georgia)\n 290: \"GL\", // Greenland\n 292: \"SM\", // San Marino\n 293: \"SI\", // Slovenia\n 294: \"MK\", // North Macedonia\n 295: \"LI\", // Liechtenstein\n 297: \"ME\", // Montenegro\n\n // Commonwealth of Independent States / Former USSR\n 401: \"KZ\", // Kazakhstan\n 402: \"BT\", // Bhutan\n 404: \"IN\", // India\n 405: \"IN\", // India\n 406: \"IN\", // India\n 410: \"PK\", // Pakistan\n 412: \"AF\", // Afghanistan\n 413: \"LK\", // Sri Lanka\n 414: \"MM\", // Myanmar\n 415: \"LB\", // Lebanon\n 416: \"JO\", // Jordan\n 417: \"SY\", // Syria\n 418: \"IQ\", // Iraq\n 419: \"KW\", // Kuwait\n 420: \"SA\", // Saudi Arabia\n 421: \"YE\", // Yemen\n 422: \"OM\", // Oman\n 424: \"AE\", // United Arab Emirates\n 425: \"IL\", // Israel\n 426: \"BH\", // Bahrain\n 427: \"QA\", // Qatar\n 428: \"MN\", // Mongolia\n 429: \"NP\", // Nepal\n 430: \"AE\", // United Arab Emirates\n 431: \"AE\", // United Arab Emirates\n 432: \"IR\", // Iran\n 434: \"UZ\", // Uzbekistan\n 436: \"TJ\", // Tajikistan\n 437: \"KG\", // Kyrgyzstan\n 438: \"TM\", // Turkmenistan\n 440: \"JP\", // Japan\n 441: \"JP\", // Japan\n 450: \"KR\", // South Korea\n 452: \"VN\", // Vietnam\n 454: \"HK\", // Hong Kong\n 455: \"MO\", // Macau\n 456: \"KH\", // Cambodia\n 457: \"LA\", // Laos\n 460: \"CN\", // China\n 461: \"CN\", // China\n 466: \"TW\", // Taiwan\n 467: \"KP\", // North Korea\n 470: \"BD\", // Bangladesh\n 472: \"MV\", // Maldives\n 502: \"MY\", // Malaysia\n 505: \"AU\", // Australia\n 510: \"ID\", // Indonesia\n 514: \"TL\", // East Timor\n 515: \"PH\", // Philippines\n 520: \"TH\", // Thailand\n 525: \"SG\", // Singapore\n 528: \"BN\", // Brunei\n 530: \"NZ\", // New Zealand\n 536: \"NR\", // Nauru\n 537: \"PG\", // Papua New Guinea\n 539: \"TO\", // Tonga\n 540: \"SB\", // Solomon Islands\n 541: \"VU\", // Vanuatu\n 542: \"FJ\", // Fiji\n 544: \"AS\", // American Samoa\n 545: \"KI\", // Kiribati\n 546: \"NC\", // New Caledonia\n 547: \"PF\", // French Polynesia\n 548: \"CK\", // Cook Islands\n 549: \"WS\", // Samoa\n 550: \"FM\", // Micronesia\n 551: \"MH\", // Marshall Islands\n 552: \"PW\", // Palau\n 553: \"TV\", // Tuvalu\n 555: \"NU\", // Niue\n\n // Africa (ITU-T E.212)\n 602: \"EG\", // Egypt\n 603: \"DZ\", // Algeria\n 604: \"MA\", // Morocco\n 605: \"TN\", // Tunisia\n 606: \"LY\", // Libya\n 607: \"GM\", // Gambia\n 608: \"SN\", // Senegal\n 609: \"MR\", // Mauritania\n 610: \"ML\", // Mali\n 611: \"GN\", // Guinea\n 612: \"CI\", // Côte d'Ivoire\n 613: \"BF\", // Burkina Faso\n 614: \"NE\", // Niger\n 615: \"TG\", // Togo\n 616: \"BJ\", // Benin\n 617: \"MU\", // Mauritius\n 618: \"LR\", // Liberia\n 619: \"SL\", // Sierra Leone\n 620: \"GH\", // Ghana\n 621: \"NG\", // Nigeria\n 622: \"TD\", // Chad\n 623: \"CF\", // Central African Republic\n 624: \"CM\", // Cameroon\n 625: \"CV\", // Cape Verde\n 626: \"ST\", // São Tomé and Príncipe\n 627: \"GQ\", // Equatorial Guinea\n 628: \"GA\", // Gabon\n 629: \"CG\", // Republic of the Congo\n 630: \"CD\", // Democratic Republic of the Congo\n 631: \"AO\", // Angola\n 632: \"GW\", // Guinea-Bissau\n 633: \"SC\", // Seychelles\n 634: \"SD\", // Sudan\n 635: \"RW\", // Rwanda\n 636: \"ET\", // Ethiopia\n 637: \"SO\", // Somalia\n 638: \"DJ\", // Djibouti\n 639: \"KE\", // Kenya\n 640: \"TZ\", // Tanzania\n 641: \"UG\", // Uganda\n 642: \"BI\", // Burundi\n 643: \"MZ\", // Mozambique\n 645: \"ZM\", // Zambia\n 646: \"MG\", // Madagascar\n 647: \"RE\", // Réunion / French Indian Ocean\n 648: \"ZW\", // Zimbabwe\n 649: \"NA\", // Namibia\n 650: \"MW\", // Malawi\n 651: \"LS\", // Lesotho\n 652: \"BW\", // Botswana\n 653: \"SZ\", // Eswatini\n 654: \"KM\", // Comoros\n 655: \"ZA\", // South Africa\n 657: \"ER\", // Eritrea\n 658: \"SH\", // Saint Helena\n 659: \"SS\", // South Sudan\n 702: \"BZ\", // Belize\n 704: \"GT\", // Guatemala\n 706: \"SV\", // El Salvador\n 708: \"HN\", // Honduras\n 710: \"NI\", // Nicaragua\n 712: \"CR\", // Costa Rica\n 714: \"PA\", // Panama\n 716: \"PE\", // Peru\n 722: \"AR\", // Argentina\n 724: \"BR\", // Brazil\n 730: \"CL\", // Chile\n 732: \"CO\", // Colombia\n 734: \"VE\", // Venezuela\n 736: \"BO\", // Bolivia\n 738: \"GY\", // Guyana\n 740: \"EC\", // Ecuador\n 742: \"GF\", // French Guiana\n 744: \"PY\", // Paraguay\n 746: \"SR\", // Suriname\n 748: \"UY\", // Uruguay\n 750: \"FK\", // Falkland Islands\n\n // North America, Caribbean\n 302: \"CA\", // Canada\n 308: \"PM\", // Saint Pierre and Miquelon\n 310: \"US\", // United States\n 311: \"US\", // United States\n 312: \"US\", // United States\n 313: \"US\", // United States\n 314: \"US\", // United States\n 315: \"US\", // United States\n 316: \"US\", // United States\n 330: \"PR\", // Puerto Rico\n 332: \"VI\", // U.S. Virgin Islands\n 334: \"MX\", // Mexico\n 338: \"JM\", // Jamaica\n 340: \"GP\", // Guadeloupe\n 342: \"BB\", // Barbados\n 344: \"AG\", // Antigua and Barbuda\n 346: \"KY\", // Cayman Islands\n 348: \"VG\", // British Virgin Islands\n 350: \"BM\", // Bermuda\n 352: \"GD\", // Grenada\n 354: \"MS\", // Montserrat\n 356: \"KN\", // Saint Kitts and Nevis\n 358: \"LC\", // Saint Lucia\n 360: \"VC\", // Saint Vincent and the Grenadines\n 362: \"CW\", // Curaçao / Netherlands Antilles\n 363: \"AW\", // Aruba\n 364: \"BS\", // Bahamas\n 365: \"AI\", // Anguilla\n 366: \"DM\", // Dominica\n 368: \"CU\", // Cuba\n 370: \"DO\", // Dominican Republic\n 372: \"HT\", // Haiti\n 374: \"TT\", // Trinidad and Tobago\n 376: \"TC\", // Turks and Caicos Islands\n\n // Special / Test MCCs\n 999: \"XX\", // Test network\n 901: \"XX\", // International / satellite\n};\n\n/**\n * Resolve an MCC (Mobile Country Code, ITU-T E.212) to ISO 3166-1 alpha-2.\n * Returns null for unknown MCCs.\n */\nexport function mccToIso(mcc: number | string | null | undefined): string | null {\n if (mcc == null) return null;\n let n: number;\n if (typeof mcc === \"string\") {\n const trimmed = mcc.trim();\n if (trimmed === \"\" || !/^\\d+$/.test(trimmed)) return null;\n n = parseInt(trimmed, 10);\n } else {\n n = mcc;\n }\n if (!Number.isFinite(n)) return null;\n return MCC_TO_ISO[n] ?? null;\n}\n\n/**\n * Reverse: get all MCCs for a given ISO 3166-1 alpha-2 country code.\n */\nexport function isoToMccs(iso: string): number[] {\n const upper = iso.toUpperCase();\n return Object.entries(MCC_TO_ISO)\n .filter(([, v]) => v === upper)\n .map(([k]) => Number(k));\n}\n","import methodsJson from \"../ocs-methods.json\" with { type: \"json\" };\n\nexport { MCC_TO_ISO, mccToIso, isoToMccs } from \"./mcc-iso.js\";\n\nexport type OcsScope = \"read\" | \"write\" | \"admin\";\n\nexport interface OcsParam {\n type: string;\n required: boolean;\n}\n\nexport interface OcsMethod {\n name: string;\n ocs_method: string;\n category: string;\n scope: OcsScope;\n description: string;\n params: Record<string, OcsParam>;\n response: Record<string, unknown>;\n annotations: string;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsIntelligenceMethod {\n name: string;\n category: \"intelligence\";\n scope: OcsScope;\n description: string;\n wraps: string[];\n params: Record<string, OcsParam>;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsBacklogMethod {\n name: string;\n ocs_method: string;\n category: string;\n scope: OcsScope;\n source: string;\n rationale: string;\n}\n\n/**\n * v1.2 — MCP App registry entry.\n *\n * Documents server-rendered UI surfaces (resourceUri + tier gating) without\n * a corresponding OCS REST method. Listed in `ocs-methods.json#v1_app_methods`\n * so the nightly fidelity reconcile script doesn't flag the app tool names\n * (e.g. `fleet_health_app`) as drift.\n */\nexport interface OcsAppMethod {\n name: string;\n category: \"apps\";\n scope: OcsScope;\n description: string;\n min_tier: \"free\" | \"pro\" | \"enterprise\";\n destructive: boolean;\n destructive_step?: number;\n mfa_gated?: boolean;\n ui_resource_uri: string;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsSpec {\n version: string;\n captured_at: string;\n sources: {\n live_docs_url: string;\n server_source_repo: string;\n server_source_commit: string;\n server_source_branch: string;\n notes: string;\n };\n v1_methods: OcsMethod[];\n v1_intelligence_methods: OcsIntelligenceMethod[];\n v1_1_backlog: OcsBacklogMethod[];\n /** v1.2c — registered MCP App tools; excluded from OCS drift detection. */\n v1_app_methods: OcsAppMethod[];\n}\n\n// Cast via `unknown` because TypeScript's strict `as` check considers the\n// inferred JSON shape and the declared OcsSpec insufficiently overlapping\n// once optional/variant fields are present across method entries.\nexport const ocsSpec: OcsSpec = methodsJson as unknown as OcsSpec;\nexport const ocsMethods: OcsMethod[] = ocsSpec.v1_methods;\nexport const ocsIntelligenceMethods: OcsIntelligenceMethod[] = ocsSpec.v1_intelligence_methods;\nexport const ocsBacklog: OcsBacklogMethod[] = ocsSpec.v1_1_backlog;\nexport const ocsAppMethods: OcsAppMethod[] = ocsSpec.v1_app_methods;\n\nexport function getMethodScope(name: string): OcsScope | undefined {\n const v1 = ocsSpec.v1_methods.find((m) => m.name === name);\n if (v1) return v1.scope;\n const intel = ocsSpec.v1_intelligence_methods.find((m) => m.name === name);\n if (intel) return intel.scope;\n return undefined;\n}\n\nexport function getMethodsByScope(scope: OcsScope): OcsMethod[] {\n return ocsSpec.v1_methods.filter((m) => m.scope === scope);\n}\n\nexport function getAllMethodNames(): string[] {\n return [\n ...ocsSpec.v1_methods.map((m) => m.name),\n ...ocsSpec.v1_intelligence_methods.map((m) => m.name),\n ];\n}\n","/**\n * Carrier MCP — v1.1 backlog tool registrations (9 tools) + v1.2 audit stubs (3 tools).\n *\n * These are OCS methods confirmed live in the eSIMVault API docs but not yet\n * exposed in the v1 server. All 9 v1.1 tools are wired here to close coverage gaps\n * identified in the 2026-05-12 forensic audit (mango/.planning/research/03-carrier-llc-audit.md).\n *\n * v1.2 AUDIT STUBS (feat/ocs-feature-audit, 2026-05-20):\n * Registered but throw NotImplementedError — implementation in follow-up PRs.\n * These stubs are intentionally NOT added to BACKLOG_TOOL_SCOPES or to the\n * carrier_ask tool registry until implemented. The registerAllBacklogTools function\n * conditionally registers them only when CARRIER_AUDIT_STUBS_ENABLED=true.\n * Stubs: carrier_webhook_config (resolve_cell_location removed — merged into get_subscriber_location_by_cell_id)\n * See: docs/research/bridge4ip-ocs-api/UNUSED-FEATURES.md\n *\n * Scope assignments (v1.1):\n * write — affect_subscriber_phone_number, modify_subscriber_mobile_plan,\n * modify_subscriber_package_active_period, modify_subscriber_voip_plan,\n * push_steering_to_subscriber\n * read — get_subscriber_location_by_cell_id, list_destination_lists,\n * resolve_cell_location, carrier_webhook_config\n * admin — reset_subscriber_gz_counter\n *\n * Schema notes:\n * - All ICCID-accepting tools use the subscriber-record lookup cache pattern\n * (resolveSubscriberByIccid) for IMSI resolution where required.\n * - pushSteeringToSubs is listed as \"write\" in the live docs; marked write here\n * pending confirmation from eSIMVault support (gap G-04).\n * - resetSubsGzCounter is admin-scoped; usage counter resets are irreversible.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { OcsClient } from \"./client.js\";\nimport {\n wrapHandler,\n resolveSubscriberByIccid,\n getDefaultResellerId,\n type ToolContext,\n} from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\n\nconst DRY_RUN_FIELD = {\n dry_run: z\n .boolean()\n .optional()\n .describe(\n \"If true, do not call OCS — return the would-be request for confirmation\",\n ),\n};\n\n/** Scope lookup for the v1.1 backlog tools + implemented v1.2 tools. */\nexport const BACKLOG_TOOL_SCOPES: Record<string, ToolScope> = {\n affect_subscriber_phone_number: \"write\",\n carrier_webhook_config: \"read\",\n get_subscriber_location_by_cell_id: \"read\",\n list_destination_lists: \"read\",\n modify_subscriber_mobile_plan: \"write\",\n modify_subscriber_package_active_period: \"write\",\n modify_subscriber_voip_plan: \"write\",\n push_steering_to_subscriber: \"write\",\n reset_subscriber_gz_counter: \"admin\",\n};\n\nexport function registerAllBacklogTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // 1. AFFECT SUBSCRIBER PHONE NUMBER\n // OCS methods: affectSubscriberFakePhoneNumber / affectSubscriberRealPhoneNumber\n // Gap: G-08 (MEDIUM). Merges two OCS methods behind one MCP tool.\n // =========================================================================\n server.registerTool(\n \"affect_subscriber_phone_number\",\n {\n title: \"Assign Phone Number to Subscriber\",\n description:\n \"Use this to assign a phone number (MSISDN) to a subscriber. Supports both fake/test MSISDNs \" +\n \"and real production MSISDNs via the `phone_type` parameter. Required for MSISDN assignment \" +\n \"workflows before activating voice services. \" +\n \"Params: `iccid` (subscriber identifier), `phone_number` (E.164 format, e.g. +31612345678), \" +\n \"`phone_type` ('fake' for test/dev, 'real' for production). \" +\n \"Returns: updated subscriber record with the new MSISDN. \" +\n \"Do NOT use this to check a subscriber's current MSISDN — use `get_subscriber` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n phone_number: z\n .string()\n .describe(\"E.164 phone number to assign (e.g. +31612345678)\"),\n phone_type: z\n .enum([\"fake\", \"real\"])\n .describe(\n \"'fake' assigns a test/dev MSISDN (affectSubscriberFakePhoneNumber in OCS); \" +\n \"'real' assigns a production MSISDN (affectSubscriberRealPhoneNumber in OCS)\",\n ),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"affect_subscriber_phone_number\",\n \"affectSubscriberFakePhoneNumber/affectSubscriberRealPhoneNumber\",\n BACKLOG_TOOL_SCOPES[\"affect_subscriber_phone_number\"]!,\n ctx,\n async ({ iccid, phone_number, phone_type }: { iccid: string; phone_number: string; phone_type: string }, token: string) => {\n const ocsMethod =\n phone_type === \"fake\"\n ? \"affectSubscriberFakePhoneNumber\"\n : \"affectSubscriberRealPhoneNumber\";\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(ocsMethod, { subscriber: iccid, phoneNumber: phone_number });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 2. GET SUBSCRIBER LOCATION BY CELL ID\n // OCS method: getSubscriberLocationByCellId (Bridge4IP GeoSense)\n // Gap: G-09 (MEDIUM). Takes a cell tuple — no subscriber identifier needed.\n // =========================================================================\n server.registerTool(\n \"get_subscriber_location_by_cell_id\",\n {\n title: \"Get Location by Cell ID (GeoSense)\",\n description:\n \"Powered by Bridge4IP GeoSense — cell-level location resolution with sub-cell accuracy where available. \" +\n \"Use this to resolve a cell tower tuple (radio type + MCC + MNC + LAC + optional cellId) \" +\n \"to a latitude/longitude estimate. \" +\n \"No subscriber identifier required — caller supplies cell parameters directly. \" +\n \"Useful for fraud detection, roaming cost attribution, and network troubleshooting when \" +\n \"you have raw cell info from an external source (e.g. a Relay LU webhook event). \" +\n \"Params: `radio_type` ('2G'|'3G'|'4G'|'5G'|'NB-IoT'), `mcc` (int), `mnc` (int), \" +\n \"`lac` (int), `cell_id` (int, optional but strongly recommended for accuracy), \" +\n \"`signal_strength` (number dBm, optional). \" +\n \"Returns: { latitude, longitude, accuracy } — accuracy is median error in meters at 50% confidence. \" +\n \"Without cell_id accuracy degrades significantly (>10 km). \" +\n \"Do NOT use this for bulk fleet location sweeps — one OCS call per cell tower; \" +\n \"use `audit_network_coverage` for fleet-level analysis instead.\",\n inputSchema: {\n radio_type: z\n .enum([\"2G\", \"3G\", \"4G\", \"5G\", \"NB-IoT\"])\n .describe(\"Radio access technology type\"),\n mcc: z.number().int().describe(\"Mobile Country Code (e.g. 250 for Russia, 234 for UK)\"),\n mnc: z.number().int().describe(\"Mobile Network Code\"),\n lac: z.number().int().describe(\"Location Area Code\"),\n cell_id: z\n .number()\n .int()\n .optional()\n .describe(\"Cell tower ID — strongly recommended for accuracy\"),\n signal_strength: z\n .number()\n .optional()\n .describe(\"Signal strength in dBm (e.g. -89). Optional, improves accuracy.\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber_location_by_cell_id\",\n \"getSubscriberLocationByCellId\",\n BACKLOG_TOOL_SCOPES[\"get_subscriber_location_by_cell_id\"]!,\n ctx,\n async (\n {\n radio_type,\n mcc,\n mnc,\n lac,\n cell_id,\n signal_strength,\n }: {\n radio_type: \"2G\" | \"3G\" | \"4G\" | \"5G\" | \"NB-IoT\";\n mcc: number;\n mnc: number;\n lac: number;\n cell_id?: number;\n signal_strength?: number;\n },\n token: string,\n ) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const params: Record<string, unknown> = { radioType: radio_type, mcc, mnc, lac };\n if (cell_id !== undefined) params.cellId = cell_id;\n if (signal_strength !== undefined) params.signalStrength = signal_strength;\n const result = await client.call(\"getSubscriberLocationByCellId\", params);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 3. LIST DESTINATION LISTS\n // OCS method: listDetailedDestinationList\n // Gap: G-13 (MEDIUM). The existing list_destination_prefixes only reads\n // prefixes WITHIN a known list ID; this tool returns the list catalog itself.\n // =========================================================================\n server.registerTool(\n \"list_destination_lists\",\n {\n title: \"List Destination Lists\",\n description:\n \"Use this to retrieve the full catalog of destination lists available to this reseller. \" +\n \"A destination list is a named set of phone number prefixes (country codes) that control \" +\n \"which numbers a subscriber may call on a voice/SMS package. \" +\n \"Returns: array of destination list records, each with `id`, `name`, and prefix count. \" +\n \"Do NOT use this to read the prefixes inside a specific list — use `list_destination_prefixes` \" +\n \"with a known `destinationListId` for that. \" +\n \"Do NOT use this for data-only eSIM products without MOC voice; destination lists only \" +\n \"apply to packages with voice/SMS allowances.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_destination_lists\",\n \"listDetailedDestinationList\",\n BACKLOG_TOOL_SCOPES[\"list_destination_lists\"]!,\n ctx,\n async ({ resellerId }: { resellerId?: number }, token: string) => {\n const id =\n resellerId ??\n (await (async () => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const info = await client.call<{ id?: number }>(\"getResellerInfo\", {});\n const resolvedId = info?.id;\n if (typeof resolvedId !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return resolvedId;\n })());\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\"listDetailedDestinationList\", id);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 4. MODIFY SUBSCRIBER MOBILE PLAN\n // OCS method: modifySubscriberMobilePlan\n // Gap: G-06 (HIGH). Needed to change which pricing plan a subscriber is billed under.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_mobile_plan\",\n {\n title: \"Modify Subscriber Mobile Plan\",\n description:\n \"Use this to change the mobile pricing plan assigned to a specific subscriber. \" +\n \"The mobile plan determines per-country rates for data, voice, and SMS. Changing the plan \" +\n \"takes effect immediately on the next OCS rating cycle. \" +\n \"Params: `iccid` (subscriber identifier), `mobile_plan_id` (integer plan ID — obtain valid \" +\n \"plan IDs from the OCS reseller settings or `get_tariff`). \" +\n \"Returns: updated subscriber record confirming the new plan assignment. \" +\n \"Do NOT use this to change package allowances — use `modify_package_limits` for that. \" +\n \"Do NOT use this to change account-level pricing — this only affects the individual subscriber.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n mobile_plan_id: z\n .number()\n .describe(\"The mobile pricing plan ID to assign to this subscriber\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_mobile_plan\",\n \"modifySubscriberMobilePlan\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_mobile_plan\"]!,\n ctx,\n async ({ iccid, mobile_plan_id }: { iccid: string; mobile_plan_id: number }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberMobilePlan\",\n { subscriber: iccid, mobilePlanId: mobile_plan_id },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 5. MODIFY SUBSCRIBER PACKAGE ACTIVE PERIOD\n // OCS method: modifySubscriberPrepaidPackageActivePeriod\n // Gap: G-07 (HIGH). Controls when a package becomes active on a subscriber.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_package_active_period\",\n {\n title: \"Modify Subscriber Package Active Period\",\n description:\n \"Use this to change the start and/or end date of a prepaid package's active period for a \" +\n \"specific subscriber. This controls WHEN the package runs, not what it contains. \" +\n \"Useful for scheduling packages in advance (e.g. activate on arrival date) or extending \" +\n \"a package that would otherwise expire while the subscriber is still travelling. \" +\n \"Params: `iccid` (subscriber identifier), `package_id` (from `list_subscriber_packages`), \" +\n \"`start_date` (ISO 8601 date, optional), `end_date` (ISO 8601 date, optional). \" +\n \"Returns: updated package record with new active period. \" +\n \"Do NOT use this to change a package's data/voice allowance — use `modify_package_limits`. \" +\n \"Do NOT use this to change the expiry date of a package — use `modify_package_expiry`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n package_id: z\n .number()\n .describe(\"The subscriber package ID (from list_subscriber_packages)\"),\n start_date: z\n .string()\n .optional()\n .describe(\"New start date in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)\"),\n end_date: z\n .string()\n .optional()\n .describe(\"New end date in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_package_active_period\",\n \"modifySubscriberPrepaidPackageActivePeriod\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_package_active_period\"]!,\n ctx,\n async ({ iccid, package_id, start_date, end_date }: { iccid: string; package_id: number; start_date?: string; end_date?: string }, token: string) => {\n const params: Record<string, unknown> = { subscriber: iccid, packageId: package_id };\n if (start_date !== undefined) params.startDate = start_date;\n if (end_date !== undefined) params.endDate = end_date;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberPrepaidPackageActivePeriod\",\n params,\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 6. MODIFY SUBSCRIBER VOIP PLAN\n // OCS method: modifySubscriberVoipPlan\n // Gap: G-11 (MEDIUM). Parallel to modify_subscriber_mobile_plan for VoIP.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_voip_plan\",\n {\n title: \"Modify Subscriber VoIP Plan\",\n description:\n \"Use this to change the VoIP pricing plan assigned to a specific subscriber. \" +\n \"VoIP plans control billing rates for VoIP calls made through the OCS platform, \" +\n \"separate from the standard mobile plan's call rates. \" +\n \"Params: `iccid` (subscriber identifier), `voip_plan_id` (integer VoIP plan ID from \" +\n \"the OCS reseller settings). \" +\n \"Returns: updated subscriber record confirming the new VoIP plan. \" +\n \"Do NOT use this for mobile (non-VoIP) plan changes — use `modify_subscriber_mobile_plan`. \" +\n \"For data-only eSIM products without VoIP services this tool has no effect.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n voip_plan_id: z\n .number()\n .describe(\"The VoIP pricing plan ID to assign to this subscriber\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_voip_plan\",\n \"modifySubscriberVoipPlan\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_voip_plan\"]!,\n ctx,\n async ({ iccid, voip_plan_id }: { iccid: string; voip_plan_id: number }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberVoipPlan\",\n { subscriber: iccid, voipPlanId: voip_plan_id },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 7. PUSH STEERING TO SUBSCRIBER\n // OCS method: pushSteeringToSubs\n // Gap: G-04 (HIGH). Must be called AFTER modify_subscriber_steering_list\n // to push the new OPLMN list to the physical device.\n // =========================================================================\n server.registerTool(\n \"push_steering_to_subscriber\",\n {\n title: \"Push Steering List to Subscriber Device\",\n description:\n \"Use this AFTER `modify_subscriber_steering_list` to actively push the updated OPLMN \" +\n \"(operator preference list) to the subscriber's physical eSIM/SIM. \" +\n \"Without this call, the steering list assignment change is recorded in OCS but the device \" +\n \"continues using the old operator preference list until it performs a network re-registration. \" +\n \"This is required for immediate operator switching (e.g. steering a subscriber away from \" +\n \"an expensive roaming partner in real time). \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: push confirmation from OCS with delivery status. \" +\n \"Do NOT call this without first calling `modify_subscriber_steering_list` — pushing without \" +\n \"an assigned steering list is a no-op and wastes an OCS call.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"push_steering_to_subscriber\",\n \"pushSteeringToSubs\",\n BACKLOG_TOOL_SCOPES[\"push_steering_to_subscriber\"]!,\n ctx,\n async ({ iccid }: { iccid: string }, token: string) => {\n const cache = new Map<string, Record<string, unknown>>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n // OCS pushSteeringToSubs expects subscriber identifier — ICCID confirmed\n // from live docs. Passing the full subscriber object as fallback.\n const subscriberId = sub.id ?? sub.subscriberId ?? iccid;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"pushSteeringToSubs\",\n { subscriber: subscriberId },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 8. RESET SUBSCRIBER GZ COUNTER\n // OCS method: resetSubsGzCounter\n // Gap: G-10 (MEDIUM). Resets usage counters — used after billing disputes.\n // Admin scope — irreversible operation.\n // =========================================================================\n server.registerTool(\n \"reset_subscriber_gz_counter\",\n {\n title: \"Reset Subscriber Green Zone Counter\",\n description:\n \"ADMIN: Use this to reset the Green Zone (Greenzone) volume counter for a subscriber. \" +\n \"The Green Zone counter tracks bytes consumed on the reseller-defined whitelist of \" +\n \"hosts/IPs after the subscriber's bundle is depleted — NOT the Diameter Gz/Gy accounting \" +\n \"interface. Typically used after a billing dispute or test-cycle reset. \" +\n \"This operation is IRREVERSIBLE — volumeOnGZ is permanently zeroed. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: new counter state with volumeOnGZ (bytes, normally 0 after reset), \" +\n \"lastResetDate, lastUpdateDate. \" +\n \"Always call `get_subscriber` with `with_gz_counter=true` first to capture the snapshot. \" +\n \"Do NOT use this to pause data usage — use `set_subscriber_traffic_restrictions` with \" +\n \"`dataAllowed=false` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"reset_subscriber_gz_counter\",\n \"resetSubsGzCounter\",\n BACKLOG_TOOL_SCOPES[\"reset_subscriber_gz_counter\"]!,\n ctx,\n async ({ iccid }: { iccid: string }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\"resetSubsGzCounter\", { subscriber: iccid });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 10. CARRIER WEBHOOK CONFIG — reads relay + notification flags from\n // getResellerInfo.trafficInfo and getResellerInfo.notificationInfo.\n // Audit gap S-04 in UNUSED-FEATURES.md — now implemented.\n //\n // trafficInfo shape (live probe against reseller 1170, 2026-05-21):\n // { relayGy: boolean, relayCallSms: boolean, relayLU: boolean, relayVoIP: boolean }\n // notificationInfo shape: passed through as-is (z.record(z.unknown())) because\n // the exact keys vary by OCS configuration and are not documented upstream.\n // =========================================================================\n\n // carrier_webhook_config is now a real tool — registered unconditionally\n // (no CARRIER_AUDIT_STUBS_ENABLED guard needed after implementation).\n server.registerTool(\n \"carrier_webhook_config\",\n {\n title: \"Carrier Webhook / Relay Flag Status\",\n description:\n \"Use this to check the current Bridge4IP webhook and relay flag configuration for \" +\n \"this reseller. Returns the active state of all four traffic relay flags: \" +\n \"Relay LU (Update Location — cell tower changes, closest to country-change signal), \" +\n \"Relay Gy (mobile data usage events), Relay VoIP (VoIP usage events), \" +\n \"Relay calls+SMS (call and SMS events). \" +\n \"Also returns which notification webhooks are enabled (prepaid package usage threshold, \" +\n \"reseller low credit, ES2 eSIM status, recurring packages) as a passthrough object. \" +\n \"All relay/notification configuration is done in the OCS portal UI — this tool is \" +\n \"READ-ONLY and reflects current state. \" +\n \"Relay LU is the highest-value flag: when active, Bridge4IP pushes real-time Update \" +\n \"Location events (mcc, mnc, lac, cellId) to the configured HTTP endpoint.\",\n inputSchema: {\n reseller_id: z\n .number()\n .int()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"carrier_webhook_config\",\n \"getResellerInfo\",\n BACKLOG_TOOL_SCOPES[\"carrier_webhook_config\"]!,\n ctx,\n async ({ reseller_id }, token) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n // Resolve reseller ID: explicit arg → token owner's reseller\n let resellerId = reseller_id;\n if (resellerId === undefined) {\n resellerId = await getDefaultResellerId(ctx.env, token);\n }\n\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.id = resellerId;\n\n const raw = await client.call<{\n id?: number;\n trafficInfo?: {\n relayGy?: boolean;\n relayCallSms?: boolean;\n relayLU?: boolean;\n relayVoIP?: boolean;\n };\n notificationInfo?: Record<string, unknown>;\n }>(\"getResellerInfo\", params);\n\n const traffic = raw.trafficInfo ?? {};\n const notification = raw.notificationInfo ?? {};\n\n const result = {\n resellerId: raw.id ?? resellerId,\n traffic: {\n relayGy: traffic.relayGy === true,\n relayCallSms: traffic.relayCallSms === true,\n relayLU: traffic.relayLU === true,\n relayVoIP: traffic.relayVoIP === true,\n },\n notification,\n };\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n}\n","/**\n * Carrier MCP — carrier_ask + carrier_ask_describe (v2.0 live routing).\n *\n * IMPLEMENTATION STATUS: LIVE (Phase 2)\n * carrier_ask now routes via Claude Haiku 4.5 on AWS Bedrock tool-use.\n * The router receives the full TOOL_REGISTRY as its tool catalog and returns\n * a single tool_use block identifying the best matching tool + extracted params.\n *\n * ACTIVATION:\n * - Requires AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY in Doppler carrier/dev+stg+prd.\n * - Set CARRIER_ASK_ENABLED=true in Doppler to activate per-env.\n * - Without the credentials/flag, carrier_ask gracefully degrades to routing_pending.\n *\n * DESIGN CHOICES:\n * - Router model: Claude Haiku 4.5 on Bedrock (us.anthropic.claude-haiku-4-5-20251001-v1:0).\n * - Auth: SigV4 via aws4fetch — no AWS SDK bundle (CF Worker compatible).\n * - tool_choice: { type: \"any\" } — forces a tool_use response.\n * - Ambiguous/no-match: sentinel \"carrier_clarify\" tool for Haiku to signal.\n * - HARD_BLOCK_TOOLS: always return confirm_token; never auto-execute.\n * - Confirm token TTL: 120s. Single-use (deleted on consume).\n * - Intent hashing: SHA-256, hex. Not stored verbatim (PII guard).\n * - Audit log: Analytics Engine, fire-and-forget. Extended schema for router.\n * - Rate-limit (429): returns friendly retry hint, never crashes.\n *\n * SAFETY FLOORS (non-negotiable):\n * - Resolved tool name validated against TOOL_REGISTRY — no hallucination.\n * - HARD_BLOCK_TOOLS always require confirm_token round-trip.\n * - No-match / ambiguous: structured response, never fabricated tool call.\n */\n\nimport { AwsClient } from \"aws4fetch\";\nimport { z } from \"zod\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { TOOL_SCOPES, DESTRUCTIVE_TOOLS, type ToolContext, wrapHandler } from \"./tools.js\";\nimport { BACKLOG_TOOL_SCOPES } from \"./tools-backlog.js\";\n\n// ---------------------------------------------------------------------------\n// Tool registry — complete list of all MCP tool names known at build time.\n// Resolved tool names are validated against this set before returning to caller.\n// ---------------------------------------------------------------------------\nconst TOOL_REGISTRY: ReadonlySet<string> = new Set([\n // v1 OCS tools (43)\n ...Object.keys(TOOL_SCOPES),\n // v1.1 backlog tools\n ...Object.keys(BACKLOG_TOOL_SCOPES),\n // intelligence composites (8)\n \"diagnose_subscriber\",\n \"fleet_health\",\n \"detect_usage_anomalies\",\n \"optimize_package\",\n \"churn_risk\",\n \"audit_network_coverage\",\n \"marketing_intelligence\",\n \"high_cost_subscribers\",\n // event ring buffer (1)\n \"list_recent_ocs_events\",\n // MCP App tools (3)\n \"fleet_health_app\",\n \"provision_esim_wizard\",\n \"balance_topup_form\",\n // router tools (self-reference)\n \"carrier_ask\",\n \"carrier_ask_describe\",\n]);\n\n// Tools that MUST NEVER auto-execute from a natural-language intent.\n// Always require confirm_token round-trip regardless of confidence.\nconst HARD_BLOCK_TOOLS: ReadonlySet<string> = new Set([\n \"clean_all_packages\",\n \"delete_subscriber_package\",\n \"modify_account_balance\",\n \"modify_subscriber_status\",\n \"change_sim_status\",\n \"reset_subscriber_gz_counter\",\n]);\n\n// ---------------------------------------------------------------------------\n// Confirm token helpers\n// ---------------------------------------------------------------------------\nconst CONFIRM_TOKEN_TTL_SECONDS = 120;\nconst CONFIRM_TOKEN_PREFIX = \"carrier_ask_confirm:\";\n\nfunction generateConfirmToken(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return bytesToHex(bytes);\n}\n\nasync function storeConfirmToken(\n kv: KVNamespace,\n token: string,\n payload: Record<string, unknown>,\n): Promise<void> {\n await kv.put(\n `${CONFIRM_TOKEN_PREFIX}${token}`,\n JSON.stringify(payload),\n { expirationTtl: CONFIRM_TOKEN_TTL_SECONDS },\n );\n}\n\nasync function consumeConfirmToken(\n kv: KVNamespace,\n token: string,\n): Promise<Record<string, unknown> | null> {\n const raw = await kv.get(`${CONFIRM_TOKEN_PREFIX}${token}`, \"text\");\n if (!raw) return null;\n await kv.delete(`${CONFIRM_TOKEN_PREFIX}${token}`);\n return JSON.parse(raw) as Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Intent hashing — SHA-256, hex-encoded.\n// ---------------------------------------------------------------------------\nexport function hashIntent(intent: string): string {\n return bytesToHex(sha256(new TextEncoder().encode(intent)));\n}\n\n// ---------------------------------------------------------------------------\n// Routing result shape\n// ---------------------------------------------------------------------------\ntype RouteResult =\n | {\n match: \"confirmed\";\n resolved_tool: string;\n resolved_params: Record<string, unknown>;\n confidence: number;\n confirm_required: false;\n execution_note: string;\n }\n | {\n match: \"pending_confirm\";\n resolved_tool: string;\n resolved_params: Record<string, unknown>;\n confidence: number;\n confirm_required: true;\n confirm_token: string;\n confirm_expires_in_seconds: number;\n dry_run_preview?: string;\n safety_note: string;\n }\n | {\n match: \"ambiguous\";\n candidates: Array<{ tool: string; reason: string }>;\n clarifying_question: string;\n }\n | {\n match: \"none\";\n closest: Array<{ tool: string; reason: string }>;\n suggestion: string;\n }\n | {\n match: \"routing_pending\";\n intent_received: string;\n note: string;\n scaffold_version: string;\n }\n | {\n match: \"rate_limited\";\n retry_after_seconds: number;\n suggestion: string;\n };\n\n// ---------------------------------------------------------------------------\n// Bedrock request/response types (Bedrock converse-compatible, tool-use subset)\n// ---------------------------------------------------------------------------\ninterface BedrockTool {\n name: string;\n description: string;\n input_schema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\ninterface BedrockPayload {\n anthropic_version: \"bedrock-2023-05-31\";\n max_tokens: number;\n system: string;\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n tools: BedrockTool[];\n tool_choice: { type: \"any\" };\n}\n\ninterface BedrockToolUseBlock {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface BedrockTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface BedrockResponse {\n content: Array<BedrockToolUseBlock | BedrockTextBlock>;\n stop_reason: string;\n}\n\n// ---------------------------------------------------------------------------\n// Router tool catalog for Bedrock.\n// Sentinel \"carrier_clarify\" signals ambiguity without hallucinating a match.\n// ---------------------------------------------------------------------------\nconst ROUTER_TOOLS: BedrockTool[] = [\n {\n name: \"carrier_clarify\",\n description:\n \"Use ONLY when the intent is genuinely ambiguous and you cannot determine a single best-matching tool. \" +\n \"Provide 1-3 candidate tools and a clarifying question.\",\n input_schema: {\n type: \"object\" as const,\n properties: {\n candidates: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n tool: { type: \"string\" },\n reason: { type: \"string\" },\n },\n required: [\"tool\", \"reason\"],\n },\n },\n clarifying_question: { type: \"string\" },\n },\n required: [\"candidates\", \"clarifying_question\"],\n },\n },\n {\n name: \"list_reseller_accounts\",\n description: \"List all reseller accounts. Intent: 'show my accounts', 'list resellers', 'what accounts do I have'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_reseller_info\",\n description: \"Get info about a specific reseller. Intent: 'reseller info', 'account details for reseller X'.\",\n input_schema: { type: \"object\" as const, properties: { reseller_id: { type: \"number\" } } },\n },\n {\n name: \"esim_status_per_account\",\n description: \"Show eSIM counts by status per account. Intent: 'esim overview', 'how many esims active per account'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_subscriber\",\n description: \"Look up a single subscriber by ICCID or MSISDN. Intent: 'get subscriber', 'look up ICCID', 'find SIM 8931...'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, msisdn: { type: \"string\" } } },\n },\n {\n name: \"list_subscribers\",\n description: \"List subscribers in an account. Intent: 'list subscribers', 'show all SIMs', 'subscribers in account X'.\",\n input_schema: { type: \"object\" as const, properties: { account_id: { type: \"number\" }, page: { type: \"number\" } } },\n },\n {\n name: \"subscriber_usage\",\n description: \"Show data usage for a subscriber (max 7 days). Intent: 'how much data did X use', 'usage for subscriber', 'data consumption'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, start: { type: \"string\" }, end: { type: \"string\" } } },\n },\n {\n name: \"subscriber_network_events\",\n description: \"Show network events (attach/detach/roaming) for a subscriber. Intent: 'network events', 'connection history', 'roaming events'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, start: { type: \"string\" }, end: { type: \"string\" } } },\n },\n {\n name: \"list_subscriber_packages\",\n description: \"List active packages for a subscriber. Intent: 'what packages does subscriber have', 'show data packages', 'subscriber plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_package_templates\",\n description: \"List available package templates. Intent: 'what packages can I assign', 'show product catalog', 'available data plans'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"assign_package\",\n description: \"Assign a one-time data package to a subscriber. Intent: 'assign package', 'give subscriber X the Y plan', 'add data package'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageTemplateId: { type: \"number\" } } },\n },\n {\n name: \"assign_recurring_package\",\n description: \"Set up auto-renewing recurring package for a subscriber. Intent: 'monthly plan', 'recurring package', 'auto-renew data'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageTemplateId: { type: \"number\" } } },\n },\n {\n name: \"modify_package_limits\",\n description: \"Change data/voice/SMS limits on an existing package. Intent: 'change package limit', 'update data cap', 'modify plan limits'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"modify_package_expiry\",\n description: \"Change the expiry date of a subscriber package. Intent: 'extend package', 'change expiry', 'push package end date'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, expiryDate: { type: \"string\" } } },\n },\n {\n name: \"modify_package_status\",\n description: \"Activate or pause a specific package. Intent: 'pause package', 'activate package', 'suspend data plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, status: { type: \"string\" } } },\n },\n {\n name: \"stop_resume_recurring_package\",\n description: \"Stop or resume a recurring package. Intent: 'cancel auto-renew', 'stop recurring', 'resume monthly plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, action: { type: \"string\" } } },\n },\n {\n name: \"delete_subscriber_package\",\n description: \"DESTRUCTIVE: Delete a package from a subscriber. Intent: 'delete package', 'remove plan from subscriber'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"clean_all_packages\",\n description: \"DESTRUCTIVE: Remove ALL packages from a subscriber. Irreversible. Intent: 'reset packages', 'clean all plans', 'wipe packages'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_status\",\n description: \"DESTRUCTIVE if terminating: Change subscriber status (ACTIVE/SUSPENDED/TERMINATED). Intent: 'suspend subscriber', 'pause SIM', 'terminate', 'reactivate'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, status: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_balance\",\n description: \"Add or set credit balance for a subscriber. Intent: 'top up subscriber', 'add credit', 'set subscriber balance'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, amount: { type: \"number\" } } },\n },\n {\n name: \"modify_account_balance\",\n description: \"DESTRUCTIVE: Modify account-level balance. Intent: 'adjust account balance', 'add account credit'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { accountId: { type: \"number\" }, amount: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_contact_info\",\n description: \"Update subscriber contact details. Intent: 'update subscriber name', 'change email for SIM', 'fix contact info'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, name: { type: \"string\" }, email: { type: \"string\" } } },\n },\n {\n name: \"set_subscriber_traffic_restrictions\",\n description: \"Enable or disable voice/SMS/data restrictions. Intent: 'block data for subscriber', 'restrict voice', 'data-only SIM'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_steering_list\",\n description: \"Set preferred network steering list for a subscriber. Intent: 'change network preference', 'steer to operator X', 'preferred network'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, steeringListId: { type: \"number\" } } },\n },\n {\n name: \"push_steering_to_subscriber\",\n description: \"Push network steering config to subscriber device. Intent: 'push steering', 'apply network config', 'force network update'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"move_subscriber_range_to_account\",\n description: \"Move a range of subscribers to a different account. Intent: 'move subscribers', 'transfer SIMs to account'.\",\n input_schema: { type: \"object\" as const, properties: { accountId: { type: \"number\" } } },\n },\n {\n name: \"hlr_get_bitrate\",\n description: \"Get current HLR bitrate cap for a subscriber. Intent: 'what speed is subscriber throttled to', 'get bitrate', 'check speed cap'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"hlr_set_bitrate\",\n description: \"Set or remove HLR speed cap (throttle). Intent: 'throttle subscriber', 'set speed limit', 'cap to 256kbps', 'remove throttle'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, bitrate: { type: \"number\" } } },\n },\n {\n name: \"change_sim_status\",\n description: \"DESTRUCTIVE: Change physical SIM card status. Intent: 'deactivate SIM', 'delete SIM card', 'suspend card'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, status: { type: \"string\" } } },\n },\n {\n name: \"send_sms\",\n description: \"Send SMS to a subscriber. Intent: 'send text to subscriber', 'SMS ICCID X', 'message subscriber'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, message: { type: \"string\" } } },\n },\n {\n name: \"get_sim_provider_status\",\n description: \"Get SIM provider / eSIM profile status. Intent: 'SIM provider status', 'eSIM profile downloaded?', 'check profile status'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"get_subscriber_location\",\n description: \"Get approximate subscriber location. Intent: 'where is subscriber', 'subscriber location', 'locate SIM'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"get_subscriber_location_by_cell_id\",\n description: \"Get granular subscriber location by cell tower. Intent: 'cell-level location', 'cell tower for subscriber', 'exact location'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_steering_lists\",\n description: \"List available network steering lists. Intent: 'show steering lists', 'available networks', 'what network profiles exist'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_network_profiles\",\n description: \"List network profiles. Intent: 'list network profiles', 'show network configs'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_location_zones\",\n description: \"List location zones. Intent: 'list zones', 'show coverage zones'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_detailed_location_zones\",\n description: \"List detailed location zones with coordinates. Intent: 'detailed zones', 'zone coordinates', 'coverage map'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_destination_prefixes\",\n description: \"List destination number prefixes. Intent: 'list prefixes', 'routing prefixes', 'number ranges'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_destination_lists\",\n description: \"List destination lists for voice/SMS routing. Intent: 'destination lists', 'routing lists'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_sponsors\",\n description: \"List sponsor accounts. Intent: 'list sponsors', 'show sponsor accounts'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_tariff\",\n description: \"Get tariff/rate rules. Intent: 'what are my rates', 'tariff info', 'pricing rules'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"create_package_template\",\n description: \"Create a new package template. Intent: 'create package', 'new product', 'add package template'.\",\n input_schema: { type: \"object\" as const, properties: { name: { type: \"string\" } } },\n },\n {\n name: \"create_location_zone\",\n description: \"Create a new location zone. Intent: 'create zone', 'add location zone', 'new coverage zone'.\",\n input_schema: { type: \"object\" as const, properties: { name: { type: \"string\" } } },\n },\n {\n name: \"modify_template_core\",\n description: \"Modify core settings of a package template. Intent: 'edit package template', 'change template name/settings'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"modify_template_recurring\",\n description: \"Modify recurring billing settings of a template. Intent: 'change template renewal', 'edit recurring settings'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"modify_template_throttling\",\n description: \"Modify throttling settings of a template. Intent: 'change template speed', 'edit throttle on template'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"subscriber_active_period\",\n description: \"Get or set the active period for a subscriber. Intent: 'active period', 'subscriber validity', 'SIM activation window'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_recent_ocs_events\",\n description: \"List recent OCS events for a subscriber (last 50, 24h window). Intent: 'recent events', 'event history', 'OCS log'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"affect_subscriber_phone_number\",\n description: \"Assign or unassign a phone number to a subscriber. Intent: 'assign phone number', 'give SIM a number', 'remove number'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, msisdn: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_mobile_plan\",\n description: \"Change the mobile plan for a subscriber. Intent: 'change mobile plan', 'switch plan', 'update rate plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, planId: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_package_active_period\",\n description: \"Modify the active period of a subscriber's package. Intent: 'extend package period', 'change package dates'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_voip_plan\",\n description: \"Change VoIP plan for a subscriber. Intent: 'change voip plan', 'update voice plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"reset_subscriber_gz_counter\",\n description: \"DESTRUCTIVE: Reset a subscriber's guaranteed zone counter. Irreversible. Intent: 'reset gz counter', 'clear gz usage'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"diagnose_subscriber\",\n description: \"Run composite diagnostic on a subscriber. Intent: 'why is subscriber offline', 'diagnose SIM', 'troubleshoot ICCID'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"fleet_health\",\n description: \"Show overall fleet health (active/suspended/churned counts, alerts). Intent: 'fleet status', 'how is my fleet', 'health overview', 'how many esims active'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"detect_usage_anomalies\",\n description: \"Detect unusual data usage patterns across the fleet. Intent: 'usage anomalies', 'abnormal data use', 'spike detection'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"optimize_package\",\n description: \"Suggest package optimizations for a subscriber based on usage. Intent: 'optimize package', 'right-size plan', 'package recommendation'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"churn_risk\",\n description: \"Identify subscribers at risk of churning. Intent: 'churn risk', 'at-risk subscribers', 'who might leave'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"audit_network_coverage\",\n description: \"Audit network coverage for subscriber or fleet. Intent: 'coverage audit', 'network coverage check', 'coverage gaps'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"marketing_intelligence\",\n description: \"Get marketing intelligence: usage trends, popular packages, growth metrics. Intent: 'marketing data', 'growth report', 'popular plans'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"high_cost_subscribers\",\n description: \"List subscribers generating highest costs. Intent: 'high cost subscribers', 'most expensive SIMs', 'cost outliers'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"fleet_health_app\",\n description: \"Open the fleet health MCP App UI. Intent: 'open fleet dashboard app', 'fleet health UI'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"provision_esim_wizard\",\n description: \"Open the eSIM provisioning wizard app. Intent: 'provision esim', 'new esim wizard', 'onboard esim'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"balance_topup_form\",\n description: \"Open the balance top-up form app. Intent: 'top up balance', 'add credit form', 'balance topup'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"carrier_ask_describe\",\n description: \"Get documentation for a specific carrier tool. Intent: 'describe tool X', 'how does assign_package work', 'tool documentation'.\",\n input_schema: { type: \"object\" as const, properties: { tool_name: { type: \"string\" } } },\n },\n];\n\n// System prompt for the Haiku router\nconst ROUTER_SYSTEM_PROMPT = `You are a carrier fleet operations router. Your job is to map a user's natural-language intent to exactly ONE tool from the Carrier MCP tool registry.\n\nRules:\n1. Pick the single best-matching tool. Never pick carrier_ask (the router itself).\n2. Extract any parameters mentioned in the intent (ICCID, account IDs, amounts, etc.) as the tool's input.\n3. Use carrier_clarify ONLY when genuinely ambiguous — when multiple tools are equally likely and you need more information.\n4. DESTRUCTIVE tools are flagged in their descriptions — still pick them if they match; the safety layer handles the confirm flow.\n5. Only include params explicitly mentioned in the intent.\n6. Context fields (iccid, account_id, reseller_id) from the routing context take precedence.`;\n\n// RouteResult variant from _routeIntent (confirm_token is \"\" placeholder; caller fills it)\ntype RoutedResult =\n | Extract<RouteResult, { match: \"confirmed\" }>\n | Extract<RouteResult, { match: \"pending_confirm\" }>\n | Extract<RouteResult, { match: \"ambiguous\" }>\n | Extract<RouteResult, { match: \"none\" }>\n | Extract<RouteResult, { match: \"routing_pending\" }>\n | Extract<RouteResult, { match: \"rate_limited\" }>;\n\n// ---------------------------------------------------------------------------\n// Default Bedrock config\n// ---------------------------------------------------------------------------\nconst DEFAULT_REGION = \"us-east-1\";\nconst DEFAULT_MODEL_ID = \"us.anthropic.claude-haiku-4-5-20251001-v1:0\";\n\n// ---------------------------------------------------------------------------\n// callBedrock — SigV4-signed InvokeModel via aws4fetch.\n// Exported for testing (mock globalThis.fetch or AwsClient in tests).\n// ---------------------------------------------------------------------------\nexport async function callBedrock(\n env: { AWS_ACCESS_KEY_ID: string; AWS_SECRET_ACCESS_KEY: string; AWS_REGION?: string; BEDROCK_MODEL_ID?: string },\n payload: BedrockPayload,\n): Promise<BedrockResponse> {\n const region = env.AWS_REGION ?? DEFAULT_REGION;\n const modelId = env.BEDROCK_MODEL_ID ?? DEFAULT_MODEL_ID;\n\n const aws = new AwsClient({\n accessKeyId: env.AWS_ACCESS_KEY_ID,\n secretAccessKey: env.AWS_SECRET_ACCESS_KEY,\n region,\n service: \"bedrock\",\n });\n\n const url = `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;\n\n const resp = await aws.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n // 429 → surface as a structured rate-limit signal\n if (resp.status === 429) {\n const retryAfter = resp.headers.get(\"retry-after\");\n const err = new Error(`Bedrock rate limit: ${body}`) as Error & { isRateLimit: true; retryAfter: string | null };\n err.isRateLimit = true;\n err.retryAfter = retryAfter;\n throw err;\n }\n throw new Error(`Bedrock invoke failed: ${resp.status} ${body}`);\n }\n\n return (await resp.json()) as BedrockResponse;\n}\n\n// ---------------------------------------------------------------------------\n// _routeIntent — core routing logic via Claude Haiku 4.5 on Bedrock.\n// Exported for testing (mock callBedrock or globalThis.fetch in tests).\n// ---------------------------------------------------------------------------\nexport async function _routeIntent(\n intent: string,\n context: { iccid?: string; account_id?: number; reseller_id?: number },\n env: ToolContext[\"env\"],\n): Promise<RoutedResult> {\n // Feature flag gate\n if (env.CARRIER_ASK_ENABLED !== \"true\" || !env.AWS_ACCESS_KEY_ID || !env.AWS_SECRET_ACCESS_KEY) {\n return {\n match: \"routing_pending\",\n intent_received: intent,\n note:\n \"carrier_ask routing engine is not yet activated. \" +\n \"Add AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY to Doppler carrier/dev+stg+prd and set CARRIER_ASK_ENABLED=true.\",\n scaffold_version: \"v2.0-bedrock\",\n };\n }\n\n // Merge context into user message (omit keys with undefined — JSON.stringify drops them)\n const definedContext = Object.fromEntries(\n Object.entries(context).filter(([, value]) => value !== undefined),\n );\n const contextNote =\n Object.keys(definedContext).length > 0\n ? `\\n\\nPre-resolved context: ${JSON.stringify(definedContext)}`\n : \"\";\n const userMessage = `${intent}${contextNote}`;\n\n const payload: BedrockPayload = {\n anthropic_version: \"bedrock-2023-05-31\",\n max_tokens: 512,\n system: ROUTER_SYSTEM_PROMPT,\n messages: [{ role: \"user\", content: userMessage }],\n tools: ROUTER_TOOLS,\n tool_choice: { type: \"any\" },\n };\n\n let response: BedrockResponse;\n try {\n response = await callBedrock({\n AWS_ACCESS_KEY_ID: env.AWS_ACCESS_KEY_ID,\n AWS_SECRET_ACCESS_KEY: env.AWS_SECRET_ACCESS_KEY,\n AWS_REGION: env.AWS_REGION,\n BEDROCK_MODEL_ID: env.BEDROCK_MODEL_ID,\n }, payload);\n } catch (err) {\n if (err instanceof Error && (err as Error & { isRateLimit?: boolean }).isRateLimit) {\n const retryAfter = (err as Error & { retryAfter: string | null }).retryAfter;\n const parsedSeconds = retryAfter ? parseInt(retryAfter, 10) : 60;\n return {\n match: \"rate_limited\",\n retry_after_seconds: Number.isFinite(parsedSeconds) ? parsedSeconds : 60,\n suggestion: \"Bedrock rate limit reached. Please retry after the indicated delay.\",\n };\n }\n throw err;\n }\n\n // Extract tool_use block\n const toolUseBlock = response.content.find(\n (block): block is BedrockToolUseBlock => block.type === \"tool_use\",\n );\n\n if (!toolUseBlock) {\n return {\n match: \"none\",\n closest: [],\n suggestion:\n \"Could not determine the right tool for this intent. Try rephrasing or use carrier_ask_describe to explore available tools.\",\n };\n }\n\n const { name: resolvedTool, input } = toolUseBlock;\n const resolvedParams = (input ?? {}) as Record<string, unknown>;\n\n // Clarification sentinel\n if (resolvedTool === \"carrier_clarify\") {\n const candidates = (resolvedParams.candidates ?? []) as Array<{ tool: string; reason: string }>;\n const clarifyingQuestion = typeof resolvedParams.clarifying_question === \"string\"\n ? resolvedParams.clarifying_question\n : \"Could you clarify your intent?\";\n return {\n match: \"ambiguous\",\n candidates,\n clarifying_question: clarifyingQuestion,\n };\n }\n\n // Hallucination guard\n if (!TOOL_REGISTRY.has(resolvedTool)) {\n return {\n match: \"none\",\n closest: [],\n suggestion: `Router returned unknown tool '${resolvedTool}'. Please try rephrasing your intent.`,\n };\n }\n\n // HARD_BLOCK: require confirm_token\n if (HARD_BLOCK_TOOLS.has(resolvedTool)) {\n return {\n match: \"pending_confirm\",\n resolved_tool: resolvedTool,\n resolved_params: resolvedParams,\n confidence: 0.95,\n confirm_required: true,\n confirm_token: \"\", // filled by caller after storeConfirmToken\n confirm_expires_in_seconds: CONFIRM_TOKEN_TTL_SECONDS,\n safety_note:\n `'${resolvedTool}' is a protected destructive operation. ` +\n \"Re-call carrier_ask with the returned confirm_token to execute.\",\n };\n }\n\n // Safe read/write tool\n return {\n match: \"confirmed\",\n resolved_tool: resolvedTool,\n resolved_params: resolvedParams,\n confidence: 0.95,\n confirm_required: false,\n execution_note:\n `Call '${resolvedTool}' directly with resolved_params to execute. ` +\n \"carrier_ask does not auto-execute — the caller makes the explicit tool call.\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Audit log write for carrier_ask routing events.\n// ---------------------------------------------------------------------------\nfunction writeCarrierAskAudit(\n env: ToolContext[\"env\"],\n row: {\n intent_hash: string;\n match: string;\n resolved_tool: string;\n confirm_token_state: \"none\" | \"issued\" | \"redeemed\" | \"expired\";\n status: \"ok\" | \"error\";\n latency_ms: number;\n sub: string;\n reseller_id: number;\n },\n): void {\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"carrier_ask\", // blob[0] tool_name\n row.resolved_tool, // blob[1] resolved tool (or \"none\")\n row.status, // blob[2] ok | error\n row.match, // blob[3] match type\n row.intent_hash, // blob[4] SHA-256 of intent\n row.confirm_token_state, // blob[5] confirm token state\n row.sub, // blob[6] user subject\n ],\n doubles: [row.latency_ms],\n indexes: [String(row.reseller_id)],\n });\n } catch {\n // Never let audit failure propagate\n }\n}\n\n// ---------------------------------------------------------------------------\n// registerAllCarrierAskTools — registers carrier_ask + carrier_ask_describe\n// ---------------------------------------------------------------------------\nexport function registerAllCarrierAskTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // carrier_ask — natural-language router\n // =========================================================================\n server.registerTool(\n \"carrier_ask\",\n {\n title: \"Natural Language Carrier Tool Router\",\n description:\n \"Use this when you want to perform a carrier operation but don't know which specific tool to call. \" +\n \"Describe your intent in plain language and carrier_ask will identify the correct tool(s) and \" +\n \"suggest the required parameters. For simple read intents, it executes directly and returns results. \" +\n \"For destructive operations it returns a confirm_token that you must pass in a second call. \" +\n \"Params: `intent` (string — natural language description of what you want to do), \" +\n \"`context` (optional: iccid, account_id, reseller_id if already known). \" +\n \"Returns: RouteResult — confirmed | pending_confirm | ambiguous | none. \" +\n \"Do NOT use this when you know the right tool — direct calls are faster and cheaper.\",\n inputSchema: {\n intent: z\n .string()\n .min(3)\n .describe(\n \"Natural-language description of the operation to perform \" +\n \"(e.g. 'suspend ICCID 89316 until next month', 'show fleet health', \" +\n \"'assign Europe 5GB package to subscriber 89316...')\",\n ),\n context: z\n .object({\n iccid: z.string().optional().describe(\"Subscriber ICCID if already known\"),\n account_id: z.number().optional().describe(\"Account ID if already known\"),\n reseller_id: z.number().optional().describe(\"Reseller ID if already known\"),\n })\n .optional()\n .describe(\"Optional pre-resolved context to improve routing accuracy\"),\n confirm_token: z\n .string()\n .optional()\n .describe(\n \"One-time token from a previous carrier_ask call with confirm_required=true. \" +\n \"Providing this executes the previously staged destructive operation.\",\n ),\n },\n },\n wrapHandler(\n \"carrier_ask\",\n \"[carrier_ask]\",\n \"read\",\n ctx,\n async (args, _token) => {\n const { intent, context = {}, confirm_token } = args;\n const intentHash = hashIntent(intent);\n const start = Date.now();\n\n // ------------------------------------------------------------------\n // Confirm token redemption path\n // ------------------------------------------------------------------\n if (confirm_token) {\n const staged = await consumeConfirmToken(ctx.env.OAUTH_KV, confirm_token);\n if (!staged) {\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: \"confirm_expired\",\n resolved_tool: \"none\",\n confirm_token_state: \"expired\",\n status: \"error\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"confirm_token_expired\",\n message:\n `Confirm token '${confirm_token}' has expired or was already used. ` +\n `Tokens expire after ${CONFIRM_TOKEN_TTL_SECONDS}s. Re-issue the original intent to get a new token.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const resolvedTool = staged.resolved_tool as string;\n if (!TOOL_REGISTRY.has(resolvedTool)) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"invalid_tool\",\n message: `Staged tool '${resolvedTool}' is not in the tool registry.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n writeCarrierAskAudit(ctx.env, {\n intent_hash:\n typeof staged.intent_hash === \"string\" ? staged.intent_hash : intentHash,\n match: \"confirm_executed\",\n resolved_tool: resolvedTool,\n confirm_token_state: \"redeemed\",\n status: \"ok\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n match: \"confirm_executed\",\n resolved_tool: resolvedTool,\n resolved_params: staged.resolved_params,\n note:\n \"Confirm token accepted. Call the resolved_tool directly with resolved_params \" +\n \"to execute the operation. carrier_ask does not auto-execute — the caller must \" +\n \"make the explicit tool call.\",\n }),\n },\n ],\n };\n }\n\n // ------------------------------------------------------------------\n // Main routing path\n // ------------------------------------------------------------------\n let route: RoutedResult;\n\n try {\n route = await _routeIntent(intent, context, ctx.env);\n } catch (err) {\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: \"error\",\n resolved_tool: \"none\",\n confirm_token_state: \"none\",\n status: \"error\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"routing_error\",\n message:\n err instanceof Error\n ? err.message\n : \"An unexpected error occurred during routing.\",\n }),\n },\n ],\n isError: true,\n };\n }\n\n // Issue confirm token for HARD_BLOCK results\n let finalRoute: RouteResult = route as RouteResult;\n let confirmTokenState: \"none\" | \"issued\" = \"none\";\n\n if (route.match === \"pending_confirm\") {\n const token = generateConfirmToken();\n await storeConfirmToken(ctx.env.OAUTH_KV, token, {\n resolved_tool: route.resolved_tool,\n resolved_params: route.resolved_params,\n intent_hash: intentHash,\n issued_at: new Date().toISOString(),\n });\n finalRoute = { ...route, confirm_token: token } as RouteResult;\n confirmTokenState = \"issued\";\n }\n\n const resolvedToolForAudit: string =\n (route.match === \"confirmed\" || route.match === \"pending_confirm\")\n ? route.resolved_tool\n : \"none\";\n\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: route.match,\n resolved_tool: resolvedToolForAudit,\n confirm_token_state: confirmTokenState,\n status: \"ok\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(finalRoute, null, 2),\n },\n ],\n };\n },\n ),\n );\n\n // =========================================================================\n // carrier_ask_describe — drill-down companion\n // =========================================================================\n server.registerTool(\n \"carrier_ask_describe\",\n {\n title: \"Describe a Carrier Tool\",\n description:\n \"Get full documentation for any registered Carrier MCP tool: description, \" +\n \"parameters, 2-3 example invocations, required scope, destructive flag, and guidance. \" +\n \"Params: `tool_name` (exact MCP tool name, e.g. 'assign_package'). \" +\n \"Returns: structured tool metadata. Does NOT execute the tool.\",\n inputSchema: {\n tool_name: z\n .string()\n .describe(\"The exact MCP tool name to describe (e.g. 'assign_package', 'hlr_set_bitrate')\"),\n },\n },\n wrapHandler(\n \"carrier_ask_describe\",\n \"[carrier_ask_describe]\",\n \"read\",\n ctx,\n async ({ tool_name }, _token) => {\n if (!TOOL_REGISTRY.has(tool_name)) {\n const closest = [...TOOL_REGISTRY]\n .filter((name) => name.includes(tool_name.split(\"_\")[0] ?? \"\") || tool_name.includes(name.split(\"_\")[0] ?? \"\"))\n .slice(0, 5);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"tool_not_found\",\n tool_name,\n message: `'${tool_name}' is not a registered Carrier MCP tool.`,\n did_you_mean: closest.length > 0 ? closest : undefined,\n total_registered: TOOL_REGISTRY.size,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const allScopes = { ...TOOL_SCOPES, ...BACKLOG_TOOL_SCOPES };\n const scope = allScopes[tool_name as keyof typeof allScopes] ?? \"read\";\n const isDestructive = DESTRUCTIVE_TOOLS.has(tool_name);\n const isHardBlock = HARD_BLOCK_TOOLS.has(tool_name);\n\n const doc = {\n tool_name,\n scope,\n destructive: isDestructive,\n hard_block: isHardBlock,\n hard_block_note: isHardBlock\n ? \"This tool is in the HARD_BLOCK list: carrier_ask will never auto-execute it. \" +\n \"It always requires an explicit confirm_token redemption.\"\n : undefined,\n dry_run_supported: isDestructive,\n examples: buildExamples(tool_name),\n note:\n \"Full parameter descriptions are available in the tool's inputSchema. \" +\n \"Call the tool with no arguments to trigger the MCP schema introspection response.\",\n };\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(doc, null, 2),\n },\n ],\n };\n },\n ),\n );\n}\n\n// ---------------------------------------------------------------------------\n// buildExamples — curated invocation examples for high-traffic tools.\n// ---------------------------------------------------------------------------\nfunction buildExamples(toolName: string): Array<{ intent: string; params: Record<string, unknown> }> {\n const examples: Record<string, Array<{ intent: string; params: Record<string, unknown> }>> = {\n assign_package: [\n { intent: \"Give subscriber 89316... the Europe 5GB package\", params: { iccid: \"89316...\", packageTemplateId: 42 } },\n { intent: \"Assign a one-time data package to this eSIM\", params: { iccid: \"89316...\", packageTemplateId: 42 } },\n ],\n assign_recurring_package: [\n { intent: \"Set up monthly auto-renewal for subscriber 89316...\", params: { iccid: \"89316...\", packageTemplateId: 55 } },\n ],\n modify_subscriber_status: [\n { intent: \"Pause Maya's subscription for 2 months\", params: { iccid: \"89316...\", status: \"SUSPENDED\" } },\n { intent: \"Reactivate subscriber 89316...\", params: { iccid: \"89316...\", status: \"ACTIVE\" } },\n ],\n hlr_set_bitrate: [\n { intent: \"Throttle ICCID 89316... to 256kbps\", params: { iccid: \"89316...\", bitrate: 256000 } },\n { intent: \"Remove speed cap from subscriber 89316...\", params: { iccid: \"89316...\", bitrate: 0 } },\n ],\n modify_subscriber_steering_list: [\n { intent: \"Connect this eSIM to the best network in Italy\", params: { iccid: \"89316...\", steeringListId: 7 } },\n ],\n push_steering_to_subscriber: [\n { intent: \"Push the new steering config to the device\", params: { iccid: \"89316...\" } },\n ],\n clean_all_packages: [\n { intent: \"Reset all packages for subscriber 89316... before reprovisioning\", params: { iccid: \"89316...\", dry_run: true } },\n ],\n fleet_health: [\n { intent: \"Show me the fleet status overview\", params: {} },\n { intent: \"How many eSIMs are active right now\", params: {} },\n ],\n diagnose_subscriber: [\n { intent: \"Why is subscriber 89316... offline?\", params: { iccid: \"89316...\" } },\n ],\n };\n\n return examples[toolName] ?? [\n { intent: `Call ${toolName} for subscriber 89316...`, params: { iccid: \"89316...\" } },\n ];\n}\n\n// Export for TOOL_INVENTORY generation and reconcile script\nexport { TOOL_REGISTRY, HARD_BLOCK_TOOLS };\n","/**\n * Carrier MCP — Tool: list_recent_ocs_events\n *\n * Reads the per-ICCID ring-buffer written by the OCS webhook receiver\n * (ocs-webhook.ts → storeEvent). Key pattern:\n * events:<reseller_id>:<iccid>:evt:<padded_ts>:<event_id> (primary, per-event)\n * events:<reseller_id>:<iccid> (legacy batch, read-compat)\n *\n * The reseller_id is resolved via the `iccid:<iccid>` routing entry; falls back\n * to 0 when no routing entry exists (same convention as the writer).\n *\n * Annotations: readOnlyHint, idempotentHint, NOT openWorldHint (closed KV read).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Re-use types from the receiver (kept local to avoid circular imports)\n// ---------------------------------------------------------------------------\n\ninterface OcsEventStored {\n event_id: string;\n event_type: string;\n iccid: string;\n occurred_at: number;\n payload: Record<string, unknown>;\n /** Optional fields that may be present on enriched events */\n subscriber_id?: number;\n account_id?: number;\n reseller_id?: number;\n}\n\ninterface IccidRoutingEntry {\n reseller_id: number;\n user_key: string;\n}\n\ninterface StoredEventBatch {\n events: OcsEventStored[];\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input schema\n// ---------------------------------------------------------------------------\n\nconst ALLOWED_EVENT_TYPES = [\n \"esim.activated\",\n \"esim.disabled\",\n \"package.expiry_warning\",\n \"location.changed\",\n \"balance.low\",\n] as const;\n\nexport const listRecentOcsEventsSchema = {\n iccid: z\n .string()\n .regex(/^\\d{19,20}$/)\n .describe(\"ICCID, 19 or 20 digits, ITU-T E.118 format\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(20)\n .describe(\"Max events to return, newest first\"),\n event_types: z\n .array(z.enum(ALLOWED_EVENT_TYPES))\n .optional()\n .describe(\"Filter to specific event types\"),\n since: z\n .string()\n .datetime()\n .optional()\n .describe(\"ISO-8601 timestamp; only events after this point\"),\n};\n\n// ---------------------------------------------------------------------------\n// Core reader — exported for tests\n// ---------------------------------------------------------------------------\n\nexport interface OcsEventOutput {\n event_id: string;\n event_type: string;\n timestamp: string;\n subscriber_id?: number;\n account_id?: number;\n reseller_id?: number;\n data: Record<string, unknown>;\n}\n\nexport interface ListRecentOcsEventsResult {\n iccid: string;\n events: OcsEventOutput[];\n total_in_buffer: number;\n filtered_count: number;\n buffer_oldest_event_timestamp: string | null;\n buffer_newest_event_timestamp: string | null;\n}\n\nexport async function listRecentOcsEvents(\n iccid: string,\n limit: number,\n eventTypes: readonly string[] | undefined,\n since: string | undefined,\n kv: Env[\"OCS_EVENT_ROUTING\"],\n): Promise<ListRecentOcsEventsResult> {\n // 1. Resolve reseller_id from routing entry (fall back to 0, same as writer)\n const routingRaw = (await kv.get(\n `iccid:${iccid}`,\n \"json\",\n )) as IccidRoutingEntry | null;\n const resellerId = routingRaw?.reseller_id ?? 0;\n\n const ringKey = `events:${resellerId}:${iccid}`;\n const itemPrefix = `${ringKey}:evt:`;\n\n // 2. Collect all per-event keys from ring-buffer (primary format)\n const fromItems: OcsEventStored[] = [];\n let listCursor: string | undefined;\n do {\n const listed = await kv.list({ prefix: itemPrefix, cursor: listCursor });\n for (const k of listed.keys) {\n const raw = await kv.get(k.name, \"text\");\n if (!raw) continue;\n try {\n fromItems.push(JSON.parse(raw) as OcsEventStored);\n } catch {\n // skip corrupt entries\n }\n }\n listCursor = listed.list_complete ? undefined : listed.cursor;\n } while (listCursor !== undefined);\n\n // 3. Legacy batch key (backwards compat with events written before per-event format)\n const legacy = (await kv.get(ringKey, \"json\")) as StoredEventBatch | null;\n\n // 4. Merge — de-duplicate by event_id; per-event items win over legacy batch\n const merged = new Map<string, OcsEventStored>();\n for (const e of legacy?.events ?? []) {\n merged.set(e.event_id, e);\n }\n for (const e of fromItems) {\n merged.set(e.event_id, e);\n }\n\n // 5. Sort by occurred_at ascending (oldest first for slicing, then we reverse)\n const allSorted = [...merged.values()].sort((a, b) => {\n if (a.occurred_at !== b.occurred_at) return a.occurred_at - b.occurred_at;\n return a.event_id.localeCompare(b.event_id);\n });\n\n const totalInBuffer = allSorted.length;\n const bufferOldest =\n allSorted.length > 0\n ? new Date(allSorted[0]!.occurred_at * 1000).toISOString()\n : null;\n const bufferNewest =\n allSorted.length > 0\n ? new Date(allSorted[allSorted.length - 1]!.occurred_at * 1000).toISOString()\n : null;\n\n // 6. Apply filters\n const sinceMs = since ? new Date(since).getTime() : null;\n\n const filtered = allSorted.filter((e) => {\n if (sinceMs !== null && e.occurred_at * 1000 <= sinceMs) return false;\n if (eventTypes && eventTypes.length > 0 && !eventTypes.includes(e.event_type))\n return false;\n return true;\n });\n\n const filteredCount = filtered.length;\n\n // 7. Newest first, slice to limit\n const sliced = filtered.slice(-limit).reverse();\n\n const events: OcsEventOutput[] = sliced.map((e) => {\n const out: OcsEventOutput = {\n event_id: e.event_id,\n event_type: e.event_type,\n timestamp: new Date(e.occurred_at * 1000).toISOString(),\n data: e.payload,\n };\n if (e.subscriber_id !== undefined) out.subscriber_id = e.subscriber_id;\n if (e.account_id !== undefined) out.account_id = e.account_id;\n if (e.reseller_id !== undefined) out.reseller_id = e.reseller_id;\n return out;\n });\n\n return {\n iccid,\n events,\n total_in_buffer: totalInBuffer,\n filtered_count: filteredCount,\n buffer_oldest_event_timestamp: bufferOldest,\n buffer_newest_event_timestamp: bufferNewest,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerListRecentOcsEventsTool(\n server: McpServer,\n env: Env,\n): void {\n server.registerTool(\n \"list_recent_ocs_events\",\n {\n title: \"List Recent OCS Events\",\n description:\n \"Return the last N OCS events buffered for a given ICCID. Events include eSIM activations, disable, package expiry warnings, location changes, and balance alerts. Buffer holds up to 50 events per ICCID, 24h TTL. Use this when a user asks 'what happened to ICCID X recently' or 'why did subscriber Y go offline'.\",\n inputSchema: listRecentOcsEventsSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async (args) => {\n const { iccid, limit, event_types, since } = args as {\n iccid: string;\n limit: number;\n event_types?: Array<(typeof ALLOWED_EVENT_TYPES)[number]>;\n since?: string;\n };\n\n try {\n const result = await listRecentOcsEvents(\n iccid,\n limit,\n event_types,\n since,\n env.OCS_EVENT_ROUTING,\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error reading OCS event buffer: ${message}` }],\n };\n }\n },\n );\n}\n","/**\n * v1.2a — Fleet Health Dashboard MCP App\n *\n * Registers a UI-enabled tool `fleet_health_app` that returns structured data\n * for rendering charts in the sandboxed iframe view, alongside the\n * `ui://fleet-health-dashboard` resource that serves the HTML panel.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport type { ToolContext } from \"../tools.js\";\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport interface FleetHealthStructuredContent {\n utilization: number;\n totalActive: number;\n totalSuspended: number;\n totalInventory: number;\n totalOther: number;\n totalAccounts: number;\n lowBalanceCount: number;\n accountList: Array<{\n name: string;\n balance: number;\n active: number;\n suspended: number;\n inventory: number;\n other: number;\n }>;\n // Required by MCP SDK tool callback return type (`structuredContent`\n // is typed as `{ [key: string]: unknown }`).\n [key: string]: unknown;\n}\n\nexport function registerFleetHealthApp(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // ── Resource ─────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"Fleet Health Dashboard\",\n \"ui://fleet-health-dashboard\",\n {\n description:\n \"Interactive Fleet Health Dashboard — eSIM status charts, account breakdown, low-balance alerts.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\"https://internal/views/fleet-health/index.html\"),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Dashboard unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://fleet-health-dashboard\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n _meta: {\n ui: {\n csp: {\n resourceDomains: [\"https://cdn.jsdelivr.net\"],\n },\n },\n },\n },\n ],\n };\n },\n );\n\n // ── Tool ─────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"fleet_health_app\",\n {\n title: \"Fleet Health Dashboard\",\n description:\n \"Renders an interactive Fleet Health Dashboard with eSIM status charts, top-10 account breakdown, and low-balance alerts. Returns structuredContent for the chart panel.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter to a specific account (omit for all)\"),\n },\n annotations: { readOnlyHint: true },\n _meta: {\n ui: {\n resourceUri: \"ui://fleet-health-dashboard\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n const [statusResult, accountsResult] = await Promise.all([\n safeCallWithToken<Record<string, unknown>[]>(\n client,\n token,\n \"esimStatusPerAccount\",\n accountId !== undefined ? { accountId } : {},\n ),\n safeCallWithToken<Record<string, unknown>[]>(\n client,\n token,\n \"listResellerAccount\",\n {},\n ),\n ]);\n\n let totalActive = 0;\n let totalSuspended = 0;\n let totalInventory = 0;\n let totalOther = 0;\n const accountList: FleetHealthStructuredContent[\"accountList\"] = [];\n\n if (statusResult.data && Array.isArray(statusResult.data)) {\n for (const account of statusResult.data) {\n const active = Number(account[\"active\"] ?? 0);\n const suspended = Number(account[\"suspended\"] ?? 0);\n const inventory = Number(\n account[\"inventory\"] ?? account[\"notActivated\"] ?? 0,\n );\n const other = Number(\n account[\"other\"] ?? account[\"terminated\"] ?? 0,\n );\n totalActive += active;\n totalSuspended += suspended;\n totalInventory += inventory;\n totalOther += other;\n accountList.push({\n name: String(account[\"name\"] ?? account[\"accountId\"] ?? \"?\"),\n balance: 0,\n active,\n suspended,\n inventory,\n other,\n });\n }\n }\n\n // Merge balance data from accounts list\n if (accountsResult.data && Array.isArray(accountsResult.data)) {\n for (const a of accountsResult.data) {\n const aName = String(a[\"name\"] ?? a[\"accountId\"] ?? \"?\");\n const entry = accountList.find((e) => e.name === aName);\n if (entry) {\n entry.balance = Number(a[\"balance\"] ?? 0);\n }\n }\n }\n\n const total = totalActive + totalSuspended + totalInventory + totalOther;\n const utilization =\n total > 0\n ? Math.round((totalActive / total) * 1000) / 10\n : 0;\n\n const totalAccounts =\n accountsResult.data && Array.isArray(accountsResult.data)\n ? accountsResult.data.length\n : accountList.length;\n\n const lowBalanceCount =\n accountsResult.data && Array.isArray(accountsResult.data)\n ? accountsResult.data.filter((a) => Number(a[\"balance\"] ?? 0) < 10)\n .length\n : 0;\n\n // Sort accountList by total eSIMs descending for top-10 bar chart\n const sortedAccounts = [...accountList]\n .sort(\n (a, b) =>\n b.active + b.suspended + b.inventory + b.other -\n (a.active + a.suspended + a.inventory + a.other),\n )\n .slice(0, 10);\n\n const errors = [statusResult.error, accountsResult.error]\n .filter(Boolean)\n .join(\"; \");\n\n const summaryLines = [\n `Fleet Utilization: ${utilization}%`,\n `Active: ${totalActive} | Suspended: ${totalSuspended} | Inventory: ${totalInventory} | Other: ${totalOther}`,\n `Total Accounts: ${totalAccounts} | Low Balance (<10): ${lowBalanceCount}`,\n ...(errors ? [`Errors: ${errors}`] : []),\n ];\n\n const structuredContent: FleetHealthStructuredContent = {\n utilization,\n totalActive,\n totalSuspended,\n totalInventory,\n totalOther,\n totalAccounts,\n lowBalanceCount,\n accountList: sortedAccounts,\n };\n\n return {\n content: [{ type: \"text\" as const, text: summaryLines.join(\"\\n\") }],\n structuredContent,\n };\n },\n );\n}\n","/**\n * v1.2b — eSIM Provisioning Wizard MCP App\n *\n * 3-step wizard: select subscriber → select package → confirm + execute.\n * Tier-gated: pro and enterprise only (free tier is skipped).\n * Step 2→3 fetches package template details for preview; step 3 (confirm) calls affectPackageToSubscriber.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport { getDefaultResellerId, type ToolContext } from \"../tools.js\";\nimport {\n loadWizardSession,\n saveWizardSession,\n deleteWizardSession,\n} from \"./app-state.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction generateWizardId(): string {\n const arr = new Uint8Array(4);\n crypto.getRandomValues(arr);\n return Array.from(arr)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ── Registration ──────────────────────────────────────────────────────────────\n\nexport function registerProvisioningWizard(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // Tier guard — free tier does not get this wizard\n if (ctx.props.tier === \"free\") return;\n\n // ── Resource ───────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"eSIM Provisioning Wizard\",\n \"ui://esim-provisioning-wizard\",\n {\n description:\n \"3-step eSIM provisioning wizard — pick subscriber, pick package, confirm + execute.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\n \"https://internal/views/provisioning-wizard/index.html\",\n ),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Provisioning wizard unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://esim-provisioning-wizard\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n _meta: { ui: {} },\n },\n ],\n };\n },\n );\n\n // ── Tool ───────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"provision_esim_wizard\",\n {\n title: \"eSIM Provisioning Wizard\",\n description:\n \"Interactive 3-step wizard to provision an eSIM: select subscriber, choose package template, preview (dry_run) and confirm execution.\",\n inputSchema: {\n step: z\n .enum([\"init\", \"select-package\", \"preview\", \"confirm\"])\n .describe(\"Current wizard step\"),\n wizardId: z\n .string()\n .optional()\n .describe(\"Wizard session ID (absent on init)\"),\n subscriber_iccid: z\n .string()\n .optional()\n .describe(\"Subscriber ICCID (required for select-package)\"),\n package_template_id: z\n .number()\n .optional()\n .describe(\"Package template ID (required for preview)\"),\n },\n _meta: {\n ui: {\n resourceUri: \"ui://esim-provisioning-wizard\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n async ({ step, wizardId, subscriber_iccid, package_template_id }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n // ── init ────────────────────────────────────────────────────────────────\n if (step === \"init\") {\n const newWizardId = generateWizardId();\n const subscribersResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listResellerAccount\",\n {},\n );\n\n const session = {\n step: \"select-subscriber\" as const,\n dry_run: false,\n initiated_at: new Date().toISOString(),\n };\n await saveWizardSession(\n ctx.env,\n ctx.props.sub,\n newWizardId,\n session,\n );\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Wizard started (id: ${newWizardId}). Select a subscriber to provision.`,\n },\n ],\n structuredContent: {\n wizardId: newWizardId,\n step: \"select-subscriber\",\n subscribers: subscribersResult.data ?? [],\n error: subscribersResult.error,\n },\n };\n }\n\n // All subsequent steps require a wizardId\n if (!wizardId) {\n return {\n content: [{ type: \"text\" as const, text: \"Missing wizardId.\" }],\n isError: true,\n };\n }\n\n // ── select-package ──────────────────────────────────────────────────────\n if (step === \"select-package\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"select-subscriber\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected select-subscriber, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n if (!subscriber_iccid) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"subscriber_iccid is required for select-package step.\",\n },\n ],\n isError: true,\n };\n }\n\n // OCS method is listPrepaidPackageTemplate; requires resellerId param.\n const resellerIdForTemplates = await getDefaultResellerId(ctx.env, token);\n const packagesResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listPrepaidPackageTemplate\",\n { resellerId: resellerIdForTemplates },\n );\n\n const updated = {\n ...session,\n step: \"select-package\" as const,\n subscriber_iccid,\n };\n await saveWizardSession(ctx.env, ctx.props.sub, wizardId, updated);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Subscriber ${subscriber_iccid} selected. Choose a package template.`,\n },\n ],\n structuredContent: {\n wizardId,\n step: \"select-package\",\n subscriber_iccid,\n packages: packagesResult.data ?? [],\n error: packagesResult.error,\n },\n };\n }\n\n // ── preview ─────────────────────────────────────────────────────────────\n if (step === \"preview\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"select-package\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected select-package, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n if (package_template_id === undefined) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"package_template_id is required for preview step.\",\n },\n ],\n isError: true,\n };\n }\n\n // Fix #19: modifyAccountPackage does not exist in OCS v1.\n // Preview step fetches the package template details (read-only) to show\n // the operator what will be assigned before confirm executes the real call.\n const previewResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listPrepaidPackageTemplate\",\n {},\n );\n\n const list = previewResult.data;\n let preview: unknown = null;\n if (Array.isArray(list)) {\n preview =\n list.find((item) => {\n if (!item || typeof item !== \"object\") return false;\n const rec = item as Record<string, unknown>;\n const tid = rec.templateId ?? rec.packageTemplateId;\n return Number(tid) === package_template_id;\n }) ?? null;\n } else if (list && typeof list === \"object\") {\n const rec = list as Record<string, unknown>;\n const tid = rec.templateId ?? rec.packageTemplateId;\n if (Number(tid) === package_template_id) preview = list;\n }\n\n const updated = {\n ...session,\n step: \"confirm\" as const,\n package_template_id,\n dry_run: true,\n };\n await saveWizardSession(ctx.env, ctx.props.sub, wizardId, updated);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Preview ready. Review changes and confirm to proceed.`,\n },\n ],\n structuredContent: {\n wizardId,\n step: \"confirm\",\n subscriber_iccid: session.subscriber_iccid,\n package_template_id,\n preview,\n previewError: previewResult.error,\n },\n };\n }\n\n // ── confirm ─────────────────────────────────────────────────────────────\n if (step === \"confirm\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"confirm\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected confirm, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n\n // Fix #19: modifyAccountPackage does not exist in OCS v1. The correct method\n // for provisioning a package is affectPackageToSubscriber, which expects an\n // integer subscriberId (not ICCID string). Resolve via getSingleSubscriber first.\n const subRecord = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"getSingleSubscriber\",\n { iccid: session.subscriber_iccid },\n );\n if (subRecord.error || !subRecord.data) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: could not resolve subscriber for ICCID ${session.subscriber_iccid}: ${subRecord.error ?? \"empty response\"}`,\n },\n ],\n isError: true,\n };\n }\n const subscriberId = subRecord.data.id ?? subRecord.data.subscriberId;\n if (subscriberId === undefined) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: getSingleSubscriber returned no id for ICCID ${session.subscriber_iccid}`,\n },\n ],\n isError: true,\n };\n }\n const result = await safeCallWithToken(\n client,\n token,\n \"affectPackageToSubscriber\",\n {\n subscriber: Number(subscriberId),\n packageTemplateId: session.package_template_id,\n },\n );\n\n await deleteWizardSession(ctx.env, ctx.props.sub, wizardId);\n\n if (result.error) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: ${result.error}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\" as const, text: \"Provisioned.\" }],\n structuredContent: {\n wizardId,\n step: \"done\",\n result: result.data,\n },\n };\n }\n\n return {\n content: [{ type: \"text\" as const, text: `Unknown step: ${step as string}.` }],\n isError: true,\n };\n },\n );\n}\n","/**\n * v1.2b — Wizard Session KV helpers\n *\n * Stores ephemeral 3-step wizard state in CARRIER_USERS KV.\n * Key pattern: app-session:<sub>:<wizardId>\n * TTL: 600 seconds (10 minutes).\n */\n\nimport type { Env } from \"../types.js\";\n\nexport interface WizardSession {\n step: \"select-subscriber\" | \"select-package\" | \"confirm\";\n subscriber_iccid?: string;\n package_template_id?: number;\n dry_run: boolean;\n initiated_at: string;\n}\n\nfunction sessionKey(sub: string, wizardId: string): string {\n return `app-session:${sub}:${wizardId}`;\n}\n\nexport async function loadWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n): Promise<WizardSession | null> {\n const raw = await env.CARRIER_USERS.get(sessionKey(sub, wizardId));\n if (!raw) return null;\n try {\n return JSON.parse(raw) as WizardSession;\n } catch {\n return null;\n }\n}\n\nexport async function saveWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n session: WizardSession,\n): Promise<void> {\n await env.CARRIER_USERS.put(\n sessionKey(sub, wizardId),\n JSON.stringify(session),\n { expirationTtl: 600 },\n );\n}\n\nexport async function deleteWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n): Promise<void> {\n await env.CARRIER_USERS.delete(sessionKey(sub, wizardId));\n}\n","/**\n * v1.2d — Balance Top-up Form MCP App\n *\n * Enterprise-only inline form for adjusting account balances via\n * `modify_account_balance`. Supports preview-only mode before committing.\n * Scoped to `admin` — pairs with MFA gate from PR #46.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport type { ToolContext } from \"../tools.js\";\nimport { wrapHandler, TOOL_SCOPES } from \"../tools.js\";\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport interface BalanceTopupStructuredContent {\n iccid: string;\n delta: number;\n current_balance?: number;\n new_balance?: number;\n preview: boolean;\n success?: boolean;\n}\n\nexport function registerBalanceTopupApp(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // Tier guard — enterprise only\n if (ctx.props.tier !== \"enterprise\") return;\n\n // ── Resource ─────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"Balance Top-up Form\",\n \"ui://balance-topup-form\",\n {\n description:\n \"Admin balance top-up form — enter an ICCID and delta amount to preview and commit account balance adjustments. Enterprise only. Requires recent MFA verification.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\"https://internal/views/balance-topup/index.html\"),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Balance top-up form unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://balance-topup-form\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n },\n ],\n };\n },\n );\n\n // ── Tool ─────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"balance_topup_form\",\n {\n title: \"Balance Top-up Form\",\n description:\n \"Enterprise admin tool: preview or commit an account balance adjustment. Set preview=true to fetch projection (no OCS write); preview=false (default) to execute. Requires admin scope + recent MFA.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID for the account lookup\"),\n delta: z\n .number()\n .describe(\"Amount to add (positive) or deduct (negative) from the account balance\"),\n preview: z\n .boolean()\n .default(true)\n .describe(\"If true, return preview without writing. If false, execute the balance change.\"),\n },\n annotations: { destructiveHint: true },\n _meta: {\n ui: {\n resourceUri: \"ui://balance-topup-form\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n wrapHandler(\n \"modify_account_balance\",\n \"modifyAccountBalance\",\n TOOL_SCOPES[\"modify_account_balance\"]!,\n ctx,\n async ({ iccid, delta, preview }: { iccid: string; delta: number; preview?: boolean }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n if (preview === true) {\n // Preview path — fetch current subscriber balance, return projection\n const result = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"getSingleSubscriber\",\n { iccid },\n );\n\n const currentBalance = result.data\n ? Number(result.data[\"balance\"] ?? result.data[\"accountBalance\"] ?? 0)\n : 0;\n const newBalance = currentBalance + delta;\n\n const structured: BalanceTopupStructuredContent = {\n iccid,\n delta,\n current_balance: currentBalance,\n new_balance: newBalance,\n preview: true,\n };\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `[Preview] ICCID: ${iccid} | Current balance: ${currentBalance} | Delta: ${delta >= 0 ? \"+\" : \"\"}${delta} | New balance: ${newBalance}. No changes made.`,\n },\n ],\n structuredContent: structured,\n };\n }\n\n // Execute path — call modify_account_balance via OCS\n const execResult = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"modifyAccountBalance\",\n { subscriber: iccid, adaptBalance: delta },\n );\n\n if (execResult.error) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `Error: ${execResult.error}` }],\n };\n }\n\n const newBalance = execResult.data\n ? Number(execResult.data[\"balance\"] ?? execResult.data[\"newBalance\"] ?? 0)\n : delta;\n\n const structured: BalanceTopupStructuredContent = {\n iccid,\n delta,\n new_balance: newBalance,\n preview: false,\n success: true,\n };\n\n return {\n content: [{ type: \"text\" as const, text: \"Balance updated.\" }],\n structuredContent: structured,\n };\n },\n ),\n );\n}\n","/**\n * MCP Apps barrel — v1.2+\n *\n * Registers all UI-enabled tools and `ui://` HTML resources on every session.\n * Tools carry `_meta.ui.resourceUri` per the MCP Apps spec; MCP-Apps-capable\n * clients (Claude Desktop, Claude.ai with MCP Apps support) render the\n * associated `ui://` resource as a sandboxed iframe. Clients that don't\n * speak MCP Apps simply ignore the `_meta.ui` metadata and call the tool\n * as a normal tool with structured output.\n *\n * Per-app tier gates live INSIDE each register*() function. The previous\n * version of this barrel gated the whole registration block on\n * `getUiCapability` from the client's `initialize` capabilities — that\n * was overly aggressive and hid the tools from clients (including\n * Claude Code) that don't yet advertise `io.modelcontextprotocol/ui`\n * but can still execute structured-output tools.\n *\n * Sub-phase ownership:\n * v1.2a — fleet-health-app\n * v1.2b — provisioning-wizard\n * v1.2d — balance-topup-form\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"../tools.js\";\nimport { registerFleetHealthApp } from \"./fleet-health-app.js\";\nimport { registerProvisioningWizard } from \"./provisioning-wizard.js\";\nimport { registerBalanceTopupApp } from \"./balance-topup.js\";\n\nexport {\n registerFleetHealthApp,\n registerProvisioningWizard,\n registerBalanceTopupApp,\n};\n\n/**\n * Register all MCP App tools and resources.\n *\n * Always registers unconditionally — tier gates are enforced inside each\n * register*() function. MCP-Apps-capable clients render the iframes;\n * other clients see the tools as normal structured-output tools.\n */\nexport function registerAllApps(server: McpServer, ctx: ToolContext): void {\n // v1.2a — Fleet Health Dashboard (free+, read scope)\n registerFleetHealthApp(server, ctx);\n\n // v1.2b — eSIM Provisioning Wizard (pro+, write scope; tier-gated internally)\n registerProvisioningWizard(server, ctx);\n\n // v1.2d — Balance Top-up Form (enterprise only, admin scope; tier-gated internally)\n registerBalanceTopupApp(server, ctx);\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/**\n * Carrier MCP business prompts (5).\n * Renamed from registerPrompts → registerAllPrompts for consistency.\n */\nexport function registerAllPrompts(server: McpServer): void {\n server.registerPrompt(\n \"fleet_health_report\",\n {\n title: \"Fleet Health Report\",\n description:\n \"Generate a comprehensive fleet health report: account balances, eSIM status breakdown, low-balance alerts, and utilization rates.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier fleet analyst. Generate a health report by:\n\n1. Call list_reseller_accounts to get all accounts and their balances\n2. Call esim_status_per_account for each account to get SIM status breakdowns\n3. Analyze and present:\n - Total eSIMs by status (active, suspended, inventory)\n - Utilization rate (active / total provisioned)\n - Accounts with low balance (< $50) — flag as urgent\n - Accounts with high inactive SIM ratio — flag for cleanup\n - Top accounts by active SIM count\n\nFormat as a structured report with sections, tables, and actionable recommendations.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"subscriber_deep_dive\",\n {\n title: \"Subscriber Deep Dive\",\n description:\n \"Comprehensive analysis of a single subscriber: profile, packages, usage patterns, location history, recommendations.\",\n argsSchema: { iccid: z.string().describe(\"The subscriber ICCID to analyse\") },\n },\n async ({ iccid }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier customer success analyst. Deep-dive into subscriber ${iccid}:\n\n1. Call get_subscriber with ICCID \"${iccid}\" for profile details\n2. Call list_subscriber_packages for their active/expired packages\n3. Call subscriber_usage for the last 7 days to see usage patterns\n4. Call subscriber_network_events for the last 7 days for connectivity\n5. Call get_subscriber_location for current location\n\nAnalyze and present:\n- Subscriber profile summary (status, account, balance, contact)\n- Package utilization: % of data/voice/SMS used vs allowance\n- Usage trends: increasing/decreasing/stable\n- Roaming behavior: which countries/networks\n- Connectivity quality: attach/detach frequency\n- Actionable recommendations:\n - If usage > 80% of allowance → suggest upgrade\n - If usage < 20% → suggest downgrade to prevent churn\n - If frequent network switches → check steering list\n - If low balance → alert for top-up`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"revenue_optimization\",\n {\n title: \"Revenue Optimization Analysis\",\n description:\n \"Analyse accounts and subscribers to find revenue optimization opportunities: underutilized packages, upgrade candidates, churn risks.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier revenue optimization analyst. Find opportunities by:\n\n1. Call list_reseller_accounts for account overview\n2. Call list_package_templates to understand the product catalog\n3. Call get_tariff to understand the cost structure\n4. For top accounts, call list_subscribers and sample subscriber_usage\n\nAnalyze and present:\n- Package template analysis: which templates are most/least popular\n- Pricing gap analysis: cost vs retail price margins\n- Upgrade candidates: subscribers consistently hitting limits\n- Downgrade/churn risks: subscribers with declining usage\n- Geographic opportunities: high-usage zones with limited coverage\n- Recommendations ranked by estimated revenue impact`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"coverage_analysis\",\n {\n title: \"Coverage & Network Analysis\",\n description:\n \"Analyse network coverage, steering lists, and subscriber roaming patterns to optimise connectivity and reduce costs.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier network coverage analyst. Analyze the fleet's connectivity by:\n\n1. Call list_steering_lists to see network steering configurations\n2. Call list_detailed_location_zones for coverage zone definitions\n3. Call list_sponsors for available sponsor networks\n4. Call list_network_profiles for connectivity configs\n5. Sample subscriber_network_events for active subscribers\n\nAnalyze and present:\n- Coverage map: which zones/countries are covered\n- Steering list effectiveness: are subs connecting to preferred networks?\n- Roaming cost hotspots: countries with high roaming fees\n- Network quality: attach/detach patterns by network\n- Recommendations for steering list optimization`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"bulk_operations_planner\",\n {\n title: \"Bulk Operations Planner\",\n description:\n \"Plan bulk operations safely: mass package assignments, account migrations, balance adjustments, or status changes.\",\n argsSchema: { operation: z.string().describe(\"Describe the bulk operation you want to perform\") },\n },\n async ({ operation }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier operations planner. The user wants to perform this bulk operation:\n\n\"${operation}\"\n\nCreate a safe execution plan:\n1. First, use read-only tools to understand the current state\n2. Identify all affected subscribers/accounts\n3. Estimate the impact (cost, service disruption, reversibility)\n4. Generate a step-by-step plan with:\n - Pre-flight checks\n - Execution order (smallest batch first as canary)\n - Rollback procedure for each step\n - Post-execution verification\n5. List all destructive tool calls that will be needed\n6. Ask for explicit confirmation before any destructive action\n\nNEVER execute destructive operations without confirmation.`,\n },\n },\n ],\n }),\n );\n}\n","/**\n * Carrier MCP — Pricing & Projects Tool Registration\n *\n * Registers 10 new MCP tools:\n * - 5 pricing/billing management tools (credit_balance, configure_billing, etc.)\n * - 5 projects/service management tools (service_catalog, credential_status, etc.)\n *\n * These tools follow the same wrapHandler pattern as OCS tools but skip\n * OCS token resolution (they operate on billing/config data only).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport { checkCallQuota, recordUsage, UPGRADE_URL } from \"./billing.js\";\nimport { PRICING_TOOLS } from \"./pricing-tools.js\";\nimport { PROJECTS_TOOLS } from \"./projects-tools.js\";\nimport { checkCredits, deductCredits } from \"./credits.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\n/**\n * Register all pricing and projects tools on the MCP server.\n * Called from agent.ts init() alongside other tool registrations.\n */\nexport function registerAllPricingTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n const allTools = [...PRICING_TOOLS, ...PROJECTS_TOOLS];\n\n for (const tool of allTools) {\n server.registerTool(\n tool.name,\n {\n title: toolNameToTitle(tool.name),\n description: tool.description,\n inputSchema: buildZodSchema(tool.inputSchema),\n annotations: {\n readOnlyHint: tool.scope === \"read\",\n ...(tool.scope !== \"read\" ? { destructiveHint: false } : {}),\n },\n },\n buildPricingHandler(tool, ctx),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handler Builder\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nfunction buildPricingHandler(\n tool: (typeof PRICING_TOOLS)[number] | (typeof PROJECTS_TOOLS)[number],\n ctx: ToolContext,\n) {\n return async (args: Record<string, unknown>): Promise<ToolResult> => {\n const start = Date.now();\n\n // Scope enforcement\n if (!ctx.props.scope.includes(tool.scope as \"read\" | \"write\" | \"admin\")) {\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Scope denied: tool '${tool.name}' requires '${tool.scope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Credit check (v2.0 system — runs in parallel with legacy quota check)\n const tier = ctx.props.tier as Tier;\n const creditResult = await checkCredits(ctx.env, ctx.props.sub, tier, tool.scope as \"read\" | \"write\" | \"admin\");\n\n if (!creditResult.allowed) {\n // Fall back to legacy quota check\n const quota = await checkCallQuota(ctx.env, ctx.props.sub, tier);\n if (!quota.allowed) {\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"quota_exceeded\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Credit limit reached. Remaining: ${creditResult.credits_remaining} credits. Resets ${creditResult.reset_at}. Upgrade at ${UPGRADE_URL}`,\n },\n ],\n };\n }\n }\n\n // Execute handler\n try {\n const result = await tool.handler(ctx.env, ctx.props, args);\n\n // Record usage (both systems)\n recordUsage(ctx.env, ctx.props.sub, tier);\n deductCredits(ctx.env, ctx.props.sub, tier, tool.scope as \"read\" | \"write\" | \"admin\");\n\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${message}` }],\n };\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toolNameToTitle(name: string): string {\n return name\n .split(\"_\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n/**\n * Build a zod schema from the JSON Schema-like inputSchema definition.\n * Supports: string, number, boolean, array of numbers.\n */\nfunction buildZodSchema(\n schema: Record<string, unknown>,\n): Record<string, z.ZodTypeAny> {\n const properties = (schema.properties ?? {}) as Record<\n string,\n { type?: string; description?: string; enum?: string[]; items?: { type?: string } }\n >;\n const result: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, prop] of Object.entries(properties)) {\n let field: z.ZodTypeAny;\n\n if (prop.enum) {\n field = z.enum(prop.enum as [string, ...string[]]);\n } else if (prop.type === \"number\") {\n field = z.number();\n } else if (prop.type === \"boolean\") {\n field = z.boolean();\n } else if (prop.type === \"array\") {\n if (prop.items?.type === \"number\") {\n field = z.array(z.number());\n } else {\n field = z.array(z.string());\n }\n } else {\n field = z.string();\n }\n\n // All pricing tool params are optional (no required fields in most cases)\n const required = (schema.required as string[] | undefined) ?? [];\n if (!required.includes(key)) {\n field = field.optional();\n }\n\n if (prop.description) {\n field = field.describe(prop.description);\n }\n\n result[key] = field;\n }\n\n return result;\n}\n","/**\n * Carrier MCP — Credits System v2.0 (Pricing Evolution)\n *\n * Implements credit-based billing inspired by Stripe's Pricing Model Evolution Guide:\n * - Monthly credit allotments per tier (Lovable pattern)\n * - Auto-billed overages when base credits exhausted (Warp pattern)\n * - Credit rollovers for irregular usage (Lovable pattern)\n * - Daily free credits for acquisition (Browserbase/Lovable pattern)\n * - Billing thresholds to prevent bill shock (Hex pattern)\n * - Volume discounts for high-usage customers\n *\n * Storage layout (CARRIER_USERS KV):\n * key: credits:<sub>:<yyyymm> value: CreditLedger\n * key: credits:daily:<sub>:<yyyymmdd> value: DailyFreeCredits\n * key: credits:config:<sub> value: CreditConfig (overrides, thresholds)\n * key: credits:rollover:<sub> value: RolloverBalance\n *\n * Credit economy:\n * 1 tool call = 1 credit (read scope)\n * 1 tool call = 2 credits (write scope)\n * 1 tool call = 5 credits (admin scope)\n * Intelligence composites = 3 credits each\n *\n * Stripe integration:\n * - Overages reported via Stripe Metered Billing (usage_records API)\n * - Billing thresholds trigger Stripe invoice finalization\n * - Credit grants created via Stripe Customer Balance Transactions\n */\n\nimport type { Env } from \"./types.js\";\nimport type { Tier, ScopeToken } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Credit Constants\n// ---------------------------------------------------------------------------\n\n/** Monthly credit allotments per tier */\nexport const TIER_CREDIT_ALLOTMENTS: Record<Tier, number> = {\n free: 5_000,\n pro: 100_000,\n enterprise: Infinity,\n};\n\n/** Daily free credits for all users (acquisition driver) */\nexport const DAILY_FREE_CREDITS = 50;\n\n/** Maximum rollover credits (cap at 2x monthly allotment) */\nexport const ROLLOVER_CAP_MULTIPLIER = 2;\n\n/** Credit cost per scope */\nexport const SCOPE_CREDIT_COSTS: Record<ScopeToken | \"intelligence\", number> = {\n read: 1,\n write: 2,\n admin: 5,\n intelligence: 3,\n};\n\n/** Volume discount tiers (cumulative monthly usage) */\nexport const VOLUME_DISCOUNTS: VolumeDiscountTier[] = [\n { threshold: 50_000, discountPct: 0 },\n { threshold: 100_000, discountPct: 10 },\n { threshold: 250_000, discountPct: 15 },\n { threshold: 500_000, discountPct: 20 },\n { threshold: 1_000_000, discountPct: 25 },\n];\n\n/** Default billing threshold (in cents) — triggers invoice at this spend level */\nexport const DEFAULT_BILLING_THRESHOLD_CENTS = 10_000; // $100\n\n/** Overage price per credit (in cents) — Pro tier */\nexport const OVERAGE_PRICE_PER_CREDIT_CENTS = 0.1; // $0.001 per credit\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VolumeDiscountTier {\n threshold: number;\n discountPct: number;\n}\n\nexport interface CreditLedger {\n /** Monthly allotment (base + rollover) */\n allotment: number;\n /** Credits consumed this period */\n consumed: number;\n /** Credits from rollovers applied this month */\n rollover_applied: number;\n /** Overage credits consumed beyond allotment */\n overage: number;\n /** Overage amount billed (cents) */\n overage_billed_cents: number;\n /** Whether billing threshold was hit this period */\n threshold_triggered: boolean;\n /** ISO 8601 last updated */\n updated_at: string;\n}\n\nexport interface DailyFreeCredits {\n /** Credits granted today */\n granted: number;\n /** Credits consumed from daily free pool */\n consumed: number;\n /** ISO date (YYYY-MM-DD) */\n date: string;\n}\n\nexport interface CreditConfig {\n /** Custom billing threshold override (cents) */\n billing_threshold_cents: number;\n /** Whether overages are enabled (Pro+) */\n overages_enabled: boolean;\n /** Whether rollovers are enabled (Pro+) */\n rollovers_enabled: boolean;\n /** Custom overage rate override (cents per credit) */\n overage_rate_cents: number;\n /** Volume discount tier override */\n volume_discount_pct: number;\n /** Notification preferences */\n notify_at_pct: number[]; // e.g., [50, 80, 95, 100]\n updated_at: string;\n}\n\nexport interface RolloverBalance {\n /** Unused credits from previous month eligible for rollover */\n credits: number;\n /** Source month (YYYYMM) */\n source_month: string;\n /** Expiry — rollovers expire after 1 month */\n expires_at: string;\n}\n\nexport interface CreditCheckResult {\n allowed: boolean;\n credits_remaining: number;\n daily_free_remaining: number;\n overage_active: boolean;\n overage_amount_cents: number;\n threshold_pct: number;\n tier: Tier;\n volume_discount_pct: number;\n reset_at: string;\n}\n\nexport interface CreditDeductionResult {\n success: boolean;\n credits_deducted: number;\n source: \"allotment\" | \"daily_free\" | \"overage\";\n new_balance: number;\n overage_triggered: boolean;\n threshold_triggered: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Credit Check\n// ---------------------------------------------------------------------------\n\n/**\n * Check if a user has sufficient credits for a tool call.\n * Order of credit consumption:\n * 1. Daily free credits (if available)\n * 2. Monthly allotment (base + rollover)\n * 3. Overage (if enabled for tier)\n */\nexport async function checkCredits(\n env: Env,\n sub: string,\n tier: Tier,\n scope: ScopeToken | \"intelligence\",\n): Promise<CreditCheckResult> {\n const cost = SCOPE_CREDIT_COSTS[scope];\n const month = currentMonth();\n const today = currentDay();\n const resetAt = firstDayNextMonth();\n\n // Enterprise always allowed\n if (tier === \"enterprise\") {\n return {\n allowed: true,\n credits_remaining: Infinity,\n daily_free_remaining: Infinity,\n overage_active: false,\n overage_amount_cents: 0,\n threshold_pct: 0,\n tier,\n volume_discount_pct: 0,\n reset_at: resetAt,\n };\n }\n\n // Load ledger\n const ledger = await getLedger(env, sub, month, tier);\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const config = await getCreditConfig(env, sub, tier);\n\n // Calculate remaining\n const monthlyRemaining = Math.max(0, ledger.allotment - ledger.consumed);\n const dailyFreeRemaining = Math.max(0, dailyFree.granted - dailyFree.consumed);\n const totalRemaining = dailyFreeRemaining + monthlyRemaining;\n\n // Check if allowed\n const overageEnabled = config.overages_enabled && tier !== \"free\";\n const allowed = totalRemaining >= cost || overageEnabled;\n\n // Volume discount\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n\n // Threshold percentage\n const thresholdPct = config.billing_threshold_cents > 0\n ? Math.round((ledger.overage_billed_cents / config.billing_threshold_cents) * 100)\n : 0;\n\n return {\n allowed,\n credits_remaining: monthlyRemaining,\n daily_free_remaining: dailyFreeRemaining,\n overage_active: monthlyRemaining < cost && dailyFreeRemaining < cost && overageEnabled,\n overage_amount_cents: ledger.overage_billed_cents,\n threshold_pct: thresholdPct,\n tier,\n volume_discount_pct: volumeDiscount,\n reset_at: resetAt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Credit Deduction\n// ---------------------------------------------------------------------------\n\n/**\n * Deduct credits for a tool call. Fire-and-forget in the hot path.\n *\n * Consumption order:\n * 1. Daily free credits first (lowest cost to user)\n * 2. Monthly allotment\n * 3. Overage (auto-billed, Pro+ only)\n */\nexport function deductCredits(\n env: Env,\n sub: string,\n tier: Tier,\n scope: ScopeToken | \"intelligence\",\n): void {\n void (async () => {\n const cost = SCOPE_CREDIT_COSTS[scope];\n const month = currentMonth();\n const today = currentDay();\n\n // Enterprise — no deduction needed\n if (tier === \"enterprise\") return;\n\n // Try daily free credits first\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const dailyRemaining = dailyFree.granted - dailyFree.consumed;\n\n if (dailyRemaining >= cost) {\n // Deduct from daily free pool\n await putDailyFreeCredits(env, sub, today, {\n ...dailyFree,\n consumed: dailyFree.consumed + cost,\n });\n return;\n }\n\n // Deduct from monthly allotment\n const ledger = await getLedger(env, sub, month, tier);\n const monthlyRemaining = ledger.allotment - ledger.consumed;\n\n if (monthlyRemaining >= cost) {\n await putLedger(env, sub, month, {\n ...ledger,\n consumed: ledger.consumed + cost,\n updated_at: new Date().toISOString(),\n });\n return;\n }\n\n // Overage path (Pro+ only)\n const config = await getCreditConfig(env, sub, tier);\n if (!config.overages_enabled || tier === \"free\") return;\n\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n const effectiveRate = OVERAGE_PRICE_PER_CREDIT_CENTS * (1 - volumeDiscount / 100);\n const overageCostCents = Math.round(cost * effectiveRate * 100) / 100;\n\n const updatedLedger: CreditLedger = {\n ...ledger,\n consumed: ledger.consumed + cost,\n overage: ledger.overage + cost,\n overage_billed_cents: ledger.overage_billed_cents + overageCostCents,\n updated_at: new Date().toISOString(),\n };\n\n // Check billing threshold\n if (\n !ledger.threshold_triggered &&\n updatedLedger.overage_billed_cents >= config.billing_threshold_cents\n ) {\n updatedLedger.threshold_triggered = true;\n // Trigger Stripe invoice finalization (async, non-blocking)\n void triggerBillingThreshold(env, sub, updatedLedger.overage_billed_cents);\n }\n\n await putLedger(env, sub, month, updatedLedger);\n\n // Push overage to Stripe at every 100-credit boundary\n if (updatedLedger.overage % 100 === 0) {\n void pushOverageToStripe(env, sub, 100, effectiveRate).catch(() => {});\n }\n })();\n}\n\n// ---------------------------------------------------------------------------\n// Credit Grant (Rollover)\n// ---------------------------------------------------------------------------\n\n/**\n * Calculate and apply rollover credits from previous month.\n * Called by the monthly cron job (scheduled handler).\n *\n * Rules:\n * - Only Pro+ tiers get rollovers\n * - Rollover = min(unused credits, allotment * ROLLOVER_CAP_MULTIPLIER)\n * - Rollovers expire after 1 month (use-it-or-lose-it next cycle)\n */\nexport async function applyMonthlyRollover(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<RolloverBalance | null> {\n if (tier === \"free\") return null;\n\n const prevMonth = previousMonth();\n const prevLedger = await getLedger(env, sub, prevMonth, tier);\n\n const unused = Math.max(0, prevLedger.allotment - prevLedger.consumed);\n if (unused === 0) return null;\n\n const maxRollover = TIER_CREDIT_ALLOTMENTS[tier] * ROLLOVER_CAP_MULTIPLIER;\n const rolloverAmount = Math.min(unused, maxRollover);\n\n const rollover: RolloverBalance = {\n credits: rolloverAmount,\n source_month: prevMonth,\n expires_at: firstDayMonthAfterNext(),\n };\n\n await env.CARRIER_USERS.put(\n `credits:rollover:${sub}`,\n JSON.stringify(rollover),\n { expirationTtl: 62 * 24 * 60 * 60 }, // ~2 months\n );\n\n // Apply to current month's ledger\n const currentMo = currentMonth();\n const currentLedger = await getLedger(env, sub, currentMo, tier);\n await putLedger(env, sub, currentMo, {\n ...currentLedger,\n allotment: currentLedger.allotment + rolloverAmount,\n rollover_applied: rolloverAmount,\n updated_at: new Date().toISOString(),\n });\n\n return rollover;\n}\n\n// ---------------------------------------------------------------------------\n// Volume Discounts\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the applicable volume discount percentage based on cumulative usage.\n */\nexport function resolveVolumeDiscount(consumed: number): number {\n let discount = 0;\n for (const tier of VOLUME_DISCOUNTS) {\n if (consumed >= tier.threshold) {\n discount = tier.discountPct;\n } else {\n break;\n }\n }\n return discount;\n}\n\n// ---------------------------------------------------------------------------\n// Billing Threshold\n// ---------------------------------------------------------------------------\n\n/**\n * Trigger billing threshold — creates a Stripe invoice for accumulated overages.\n * Prevents bill shock by invoicing incrementally (Hex pattern).\n */\nasync function triggerBillingThreshold(\n env: Env,\n sub: string,\n amountCents: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return;\n\n // Create an invoice item for the threshold amount\n const body = new URLSearchParams({\n customer: customerId,\n amount: String(Math.round(amountCents)),\n currency: \"usd\",\n description: `Carrier MCP overage credits (threshold reached)`,\n });\n\n const resp = await fetch(\"https://api.stripe.com/v1/invoiceitems\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!resp.ok) return;\n\n // Create and finalize the invoice\n const invoiceBody = new URLSearchParams({\n customer: customerId,\n auto_advance: \"true\", // Auto-finalize and attempt payment\n \"collection_method\": \"charge_automatically\",\n description: \"Carrier MCP — Overage billing threshold invoice\",\n });\n\n await fetch(\"https://api.stripe.com/v1/invoices\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: invoiceBody.toString(),\n });\n}\n\n/**\n * Push overage usage records to Stripe Metered Billing.\n */\nasync function pushOverageToStripe(\n env: Env,\n sub: string,\n quantity: number,\n ratePerCredit: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n\n const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);\n if (!subItemId) return;\n\n const body = new URLSearchParams({\n quantity: String(quantity),\n timestamp: String(Math.floor(Date.now() / 1000)),\n action: \"increment\",\n });\n\n await fetch(\n `https://api.stripe.com/v1/subscription_items/${subItemId}/usage_records`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n // Store rate for reconciliation\n await env.CARRIER_USERS.put(\n `overage_rate:${sub}`,\n JSON.stringify({ rate_cents: ratePerCredit, updated_at: new Date().toISOString() }),\n { expirationTtl: 35 * 24 * 60 * 60 },\n );\n}\n\n// ---------------------------------------------------------------------------\n// KV Helpers\n// ---------------------------------------------------------------------------\n\nasync function getLedger(\n env: Env,\n sub: string,\n month: string,\n tier: Tier,\n): Promise<CreditLedger> {\n const key = `credits:${sub}:${month}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"allotment\" in raw) {\n return raw as CreditLedger;\n }\n // Initialize new ledger for the month\n const allotment = TIER_CREDIT_ALLOTMENTS[tier];\n return {\n allotment,\n consumed: 0,\n rollover_applied: 0,\n overage: 0,\n overage_billed_cents: 0,\n threshold_triggered: false,\n updated_at: new Date().toISOString(),\n };\n}\n\nasync function putLedger(\n env: Env,\n sub: string,\n month: string,\n ledger: CreditLedger,\n): Promise<void> {\n const key = `credits:${sub}:${month}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(ledger), {\n expirationTtl: 65 * 24 * 60 * 60, // ~2 months\n });\n}\n\nasync function getDailyFreeCredits(\n env: Env,\n sub: string,\n day: string,\n): Promise<DailyFreeCredits> {\n const key = `credits:daily:${sub}:${day}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"granted\" in raw) {\n return raw as DailyFreeCredits;\n }\n // Initialize daily free credits\n return {\n granted: DAILY_FREE_CREDITS,\n consumed: 0,\n date: day,\n };\n}\n\nasync function putDailyFreeCredits(\n env: Env,\n sub: string,\n day: string,\n credits: DailyFreeCredits,\n): Promise<void> {\n const key = `credits:daily:${sub}:${day}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(credits), {\n expirationTtl: 2 * 24 * 60 * 60, // 2 days\n });\n}\n\nasync function getCreditConfig(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<CreditConfig> {\n const key = `credits:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"billing_threshold_cents\" in raw) {\n return raw as CreditConfig;\n }\n // Default config\n return {\n billing_threshold_cents: DEFAULT_BILLING_THRESHOLD_CENTS,\n overages_enabled: tier !== \"free\",\n rollovers_enabled: tier !== \"free\",\n overage_rate_cents: OVERAGE_PRICE_PER_CREDIT_CENTS,\n volume_discount_pct: 0,\n notify_at_pct: [50, 80, 95, 100],\n updated_at: new Date().toISOString(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Update Credit Config\n// ---------------------------------------------------------------------------\n\n/**\n * Update a user's credit configuration (admin or self-service).\n */\nexport async function updateCreditConfig(\n env: Env,\n sub: string,\n updates: Partial<CreditConfig>,\n): Promise<CreditConfig> {\n const tier = await resolveUserTier(env, sub);\n const current = await getCreditConfig(env, sub, tier);\n const updated: CreditConfig = {\n ...current,\n ...updates,\n updated_at: new Date().toISOString(),\n };\n const key = `credits:config:${sub}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(updated));\n return updated;\n}\n\n/**\n * Get credit usage summary for a user (used by billing UI).\n */\nexport async function getCreditSummary(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<{\n ledger: CreditLedger;\n daily_free: DailyFreeCredits;\n config: CreditConfig;\n rollover: RolloverBalance | null;\n volume_discount_pct: number;\n}> {\n const month = currentMonth();\n const today = currentDay();\n const ledger = await getLedger(env, sub, month, tier);\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const config = await getCreditConfig(env, sub, tier);\n const rolloverRaw = await env.CARRIER_USERS.get(\n `credits:rollover:${sub}`,\n \"json\",\n ).catch(() => null);\n const rollover = rolloverRaw as RolloverBalance | null;\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n\n return { ledger, daily_free: dailyFree, config, rollover, volume_discount_pct: volumeDiscount };\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Credit Grants\n// ---------------------------------------------------------------------------\n\n/**\n * Issue a credit grant to a customer via Stripe Customer Balance Transactions.\n * Used for promotional credits, referral bonuses, and compensation.\n */\nexport async function issueStripeCredits(\n env: Env,\n sub: string,\n amountCents: number,\n description: string,\n): Promise<boolean> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return false;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return false;\n\n const body = new URLSearchParams({\n amount: String(-Math.abs(amountCents)), // Negative = credit to customer\n currency: \"usd\",\n description,\n });\n\n const resp = await fetch(\n `https://api.stripe.com/v1/customers/${customerId}/balance_transactions`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n return resp.ok;\n}\n\n// ---------------------------------------------------------------------------\n// Internal Helpers\n// ---------------------------------------------------------------------------\n\nasync function resolveUserTier(env: Env, sub: string): Promise<Tier> {\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"tier\" in raw) {\n const t = (raw as { tier: string }).tier;\n if (t === \"pro\" || t === \"enterprise\") return t;\n }\n return \"free\";\n}\n\nfunction currentMonth(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction currentDay(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}${String(now.getUTCDate()).padStart(2, \"0\")}`;\n}\n\nfunction previousMonth(): string {\n const now = new Date();\n const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 1, 1));\n return `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction firstDayNextMonth(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 1;\n if (m === 12) return new Date(Date.UTC(y + 1, 0, 1)).toISOString();\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n\nfunction firstDayMonthAfterNext(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 2;\n if (m >= 12) return new Date(Date.UTC(y + 1, m - 12, 1)).toISOString();\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n","/**\n * Carrier MCP — Billing Thresholds (Hex Pattern)\n *\n * Prevents bill shock by:\n * 1. Triggering invoices at predefined spend levels\n * 2. Sending notifications at configurable usage percentages\n * 3. Hard-stopping overages at a user-defined maximum\n *\n * Integrates with Stripe:\n * - Uses Stripe Billing Thresholds on subscriptions\n * - Creates threshold-triggered invoices for overage accumulation\n * - Sends webhook events for notification dispatch\n *\n * Reference: Hex case study — \"Mitigating the risk of bill shock\"\n * - Invoices trigger automatically at predefined amounts\n * - Acts as spend alerts, preventing unexpected charges\n */\n\nimport type { Env } from \"./types.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ThresholdConfig {\n /** Soft thresholds — trigger notifications (percentage of limit) */\n notification_thresholds: number[];\n /** Hard threshold — stop overages at this amount (cents). 0 = no hard cap */\n hard_cap_cents: number;\n /** Invoice threshold — trigger invoice at this overage amount (cents) */\n invoice_threshold_cents: number;\n /** Whether to auto-pause overages when hard cap is hit */\n auto_pause_on_cap: boolean;\n /** Email for threshold notifications */\n notification_email: string | null;\n /** Webhook URL for threshold events */\n webhook_url: string | null;\n}\n\nexport interface ThresholdEvent {\n type: \"notification\" | \"invoice_triggered\" | \"hard_cap_reached\" | \"overage_paused\";\n sub: string;\n tier: Tier;\n current_spend_cents: number;\n threshold_cents: number;\n pct_of_limit: number;\n timestamp: string;\n}\n\nexport interface ThresholdCheckResult {\n /** Whether the user can continue consuming overage credits */\n overage_allowed: boolean;\n /** Events triggered by this check */\n events: ThresholdEvent[];\n /** Current spend as percentage of hard cap (0 if no cap) */\n spend_pct: number;\n /** Remaining before hard cap (Infinity if no cap) */\n remaining_cents: number;\n}\n\n// ---------------------------------------------------------------------------\n// Default Configs\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD_CONFIGS: Record<Tier, ThresholdConfig> = {\n free: {\n notification_thresholds: [80, 95, 100],\n hard_cap_cents: 0, // Free tier has no overages\n invoice_threshold_cents: 0,\n auto_pause_on_cap: true,\n notification_email: null,\n webhook_url: null,\n },\n pro: {\n notification_thresholds: [50, 75, 90, 100],\n hard_cap_cents: 50_000, // $500 hard cap default\n invoice_threshold_cents: 10_000, // Invoice every $100\n auto_pause_on_cap: false,\n notification_email: null,\n webhook_url: null,\n },\n enterprise: {\n notification_thresholds: [75, 90],\n hard_cap_cents: 0, // No cap for enterprise\n invoice_threshold_cents: 100_000, // Invoice every $1,000\n auto_pause_on_cap: false,\n notification_email: null,\n webhook_url: null,\n },\n};\n\n// ---------------------------------------------------------------------------\n// Core Functions\n// ---------------------------------------------------------------------------\n\n/**\n * Check billing thresholds before allowing overage consumption.\n * Returns whether overage is still allowed and any triggered events.\n */\nexport async function checkBillingThresholds(\n env: Env,\n sub: string,\n tier: Tier,\n currentSpendCents: number,\n additionalSpendCents: number,\n): Promise<ThresholdCheckResult> {\n const config = await getThresholdConfig(env, sub, tier);\n const events: ThresholdEvent[] = [];\n const projectedSpend = currentSpendCents + additionalSpendCents;\n\n // Check hard cap\n if (config.hard_cap_cents > 0 && projectedSpend >= config.hard_cap_cents) {\n events.push({\n type: \"hard_cap_reached\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.hard_cap_cents,\n pct_of_limit: 100,\n timestamp: new Date().toISOString(),\n });\n\n if (config.auto_pause_on_cap) {\n events.push({\n type: \"overage_paused\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.hard_cap_cents,\n pct_of_limit: 100,\n timestamp: new Date().toISOString(),\n });\n\n return {\n overage_allowed: false,\n events,\n spend_pct: 100,\n remaining_cents: 0,\n };\n }\n }\n\n // Check invoice threshold\n if (config.invoice_threshold_cents > 0) {\n const prevInvoiceCount = Math.floor(currentSpendCents / config.invoice_threshold_cents);\n const newInvoiceCount = Math.floor(projectedSpend / config.invoice_threshold_cents);\n\n if (newInvoiceCount > prevInvoiceCount) {\n events.push({\n type: \"invoice_triggered\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.invoice_threshold_cents * newInvoiceCount,\n pct_of_limit: config.hard_cap_cents > 0\n ? Math.round((projectedSpend / config.hard_cap_cents) * 100)\n : 0,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n // Check notification thresholds\n if (config.hard_cap_cents > 0) {\n for (const pct of config.notification_thresholds) {\n const thresholdAmount = Math.round((pct / 100) * config.hard_cap_cents);\n if (currentSpendCents < thresholdAmount && projectedSpend >= thresholdAmount) {\n events.push({\n type: \"notification\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: thresholdAmount,\n pct_of_limit: pct,\n timestamp: new Date().toISOString(),\n });\n }\n }\n }\n\n // Dispatch events (fire-and-forget)\n if (events.length > 0) {\n void dispatchThresholdEvents(env, sub, events, config);\n }\n\n const spendPct = config.hard_cap_cents > 0\n ? Math.round((projectedSpend / config.hard_cap_cents) * 100)\n : 0;\n const remaining = config.hard_cap_cents > 0\n ? Math.max(0, config.hard_cap_cents - projectedSpend)\n : Infinity;\n\n return {\n overage_allowed: true,\n events,\n spend_pct: spendPct,\n remaining_cents: remaining,\n };\n}\n\n/**\n * Get threshold config for a user, with fallback to tier defaults.\n */\nexport async function getThresholdConfig(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<ThresholdConfig> {\n const key = `threshold:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"notification_thresholds\" in raw) {\n return raw as ThresholdConfig;\n }\n return DEFAULT_THRESHOLD_CONFIGS[tier];\n}\n\n/**\n * Update threshold config for a user.\n */\nexport async function updateThresholdConfig(\n env: Env,\n sub: string,\n updates: Partial<ThresholdConfig>,\n): Promise<ThresholdConfig> {\n const tier = await resolveUserTier(env, sub);\n const current = await getThresholdConfig(env, sub, tier);\n const updated: ThresholdConfig = { ...current, ...updates };\n const key = `threshold:config:${sub}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(updated));\n return updated;\n}\n\n/**\n * Set up Stripe subscription billing thresholds.\n * Called when a user upgrades to Pro or changes their threshold config.\n */\nexport async function syncStripeThresholds(\n env: Env,\n sub: string,\n config: ThresholdConfig,\n): Promise<boolean> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return false;\n\n const subscriptionId = await env.CARRIER_USERS.get(`stripe_subscription_id:${sub}`);\n if (!subscriptionId) return false;\n\n // Update Stripe subscription with billing thresholds\n const body = new URLSearchParams();\n\n if (config.invoice_threshold_cents > 0) {\n body.set(\n \"billing_thresholds[amount_gte]\",\n String(config.invoice_threshold_cents),\n );\n }\n\n const resp = await fetch(\n `https://api.stripe.com/v1/subscriptions/${subscriptionId}`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n return resp.ok;\n}\n\n// ---------------------------------------------------------------------------\n// Event Dispatch\n// ---------------------------------------------------------------------------\n\n/**\n * Dispatch threshold events to configured notification channels.\n */\nasync function dispatchThresholdEvents(\n env: Env,\n sub: string,\n events: ThresholdEvent[],\n config: ThresholdConfig,\n): Promise<void> {\n // Store events in KV for UI display\n const eventsKey = `threshold:events:${sub}`;\n const existingRaw = await env.CARRIER_USERS.get(eventsKey, \"json\").catch(() => null);\n const existing = Array.isArray(existingRaw) ? existingRaw as ThresholdEvent[] : [];\n const allEvents = [...existing, ...events].slice(-50); // Keep last 50 events\n await env.CARRIER_USERS.put(eventsKey, JSON.stringify(allEvents), {\n expirationTtl: 35 * 24 * 60 * 60,\n });\n\n // Webhook dispatch\n if (config.webhook_url) {\n await fetch(config.webhook_url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ events }),\n }).catch(() => {});\n }\n\n // Audit log (Analytics Engine)\n for (const event of events) {\n const ae = (env as Env & { AUDIT_LOG?: { writeDataPoint: (p: unknown) => void } }).AUDIT_LOG;\n if (ae) {\n ae.writeDataPoint({\n blobs: [\n `threshold_${event.type}`,\n sub,\n event.tier,\n ],\n doubles: [event.current_spend_cents, event.threshold_cents],\n indexes: [sub],\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function resolveUserTier(env: Env, sub: string): Promise<Tier> {\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"tier\" in raw) {\n const t = (raw as { tier: string }).tier;\n if (t === \"pro\" || t === \"enterprise\") return t;\n }\n return \"free\";\n}\n","/**\n * Carrier MCP — Pricing & Credits MCP Tools\n *\n * Exposes credit management, billing configuration, and usage analytics\n * as MCP tools. These tools allow AI agents and users to:\n * - Check credit balance and usage\n * - Configure billing thresholds\n * - View volume discount status\n * - Manage overage settings\n * - View billing history and projections\n *\n * Inspired by Stripe Projects CLI patterns:\n * - `stripe projects billing show` → credit_balance\n * - `stripe projects upgrade` → upgrade_plan\n * - `stripe projects billing add` → configure_billing\n */\n\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport {\n checkCredits,\n getCreditSummary,\n updateCreditConfig,\n TIER_CREDIT_ALLOTMENTS,\n SCOPE_CREDIT_COSTS,\n VOLUME_DISCOUNTS,\n DAILY_FREE_CREDITS,\n type CreditConfig,\n} from \"./credits.js\";\nimport {\n getThresholdConfig,\n updateThresholdConfig,\n type ThresholdConfig,\n} from \"./billing-thresholds.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Tool Definitions (for registration in tools.ts)\n// ---------------------------------------------------------------------------\n\nexport interface PricingToolDef {\n name: string;\n description: string;\n scope: ToolScope;\n inputSchema: Record<string, unknown>;\n handler: (\n env: Env,\n props: CarrierProps,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n}\n\nexport const PRICING_TOOLS: PricingToolDef[] = [\n // -------------------------------------------------------------------------\n // credit_balance — View current credit balance and usage\n // -------------------------------------------------------------------------\n {\n name: \"credit_balance\",\n description:\n \"View your current credit balance, daily free credits, overage status, \" +\n \"volume discount tier, and billing threshold status. Use this to understand \" +\n \"your current usage and remaining capacity before making API calls.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const tier = props.tier as Tier;\n const summary = await getCreditSummary(env, props.sub, tier);\n const creditCheck = await checkCredits(env, props.sub, tier, \"read\");\n\n return {\n tier,\n credits: {\n monthly_allotment: summary.ledger.allotment,\n consumed: summary.ledger.consumed,\n remaining: Math.max(0, summary.ledger.allotment - summary.ledger.consumed),\n rollover_applied: summary.ledger.rollover_applied,\n overage_consumed: summary.ledger.overage,\n overage_billed_cents: summary.ledger.overage_billed_cents,\n },\n daily_free: {\n granted: summary.daily_free.granted,\n consumed: summary.daily_free.consumed,\n remaining: Math.max(0, summary.daily_free.granted - summary.daily_free.consumed),\n },\n volume_discount: {\n current_pct: summary.volume_discount_pct,\n next_tier: getNextVolumeDiscountTier(summary.ledger.consumed),\n },\n billing: {\n overages_enabled: summary.config.overages_enabled,\n threshold_triggered: summary.ledger.threshold_triggered,\n billing_threshold_cents: summary.config.billing_threshold_cents,\n overage_rate_cents: summary.config.overage_rate_cents,\n },\n rollover: summary.rollover\n ? {\n credits: summary.rollover.credits,\n source_month: summary.rollover.source_month,\n expires_at: summary.rollover.expires_at,\n }\n : null,\n reset_at: creditCheck.reset_at,\n credit_costs: SCOPE_CREDIT_COSTS,\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // configure_billing — Update billing preferences\n // -------------------------------------------------------------------------\n {\n name: \"configure_billing\",\n description:\n \"Configure your billing preferences: enable/disable overages, set billing \" +\n \"thresholds (bill shock prevention), configure notification percentages, \" +\n \"and set hard spending caps. Pro and Enterprise tiers only.\",\n scope: \"write\",\n inputSchema: {\n type: \"object\",\n properties: {\n overages_enabled: {\n type: \"boolean\",\n description: \"Enable or disable auto-billed overages when monthly credits are exhausted\",\n },\n billing_threshold_cents: {\n type: \"number\",\n description: \"Amount in cents at which an invoice is automatically generated (e.g., 10000 = $100)\",\n },\n hard_cap_cents: {\n type: \"number\",\n description: \"Maximum overage spend in cents before overages are paused (0 = no cap)\",\n },\n auto_pause_on_cap: {\n type: \"boolean\",\n description: \"Whether to automatically pause overages when hard cap is reached\",\n },\n notify_at_pct: {\n type: \"array\",\n items: { type: \"number\" },\n description: \"Percentage thresholds at which to send notifications (e.g., [50, 80, 95, 100])\",\n },\n notification_email: {\n type: \"string\",\n description: \"Email address for billing threshold notifications\",\n },\n webhook_url: {\n type: \"string\",\n description: \"Webhook URL for billing threshold events\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const tier = props.tier as Tier;\n if (tier === \"free\") {\n return {\n error: \"Billing configuration requires Pro or Enterprise tier\",\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n }\n\n // Update credit config\n const creditUpdates: Partial<CreditConfig> = {};\n if (typeof args.overages_enabled === \"boolean\") {\n creditUpdates.overages_enabled = args.overages_enabled;\n }\n if (typeof args.billing_threshold_cents === \"number\") {\n creditUpdates.billing_threshold_cents = args.billing_threshold_cents;\n }\n if (Array.isArray(args.notify_at_pct)) {\n creditUpdates.notify_at_pct = args.notify_at_pct as number[];\n }\n\n const updatedCreditConfig = Object.keys(creditUpdates).length > 0\n ? await updateCreditConfig(env, props.sub, creditUpdates)\n : await getCreditConfigForSub(env, props.sub, tier);\n\n // Update threshold config\n const thresholdUpdates: Partial<ThresholdConfig> = {};\n if (typeof args.hard_cap_cents === \"number\") {\n thresholdUpdates.hard_cap_cents = args.hard_cap_cents;\n }\n if (typeof args.auto_pause_on_cap === \"boolean\") {\n thresholdUpdates.auto_pause_on_cap = args.auto_pause_on_cap;\n }\n if (typeof args.notification_email === \"string\") {\n thresholdUpdates.notification_email = args.notification_email;\n }\n if (typeof args.webhook_url === \"string\") {\n thresholdUpdates.webhook_url = args.webhook_url;\n }\n\n const updatedThresholdConfig = Object.keys(thresholdUpdates).length > 0\n ? await updateThresholdConfig(env, props.sub, thresholdUpdates)\n : await getThresholdConfig(env, props.sub, tier);\n\n return {\n status: \"updated\",\n credit_config: {\n overages_enabled: updatedCreditConfig.overages_enabled,\n billing_threshold_cents: updatedCreditConfig.billing_threshold_cents,\n overage_rate_cents: updatedCreditConfig.overage_rate_cents,\n notify_at_pct: updatedCreditConfig.notify_at_pct,\n },\n threshold_config: {\n hard_cap_cents: updatedThresholdConfig.hard_cap_cents,\n auto_pause_on_cap: updatedThresholdConfig.auto_pause_on_cap,\n invoice_threshold_cents: updatedThresholdConfig.invoice_threshold_cents,\n notification_email: updatedThresholdConfig.notification_email,\n webhook_url: updatedThresholdConfig.webhook_url,\n },\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // usage_projection — Project future usage and costs\n // -------------------------------------------------------------------------\n {\n name: \"usage_projection\",\n description:\n \"Project your credit usage and costs for the remainder of the billing period \" +\n \"based on current consumption rate. Includes overage cost estimates and \" +\n \"recommendations for plan changes.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n days_to_project: {\n type: \"number\",\n description: \"Number of days to project forward (default: remaining days in month)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const tier = props.tier as Tier;\n const summary = await getCreditSummary(env, props.sub, tier);\n\n const now = new Date();\n const dayOfMonth = now.getUTCDate();\n const daysInMonth = new Date(\n now.getUTCFullYear(),\n now.getUTCMonth() + 1,\n 0,\n ).getUTCDate();\n const daysRemaining = typeof args.days_to_project === \"number\"\n ? args.days_to_project\n : daysInMonth - dayOfMonth;\n\n // Calculate daily burn rate\n const dailyBurnRate = dayOfMonth > 0 ? summary.ledger.consumed / dayOfMonth : 0;\n const projectedTotal = Math.round(summary.ledger.consumed + dailyBurnRate * daysRemaining);\n const projectedOverage = Math.max(0, projectedTotal - summary.ledger.allotment);\n\n // Calculate projected overage cost\n const volumeDiscount = getVolumeDiscountForUsage(projectedTotal);\n const effectiveRate = summary.config.overage_rate_cents * (1 - volumeDiscount / 100);\n const projectedOverageCents = Math.round(projectedOverage * effectiveRate);\n\n // Recommendation\n const recommendation = generateRecommendation(\n tier,\n projectedTotal,\n summary.ledger.allotment,\n projectedOverageCents,\n );\n\n return {\n current_period: {\n day_of_month: dayOfMonth,\n days_in_month: daysInMonth,\n days_remaining: daysRemaining,\n },\n usage: {\n consumed_to_date: summary.ledger.consumed,\n daily_burn_rate: Math.round(dailyBurnRate),\n projected_total: projectedTotal,\n allotment: summary.ledger.allotment,\n },\n overage_projection: {\n projected_overage_credits: projectedOverage,\n projected_overage_cents: projectedOverageCents,\n volume_discount_pct: volumeDiscount,\n effective_rate_cents: effectiveRate,\n },\n recommendation,\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // pricing_plans — View available plans and pricing\n // -------------------------------------------------------------------------\n {\n name: \"pricing_plans\",\n description:\n \"View all available Carrier MCP pricing plans with credit allotments, \" +\n \"features, overage rates, and volume discount tiers. Use this to compare \" +\n \"plans and understand upgrade benefits.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (_env, props) => {\n const currentTier = props.tier as Tier;\n\n return {\n current_plan: currentTier,\n plans: [\n {\n id: \"free\",\n name: \"Free\",\n price_monthly_cents: 0,\n credits_monthly: TIER_CREDIT_ALLOTMENTS.free,\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\"],\n features: [\n \"5,000 monthly credits\",\n \"50 daily free credits\",\n \"Read-only OCS access\",\n \"Basic fleet monitoring\",\n ],\n overages: false,\n rollovers: false,\n volume_discounts: false,\n },\n {\n id: \"pro\",\n name: \"Pro\",\n price_monthly_cents: 4_900,\n credits_monthly: TIER_CREDIT_ALLOTMENTS.pro,\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\", \"write\"],\n features: [\n \"100,000 monthly credits\",\n \"50 daily free credits\",\n \"Read + Write OCS access\",\n \"Intelligence composites\",\n \"Auto-billed overages at $0.001/credit\",\n \"Credit rollovers (unused → next month)\",\n \"Volume discounts (up to 25% off overages)\",\n \"Billing thresholds (bill shock prevention)\",\n \"Configurable hard spending caps\",\n \"Priority support\",\n ],\n overages: true,\n rollovers: true,\n volume_discounts: true,\n overage_rate_cents: 0.1,\n },\n {\n id: \"enterprise\",\n name: \"Enterprise\",\n price_monthly_cents: 49_900,\n credits_monthly: \"unlimited\",\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\", \"write\", \"admin\"],\n features: [\n \"Unlimited credits\",\n \"All OCS scopes (incl. admin)\",\n \"Intelligence composites\",\n \"Custom rate limits\",\n \"SSO / SAML\",\n \"Dedicated support\",\n \"SLA guarantee\",\n \"Custom billing terms\",\n ],\n overages: false,\n rollovers: false,\n volume_discounts: false,\n },\n ],\n volume_discount_tiers: VOLUME_DISCOUNTS,\n credit_costs: SCOPE_CREDIT_COSTS,\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // billing_events — View recent billing threshold events\n // -------------------------------------------------------------------------\n {\n name: \"billing_events\",\n description:\n \"View recent billing threshold events: notifications, invoice triggers, \" +\n \"hard cap alerts, and overage pauses. Useful for monitoring spend and \" +\n \"understanding billing activity.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Maximum number of events to return (default: 20, max: 50)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const limit = Math.min(\n typeof args.limit === \"number\" ? args.limit : 20,\n 50,\n );\n\n const eventsKey = `threshold:events:${props.sub}`;\n const raw = await env.CARRIER_USERS.get(eventsKey, \"json\").catch(() => null);\n const events = Array.isArray(raw) ? raw.slice(-limit) : [];\n\n return {\n events,\n total: events.length,\n threshold_config: await getThresholdConfig(env, props.sub, props.tier as Tier),\n };\n },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getNextVolumeDiscountTier(\n consumed: number,\n): { threshold: number; discount_pct: number; credits_until: number } | null {\n for (const tier of VOLUME_DISCOUNTS) {\n if (consumed < tier.threshold) {\n return {\n threshold: tier.threshold,\n discount_pct: tier.discountPct,\n credits_until: tier.threshold - consumed,\n };\n }\n }\n return null; // Already at max discount\n}\n\nfunction getVolumeDiscountForUsage(usage: number): number {\n let discount = 0;\n for (const tier of VOLUME_DISCOUNTS) {\n if (usage >= tier.threshold) {\n discount = tier.discountPct;\n } else {\n break;\n }\n }\n return discount;\n}\n\nfunction generateRecommendation(\n tier: Tier,\n projectedTotal: number,\n allotment: number,\n projectedOverageCents: number,\n): { action: string; reason: string; savings_cents?: number } {\n if (tier === \"free\" && projectedTotal > allotment * 0.8) {\n return {\n action: \"upgrade_to_pro\",\n reason:\n \"You're projected to exceed 80% of your free tier credits. \" +\n \"Pro gives you 100,000 credits/month with overages, rollovers, and volume discounts.\",\n };\n }\n\n if (tier === \"pro\" && projectedOverageCents > 4_900) {\n // Overages exceed the cost of Enterprise\n return {\n action: \"upgrade_to_enterprise\",\n reason:\n \"Your projected overage costs exceed the Enterprise plan price. \" +\n \"Enterprise gives unlimited credits at $499/month.\",\n savings_cents: projectedOverageCents - 4_900 + 4_900, // overage + pro fee vs enterprise\n };\n }\n\n if (tier === \"pro\" && projectedTotal < allotment * 0.3) {\n return {\n action: \"no_change\",\n reason:\n \"You're using less than 30% of your Pro allotment. \" +\n \"Unused credits will roll over to next month (up to 2x your allotment).\",\n };\n }\n\n return {\n action: \"no_change\",\n reason: \"Your current plan is well-suited to your usage pattern.\",\n };\n}\n\nasync function getCreditConfigForSub(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<CreditConfig> {\n const key = `credits:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"billing_threshold_cents\" in raw) {\n return raw as CreditConfig;\n }\n return {\n billing_threshold_cents: 10_000,\n overages_enabled: tier !== \"free\",\n rollovers_enabled: tier !== \"free\",\n overage_rate_cents: 0.1,\n volume_discount_pct: 0,\n notify_at_pct: [50, 80, 95, 100],\n updated_at: new Date().toISOString(),\n };\n}\n","/**\n * Carrier MCP — Projects Tools (Stripe Projects CLI Pattern)\n *\n * Implements the Stripe Projects CLI paradigm for Carrier:\n * - Service catalog browsing (carrier ecosystem services)\n * - Credential vault management (API token rotation, env sync)\n * - Billing management via natural language (upgrade/downgrade)\n * - LLM context generation for AI agent workflows\n * - Multi-environment management (dev/staging/prod)\n *\n * These tools enable AI agents to:\n * 1. Discover and provision Carrier services\n * 2. Manage credentials securely\n * 3. Handle billing operations programmatically\n * 4. Generate context for downstream AI workflows\n *\n * Inspired by: `stripe projects init`, `stripe projects add`, `stripe projects catalog`\n */\n\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport type { Tier } from \"./billing.js\";\nimport { TIER_CREDIT_ALLOTMENTS, SCOPE_CREDIT_COSTS } from \"./credits.js\";\n\n// ---------------------------------------------------------------------------\n// Service Catalog\n// ---------------------------------------------------------------------------\n\nexport interface CarrierService {\n id: string;\n name: string;\n category: string;\n description: string;\n tier_required: Tier;\n scopes_required: string[];\n endpoints: string[];\n docs_url: string;\n}\n\nconst CARRIER_SERVICE_CATALOG: CarrierService[] = [\n {\n id: \"mcp\",\n name: \"Carrier MCP\",\n category: \"connectivity\",\n description: \"Model Context Protocol server — 103 natural-language tools for MVNO/eSIM fleet management\",\n tier_required: \"free\",\n scopes_required: [\"read\"],\n endpoints: [\"https://mcp.carrier.llc/mcp\"],\n docs_url: \"https://mcp.carrier.llc/docs\",\n },\n {\n id: \"api\",\n name: \"Carrier REST API\",\n category: \"connectivity\",\n description: \"RESTful HTTP API for programmatic OCS access — same tool surface as MCP over standard REST\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://api.carrier.llc/v1\"],\n docs_url: \"https://api.carrier.llc/docs\",\n },\n {\n id: \"intelligence\",\n name: \"Carrier Intelligence\",\n category: \"analytics\",\n description: \"AI-powered fleet analytics — churn prediction, usage anomalies, coverage optimization, revenue intelligence\",\n tier_required: \"pro\",\n scopes_required: [\"read\"],\n endpoints: [\"https://mcp.carrier.llc/mcp\"],\n docs_url: \"https://mcp.carrier.llc/docs#intelligence\",\n },\n {\n id: \"connect\",\n name: \"Carrier Connect\",\n category: \"marketplace\",\n description: \"MNO/MVNO network marketplace — browse operators, coverage maps, steering list management\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://app.carrier.llc/connect\"],\n docs_url: \"https://mcp.carrier.llc/docs#connect\",\n },\n {\n id: \"atlas\",\n name: \"Carrier Atlas\",\n category: \"coverage\",\n description: \"Global coverage intelligence — real-time network quality, latency maps, operator benchmarks\",\n tier_required: \"enterprise\",\n scopes_required: [\"read\"],\n endpoints: [\"https://atlas.carrier.llc/api/v1\"],\n docs_url: \"https://atlas.carrier.llc/docs\",\n },\n {\n id: \"billing\",\n name: \"Carrier Billing\",\n category: \"billing\",\n description: \"Operator billing engine — CDR ingestion, invoice generation, Stripe Connect payouts\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://api.carrier.llc/v1/billing\"],\n docs_url: \"https://api.carrier.llc/docs#billing\",\n },\n {\n id: \"webhooks\",\n name: \"Carrier Webhooks\",\n category: \"integration\",\n description: \"Real-time event delivery — OCS events, billing alerts, threshold notifications via HTTP webhooks\",\n tier_required: \"pro\",\n scopes_required: [\"read\"],\n endpoints: [\"https://api.carrier.llc/v1/webhooks\"],\n docs_url: \"https://api.carrier.llc/docs#webhooks\",\n },\n {\n id: \"console\",\n name: \"Carrier Console\",\n category: \"dashboard\",\n description: \"Visual operator dashboard — fleet management, analytics, billing, onboarding for non-technical operators\",\n tier_required: \"free\",\n scopes_required: [\"read\"],\n endpoints: [\"https://app.carrier.llc\"],\n docs_url: \"https://app.carrier.llc/docs\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Tool Definitions\n// ---------------------------------------------------------------------------\n\nexport interface ProjectsToolDef {\n name: string;\n description: string;\n scope: ToolScope;\n inputSchema: Record<string, unknown>;\n handler: (\n env: Env,\n props: CarrierProps,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n}\n\nexport const PROJECTS_TOOLS: ProjectsToolDef[] = [\n // -------------------------------------------------------------------------\n // service_catalog — Browse available Carrier services\n // -------------------------------------------------------------------------\n {\n name: \"service_catalog\",\n description:\n \"Browse the Carrier service catalog — discover available services, their \" +\n \"requirements, endpoints, and documentation. Filter by category or tier. \" +\n \"Similar to `stripe projects catalog`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n category: {\n type: \"string\",\n enum: [\"connectivity\", \"analytics\", \"marketplace\", \"coverage\", \"billing\", \"integration\", \"dashboard\"],\n description: \"Filter services by category\",\n },\n tier: {\n type: \"string\",\n enum: [\"free\", \"pro\", \"enterprise\"],\n description: \"Filter services accessible at this tier level\",\n },\n },\n required: [],\n },\n handler: async (_env, props, args) => {\n let services = [...CARRIER_SERVICE_CATALOG];\n\n if (typeof args.category === \"string\") {\n services = services.filter((s) => s.category === args.category);\n }\n\n if (typeof args.tier === \"string\") {\n const tierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n const maxTier = tierOrder[args.tier] ?? 0;\n services = services.filter(\n (s) => (tierOrder[s.tier_required] ?? 0) <= maxTier,\n );\n }\n\n // Mark which services are accessible with current tier\n const currentTierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n const userTierLevel = currentTierOrder[props.tier] ?? 0;\n\n return {\n services: services.map((s) => ({\n ...s,\n accessible: (currentTierOrder[s.tier_required] ?? 0) <= userTierLevel,\n })),\n total: services.length,\n current_tier: props.tier,\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // credential_status — Check credential health and rotation status\n // -------------------------------------------------------------------------\n {\n name: \"credential_status\",\n description:\n \"Check the health and status of your Carrier credentials — API token validity, \" +\n \"encryption status, last rotation date, and expiry warnings. \" +\n \"Similar to `stripe projects env --pull` status check.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const sub = props.sub;\n const orgId = props.org_id;\n\n // stdio mode has no KV — token comes from env vars.\n if (!env.CARRIER_USERS) {\n return {\n credentials: {\n esimvault_token: {\n present: true,\n encrypted: false,\n last_updated: null,\n age_days: null,\n rotation_recommended: false,\n source: \"env-var (stdio)\",\n },\n oauth: { active: false, method: props.auth_method ?? \"stdio\" },\n },\n environment: {\n org_id: orgId ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n },\n recommendations: [\"stdio mode — token managed via ESIMVAULT_API_TOKEN env var, no rotation tracking\"],\n };\n }\n\n // KV key shape mirrors auth.ts: org:<orgId> or user:clerk_<userId>.\n const primaryKey = orgId ? `org:${orgId}` : `user:clerk_${sub}`;\n const legacyKey = orgId ? null : `user:${sub}`;\n\n let record = await env.CARRIER_USERS.get(primaryKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n if (!record && legacyKey) {\n record = await env.CARRIER_USERS.get(legacyKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n }\n\n const hasToken = !!(record && \"esimvault_token_enc\" in record && record.esimvault_token_enc);\n\n // Check OAuth grant status — guard OAUTH_KV (also absent in stdio)\n const oauthKey = `oauth:grant:${sub}`;\n const oauthGrant = env.OAUTH_KV\n ? await env.OAUTH_KV.get(oauthKey, \"json\").catch(() => null) as Record<string, unknown> | null\n : null;\n\n const updatedAt = record && \"updated_at\" in record\n ? record.updated_at as string\n : null;\n\n // Calculate token age\n let tokenAgeDays: number | null = null;\n if (updatedAt) {\n const updated = new Date(updatedAt);\n tokenAgeDays = Math.floor((Date.now() - updated.getTime()) / (1000 * 60 * 60 * 24));\n }\n\n return {\n credentials: {\n esimvault_token: {\n present: hasToken,\n encrypted: hasToken, // All tokens are AES-256-GCM encrypted\n last_updated: updatedAt,\n age_days: tokenAgeDays,\n rotation_recommended: tokenAgeDays !== null && tokenAgeDays > 90,\n },\n oauth: {\n active: !!oauthGrant,\n method: props.auth_method ?? \"oauth\",\n },\n },\n environment: {\n org_id: orgId ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n },\n recommendations: generateCredentialRecommendations(hasToken, tokenAgeDays),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // rotate_credentials — Initiate credential rotation\n // -------------------------------------------------------------------------\n {\n name: \"rotate_credentials\",\n description:\n \"Initiate rotation of your eSIMVault API credentials. Generates a new \" +\n \"encrypted token and invalidates the old one. Requires write scope. \" +\n \"Similar to `stripe projects rotate <service>`.\",\n scope: \"write\",\n inputSchema: {\n type: \"object\",\n properties: {\n new_token: {\n type: \"string\",\n description: \"New eSIMVault API token to encrypt and store. Get from eSIMVault dashboard.\",\n },\n confirm: {\n type: \"boolean\",\n description: \"Confirm rotation — this will replace the current token immediately\",\n },\n },\n required: [\"new_token\", \"confirm\"],\n },\n handler: async (env, props, args) => {\n if (!args.confirm) {\n return {\n status: \"cancelled\",\n message: \"Rotation cancelled — set confirm: true to proceed\",\n };\n }\n\n const newToken = args.new_token as string;\n if (!newToken || newToken.length < 10) {\n return {\n error: \"Invalid token — must be at least 10 characters\",\n };\n }\n\n // Encrypt the new token\n const encryptionKey = (env as Env & { CARRIER_TOKEN_ENCRYPTION_KEY?: string })\n .CARRIER_TOKEN_ENCRYPTION_KEY;\n if (!encryptionKey) {\n return { error: \"Encryption key not configured — contact support\" };\n }\n\n const encrypted = await encryptToken(newToken, encryptionKey);\n const orgId = props.org_id;\n const recordKey = orgId ? `org:${orgId}` : `user:${props.sub}`;\n\n // Update the record\n const existing = await env.CARRIER_USERS.get(recordKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n if (!existing) {\n return { error: \"User record not found\" };\n }\n\n const updated = {\n ...existing,\n esimvault_token_enc: encrypted,\n updated_at: new Date().toISOString(),\n };\n\n await env.CARRIER_USERS.put(recordKey, JSON.stringify(updated));\n\n return {\n status: \"rotated\",\n message: \"Credentials rotated successfully. New token is active immediately.\",\n encrypted: true,\n rotated_at: new Date().toISOString(),\n next_rotation_recommended: new Date(\n Date.now() + 90 * 24 * 60 * 60 * 1000,\n ).toISOString(),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // llm_context — Generate LLM context for AI agent workflows\n // -------------------------------------------------------------------------\n {\n name: \"llm_context\",\n description:\n \"Generate a comprehensive LLM context document describing your Carrier \" +\n \"environment, available tools, current tier, usage patterns, and best \" +\n \"practices. Designed for AI agents that need to understand your setup. \" +\n \"Similar to `stripe projects llm-context`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n format: {\n type: \"string\",\n enum: [\"markdown\", \"json\", \"yaml\"],\n description: \"Output format for the context document (default: markdown)\",\n },\n include_examples: {\n type: \"boolean\",\n description: \"Include example tool invocations (default: true)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n void env; // used for future expansion\n const format = (args.format as string) ?? \"markdown\";\n const includeExamples = args.include_examples !== false;\n const tier = props.tier as Tier;\n\n // Build context\n const context = {\n project: {\n name: \"Carrier MCP\",\n description: \"Programmable connectivity API control plane for MVNO/eSIM fleet management\",\n version: \"2.0\",\n transport: \"StreamableHTTP\",\n endpoint: \"https://mcp.carrier.llc/mcp\",\n },\n environment: {\n tier,\n scopes: props.scope,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n org_id: props.org_id ?? null,\n auth_method: props.auth_method ?? \"oauth\",\n },\n capabilities: {\n total_tools: 103, // full tool count\n read_tools: 35,\n write_tools: 20,\n admin_tools: 10,\n intelligence_tools: 8,\n pricing_tools: 5,\n projects_tools: 5,\n prompts: 5,\n },\n billing: {\n credits_monthly: TIER_CREDIT_ALLOTMENTS[tier],\n credit_costs: SCOPE_CREDIT_COSTS,\n overages_available: tier !== \"free\",\n volume_discounts_available: tier !== \"free\",\n },\n available_services: CARRIER_SERVICE_CATALOG.filter((s) => {\n const tierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n return (tierOrder[s.tier_required] ?? 0) <= (tierOrder[tier] ?? 0);\n }).map((s) => ({ id: s.id, name: s.name, category: s.category })),\n best_practices: [\n \"Always check credit_balance before batch operations\",\n \"Use intelligence tools for fleet diagnostics before manual investigation\",\n \"Configure billing thresholds to prevent bill shock on overage-enabled plans\",\n \"Rotate credentials every 90 days for security\",\n \"Use carrier_ask when unsure which tool to call\",\n \"Prefer read-scope tools (1 credit) over write-scope (2 credits) when possible\",\n ],\n examples: includeExamples\n ? [\n {\n task: \"Check fleet health\",\n tool: \"fleet_health\",\n description: \"Aggregates eSIM status counts and low-balance accounts\",\n },\n {\n task: \"Diagnose offline subscriber\",\n tool: \"diagnose_subscriber\",\n args: { iccid: \"8944...\" },\n description: \"Chains multiple API calls to analyze connectivity issues\",\n },\n {\n task: \"Check billing status\",\n tool: \"credit_balance\",\n description: \"View current credits, overages, and volume discounts\",\n },\n {\n task: \"Browse available services\",\n tool: \"service_catalog\",\n description: \"Discover Carrier ecosystem services and their requirements\",\n },\n ]\n : [],\n };\n\n if (format === \"json\") {\n return context;\n }\n\n if (format === \"yaml\") {\n return { format: \"yaml\", content: jsonToYaml(context) };\n }\n\n // Markdown format\n return {\n format: \"markdown\",\n content: generateMarkdownContext(context),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // environment_info — View environment configuration\n // -------------------------------------------------------------------------\n {\n name: \"environment_info\",\n description:\n \"View your Carrier environment configuration — active organization, \" +\n \"reseller details, connected services, and deployment environment. \" +\n \"Similar to `stripe projects status`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const sub = props.sub;\n const orgId = props.org_id;\n\n // Get org details if available\n let orgDetails: Record<string, unknown> | null = null;\n if (orgId) {\n orgDetails = await env.CARRIER_USERS.get(`org:${orgId}`, \"json\").catch(() => null) as Record<string, unknown> | null;\n }\n\n // Check connected services\n const hasStripe = !!(await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`));\n const hasWebhook = !!(await env.CARRIER_USERS.get(`webhook_url:${sub}`));\n\n return {\n environment: {\n user_sub: sub,\n org_id: orgId ?? null,\n org_name: orgDetails?.name ?? null,\n org_slug: orgDetails?.slug ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n tier: props.tier,\n scopes: props.scope,\n auth_method: props.auth_method ?? \"oauth\",\n },\n connected_services: {\n esimvault: true, // Always connected (required for operation)\n stripe_billing: hasStripe,\n webhooks: hasWebhook,\n carrier_console: true,\n carrier_api: props.tier !== \"free\",\n },\n endpoints: {\n mcp: \"https://mcp.carrier.llc/mcp\",\n api: \"https://api.carrier.llc/v1\",\n console: \"https://app.carrier.llc\",\n billing_portal: \"https://accounts.carrier.llc/user/billing\",\n },\n configuration: {\n ocs_base_url: \"https://ocs.esimvault.cloud\",\n admin_enabled: props.scope.includes(\"admin\"),\n intelligence_enabled: props.tier !== \"free\",\n },\n };\n },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction generateCredentialRecommendations(\n hasToken: boolean,\n tokenAgeDays: number | null,\n): string[] {\n const recommendations: string[] = [];\n\n if (!hasToken) {\n recommendations.push(\n \"No eSIMVault token configured. Complete setup at https://app.carrier.llc/setup\",\n );\n }\n\n if (tokenAgeDays !== null && tokenAgeDays > 90) {\n recommendations.push(\n `Token is ${tokenAgeDays} days old. Rotate credentials for security (recommended every 90 days).`,\n );\n }\n\n if (tokenAgeDays !== null && tokenAgeDays > 180) {\n recommendations.push(\n \"URGENT: Token is over 180 days old. Immediate rotation strongly recommended.\",\n );\n }\n\n if (recommendations.length === 0) {\n recommendations.push(\"All credentials are healthy. No action needed.\");\n }\n\n return recommendations;\n}\n\nasync function encryptToken(token: string, hexKey: string): Promise<string> {\n const keyBytes = hexToBytes(hexKey);\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const key = await crypto.subtle.importKey(\n \"raw\",\n keyBytes.buffer as ArrayBuffer,\n { name: \"AES-GCM\" },\n false,\n [\"encrypt\"],\n );\n const encoded = new TextEncoder().encode(token);\n const ciphertext = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encoded,\n );\n // Format: base64(iv:ciphertext+tag)\n const combined = new Uint8Array(iv.length + ciphertext.byteLength);\n combined.set(iv, 0);\n combined.set(new Uint8Array(ciphertext), iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);\n }\n return bytes;\n}\n\nfunction jsonToYaml(obj: unknown, indent = 0): string {\n const spaces = \" \".repeat(indent);\n if (obj === null || obj === undefined) return `${spaces}null`;\n if (typeof obj === \"string\") return `${spaces}${obj}`;\n if (typeof obj === \"number\" || typeof obj === \"boolean\") return `${spaces}${obj}`;\n if (Array.isArray(obj)) {\n return obj.map((item) => `${spaces}- ${typeof item === \"object\" ? \"\\n\" + jsonToYaml(item, indent + 1) : item}`).join(\"\\n\");\n }\n if (typeof obj === \"object\") {\n return Object.entries(obj as Record<string, unknown>)\n .map(([key, val]) => {\n if (typeof val === \"object\" && val !== null) {\n return `${spaces}${key}:\\n${jsonToYaml(val, indent + 1)}`;\n }\n return `${spaces}${key}: ${val}`;\n })\n .join(\"\\n\");\n }\n return String(obj);\n}\n\nfunction generateMarkdownContext(context: Record<string, unknown>): string {\n const proj = context.project as Record<string, unknown>;\n const envInfo = context.environment as Record<string, unknown>;\n const caps = context.capabilities as Record<string, unknown>;\n const billing = context.billing as Record<string, unknown>;\n const practices = context.best_practices as string[];\n\n return `# Carrier MCP — LLM Context\n\n## Project\n- **Name:** ${proj.name}\n- **Description:** ${proj.description}\n- **Version:** ${proj.version}\n- **Transport:** ${proj.transport}\n- **Endpoint:** ${proj.endpoint}\n\n## Environment\n- **Tier:** ${envInfo.tier}\n- **Scopes:** ${(envInfo.scopes as string[]).join(\", \")}\n- **Reseller:** ${envInfo.reseller_name} (ID: ${envInfo.reseller_id})\n- **Auth:** ${envInfo.auth_method}\n\n## Capabilities\n- Total tools: ${caps.total_tools}\n- Read: ${caps.read_tools} | Write: ${caps.write_tools} | Admin: ${caps.admin_tools}\n- Intelligence: ${caps.intelligence_tools} | Pricing: ${caps.pricing_tools} | Projects: ${caps.projects_tools}\n- Prompts: ${caps.prompts}\n\n## Billing\n- Monthly credits: ${billing.credits_monthly}\n- Credit costs: read=1, write=2, admin=5, intelligence=3\n- Overages: ${billing.overages_available ? \"enabled\" : \"disabled\"}\n- Volume discounts: ${billing.volume_discounts_available ? \"available\" : \"not available\"}\n\n## Best Practices\n${practices.map((p) => `- ${p}`).join(\"\\n\")}\n`;\n}\n","/**\n * Carrier MCP — Manus Scheduled Tasks + Usage Telemetry tools (v1.0.0).\n *\n * NEW TOOLS:\n * ui_agent_schedule_create — create a recurring Manus agent run (cron-based)\n * ui_agent_schedule_list — list the caller's schedules\n * ui_agent_schedule_delete — delete a schedule by ID\n * ui_agent_schedule_pause — pause a schedule\n * ui_agent_schedule_resume — resume a paused schedule\n * ui_agent_usage — current month spend + remaining credits (60s KV cache)\n *\n * SCOPE GATES:\n * - schedule_create / delete / pause / resume: admin only\n * - schedule_list / usage: read\n *\n * CRON SAFETY:\n * - Minimum interval: 5 minutes (rejects * * * * * and sub-5-min step/list expressions)\n *\n * AUDIT:\n * - Every mutating call writes an AE row.\n * - ui_agent_usage emits threshold events when remaining_credits < 1000 (warning) or < 100 (critical).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport {\n createSchedule,\n listSchedules,\n deleteSchedule,\n pauseSchedule,\n resumeSchedule,\n validateCron,\n ManusScheduleError,\n} from \"./manus-schedule.js\";\nimport { getUsage, emitUsageThresholdIfNeeded } from \"./manus-usage.js\";\n\n/** Doc + registry merge — keep aligned with scope checks in registerScheduleAndUsageTools. */\nexport const UI_AGENT_SCHEDULE_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_agent_schedule_create: \"admin\",\n ui_agent_schedule_list: \"read\",\n ui_agent_schedule_delete: \"admin\",\n ui_agent_schedule_pause: \"admin\",\n ui_agent_schedule_resume: \"admin\",\n ui_agent_usage: \"read\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nfunction noManusKeyError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message:\n \"MANUS_API_KEY is not configured on this Carrier MCP deployment. \" +\n \"Schedule and usage tools require a Manus API key. \" +\n \"Contact your Carrier MCP administrator.\",\n }),\n },\n ],\n };\n}\n\nfunction scopeError(toolName: string, required: string, actual: string[]): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: tool '${toolName}' requires '${required}' scope. Your token has: [${actual.join(\", \")}].`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\n\nexport function registerScheduleAndUsageTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // ui_agent_schedule_create\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_create\",\n {\n title: \"Create Manus Schedule (UI Agent)\",\n description:\n \"Creates a recurring Manus agent run on a cron schedule. \" +\n \"Use this to automate periodic OCS audits, fleet health checks, or any recurring \" +\n \"browser-automation task. Minimum interval: 5 minutes (*/1, */2, */3, */4 and '* * * * *' are rejected). \" +\n \"Requires admin scope. Returns schedule_id.\",\n inputSchema: {\n name: z.string().describe(\"Human-readable name for this schedule\"),\n cron: z\n .string()\n .describe(\n \"Standard 5-field cron expression (minute hour day month weekday). \" +\n \"Minimum interval: 5 minutes. Example: '0 */6 * * *' = every 6 hours.\",\n ),\n prompt_template: z\n .string()\n .describe(\"Agent prompt/task template the Manus agent will execute on each run\"),\n profile: z\n .string()\n .optional()\n .describe(\"Manus agent profile to use. Defaults to 'manus-1.6-lite'.\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_create\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n const cronError = validateCron(args.cron);\n if (cronError) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: \"invalid_cron\", message: cronError }) }],\n };\n }\n\n try {\n const result = await createSchedule(ctx.env.MANUS_API_KEY, {\n name: args.name,\n cron: args.cron,\n prompt_template: args.prompt_template,\n agent_profile: args.profile,\n });\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok || !result.schedule_id) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_create_failed\",\n message: result.error?.message ?? \"Manus schedule.create returned ok=false\",\n code: result.error?.code,\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"created\",\n schedule_id: result.schedule_id,\n name: args.name,\n cron: args.cron,\n }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_list\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_list\",\n {\n title: \"List Manus Schedules\",\n description:\n \"Lists all Manus recurring schedules configured for this API key. \" +\n \"Returns schedule IDs, names, cron expressions, status (active/paused), \" +\n \"and next/last run timestamps.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"read\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_list\", \"read\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await listSchedules(ctx.env.MANUS_API_KEY);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_list_failed\",\n message: result.error?.message ?? \"Manus schedule.list returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ schedules: result.schedules ?? [] }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_delete\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_delete\",\n {\n title: \"Delete Manus Schedule\",\n description:\n \"Permanently deletes a Manus recurring schedule. \" +\n \"This cannot be undone. Use ui_agent_schedule_pause to temporarily suspend instead. \" +\n \"Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to delete\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_delete\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await deleteSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_delete_failed\",\n message: result.error?.message ?? \"Manus schedule.delete returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"deleted\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_pause\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_pause\",\n {\n title: \"Pause Manus Schedule\",\n description:\n \"Pauses an active Manus recurring schedule. The schedule is preserved and can be \" +\n \"resumed later with ui_agent_schedule_resume. Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to pause\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_pause\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await pauseSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_pause_failed\",\n message: result.error?.message ?? \"Manus schedule.pause returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"paused\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_resume\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_resume\",\n {\n title: \"Resume Manus Schedule\",\n description:\n \"Resumes a paused Manus recurring schedule. Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to resume\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_resume\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await resumeSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_resume_failed\",\n message: result.error?.message ?? \"Manus schedule.resume returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"active\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_usage\n // =========================================================================\n server.registerTool(\n \"ui_agent_usage\",\n {\n title: \"Manus Usage & Credits\",\n description:\n \"Returns current month Manus credit spend, remaining balance, and task count. \" +\n \"Result is cached for 60 seconds in KV to avoid rate-limiting the Manus API. \" +\n \"Emits an Analytics Engine event when remaining_credits drops below 1000 (warning) \" +\n \"or 100 (critical). Use this to track Carrier's Manus credit burn.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"read\")) {\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_usage\", \"read\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const { data, from_cache } = await getUsage(ctx.env.MANUS_API_KEY, ctx.env);\n\n // Emit threshold AE event if needed (fire-and-forget)\n emitUsageThresholdIfNeeded(ctx.env, data);\n\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ ...data, from_cache }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n const msg = err instanceof Error ? err.message : String(err);\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n}\n","/**\n * Shared Manus HTTP API v2 base URL (dot-notation routes appended, e.g. /usage.get).\n */\nexport const MANUS_API_BASE = \"https://api.manus.ai/v2\";\n","/**\n * Manus Schedule API v2 client.\n *\n * Endpoints (Manus open.manus.ai/docs/v2 dot-notation pattern):\n * POST /v2/schedule.create — create a recurring scheduled agent run\n * GET /v2/schedule.list — list all schedules for this API key\n * POST /v2/schedule.delete — delete a schedule by ID\n * POST /v2/schedule.pause — pause a schedule\n * POST /v2/schedule.resume — resume a paused schedule\n *\n * Auth: `x-manus-api-key` header (same pattern as task.create).\n */\n\nimport { MANUS_API_BASE } from \"./manus-common.js\";\n\n// ---------------------------------------------------------------------------\n// Domain types\n// ---------------------------------------------------------------------------\n\nexport interface ManusSchedule {\n schedule_id: string;\n name: string;\n cron: string;\n status: \"active\" | \"paused\" | string;\n agent_profile?: string;\n prompt_template: string;\n created_at?: string;\n updated_at?: string;\n last_run_at?: string;\n next_run_at?: string;\n}\n\nexport interface ManusScheduleCreateResult {\n ok: boolean;\n schedule_id?: string;\n error?: { code: string; message: string };\n}\n\nexport interface ManusScheduleListResult {\n ok: boolean;\n schedules?: ManusSchedule[];\n error?: { code: string; message: string };\n}\n\nexport interface ManusScheduleActionResult {\n ok: boolean;\n error?: { code: string; message: string };\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class ManusScheduleError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n ) {\n super(message);\n this.name = \"ManusScheduleError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cron validation\n// Minimum interval: 5 minutes. Expands the minute field (lists, ranges,\n// steps, */N) and rejects if any adjacent firing gap (including wrap) is < 5.\n// ---------------------------------------------------------------------------\n\n/**\n * Expands the minute field into sorted unique minutes 0–59, or null if unsupported.\n */\nfunction expandCronMinuteField(minuteField: string): number[] | null {\n if (minuteField === \"*\" || minuteField.includes(\" \")) {\n return null;\n }\n\n const tokens = minuteField.split(\",\").map((t) => t.trim()).filter(Boolean);\n const set = new Set<number>();\n\n for (const token of tokens) {\n const stepWildcard = /^[*]\\/(\\d+)$/.exec(token);\n if (stepWildcard) {\n const step = parseInt(stepWildcard[1] ?? \"0\", 10);\n if (step < 1) return null;\n for (let m = 0; m < 60; m += step) set.add(m);\n continue;\n }\n\n const rangeWithStep = /^(\\d+)-(\\d+)\\/(\\d+)$/.exec(token);\n if (rangeWithStep) {\n const start = parseInt(rangeWithStep[1] ?? \"0\", 10);\n const end = parseInt(rangeWithStep[2] ?? \"0\", 10);\n const step = parseInt(rangeWithStep[3] ?? \"0\", 10);\n if (step < 1 || start > end) return null;\n for (let m = start; m <= end; m += step) set.add(m);\n continue;\n }\n\n const rangeOnly = /^(\\d+)-(\\d+)$/.exec(token);\n if (rangeOnly) {\n const start = parseInt(rangeOnly[1] ?? \"0\", 10);\n const end = parseInt(rangeOnly[2] ?? \"0\", 10);\n if (start > end) return null;\n for (let m = start; m <= end; m++) set.add(m);\n continue;\n }\n\n const single = /^(\\d+)$/.exec(token);\n if (single) {\n set.add(parseInt(single[1] ?? \"0\", 10));\n continue;\n }\n\n return null;\n }\n\n const arr = Array.from(set).sort((a, b) => a - b);\n for (const v of arr) {\n if (v < 0 || v > 59) return null;\n }\n return arr;\n}\n\nfunction minuteFieldViolatesFiveMinuteRule(\n minuteField: string,\n fullCron: string,\n): string | null {\n const minutes = expandCronMinuteField(minuteField);\n if (minutes === null) {\n return (\n `Cron expression rejected: unrecognized or unsupported minute field '${minuteField}'. ` +\n \"Minimum interval is 5 minutes; use lists, ranges with step ≥ 5, or */5 or higher.\"\n );\n }\n if (minutes.length === 0) {\n return `Cron expression rejected: minute field '${minuteField}' expands to no valid minutes.`;\n }\n if (minutes.length === 1) {\n return null;\n }\n\n for (let i = 1; i < minutes.length; i++) {\n const gap = (minutes[i] ?? 0) - (minutes[i - 1] ?? 0);\n if (gap < 5) {\n return (\n `Cron expression rejected: '${fullCron}' implies a ${gap}-minute gap in the minute field. ` +\n \"Minimum allowed interval is 5 minutes.\"\n );\n }\n }\n\n const wrapGap = 60 - (minutes[minutes.length - 1] ?? 0) + (minutes[0] ?? 0);\n if (wrapGap < 5) {\n return (\n `Cron expression rejected: '${fullCron}' implies a ${wrapGap}-minute wraparound gap in the minute field. ` +\n \"Minimum allowed interval is 5 minutes.\"\n );\n }\n\n return null;\n}\n\n/**\n * Returns an error string if the cron expression is invalid or too frequent,\n * or null if it's acceptable.\n *\n * Rules:\n * - Must have exactly 5 fields (standard cron, no seconds).\n * - Minute field must not be `*` (would run every minute).\n * - The minute field is expanded (including star/N steps, a-b ranges, a-b/c\n * range-steps, and comma unions); every gap between consecutive runs within\n * the hour, and the wrap gap to the next hour, must be at least 5 minutes.\n */\nexport function validateCron(cron: string): string | null {\n const parts = cron.trim().split(/\\s+/);\n if (parts.length !== 5) {\n return `Invalid cron expression: expected 5 fields (minute hour day month weekday), got ${parts.length}.`;\n }\n\n const [minuteField] = parts;\n\n if (minuteField === \"*\") {\n return \"Cron expression rejected: '* * * * *' runs every minute. Minimum allowed interval is 5 minutes.\";\n }\n\n return minuteFieldViolatesFiveMinuteRule(minuteField ?? \"\", cron);\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nexport async function createSchedule(\n apiKey: string,\n params: {\n name: string;\n cron: string;\n prompt_template: string;\n agent_profile?: string;\n },\n): Promise<ManusScheduleCreateResult> {\n const body: Record<string, unknown> = {\n name: params.name,\n cron: params.cron,\n prompt_template: params.prompt_template,\n agent_profile: params.agent_profile ?? \"manus-1.6-lite\",\n interactive_mode: false,\n hide_in_task_list: false,\n };\n\n const res = await fetch(`${MANUS_API_BASE}/schedule.create`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.create failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleCreateResult;\n}\n\nexport async function listSchedules(\n apiKey: string,\n): Promise<ManusScheduleListResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.list`, {\n headers: { \"x-manus-api-key\": apiKey },\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.list failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n const data = (await res.json()) as ManusScheduleListResult | ManusSchedule[];\n // Manus may return a bare array or a wrapped object\n if (Array.isArray(data)) {\n return { ok: true, schedules: data };\n }\n return data;\n}\n\nexport async function deleteSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.delete`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.delete failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n\nexport async function pauseSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.pause`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.pause failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n\nexport async function resumeSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.resume`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.resume failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n","/**\n * Manus Usage/Credits API v2 client.\n *\n * Endpoints (open.manus.ai/docs/v2 dot-notation pattern):\n * GET /v2/usage.get — current month's task count + credit spend\n * GET /v2/credits.get — remaining credit balance\n *\n * KV cache key: `manus_usage_cache` — 60-second TTL.\n *\n * Threshold events emitted to Analytics Engine (AUDIT_LOG):\n * remaining_credits < 1000 → warning\n * remaining_credits < 100 → critical\n */\n\nimport { MANUS_API_BASE } from \"./manus-common.js\";\nimport type { Env } from \"./types.js\";\n\nexport class ManusUsageError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n ) {\n super(message);\n this.name = \"ManusUsageError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain types\n// ---------------------------------------------------------------------------\n\nexport interface ManusUsageData {\n month: string; // \"YYYY-MM\"\n spent_credits: number;\n remaining_credits: number;\n task_count: number;\n}\n\ninterface ManusUsageApiResponse {\n ok?: boolean;\n month?: string;\n spent_credits?: number;\n credits_used?: number; // alternate key some endpoints use\n remaining_credits?: number;\n credits_remaining?: number;\n task_count?: number;\n tasks_run?: number;\n error?: { code: string; message: string };\n}\n\ninterface ManusCreditsApiResponse {\n ok?: boolean;\n remaining_credits?: number;\n credits_remaining?: number;\n balance?: number;\n error?: { code: string; message: string };\n}\n\n// ---------------------------------------------------------------------------\n// KV cache\n// ---------------------------------------------------------------------------\n\nconst CACHE_KEY = \"manus_usage_cache\";\nconst CACHE_TTL_SECONDS = 60;\n\ninterface CachedUsage {\n data: ManusUsageData;\n fetched_at: number; // epoch ms\n}\n\n// ---------------------------------------------------------------------------\n// Threshold constants\n// ---------------------------------------------------------------------------\n\nexport const USAGE_THRESHOLD_WARNING = 1000;\nexport const USAGE_THRESHOLD_CRITICAL = 100;\n\n// ---------------------------------------------------------------------------\n// Fetch from Manus API\n// ---------------------------------------------------------------------------\n\nasync function fetchUsageFromApi(apiKey: string): Promise<ManusUsageData> {\n const now = new Date();\n const month = `${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n\n // Fetch usage + credits in parallel\n const [usageRes, creditsRes] = await Promise.all([\n fetch(`${MANUS_API_BASE}/usage.get`, {\n headers: { \"x-manus-api-key\": apiKey },\n }),\n fetch(`${MANUS_API_BASE}/credits.get`, {\n headers: { \"x-manus-api-key\": apiKey },\n }),\n ]);\n\n if (!usageRes.ok && !creditsRes.ok) {\n throw new ManusUsageError(\n `Manus usage APIs failed: usage.get HTTP ${usageRes.status}, credits.get HTTP ${creditsRes.status}`,\n Math.max(usageRes.status, creditsRes.status),\n );\n }\n\n let spentCredits = 0;\n let remainingCredits = 0;\n let taskCount = 0;\n\n if (usageRes.ok) {\n const usageData = (await usageRes.json()) as ManusUsageApiResponse;\n spentCredits = usageData.spent_credits ?? usageData.credits_used ?? 0;\n taskCount = usageData.task_count ?? usageData.tasks_run ?? 0;\n // usage.get may also return remaining_credits\n if (usageData.remaining_credits !== undefined || usageData.credits_remaining !== undefined) {\n remainingCredits = usageData.remaining_credits ?? usageData.credits_remaining ?? 0;\n }\n }\n\n if (creditsRes.ok) {\n const creditsData = (await creditsRes.json()) as ManusCreditsApiResponse;\n // credits.get is the authoritative source for remaining balance\n const fromCreditsApi =\n creditsData.remaining_credits ??\n creditsData.credits_remaining ??\n creditsData.balance;\n if (fromCreditsApi !== undefined) {\n remainingCredits = fromCreditsApi;\n }\n }\n\n return { month, spent_credits: spentCredits, remaining_credits: remainingCredits, task_count: taskCount };\n}\n\n// ---------------------------------------------------------------------------\n// Public: getUsage — with KV cache\n// ---------------------------------------------------------------------------\n\nexport async function getUsage(\n apiKey: string,\n env: Env,\n): Promise<{ data: ManusUsageData; from_cache: boolean }> {\n // Check KV cache\n const cached = await env.CARRIER_USERS.get<CachedUsage>(CACHE_KEY, \"json\");\n const nowMs = Date.now();\n\n if (cached && nowMs - cached.fetched_at < CACHE_TTL_SECONDS * 1000) {\n return { data: cached.data, from_cache: true };\n }\n\n // Fetch fresh data\n const data = await fetchUsageFromApi(apiKey);\n\n // Write to KV with TTL\n await env.CARRIER_USERS.put(\n CACHE_KEY,\n JSON.stringify({ data, fetched_at: nowMs } satisfies CachedUsage),\n { expirationTtl: CACHE_TTL_SECONDS },\n );\n\n return { data, from_cache: false };\n}\n\n// ---------------------------------------------------------------------------\n// Threshold check — emits AE events on warning/critical\n// ---------------------------------------------------------------------------\n\nexport function emitUsageThresholdIfNeeded(\n env: Env,\n data: ManusUsageData,\n): void {\n const { remaining_credits, month, task_count } = data;\n\n if (remaining_credits < USAGE_THRESHOLD_CRITICAL) {\n writeUsageThresholdAudit(env, \"critical\", remaining_credits, month, task_count);\n } else if (remaining_credits < USAGE_THRESHOLD_WARNING) {\n writeUsageThresholdAudit(env, \"warning\", remaining_credits, month, task_count);\n }\n}\n\nfunction writeUsageThresholdAudit(\n env: Env,\n severity: \"warning\" | \"critical\",\n remainingCredits: number,\n month: string,\n taskCount: number,\n): void {\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_usage_threshold\",\n severity,\n month,\n String(taskCount),\n ],\n doubles: [remainingCredits],\n indexes: [\"manus_usage\"],\n });\n } catch (err) {\n console.error(`[manus-usage] threshold audit write failed: ${(err as Error).message}`);\n }\n}\n","/**\n * Carrier MCP — UI-Agent tools (v1.1.1).\n *\n * These tools handle OCS operations that are NOT exposed via the OCS REST API\n * (confirmed by NOC/Bridge4IP on 2026-05-13). Instead of calling OCS JSON-RPC,\n * they spawn a Manus \"lite\" agent that drives the OCS web dashboard via browser\n * automation to complete the operation.\n *\n * Gap IDs covered:\n * G-01 createSteeringList — create a new steering list\n * G-02 buildSteeringList — add/remove operators in a steering list\n * G-03 setSteeringListOnAccount — assign steering list at account level\n * G-05 createAccount — create a new reseller sub-account\n * G-12 destination list CRUD — create/edit/delete destination lists\n * G-18 deletePackageTemplate — delete a package template\n * G-19 editLocationZone/deleteLocationZone — edit or delete location zones\n *\n * AUTH FLOW:\n * OCS portal credentials are stored in Clerk privateMetadata (org or user level).\n * At dispatch time, getOcsPortalCredentials() reads them via the Clerk Backend API.\n * Credentials are passed to the Manus agent prompt — the agent uses them to log\n * into the OCS dashboard before performing the requested operation.\n *\n * MANUS API:\n * Uses v2 task.create with agent_profile \"manus-1.6-lite\", hide_in_task_list true,\n * and structured_output_schema to extract a typed result from the agent's work.\n *\n * SAFETY:\n * - All UI-agent tools require \"write\" or \"admin\" scope.\n * - Destructive operations support dry_run (returns the prompt without dispatching).\n * - Audit log records ui_agent_dispatched status + Manus task_id.\n * - Credentials are never logged or returned in tool output.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport { getOcsPortalCredentials } from \"./clerk.js\";\nimport { MANUS_API_BASE } from \"./manus-common.js\";\n\n// ---------------------------------------------------------------------------\n// Manus API v2 client\n// ---------------------------------------------------------------------------\n\ninterface ManusTaskResult {\n ok: boolean;\n task_id?: string;\n task_url?: string;\n error?: { code: string; message: string };\n}\n\nasync function createManusTask(\n apiKey: string,\n prompt: string,\n title: string,\n outputSchema?: Record<string, unknown>,\n): Promise<ManusTaskResult> {\n const body: Record<string, unknown> = {\n message: { content: prompt },\n agent_profile: \"manus-1.6-lite\",\n hide_in_task_list: true,\n interactive_mode: false,\n title,\n };\n if (outputSchema) {\n body.structured_output_schema = outputSchema;\n }\n\n const res = await fetch(`${MANUS_API_BASE}/task.create`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n return (await res.json()) as ManusTaskResult;\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nconst OCS_DASHBOARD_DEFAULT = \"https://ocs.esimvault.cloud\";\n\nfunction noCredentialsError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"ocs_portal_not_linked\",\n message:\n \"OCS portal credentials are not configured. An organisation admin must link their OCS portal \" +\n \"login via the Carrier Console settings page (Organisation Profile → OCS Portal) before \" +\n \"UI-agent operations can be dispatched.\",\n action: \"Navigate to https://console.carrier.llc/settings and link your OCS portal credentials.\",\n }),\n },\n ],\n };\n}\n\nfunction noManusKeyError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message:\n \"MANUS_API_KEY is not configured on this Carrier MCP deployment. \" +\n \"UI-agent tools require a Manus API key to spawn browser automation agents. \" +\n \"Contact your Carrier MCP administrator.\",\n }),\n },\n ],\n };\n}\n\nfunction buildLoginPreamble(dashboardUrl: string): string {\n return (\n `STEP 1 — LOGIN:\\n` +\n `Navigate to ${dashboardUrl}/login (or the main page if no /login path).\\n` +\n `Enter the OCS portal username and password provided below.\\n` +\n `Wait for the dashboard to fully load after login.\\n` +\n `If already logged in (session cookie persists), skip to STEP 2.\\n\\n`\n );\n}\n\n/**\n * Common structured output schema for UI-agent results.\n */\nconst UI_AGENT_RESULT_SCHEMA = {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", description: \"Whether the operation completed successfully\" },\n summary: { type: \"string\", description: \"Human-readable summary of what was done\" },\n entity_id: { type: \"string\", description: \"ID of the created/modified entity (if applicable)\" },\n error_message: { type: \"string\", description: \"Error description if the operation failed\" },\n screenshots_taken: { type: \"number\", description: \"Number of screenshots captured during the operation\" },\n },\n required: [\"success\", \"summary\"],\n};\n\n// ---------------------------------------------------------------------------\n// UI-Agent tool wrapper — scope enforcement + Clerk creds + Manus dispatch\n// ---------------------------------------------------------------------------\nfunction wrapUiAgentHandler(\n toolName: string,\n gapId: string,\n requiredScope: ToolScope,\n ctx: ToolContext,\n buildPrompt: (args: Record<string, unknown>, dashboardUrl: string) => string,\n) {\n return async (args: Record<string, unknown> & { dry_run?: boolean }): Promise<ToolResult> => {\n const start = Date.now();\n const isDryRun = args.dry_run === true;\n\n // Scope enforcement\n if (!ctx.props.scope.includes(requiredScope)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: tool '${toolName}' requires '${requiredScope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Check Manus API key\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n // Resolve OCS portal credentials from Clerk privateMetadata\n const clerkUserId = ctx.props.sub.startsWith(\"clerk_\")\n ? ctx.props.sub.slice(6) // strip \"clerk_\" prefix\n : undefined;\n const creds = await getOcsPortalCredentials(ctx.env, ctx.props.org_id, clerkUserId);\n if (!creds) {\n return noCredentialsError();\n }\n\n const dashboardUrl = ctx.env.OCS_DASHBOARD_URL ?? OCS_DASHBOARD_DEFAULT;\n const prompt = buildPrompt(args, dashboardUrl);\n\n // Inject login credentials into the prompt (never logged/returned)\n const fullPrompt =\n `You are a Carrier MCP UI automation agent. Your task is to perform an OCS dashboard operation ` +\n `that is not available via the OCS REST API.\\n\\n` +\n `OCS PORTAL CREDENTIALS (use these to log in — NEVER include them in your output):\\n` +\n ` Username: ${creds.username}\\n` +\n ` Password: ${creds.password}\\n\\n` +\n buildLoginPreamble(dashboardUrl) +\n `STEP 2 — OPERATION:\\n` +\n prompt +\n `\\n\\nSTEP 3 — VERIFICATION:\\n` +\n `After completing the operation, verify the result by checking the dashboard shows the expected state.\\n` +\n `Take a screenshot of the final state for audit purposes.\\n` +\n `Report success or failure with a clear summary.`;\n\n // Dry-run: return the prompt (with credentials redacted) without dispatching\n if (isDryRun) {\n const redactedPrompt = fullPrompt\n .replaceAll(creds.password, \"***REDACTED***\")\n .replaceAll(creds.username, \"***REDACTED***\");\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"dry_run\",\n dry_run: true,\n duration_ms: 0,\n event_type: \"ui_agent_dispatch\",\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n dry_run: true,\n tool: toolName,\n gap_id: gapId,\n agent_prompt_preview: redactedPrompt,\n note: \"No Manus agent was dispatched. Set dry_run=false to execute.\",\n }, null, 2),\n },\n ],\n };\n }\n\n // Dispatch Manus task\n try {\n const result = await createManusTask(\n ctx.env.MANUS_API_KEY,\n fullPrompt,\n `Carrier MCP UI Agent: ${toolName} (${gapId})`,\n UI_AGENT_RESULT_SCHEMA,\n );\n\n if (!result.ok || !result.task_id) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_dispatch_failed\",\n message: result.error?.message ?? \"Failed to create Manus task\",\n code: result.error?.code,\n }),\n },\n ],\n };\n }\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"ui_agent_dispatched\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n manus_task_id: result.task_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"ui_agent_dispatched\",\n tool: toolName,\n gap_id: gapId,\n manus_task_id: result.task_id,\n manus_task_url: result.task_url,\n note:\n \"A Manus browser automation agent has been dispatched to perform this operation \" +\n \"on the OCS web dashboard. The agent will log in, execute the operation, and verify \" +\n \"the result. You can track progress at the task URL above. \" +\n \"Real-time completion updates arrive via webhook and are recorded in the audit log. \" +\n \"The poll_endpoint below is provided for backward compatibility.\",\n webhook_status: \"active\",\n poll_endpoint: `GET ${MANUS_API_BASE}/task.listMessages?task_id=${result.task_id}&order=desc&limit=5`,\n }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error dispatching UI agent: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Scope + destructive metadata for UI-agent tools\n// ---------------------------------------------------------------------------\nexport const UI_AGENT_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_create_steering_list: \"write\",\n ui_build_steering_list: \"write\",\n ui_set_account_steering_list: \"write\",\n ui_create_account: \"admin\",\n ui_create_destination_list: \"write\",\n ui_edit_destination_list: \"write\",\n ui_delete_destination_list: \"admin\",\n ui_delete_package_template: \"admin\",\n ui_edit_location_zone: \"write\",\n ui_delete_location_zone: \"admin\",\n};\n\nexport const UI_AGENT_DESTRUCTIVE_TOOLS = new Set([\n \"ui_create_steering_list\",\n \"ui_build_steering_list\",\n \"ui_set_account_steering_list\",\n \"ui_create_account\",\n \"ui_create_destination_list\",\n \"ui_edit_destination_list\",\n \"ui_delete_destination_list\",\n \"ui_delete_package_template\",\n \"ui_edit_location_zone\",\n \"ui_delete_location_zone\",\n]);\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\nexport function registerAllUiAgentTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // G-01: ui_create_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_create_steering_list\",\n {\n title: \"Create Steering List (UI Agent)\",\n description:\n \"Creates a new network steering list (OPLMN preference configuration) via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. A Manus browser agent will be dispatched \" +\n \"to perform the operation. Params: `name` (steering list name), `description` (optional). \" +\n \"Returns: dispatch confirmation with Manus task ID for tracking.\",\n inputSchema: {\n name: z.string().describe(\"Name for the new steering list\"),\n description: z.string().optional().describe(\"Optional description for the steering list\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_steering_list\", \"G-01\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Steering Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new steering list with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n `Click the \"Create\" or \"Add\" button to create the steering list.\\n` +\n `After creation, note the new steering list ID from the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-02: ui_build_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_build_steering_list\",\n {\n title: \"Build Steering List (UI Agent)\",\n description:\n \"Adds or removes operators (MCC-MNC) from an existing steering list via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. Params: `steering_list_id`, \" +\n \"`add_operators` (array of MCC-MNC to add), `remove_operators` (array to remove), \" +\n \"`operator_type` ('priority' or 'excluded').\",\n inputSchema: {\n steering_list_id: z.number().describe(\"ID of the steering list to modify\"),\n add_operators: z.array(z.string()).optional().describe(\"MCC-MNC codes to add (e.g. ['20801', '26201'])\"),\n remove_operators: z.array(z.string()).optional().describe(\"MCC-MNC codes to remove\"),\n operator_type: z.enum([\"priority\", \"excluded\"]).default(\"priority\").describe(\"Whether operators are priority or excluded\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_build_steering_list\", \"G-02\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Steering Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open steering list ID ${args.steering_list_id} for editing.\\n` +\n `Operator type: ${args.operator_type ?? \"priority\"}\\n` +\n (args.add_operators && (args.add_operators as string[]).length > 0\n ? `Add the following operators: ${(args.add_operators as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_operators && (args.remove_operators as string[]).length > 0\n ? `Remove the following operators: ${(args.remove_operators as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated operator list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-03: ui_set_account_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_set_account_steering_list\",\n {\n title: \"Set Account Steering List (UI Agent)\",\n description:\n \"Assigns or removes a steering list at the account level via the OCS web dashboard. \" +\n \"The subscriber-level counterpart `modify_subscriber_steering_list` is available via API; \" +\n \"this account-level operation is UI-only. Params: `account_id`, `steering_list_id` (0 to remove).\",\n inputSchema: {\n account_id: z.number().describe(\"Account ID to assign the steering list to\"),\n steering_list_id: z.number().describe(\"Steering list ID to assign (0 to remove/unset)\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_set_account_steering_list\", \"G-03\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Accounts section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open account ID ${args.account_id}.\\n` +\n (args.steering_list_id === 0\n ? `Remove/unset the steering list assignment from this account.\\n`\n : `Assign steering list ID ${args.steering_list_id} to this account.\\n`) +\n `Save the changes and verify the steering list assignment is updated.\\n`,\n ),\n );\n\n // =========================================================================\n // G-05: ui_create_account\n // =========================================================================\n server.registerTool(\n \"ui_create_account\",\n {\n title: \"Create Account (UI Agent)\",\n description:\n \"Creates a new sub-account under the reseller via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. Params: `name` (account name), \" +\n \"`description` (optional), `initial_balance` (optional, default 0).\",\n inputSchema: {\n name: z.string().describe(\"Name for the new account\"),\n description: z.string().optional().describe(\"Optional description\"),\n initial_balance: z.number().optional().describe(\"Initial balance in account currency (default 0)\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_account\", \"G-05\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Accounts section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new account with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n (args.initial_balance ? ` Initial balance: ${args.initial_balance}\\n` : \"\") +\n `Click the \"Create\" or \"Add\" button.\\n` +\n `After creation, note the new account ID from the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_create_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_create_destination_list\",\n {\n title: \"Create Destination List (UI Agent)\",\n description:\n \"Creates a new destination list (named set of phone number prefixes for MOC call permissions) \" +\n \"via the OCS web dashboard. Params: `name`, `prefixes` (array of prefix strings), `description`.\",\n inputSchema: {\n name: z.string().describe(\"Name for the new destination list\"),\n prefixes: z.array(z.string()).optional().describe(\"Phone number prefixes to include (e.g. ['+31', '+49'])\"),\n description: z.string().optional().describe(\"Optional description\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_destination_list\", \"G-12\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new destination list with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n (args.prefixes && (args.prefixes as string[]).length > 0\n ? ` Prefixes to add: ${(args.prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the new destination list and note the ID.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_edit_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_edit_destination_list\",\n {\n title: \"Edit Destination List (UI Agent)\",\n description:\n \"Edits an existing destination list via the OCS web dashboard. \" +\n \"Params: `destination_list_id`, `add_prefixes`, `remove_prefixes`, `new_name`.\",\n inputSchema: {\n destination_list_id: z.number().describe(\"ID of the destination list to edit\"),\n add_prefixes: z.array(z.string()).optional().describe(\"Prefixes to add\"),\n remove_prefixes: z.array(z.string()).optional().describe(\"Prefixes to remove\"),\n new_name: z.string().optional().describe(\"Rename the destination list\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_edit_destination_list\", \"G-12\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open destination list ID ${args.destination_list_id} for editing.\\n` +\n (args.new_name ? `Rename to: ${args.new_name}\\n` : \"\") +\n (args.add_prefixes && (args.add_prefixes as string[]).length > 0\n ? `Add prefixes: ${(args.add_prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_prefixes && (args.remove_prefixes as string[]).length > 0\n ? `Remove prefixes: ${(args.remove_prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated prefix list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_delete_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_delete_destination_list\",\n {\n title: \"Delete Destination List (UI Agent)\",\n description:\n \"Deletes a destination list via the OCS web dashboard. \" +\n \"Params: `destination_list_id`. WARNING: This is destructive and cannot be undone.\",\n inputSchema: {\n destination_list_id: z.number().describe(\"ID of the destination list to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_destination_list\", \"G-12\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find destination list ID ${args.destination_list_id}.\\n` +\n `Delete this destination list. Confirm the deletion when prompted.\\n` +\n `Verify the list no longer appears in the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-18: ui_delete_package_template\n // =========================================================================\n server.registerTool(\n \"ui_delete_package_template\",\n {\n title: \"Delete Package Template (UI Agent)\",\n description:\n \"Deletes a package template from the product catalog via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. \" +\n \"Params: `template_id`. WARNING: This is destructive.\",\n inputSchema: {\n template_id: z.number().describe(\"ID of the package template to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_package_template\", \"G-18\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Package Templates section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find package template ID ${args.template_id}.\\n` +\n `Delete this package template. Confirm the deletion when prompted.\\n` +\n `Verify the template no longer appears in the template list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-19: ui_edit_location_zone\n // =========================================================================\n server.registerTool(\n \"ui_edit_location_zone\",\n {\n title: \"Edit Location Zone (UI Agent)\",\n description:\n \"Edits an existing location zone via the OCS web dashboard. \" +\n \"`create_location_zone` is available via API; edit is UI-only. \" +\n \"Params: `zone_id`, `new_name`, `add_countries`, `remove_countries`.\",\n inputSchema: {\n zone_id: z.number().describe(\"ID of the location zone to edit\"),\n new_name: z.string().optional().describe(\"Rename the location zone\"),\n add_countries: z.array(z.string()).optional().describe(\"ISO country codes to add (e.g. ['NL', 'DE'])\"),\n remove_countries: z.array(z.string()).optional().describe(\"ISO country codes to remove\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_edit_location_zone\", \"G-19\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Location Zones section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open location zone ID ${args.zone_id} for editing.\\n` +\n (args.new_name ? `Rename to: ${args.new_name}\\n` : \"\") +\n (args.add_countries && (args.add_countries as string[]).length > 0\n ? `Add countries: ${(args.add_countries as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_countries && (args.remove_countries as string[]).length > 0\n ? `Remove countries: ${(args.remove_countries as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated country list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-19: ui_delete_location_zone\n // =========================================================================\n server.registerTool(\n \"ui_delete_location_zone\",\n {\n title: \"Delete Location Zone (UI Agent)\",\n description:\n \"Deletes a location zone via the OCS web dashboard. \" +\n \"`create_location_zone` is available via API; delete is UI-only. \" +\n \"Params: `zone_id`. WARNING: Zones in use by active templates may not be deletable.\",\n inputSchema: {\n zone_id: z.number().describe(\"ID of the location zone to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_location_zone\", \"G-19\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Location Zones section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find location zone ID ${args.zone_id}.\\n` +\n `Delete this location zone. Confirm the deletion when prompted.\\n` +\n `If the dashboard shows an error (e.g. zone in use by active templates), report the error.\\n` +\n `Verify the zone no longer appears in the zone list.\\n`,\n ),\n );\n}\n","/**\n * Clerk integration for the Carrier MCP Worker.\n *\n * Human identity is delegated to Clerk (sign-in, sign-up, MFA, social).\n * MCP-client tokens are still minted by @cloudflare/workers-oauth-provider —\n * the Clerk session only gates the OAuth `/authorize` consent step.\n *\n * v1.1a: org_id / org_role / org_name from the \"carrier-mcp\" JWT template\n * are read from sessionClaims. Email + publicMetadata still come from\n * users.getUser() until the template carries email.\n * v1.1c: reads Clerk Billing plan + features from session claims via auth.has()\n * so tier checks don't require a round-trip when Clerk Billing is enabled.\n * v1.1f: surfaces twoFactorVerified + factorVerificationAge for the MFA gate\n * on admin-scope OAuth grants (see mfa.ts).\n * v1.2: M2M JWT acceptance — Authorization: Bearer <clerk_m2m_jwt> issued via\n * Clerk client_credentials flow. Subject is a machine ID (mch_ prefix).\n * Custom claims (reseller_id, reseller_name, tier, scopes) are read from\n * the M2M client's privateMetadata-backed JWT claims.\n */\n\nimport { createClerkClient, type ClerkClient } from \"@clerk/backend\";\nimport type { ClerkJwtClaims, ClerkPublicMetadata, CarrierPrivateMetadata, OcsPortalCredentials, Env } from \"./types.js\";\n\n/** Prefix Clerk uses for M2M machine subject IDs. */\nconst M2M_SUBJECT_PREFIX = \"mch_\";\n\nlet cached: ClerkClient | null = null;\n\nexport function getClerkClient(env: Env): ClerkClient {\n if (!cached) {\n cached = createClerkClient({\n secretKey: env.CLERK_SECRET_KEY,\n publishableKey: env.CLERK_PUBLISHABLE_KEY,\n ...(env.CLERK_MACHINE_SECRET_KEY\n ? { machineSecretKey: env.CLERK_MACHINE_SECRET_KEY }\n : {}),\n });\n }\n return cached;\n}\n\nexport type ClerkPlan = \"free\" | \"pro\" | \"enterprise\";\n\nexport interface ClerkAuthResult {\n /** Clerk user ID (e.g. \"user_2pXkL9aB...\"). Prefix with \"clerk_\" for our `sub`. */\n userId: string;\n email: string;\n publicMetadata: ClerkPublicMetadata;\n /** v1.1a — Active Clerk organisation ID from sessionClaims (carrier-mcp JWT template). */\n orgId?: string;\n /** v1.1a — Active Clerk organisation role, e.g. \"org:admin\". */\n orgRole?: string;\n /** v1.1a — Active Clerk organisation display name (org_name claim). */\n orgName?: string;\n /**\n * v1.1c Clerk Billing — active subscription plan resolved via auth.has({ plan }).\n * `undefined` when Clerk Billing is not enabled or the user has no plan claim.\n */\n plan?: ClerkPlan;\n /**\n * v1.1c Clerk Billing — feature entitlements resolved via auth.has({ feature }).\n * Populated when CLERK_BILLING_FEATURES env lists features to probe.\n */\n features: Record<string, boolean>;\n /**\n * v1.1f MFA gate — true if the session JWT carries two-factor verification.\n * Computed from auth.sessionClaims.two_factor || factor_verification_age.\n */\n twoFactorVerified: boolean;\n /**\n * v1.1f MFA gate — seconds since the user last completed a 2FA challenge,\n * or `undefined` when the session predates the JWT template's second_factor_age claim.\n */\n factorVerificationAge?: number;\n /**\n * v1.2 — How this auth result was produced.\n * \"session\" → Clerk session cookie / session token (existing path).\n * \"m2m\" → Clerk M2M JWT (Authorization: Bearer <mch_ subject JWT>).\n * Downstream code (audit log, tools-call) uses this to tag machine vs human traffic.\n */\n auth_method: \"session\" | \"m2m\";\n}\n\n/** Clerk Billing plans we probe via auth.has({ plan }). Order matches tier hierarchy. */\nconst CLERK_PLANS: ClerkPlan[] = [\"enterprise\", \"pro\", \"free\"];\n\n/**\n * v1.2 — Validate a Clerk M2M JWT from `Authorization: Bearer <jwt>`.\n *\n * Uses `acceptsToken: 'm2m_token'` so the Clerk SDK handles JWKS fetch,\n * signature verification, and `iss` / expiry checks natively.\n *\n * Custom claims (reseller_id, reseller_name, tier, scopes) must be\n * configured in the Clerk Dashboard → M2M client → JWT template or\n * privateMetadata-backed claims.\n *\n * Returns null when:\n * - No Authorization: Bearer header present\n * - The JWT is not a valid M2M token (wrong iss, bad sig, expired)\n * - The subject does not start with the M2M prefix (mch_)\n */\nexport async function authenticateM2MRequest(\n request: Request,\n env: Env,\n): Promise<ClerkAuthResult | null> {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader || !/^Bearer\\s+/i.test(authHeader)) return null;\n\n const token = authHeader.replace(/^Bearer\\s+/i, \"\").trim();\n if (!token) return null;\n\n const client = getClerkClient(env);\n const origin = new URL(request.url).origin;\n\n let requestState: unknown;\n try {\n requestState = await client.authenticateRequest(request, {\n acceptsToken: \"m2m_token\" as \"session_token\",\n authorizedParties: [origin, \"https://accounts.carrier.llc\"],\n });\n } catch {\n return null;\n }\n\n if ((requestState as { status: string }).status !== \"signed-in\") return null;\n\n type M2MAuth = {\n subject?: string | null;\n claims?: Record<string, unknown> | null;\n };\n const auth = (requestState as { toAuth: () => M2MAuth | null }).toAuth();\n // M2M auth object carries `subject` (the machine ID) and `claims`.\n if (\n !auth ||\n typeof auth.subject !== \"string\" ||\n !auth.subject.startsWith(M2M_SUBJECT_PREFIX)\n ) {\n return null;\n }\n\n // Claims are set in the Clerk M2M client's JWT template / privateMetadata.\n const claims = (auth.claims ?? {}) as ClerkJwtClaims & Record<string, unknown>;\n\n const resellerId =\n typeof claims.reseller_id === \"number\" ? claims.reseller_id : undefined;\n const resellerName =\n typeof claims.reseller_name === \"string\" ? claims.reseller_name : \"\";\n const tier =\n claims.tier === \"free\" ||\n claims.tier === \"pro\" ||\n claims.tier === \"enterprise\"\n ? claims.tier\n : undefined;\n const scopes = Array.isArray(claims.scopes)\n ? (claims.scopes as Array<\"read\" | \"write\" | \"admin\">)\n : undefined;\n\n return {\n // Use the machine subject as the userId so downstream code (sub = `clerk_${userId}`)\n // produces a stable, unique identity for audit logging.\n userId: auth.subject,\n email: \"\",\n publicMetadata: {\n reseller_id: resellerId,\n reseller_name: resellerName || undefined,\n tier,\n scopes,\n role: \"user\",\n },\n orgId: typeof claims.org_id === \"string\" ? claims.org_id : undefined,\n orgRole: typeof claims.org_role === \"string\" ? claims.org_role : undefined,\n orgName: typeof claims.org_name === \"string\" ? claims.org_name : undefined,\n plan: tier,\n features: {},\n twoFactorVerified: false,\n factorVerificationAge: undefined,\n auth_method: \"m2m\",\n };\n}\n\n/**\n * Validate the incoming request against Clerk.\n * Returns null when the request is unauthenticated.\n *\n * v1.2: When `Authorization: Bearer <jwt>` is present, tries M2M acceptance\n * first. If the JWT is a valid Clerk M2M token (subject starts with mch_),\n * returns immediately without a users.getUser() round-trip.\n * Falls through to session-cookie path only when M2M validation yields null.\n *\n * Calls users.getUser() once for email and publicMetadata (reseller_id, tier,\n * scopes, role). org_id / org_role / org_name are read from sessionClaims when\n * the JWT template includes them.\n */\nexport async function authenticateClerkRequest(\n request: Request,\n env: Env,\n): Promise<ClerkAuthResult | null> {\n // v1.2 — M2M fast-path: try before session cookie so machine clients that\n // send a valid Bearer JWT never hit the session-token branch.\n const authHeader = request.headers.get(\"Authorization\");\n const hasBearer = authHeader !== null && /^Bearer\\s+/i.test(authHeader);\n if (hasBearer) {\n const m2mResult = await authenticateM2MRequest(request, env);\n if (m2mResult !== null) return m2mResult;\n // Bearer present but NOT a Clerk M2M JWT — fall through so the\n // OAuthProvider's regular bearer handler (OAUTH_KV tokens) stays intact.\n // The session-cookie branch below will also return null for a Bearer-only\n // request, which is the correct behaviour.\n }\n\n const client = getClerkClient(env);\n const origin = new URL(request.url).origin;\n\n const requestState = await client.authenticateRequest(request, {\n acceptsToken: \"session_token\",\n authorizedParties: [origin, \"https://accounts.carrier.llc\"],\n });\n if (requestState.status !== \"signed-in\") return null;\n\n const auth = requestState.toAuth();\n if (!auth || !(\"userId\" in auth) || !auth.userId) return null;\n\n const claims = (auth.sessionClaims ?? {}) as ClerkJwtClaims &\n Record<string, unknown>;\n\n const user = await client.users.getUser(auth.userId);\n const email =\n user.emailAddresses.find((e) => e.id === user.primaryEmailAddressId)\n ?.emailAddress ??\n user.emailAddresses[0]?.emailAddress ??\n \"\";\n const publicMetadata = (user.publicMetadata ?? {}) as ClerkPublicMetadata;\n\n // v1.1c Clerk Billing — probe plan + features via the session's has() helper.\n const plan = resolvePlan(auth);\n const features = resolveFeatures(auth, env);\n\n // v1.1f MFA — extract second-factor verification state from session claims.\n const twoFactorVerified = Boolean(\n claims.two_factor_verified ??\n claims.second_factor_verified ??\n (typeof claims.fva === \"object\" &&\n claims.fva !== null &&\n Array.isArray(claims.fva) &&\n (claims.fva as unknown[])[1] !== -1),\n );\n const factorVerificationAge =\n typeof claims.second_factor_age === \"number\"\n ? (claims.second_factor_age as number)\n : Array.isArray(claims.fva) &&\n typeof (claims.fva as unknown[])[1] === \"number\" &&\n ((claims.fva as number[])[1] ?? -1) >= 0\n ? // Clerk's `fva` tuple is ages in minutes; MFA compares seconds (mfa.ts).\n ((claims.fva as number[])[1] as number) * 60\n : undefined;\n\n return {\n userId: auth.userId,\n email,\n publicMetadata,\n orgId: claims.org_id ?? auth.orgId ?? undefined,\n orgRole: claims.org_role ?? auth.orgRole ?? undefined,\n orgName: claims.org_name,\n plan,\n features,\n twoFactorVerified,\n factorVerificationAge,\n auth_method: \"session\",\n };\n}\n\nfunction resolvePlan(auth: {\n has?: (p: Record<string, string>) => boolean;\n}): ClerkPlan | undefined {\n if (typeof auth.has !== \"function\") return undefined;\n for (const plan of CLERK_PLANS) {\n try {\n if (auth.has({ plan })) return plan;\n } catch {\n // has() may throw for an unconfigured plan — try the next tier\n continue;\n }\n }\n return undefined;\n}\n\nfunction resolveFeatures(\n auth: { has?: (p: Record<string, string>) => boolean },\n env: Env,\n): Record<string, boolean> {\n const list = (env.CLERK_BILLING_FEATURES ?? \"\")\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean);\n const out: Record<string, boolean> = {};\n if (typeof auth.has !== \"function\") return out;\n for (const feature of list) {\n try {\n out[feature] = auth.has({ feature });\n } catch {\n out[feature] = false;\n }\n }\n return out;\n}\n\n/**\n * Build the Clerk-hosted sign-in URL with a redirect back to the current request.\n */\nexport function buildSignInRedirect(env: Env, requestUrl: string): string {\n const signInBase =\n env.CLERK_SIGN_IN_URL ?? \"https://accounts.carrier.llc/sign-in\";\n const url = new URL(signInBase);\n url.searchParams.set(\"redirect_url\", requestUrl);\n return url.toString();\n}\n\nexport function buildSignUpRedirect(env: Env, requestUrl: string): string {\n const signUpBase =\n env.CLERK_SIGN_UP_URL ?? \"https://accounts.carrier.llc/sign-up\";\n const url = new URL(signUpBase);\n url.searchParams.set(\"redirect_url\", requestUrl);\n return url.toString();\n}\n\n// ---------------------------------------------------------------------------\n// v1.1.1 — OCS portal credentials from Clerk privateMetadata.\n// Used by tools-ui-agent.ts to authenticate the Manus browser agent against\n// the OCS web dashboard for UI-only operations.\n//\n// Resolution order:\n// 1. Organization privateMetadata (org_id present)\n// 2. User privateMetadata (solo user, no org)\n//\n// Returns null when no credentials are stored — the UI agent tool surfaces\n// a clear \"link your OCS portal\" message to the user.\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch OCS portal credentials from Clerk privateMetadata.\n * Uses the Clerk REST API directly (no SDK method for privateMetadata on CF Workers).\n */\nexport async function getOcsPortalCredentials(\n env: Env,\n orgId?: string,\n userId?: string,\n): Promise<OcsPortalCredentials | null> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Try org-level first\n if (orgId) {\n try {\n const res = await fetch(`${baseUrl}/organizations/${orgId}`, { headers });\n if (res.ok) {\n const org = (await res.json()) as { private_metadata?: CarrierPrivateMetadata };\n if (org.private_metadata?.ocs_portal?.username && org.private_metadata.ocs_portal.password) {\n return org.private_metadata.ocs_portal;\n }\n }\n } catch {\n // Fall through to user-level\n }\n }\n\n // Fallback: user-level privateMetadata\n if (userId) {\n try {\n const res = await fetch(`${baseUrl}/users/${userId}`, { headers });\n if (res.ok) {\n const user = (await res.json()) as { private_metadata?: CarrierPrivateMetadata };\n if (user.private_metadata?.ocs_portal?.username && user.private_metadata.ocs_portal.password) {\n return user.private_metadata.ocs_portal;\n }\n }\n } catch {\n // No credentials available\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Projects provisioning helpers\n// ---------------------------------------------------------------------------\n\nexport interface CreateOrgOptions {\n name: string;\n slug: string;\n email: string;\n}\n\n/**\n * Provision a Clerk organisation for a Stripe Projects operator install.\n * If an org with the given slug already exists, returns the existing org ID.\n * Creates a membership for the provided email address (creates the user if absent).\n */\nexport async function createClerkOrgForOperator(\n env: Env,\n opts: CreateOrgOptions,\n): Promise<string> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Check if org slug already exists\n const listRes = await fetch(\n `${baseUrl}/organizations?query=${encodeURIComponent(opts.slug)}&limit=1`,\n { headers },\n );\n if (listRes.ok) {\n const list = (await listRes.json()) as {\n data?: Array<{ id: string; slug: string }>;\n };\n const existing = list.data?.find((o) => o.slug === opts.slug);\n if (existing) return existing.id;\n }\n\n // Create new org\n const createRes = await fetch(`${baseUrl}/organizations`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n name: opts.name,\n slug: opts.slug,\n public_metadata: { source: \"stripe_projects\", email: opts.email },\n }),\n });\n if (!createRes.ok) {\n const errText = await createRes.text();\n throw new Error(`Failed to create Clerk org: ${errText}`);\n }\n const org = (await createRes.json()) as { id: string };\n return org.id;\n}\n\n// ---------------------------------------------------------------------------\n// OAuth token minting for Stripe Projects\n// ---------------------------------------------------------------------------\n\n/**\n * Mint a Carrier OAuth bearer token for a Stripe Projects operator.\n * Token is bound to the org, has read+write scope, and 30-day TTL.\n * Stored in OAUTH_KV so it's validated by OAuthProvider on subsequent requests.\n */\nexport async function mintProjectsToken(\n env: Env,\n orgId: string,\n): Promise<string> {\n // Generate a cryptographically random bearer token\n const tokenBytes = crypto.getRandomValues(new Uint8Array(32));\n const token = Array.from(tokenBytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n const ttl = 30 * 24 * 60 * 60; // 30 days in seconds\n const expiresAt = Date.now() + ttl * 1000;\n\n const record = {\n sub: `clerk_org_${orgId}`,\n org_id: orgId,\n scopes: [\"read\", \"write\"],\n issued_at: new Date().toISOString(),\n expires_at: new Date(expiresAt).toISOString(),\n source: \"stripe_projects\",\n };\n\n // Store under OAUTH_KV so the OAuthProvider validates it as a bearer token.\n // Key matches the pattern used by @cloudflare/workers-oauth-provider for bearer lookup.\n await (env as Env & { OAUTH_KV: KVNamespace }).OAUTH_KV.put(\n `token:${token}`,\n JSON.stringify(record),\n { expirationTtl: ttl },\n );\n\n return token;\n}\n\n/**\n * Store OCS portal credentials in Clerk org (or user) privateMetadata.\n * Called from the /setup endpoint or the console settings page.\n */\nexport async function setOcsPortalCredentials(\n env: Env,\n credentials: OcsPortalCredentials,\n orgId?: string,\n userId?: string,\n): Promise<boolean> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n const body = JSON.stringify({\n private_metadata: { ocs_portal: credentials },\n });\n\n // Prefer org-level storage\n const entityType = orgId ? \"organizations\" : \"users\";\n const entityId = orgId ?? userId;\n if (!entityId) return false;\n\n try {\n const res = await fetch(`${baseUrl}/${entityType}/${entityId}/metadata`, {\n method: \"PATCH\",\n headers,\n body,\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n","/**\n * Carrier MCP — UI-Agent ask-reply tools.\n *\n * Provides the resumption path for Manus tasks that paused with stop_reason \"ask\".\n * When the Manus agent needs human input (e.g. 2FA code, ambiguous OCS field),\n * the webhook handler writes a pending-ask entry to KV. These tools allow\n * callers to list pending asks and reply to resume the task.\n *\n * Manus `task.reply` is invoked via `askReply` in `manus-client.ts` (primary/fallback key chain).\n *\n * TOOLS\n * -----\n * ui_agent_reply — submit a reply to a paused Manus task\n * ui_agent_list_pending — list all tasks currently waiting for input\n *\n * SAFETY\n * ------\n * - Both tools require \"write\" scope minimum.\n * - Reply content is NEVER recorded in the audit log (may contain credentials/codes).\n * - Only reply length is logged.\n * - KV pending-ask entries expire automatically at 24h TTL.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport { PENDING_ASK_PREFIX, PENDING_ASK_TTL_SECONDS } from \"./manus-webhook.js\";\nimport type { ManusPendingAsk } from \"./manus-webhook.js\";\nimport { askReply, getManusKeys, type ManusTaskResult } from \"./manus-client.js\";\n\n/** Doc + registry merge — ui_agent_reply enforces write|admin; list_pending allows any non-empty scope. */\nexport const UI_AGENT_ASK_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_agent_reply: \"write\",\n ui_agent_list_pending: \"read\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared ToolResult type (mirrors tools-ui-agent.ts)\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Pending-ask entry with computed expiry\n// ---------------------------------------------------------------------------\n\ninterface PendingAskEntry extends ManusPendingAsk {\n expires_at: string; // ISO 8601 — computed from asked_at + TTL\n}\n\nfunction computeExpiresAt(askedAt: string): string {\n const asked = new Date(askedAt).getTime();\n if (isNaN(asked)) return \"\";\n return new Date(asked + PENDING_ASK_TTL_SECONDS * 1000).toISOString();\n}\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\n\nexport function registerUiAgentAskTools(server: McpServer, ctx: ToolContext): void {\n\n // =========================================================================\n // ui_agent_reply — resume a paused Manus task\n // =========================================================================\n server.registerTool(\n \"ui_agent_reply\",\n {\n title: \"Reply to Paused UI Agent Task\",\n description:\n \"Resumes a Manus browser automation task that paused with stop_reason 'ask'. \" +\n \"Use ui_agent_list_pending to find tasks waiting for input. \" +\n \"Provide the task_id and your reply (e.g. a 2FA code, a field value, or a yes/no answer). \" +\n \"The reply content is never recorded in audit logs — only its length is logged.\",\n inputSchema: {\n task_id: z.string().describe(\"Manus task ID to resume (from ui_agent_list_pending)\"),\n reply: z.string().describe(\"Your answer to the agent's question (e.g. a 2FA code or confirmation)\"),\n },\n },\n async (args: { task_id: string; reply: string }): Promise<ToolResult> => {\n const start = Date.now();\n const { task_id, reply } = args;\n\n // Scope enforcement — require write minimum\n if (!ctx.props.scope.includes(\"write\") && !ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: 'ui_agent_reply' requires 'write' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n const keys = getManusKeys(ctx.env);\n if (!keys) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message: \"MANUS_API_KEY is not configured on this deployment.\",\n }),\n },\n ],\n };\n }\n\n // Check that a pending-ask entry exists for this task_id\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n const pendingRaw = await ctx.env.CARRIER_USERS.get(pendingKey);\n if (pendingRaw === null) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"task_not_pending\",\n message: `No pending-ask entry found for task_id=${task_id}. ` +\n \"The task may have already been resumed, completed, or expired (24h TTL). \" +\n \"Use ui_agent_list_pending to see currently waiting tasks.\",\n }),\n },\n ],\n };\n }\n\n let result: ManusTaskResult;\n try {\n const replyOutcome = await askReply(keys, task_id, reply);\n result = replyOutcome.data;\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error calling Manus task.reply: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n\n if (!result.ok) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_reply_failed\",\n message: result.error?.message ?? \"Manus task.reply returned ok=false\",\n code: result.error?.code,\n task_id,\n }),\n },\n ],\n };\n }\n\n // Audit: log reply length only — NEVER the reply content (may contain 2FA codes/credentials)\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"ui_agent_resumed\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n\n // Remove the pending-ask KV entry — task is now running again.\n // The next webhook with stop_reason=\"finish\" will also clear it, but\n // removing it here immediately prevents duplicate replies.\n await ctx.env.CARRIER_USERS.delete(pendingKey);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"resumed\",\n task_id,\n reply_length: reply.length,\n message:\n \"The Manus agent has received your reply and is continuing the task. \" +\n \"The task will emit a task_stopped webhook when complete.\",\n }, null, 2),\n },\n ],\n };\n },\n );\n\n // =========================================================================\n // ui_agent_list_pending — list tasks waiting for input\n // =========================================================================\n server.registerTool(\n \"ui_agent_list_pending\",\n {\n title: \"List Pending UI Agent Tasks (Waiting for Input)\",\n description:\n \"Returns all Manus browser automation tasks that are currently paused waiting for human input \" +\n \"(stop_reason 'ask'). Shows the agent's question, task URL, and when it was asked. \" +\n \"Entries expire after 24 hours. Use ui_agent_reply to resume a task.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n // Scope: read is sufficient (listing only, no mutations)\n if (ctx.props.scope.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: \"Scope denied: no scopes present on token.\",\n },\n ],\n };\n }\n\n // List all manus_pending_ask:* keys from CARRIER_USERS KV\n let keys: Array<{ name: string }>;\n try {\n const listing = await ctx.env.CARRIER_USERS.list({ prefix: PENDING_ASK_PREFIX });\n keys = listing.keys;\n } catch (err) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error listing pending tasks: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n\n if (keys.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n pending_tasks: [],\n count: 0,\n message: \"No Manus tasks are currently waiting for input.\",\n }, null, 2),\n },\n ],\n };\n }\n\n // Fetch each entry in parallel\n const entries = await Promise.all(\n keys.map(async ({ name }): Promise<PendingAskEntry | null> => {\n const raw = await ctx.env.CARRIER_USERS.get(name);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as ManusPendingAsk;\n return {\n ...parsed,\n expires_at: computeExpiresAt(parsed.asked_at),\n };\n } catch {\n return null;\n }\n }),\n );\n\n const validEntries = entries.filter((e): e is PendingAskEntry => e !== null);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n pending_tasks: validEntries,\n count: validEntries.length,\n }, null, 2),\n },\n ],\n };\n },\n );\n}\n","/**\n * Manus webhook receiver.\n *\n * Receives push notifications from Manus for UI-agent tasks dispatched by\n * tools-ui-agent.ts. Eliminates the need for client-side polling.\n *\n * ROUTE\n * -----\n * POST /manus-webhook\n *\n * AUTHENTICATION\n * --------------\n * Header: X-Manus-Signature: <hex>\n * Payload: HMAC-SHA256(key=MANUS_WEBHOOK_SECRET, message=raw_request_body)\n * Format: raw hex string (no \"sha256=\" prefix — per Manus docs).\n *\n * IDEMPOTENCY\n * -----------\n * event_id stored in CARRIER_USERS KV under key `manus_event:{event_id}` with\n * 7-day TTL. Replayed events return 200+deduplicated without re-processing.\n *\n * EVENT TYPES\n * -----------\n * task_created — fires immediately after task.create; logged only.\n * task_stopped — fires on completion or ask; updates audit log + AE.\n * stop_reason:\n * \"finish\" — task completed; attachment URLs logged if present.\n * Clears any pending-ask KV entry for this task.\n * \"ask\" — task paused, waiting for user input.\n * Writes manus_pending_ask:{task_id} to CARRIER_USERS KV (24h TTL).\n * Emits ui_agent_needs_input AE event with truncated question.\n *\n * PENDING-ASK KV SCHEMA\n * ---------------------\n * Key: manus_pending_ask:{task_id}\n * Value: JSON { task_id, question, task_url, asked_at }\n * TTL: 24 hours (86400 seconds)\n *\n * AUDIT LOG SCHEMA (Analytics Engine blobs[]):\n * blobs[0] = \"manus_webhook\"\n * blobs[1] = event_type (\"task_created\" | \"task_stopped\")\n * blobs[2] = stop_reason (\"finish\" | \"ask\" | \"ui_agent_awaiting_input\" | \"\")\n * blobs[3] = task_id\n * blobs[4] = attachment_count (stringified number) or truncated question for ask events\n * doubles[0] = latency_ms (0 for task_created)\n * indexes[0] = task_id\n */\n\nimport type { Env } from \"./types.js\";\nimport { timingSafeEqual } from \"./timing-safe-equal.js\";\n\n// ---------------------------------------------------------------------------\n// Manus webhook payload shapes\n// ---------------------------------------------------------------------------\n\ninterface ManusTaskDetail {\n task_id: string;\n task_title?: string;\n task_url?: string;\n}\n\ninterface ManusAttachment {\n name: string;\n url: string;\n}\n\ninterface ManusWebhookPayload {\n event_id: string;\n event_type: \"task_created\" | \"task_stopped\" | string;\n task_detail: ManusTaskDetail;\n message?: string;\n attachments?: ManusAttachment[];\n stop_reason?: \"finish\" | \"ask\" | string;\n}\n\n// ---------------------------------------------------------------------------\n// R2 attachment persistence constants\n// ---------------------------------------------------------------------------\n\n/** Max bytes to fetch per attachment (25 MB). */\nconst MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;\n/** R2 key prefix for Manus attachment files. */\nconst R2_PREFIX = \"manus-attachments\";\n/**\n * Patterns that identify Cloudflare-hosted URLs.\n * Attachments already on CF infrastructure are skipped — no re-upload needed.\n */\nconst CF_ZONE_PATTERNS: RegExp[] = [\n /\\.r2\\.dev$/,\n /\\.carrier\\.llc$/,\n /\\.cloudflare\\.net$/,\n /\\.workers\\.dev$/,\n];\n\n// ---------------------------------------------------------------------------\n// Exported types for tools-ui-agent-ask.ts\n// ---------------------------------------------------------------------------\n\nexport interface ManusPendingAsk {\n task_id: string;\n question: string;\n task_url: string;\n asked_at: string; // ISO 8601\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SIGNATURE_HEADER = \"x-manus-signature\";\n/** 7-day TTL for idempotency keys. */\nconst DEDUP_TTL_SECONDS = 7 * 24 * 3600;\n/** 24-hour TTL for pending-ask entries. */\nexport const PENDING_ASK_TTL_SECONDS = 24 * 3600;\n/** KV key prefix for pending-ask entries. */\nexport const PENDING_ASK_PREFIX = \"manus_pending_ask:\";\n/** Max chars of question to store in AE audit (credentials protection). */\nconst QUESTION_TRUNCATE_CHARS = 200;\n\n// ---------------------------------------------------------------------------\n// Handler entry point\n// ---------------------------------------------------------------------------\n\nexport async function handleManusWebhook(\n request: Request,\n env: Env,\n): Promise<Response> {\n if (!env.MANUS_WEBHOOK_SECRET) {\n console.error(\"[manus-webhook] MANUS_WEBHOOK_SECRET not configured\");\n return new Response(\"Webhook receiver not configured\", { status: 503 });\n }\n\n // 1. Read raw body (must happen before any .json() / .text() calls)\n const body = await request.text();\n\n // 2. Verify HMAC-SHA256 signature\n const sigHeader = request.headers.get(SIGNATURE_HEADER);\n const verified = await verifyHmacSignature(body, sigHeader, env.MANUS_WEBHOOK_SECRET);\n if (!verified) {\n console.warn(\"[manus-webhook] rejected — invalid or missing signature\");\n return new Response(\"Unauthorized\", { status: 401 });\n }\n\n // 3. Parse payload\n let payload: ManusWebhookPayload;\n try {\n payload = JSON.parse(body) as ManusWebhookPayload;\n } catch {\n return new Response(\"Invalid JSON body\", { status: 400 });\n }\n\n if (!payload.event_id || !payload.event_type || !payload.task_detail?.task_id) {\n return new Response(\n \"Missing required fields: event_id, event_type, task_detail.task_id\",\n { status: 400 },\n );\n }\n\n const { event_id, event_type, task_detail, attachments, stop_reason, message } = payload;\n const { task_id } = task_detail;\n\n // 4. Idempotency — CARRIER_USERS KV, 7-day TTL\n const dedupKey = `manus_event:${event_id}`;\n const alreadyProcessed = await env.CARRIER_USERS.get(dedupKey);\n if (alreadyProcessed !== null) {\n console.log(`[manus-webhook] deduplicated event_id=${event_id}`);\n return Response.json({ ok: true, deduplicated: true });\n }\n\n // 5. Mark as processed (write before handling so concurrent replays are safe)\n await env.CARRIER_USERS.put(dedupKey, \"1\", {\n expirationTtl: DEDUP_TTL_SECONDS,\n });\n\n try {\n // 6. Handle event\n if (event_type === \"task_created\") {\n handleTaskCreated(env, task_id, event_id);\n return Response.json({ ok: true });\n }\n\n if (event_type === \"task_stopped\") {\n await handleTaskStopped(env, task_id, event_id, stop_reason, attachments, message, task_detail.task_url);\n return Response.json({ ok: true });\n }\n\n // Unknown event type — log + ack\n console.log(`[manus-webhook] unknown event_type=${event_type} task_id=${task_id}`);\n return Response.json({ ok: true });\n } catch (err) {\n try {\n await env.CARRIER_USERS.delete(dedupKey);\n } catch (rollbackErr) {\n console.error(\n `[manus-webhook] dedup rollback failed: ${(rollbackErr as Error).message}`,\n );\n }\n throw err;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Event handlers\n// ---------------------------------------------------------------------------\n\nfunction handleTaskCreated(env: Env, task_id: string, event_id: string): void {\n console.log(`[manus-webhook] task_created task_id=${task_id} event_id=${event_id}`);\n\n writeManusAudit(env, {\n event_type: \"task_created\",\n task_id,\n stop_reason: \"\",\n attachment_count: 0,\n latency_ms: 0,\n });\n}\n\nasync function handleTaskStopped(\n env: Env,\n task_id: string,\n event_id: string,\n stop_reason: string | undefined,\n attachments: ManusAttachment[] | undefined,\n message: string | undefined,\n task_url: string | undefined,\n): Promise<void> {\n const reason = stop_reason ?? \"unknown\";\n const attachmentCount = attachments?.length ?? 0;\n\n if (reason === \"finish\") {\n console.log(\n `[manus-webhook] task_stopped:finish task_id=${task_id} attachments=${attachmentCount}`,\n );\n if (attachmentCount > 0) {\n const urls = (attachments ?? []).map((a) => `${a.name}: ${a.url}`).join(\", \");\n console.log(`[manus-webhook] attachments task_id=${task_id} urls=[${urls}]`);\n }\n\n // Persist attachments to R2 before clearing the pending-ask entry.\n if (attachmentCount > 0) {\n for (const attachment of attachments ?? []) {\n await persistAttachmentToR2(env, task_id, attachment);\n }\n }\n\n // Clear any pending-ask entry now that the task has finished.\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n await env.CARRIER_USERS.delete(pendingKey);\n console.log(`[manus-webhook] cleared pending-ask for task_id=${task_id}`);\n\n } else if (reason === \"ask\") {\n const question = message ?? \"\";\n const truncatedQuestion = question.slice(0, QUESTION_TRUNCATE_CHARS);\n\n console.log(\n `[manus-webhook] task_stopped:needs_user_input task_id=${task_id} question_len=${question.length}`,\n );\n\n // Write pending-ask entry to KV with 24h TTL.\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n const pendingEntry: ManusPendingAsk = {\n task_id,\n question,\n task_url: task_url ?? \"\",\n asked_at: new Date().toISOString(),\n };\n await env.CARRIER_USERS.put(pendingKey, JSON.stringify(pendingEntry), {\n expirationTtl: PENDING_ASK_TTL_SECONDS,\n });\n\n // Emit ask-specific AE event with truncated question (blobs[2]=\"ui_agent_awaiting_input\").\n // The generic writeManusAudit below also fires (blobs[2]=\"ask\") for compatibility.\n writeManusAuditAsk(env, {\n task_id,\n truncated_question: truncatedQuestion,\n event_id,\n });\n\n } else {\n console.log(\n `[manus-webhook] task_stopped:${reason} task_id=${task_id} event_id=${event_id}`,\n );\n }\n\n writeManusAudit(env, {\n event_type: \"task_stopped\",\n task_id,\n stop_reason: reason,\n attachment_count: attachmentCount,\n latency_ms: 0, // no task_created timestamp available without a lookup; 0 is accurate per current design\n });\n}\n\n// ---------------------------------------------------------------------------\n// R2 attachment persistence\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch an attachment from Manus and stream it to R2.\n * Skips CF-hosted URLs (already on Cloudflare infrastructure).\n * Enforces 25 MB cap via Content-Length header and buffer size check.\n */\nasync function persistAttachmentToR2(\n env: Env,\n task_id: string,\n attachment: ManusAttachment,\n): Promise<void> {\n // Skip CF-hosted URLs — no re-upload needed\n try {\n const hostname = new URL(attachment.url).hostname;\n if (CF_ZONE_PATTERNS.some((re) => re.test(hostname))) {\n console.log(`[manus-webhook] skipping CF-hosted attachment url=${attachment.url}`);\n return;\n }\n } catch {\n console.warn(`[manus-webhook] invalid attachment URL: ${attachment.url}`);\n return;\n }\n\n let res: Response;\n try {\n res = await fetch(attachment.url);\n } catch (err) {\n console.error(`[manus-webhook] fetch attachment failed url=${attachment.url}: ${(err as Error).message}`);\n return;\n }\n\n if (!res.ok) {\n console.warn(`[manus-webhook] attachment fetch non-ok status=${res.status} url=${attachment.url}`);\n return;\n }\n\n // Check Content-Length header before buffering\n const contentLengthHeader = res.headers.get(\"content-length\");\n if (contentLengthHeader !== null) {\n const declared = parseInt(contentLengthHeader, 10);\n if (!isNaN(declared) && declared > MAX_ATTACHMENT_BYTES) {\n console.warn(\n `[manus-webhook] attachment too large (content-length=${declared}) url=${attachment.url} — skipping`,\n );\n return;\n }\n }\n\n let buffer: ArrayBuffer;\n try {\n buffer = await res.arrayBuffer();\n } catch (err) {\n console.error(`[manus-webhook] attachment buffer failed: ${(err as Error).message}`);\n return;\n }\n\n if (buffer.byteLength > MAX_ATTACHMENT_BYTES) {\n console.warn(\n `[manus-webhook] attachment too large (actual=${buffer.byteLength}) url=${attachment.url} — skipping`,\n );\n return;\n }\n\n const filename = sanitiseFilename(attachment.name);\n const r2Key = `${R2_PREFIX}/${task_id}/${filename}`;\n const contentType = res.headers.get(\"content-type\") ?? \"application/octet-stream\";\n\n try {\n await env.DOWNLOADS.put(r2Key, buffer, {\n httpMetadata: { contentType },\n });\n console.log(`[manus-webhook] stored attachment r2=${r2Key} size=${buffer.byteLength}`);\n } catch (err) {\n console.error(`[manus-webhook] R2 put failed key=${r2Key}: ${(err as Error).message}`);\n }\n}\n\n/**\n * Sanitise an attachment filename for safe use as an R2 key component.\n * - Strips path separators\n * - Collapses whitespace to underscores\n * - Replaces unsafe characters\n * - Truncates to 200 chars\n */\nfunction sanitiseFilename(name: string): string {\n return name\n .replace(/[/\\\\]/g, \"_\")\n .replace(/\\s+/g, \"_\")\n .replace(/[^a-zA-Z0-9._\\-]/g, \"_\")\n .slice(0, 200);\n}\n\n// ---------------------------------------------------------------------------\n// Analytics Engine writes\n// ---------------------------------------------------------------------------\n\ninterface ManusAuditEntry {\n event_type: string;\n task_id: string;\n stop_reason: string;\n attachment_count: number;\n latency_ms: number;\n}\n\nfunction writeManusAudit(env: Env, entry: ManusAuditEntry): void {\n // Fire-and-forget — AE writes are best-effort\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_webhook\",\n entry.event_type,\n entry.stop_reason,\n entry.task_id,\n String(entry.attachment_count),\n ],\n doubles: [entry.latency_ms],\n indexes: [entry.task_id],\n });\n } catch (err) {\n console.error(`[manus-webhook] audit write failed: ${(err as Error).message}`);\n }\n}\n\nfunction writeManusAuditAsk(\n env: Env,\n entry: { task_id: string; truncated_question: string; event_id: string },\n): void {\n // Separate AE event for ask-path — status distinguishes from finish.\n // blobs[2] = \"ui_agent_awaiting_input\" distinguishes from \"finish\" status.\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_webhook\",\n \"task_stopped\",\n \"ui_agent_awaiting_input\",\n entry.task_id,\n entry.truncated_question,\n entry.event_id,\n ],\n doubles: [0],\n indexes: [entry.task_id],\n });\n } catch (err) {\n console.error(`[manus-webhook] ask audit write failed: ${(err as Error).message}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// HMAC-SHA256 signature verification\n// ---------------------------------------------------------------------------\n\n/**\n * Verify HMAC-SHA256 signature from Manus.\n * Header value is a raw hex string (64 chars, no \"sha256=\" prefix).\n * Falls back to also accepting \"sha256=<hex>\" for forward-compat.\n */\nasync function verifyHmacSignature(\n body: string,\n header: string | null,\n secret: string,\n): Promise<boolean> {\n if (!header) return false;\n\n // Accept raw hex or \"sha256=<hex>\"\n const hex = header.startsWith(\"sha256=\") ? header.slice(7) : header;\n if (!/^[0-9a-f]{64}$/i.test(hex)) return false;\n\n const enc = new TextEncoder();\n let keyMaterial: CryptoKey;\n try {\n keyMaterial = await crypto.subtle.importKey(\n \"raw\",\n enc.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n } catch {\n return false;\n }\n\n const sig = await crypto.subtle.sign(\"HMAC\", keyMaterial, enc.encode(body));\n const computed = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n const normalizedHex = hex.toLowerCase();\n return timingSafeEqual(computed, normalizedHex);\n}\n","/**\n * Carrier MCP — Manus API v2 client.\n *\n * Implements ALL Manus API v2 endpoints per the official OpenAPI spec.\n * Auth: `x-manus-api-key` header on every request.\n *\n * KEY CHAIN:\n * Primary key: env.MANUS_API_KEY\n * Fallback key: env.MANUS_API_KEY_FALLBACK (optional)\n * On HTTP 401/403/429, automatically retries with the fallback key.\n *\n * PROFILES (from official spec):\n * \"manus-1.6\" — standard capability (default)\n * \"manus-1.6-lite\" — lightweight, faster responses\n * \"manus-1.6-max\" — maximum capability\n *\n * @see https://open.manus.ai/docs/v2/introduction\n */\n\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Base URL for all Manus API v2 calls. Paths are appended directly. */\nexport const MANUS_API_BASE = \"https://api.manus.ai/v2\";\n\n// ---------------------------------------------------------------------------\n// Profiles (from official OpenAPI spec)\n// ---------------------------------------------------------------------------\n\nexport const MANUS_PROFILES = [\n \"manus-1.6\",\n \"manus-1.6-lite\",\n \"manus-1.6-max\",\n] as const;\n\nexport type ManusProfile = (typeof MANUS_PROFILES)[number];\n\nexport const MANUS_DEFAULT_PROFILE: ManusProfile = \"manus-1.6\";\n\n/** One-line description per profile for the ui_agent_profiles_list tool. */\nexport const MANUS_PROFILE_DESCRIPTIONS: Record<ManusProfile, string> = {\n \"manus-1.6\":\n \"Standard capability agent — balanced speed and quality, default for all tasks.\",\n \"manus-1.6-lite\":\n \"Lightweight, fast, lowest cost — suitable for most OCS dashboard operations.\",\n \"manus-1.6-max\":\n \"Maximum capability — for operations requiring advanced reasoning and complex multi-step flows.\",\n};\n\n// ---------------------------------------------------------------------------\n// Key helpers\n// ---------------------------------------------------------------------------\n\nexport interface ManusKeys {\n primary: string;\n fallback?: string;\n}\n\nexport function getManusKeys(env: Env): ManusKeys | null {\n if (!env.MANUS_API_KEY) return null;\n return {\n primary: env.MANUS_API_KEY,\n fallback: env.MANUS_API_KEY_FALLBACK,\n };\n}\n\nexport function resolveManusProfile(env: Env): ManusProfile {\n const val = env.MANUS_DEFAULT_PROFILE;\n if (val && (MANUS_PROFILES as readonly string[]).includes(val)) {\n return val as ManusProfile;\n }\n return MANUS_DEFAULT_PROFILE;\n}\n\n/**\n * Validates a caller-supplied profile string against the whitelist.\n * Returns the profile on success or throws with a descriptive error.\n */\nexport function validateManusProfile(profile: string): ManusProfile {\n if ((MANUS_PROFILES as readonly string[]).includes(profile)) {\n return profile as ManusProfile;\n }\n throw new Error(\n `Invalid agent_profile \"${profile}\". Accepted profiles: ${MANUS_PROFILES.join(\", \")}. ` +\n `Use ui_agent_profiles_list to see available options.`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Domain types (from OpenAPI spec components/schemas)\n// ---------------------------------------------------------------------------\n\n/** Standard API envelope — all responses use this shape. */\nexport interface ManusApiResponse {\n ok: boolean;\n request_id?: string;\n error?: { code: string; message: string };\n}\n\n/** Task object from task.detail / task.create / task.list */\nexport interface ManusTask extends ManusApiResponse {\n id?: string;\n task_id?: string;\n task_url?: string;\n status?: \"running\" | \"stopped\" | \"waiting\" | \"error\";\n title?: string;\n task_type?: \"standard\" | \"project\" | \"agent_subtask\";\n share_visibility?: \"private\" | \"team\" | \"public\";\n agent_profile?: ManusProfile;\n credit_usage?: number;\n created_at?: number;\n updated_at?: number;\n created_by_api_key?: { id: string; name: string } | null;\n}\n\n/** Alias for backward compatibility */\nexport type ManusTaskResult = ManusTask;\n\n/** Task attachment */\nexport interface ManusTaskAttachment {\n type?: \"image\" | \"file\" | \"voice\" | \"slides\";\n filename?: string;\n url?: string;\n content_type?: string;\n}\n\n/** Task event from task.listMessages */\nexport interface ManusTaskEvent {\n id?: string;\n type?:\n | \"user_message\"\n | \"assistant_message\"\n | \"error_message\"\n | \"status_update\"\n | \"tool_used\"\n | \"plan_update\"\n | \"new_plan_step\"\n | \"explanation\"\n | \"user_stop\"\n | \"structured_output_result\";\n timestamp?: number;\n user_message?: {\n content?: string;\n message_type?: \"text\" | \"voice\";\n attachments?: ManusTaskAttachment[];\n };\n assistant_message?: {\n content?: string;\n attachments?: ManusTaskAttachment[];\n };\n error_message?: {\n error_type?: string;\n content?: string;\n };\n status_update?: {\n agent_status?: \"running\" | \"stopped\" | \"waiting\" | \"error\";\n status_detail?: string;\n waiting_for_event_type?: string;\n waiting_for_event_id?: string;\n confirm_input_schema?: Record<string, unknown>;\n };\n structured_output_result?: {\n success?: boolean;\n value?: unknown;\n error?: string;\n };\n // Verbose-only fields\n tool_used?: { name?: string; input?: string; output?: string };\n plan_update?: { steps?: unknown[] };\n new_plan_step?: { step?: unknown };\n explanation?: { content?: string };\n}\n\n/** Paginated message list from task.listMessages */\nexport interface ManusMessageList extends ManusApiResponse {\n task_id?: string;\n messages: ManusTaskEvent[];\n has_more?: boolean;\n next_cursor?: string;\n}\n\n/** Backward-compatible alias for code that uses ManusMessage */\nexport interface ManusMessage {\n id?: string;\n message_id?: string;\n task_id?: string;\n role: \"user\" | \"assistant\" | string;\n content: string;\n created_at?: string;\n}\n\n/** Attachment from old interface (backward compat) */\nexport interface ManusAttachment {\n name: string;\n url: string;\n content_type?: string;\n}\n\n/** Project object */\nexport interface ManusProject {\n id?: string;\n name?: string;\n description?: string;\n instruction?: string;\n created_at?: number;\n updated_at?: number;\n}\n\n/** Connector info */\nexport interface ManusConnectorInfo {\n id?: string;\n name?: string;\n type?: \"builtin\" | \"byok\" | \"mcp\";\n description?: string;\n}\n\n/** Skill info */\nexport interface ManusSkillInfo {\n id?: string;\n name?: string;\n description?: string;\n owner_type?: \"personal\" | \"official\" | \"team\" | \"marketplace\";\n}\n\n/** File info */\nexport interface ManusFile {\n id?: string;\n filename?: string;\n status?: \"pending\" | \"uploaded\" | \"deleted\" | \"error\";\n created_at?: number;\n}\n\n/** File detail */\nexport interface ManusFileDetail extends ManusFile {\n size?: number;\n content_type?: string;\n download_url?: string;\n}\n\n/** Agent */\nexport interface ManusAgent {\n id?: string;\n task_id?: string;\n nickname?: string;\n description?: string;\n avatar_url?: string;\n created_at?: number;\n updated_at?: number;\n}\n\n/** Browser client */\nexport interface ManusBrowserClient {\n client_id?: string;\n client_name?: string;\n ua?: string;\n}\n\n/** Webhook */\nexport interface ManusWebhook {\n id?: string;\n url?: string;\n status?: \"active\" | \"inactive\";\n created_at?: number;\n}\n\n/** Usage record */\nexport interface ManusUsageRecord {\n task_id?: string;\n title?: string;\n credits?: number;\n type?: string;\n created_at?: number;\n}\n\n/** Team usage log entry */\nexport interface ManusTeamUsageLog {\n user_id?: string;\n user_name?: string;\n email?: string;\n task_count?: number;\n credits?: number;\n}\n\n/** Daily statistic */\nexport interface ManusDailyStatistic {\n date?: number;\n credits?: number;\n}\n\n/** Website checkpoint */\nexport interface ManusWebsiteCheckpoint {\n version_id?: string;\n message?: string;\n status?: \"pending\" | \"success\" | \"failed\" | \"unspecified\";\n created_at?: number;\n}\n\n/** Task list item (from task.list) */\nexport interface ManusTaskListResponse extends ManusApiResponse {\n data?: ManusTask[];\n has_more?: boolean;\n next_cursor?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Fallback wrapper\n// ---------------------------------------------------------------------------\n\n/** Status codes that trigger a fallback retry. */\nconst FALLBACK_TRIGGER_CODES = new Set([401, 403, 429]);\n\nexport interface WithFallbackResult<T> {\n data: T;\n key_used: \"primary\" | \"fallback\";\n _httpStatus: number;\n}\n\nexport class ManusApiError extends Error {\n constructor(\n message: string,\n public readonly httpStatus: number,\n public readonly manusError: string | undefined,\n public readonly keyUsed: \"primary\" | \"fallback\",\n public readonly bothFailed: boolean,\n ) {\n super(message);\n this.name = \"ManusApiError\";\n }\n}\n\n/**\n * Execute `fn` with primary key; on FALLBACK_TRIGGER_CODES retry with fallback.\n * Throws ManusApiError only when all available keys fail on a trigger code.\n */\nexport async function withFallback<T>(\n fn: (apiKey: string) => Promise<WithFallbackResult<T>>,\n keys: ManusKeys,\n): Promise<WithFallbackResult<T>> {\n const primaryResult = await fn(keys.primary);\n\n if (!FALLBACK_TRIGGER_CODES.has(primaryResult._httpStatus)) {\n return { ...primaryResult, key_used: \"primary\" };\n }\n\n // Primary returned a trigger code — try fallback if available\n if (!keys.fallback) {\n throw new ManusApiError(\n `Manus API request failed: HTTP ${primaryResult._httpStatus}`,\n primaryResult._httpStatus,\n undefined,\n \"primary\",\n false,\n );\n }\n\n const fallbackResult = await fn(keys.fallback);\n\n if (!FALLBACK_TRIGGER_CODES.has(fallbackResult._httpStatus)) {\n return { ...fallbackResult, key_used: \"fallback\" };\n }\n\n throw new ManusApiError(\n `Manus API request failed with both keys: HTTP ${fallbackResult._httpStatus}`,\n fallbackResult._httpStatus,\n undefined,\n \"fallback\",\n true,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Internal fetch helpers\n// ---------------------------------------------------------------------------\n\nasync function manusPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>,\n): Promise<WithFallbackResult<T>> {\n const res = await fetch(`${MANUS_API_BASE}/${path}`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = (await res.json()) as T;\n return { _httpStatus: res.status, data, key_used: \"primary\" };\n}\n\nasync function manusGet<T>(\n path: string,\n apiKey: string,\n params?: Record<string, string | number | boolean | undefined>,\n): Promise<WithFallbackResult<T>> {\n const url = new URL(`${MANUS_API_BASE}/${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) {\n url.searchParams.set(k, String(v));\n }\n }\n }\n const res = await fetch(url.toString(), {\n headers: { \"x-manus-api-key\": apiKey },\n });\n const data = (await res.json()) as T;\n return { _httpStatus: res.status, data, key_used: \"primary\" };\n}\n\n// ---------------------------------------------------------------------------\n// TASK ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/task.create */\nexport async function createTask(\n keys: ManusKeys,\n opts: {\n prompt: string;\n title?: string;\n profile?: ManusProfile | string;\n outputSchema?: Record<string, unknown>;\n projectId?: string;\n locale?: string;\n interactiveMode?: boolean;\n hideInTaskList?: boolean;\n shareVisibility?: \"private\" | \"team\" | \"public\";\n connectors?: string[];\n enableSkills?: string[];\n forceSkills?: string[];\n },\n): Promise<WithFallbackResult<ManusTask>> {\n const message: Record<string, unknown> = { content: opts.prompt };\n if (opts.connectors?.length) message.connectors = opts.connectors;\n if (opts.enableSkills?.length) message.enable_skills = opts.enableSkills;\n if (opts.forceSkills?.length) message.force_skills = opts.forceSkills;\n\n const body: Record<string, unknown> = {\n message,\n agent_profile: opts.profile ?? MANUS_DEFAULT_PROFILE,\n hide_in_task_list: opts.hideInTaskList ?? true,\n interactive_mode: opts.interactiveMode ?? false,\n };\n if (opts.title) body.title = opts.title;\n if (opts.projectId) body.project_id = opts.projectId;\n if (opts.locale) body.locale = opts.locale;\n if (opts.shareVisibility) body.share_visibility = opts.shareVisibility;\n if (opts.outputSchema) body.structured_output_schema = opts.outputSchema;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.create\", apiKey, body),\n keys,\n );\n}\n\n/** GET /v2/task.detail */\nexport async function getTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusTask>> {\n return withFallback(\n (apiKey) => manusGet<ManusTask>(\"task.detail\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** GET /v2/task.list */\nexport async function listTasks(\n keys: ManusKeys,\n opts?: {\n scope?: \"standard\" | \"project\" | \"agent_subtask\";\n agentId?: string;\n projectId?: string;\n limit?: number;\n cursor?: string;\n },\n): Promise<WithFallbackResult<ManusTaskListResponse>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusTaskListResponse>(\"task.list\", apiKey, {\n scope: opts?.scope,\n agent_id: opts?.agentId,\n project_id: opts?.projectId,\n limit: opts?.limit,\n cursor: opts?.cursor,\n }),\n keys,\n );\n}\n\n/** GET /v2/task.listMessages */\nexport async function listMessages(\n keys: ManusKeys,\n taskId: string,\n opts?: {\n order?: \"asc\" | \"desc\";\n limit?: number;\n cursor?: string;\n verbose?: boolean;\n slidesFormat?: string;\n },\n): Promise<WithFallbackResult<ManusMessageList>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusMessageList>(\"task.listMessages\", apiKey, {\n task_id: taskId,\n order: opts?.order ?? \"desc\",\n limit: opts?.limit ?? 20,\n cursor: opts?.cursor,\n verbose: opts?.verbose,\n slides_format: opts?.slidesFormat,\n }),\n keys,\n );\n}\n\n/** POST /v2/task.sendMessage — reply to a task (replaces the old task.reply) */\nexport async function sendMessage(\n keys: ManusKeys,\n taskId: string,\n content: string,\n opts?: {\n agentProfile?: ManusProfile | string;\n connectors?: string[];\n enableSkills?: string[];\n forceSkills?: string[];\n outputSchema?: Record<string, unknown>;\n },\n): Promise<WithFallbackResult<ManusTask>> {\n const message: Record<string, unknown> = { content };\n if (opts?.connectors?.length) message.connectors = opts.connectors;\n if (opts?.enableSkills?.length) message.enable_skills = opts.enableSkills;\n if (opts?.forceSkills?.length) message.force_skills = opts.forceSkills;\n\n const body: Record<string, unknown> = {\n task_id: taskId,\n message,\n };\n if (opts?.agentProfile) body.agent_profile = opts.agentProfile;\n if (opts?.outputSchema) body.structured_output_schema = opts.outputSchema;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.sendMessage\", apiKey, body),\n keys,\n );\n}\n\n/**\n * Backward-compatible alias for sendMessage.\n * The old code called `askReply(keys, taskId, reply)` — this maps to task.sendMessage.\n */\nexport async function askReply(\n keys: ManusKeys,\n taskId: string,\n reply: string,\n): Promise<WithFallbackResult<ManusTask>> {\n return sendMessage(keys, taskId, reply);\n}\n\n/** POST /v2/task.confirmAction — confirm a pending action (not for messageAskUser) */\nexport async function confirmAction(\n keys: ManusKeys,\n taskId: string,\n eventId: string,\n input?: Record<string, unknown>,\n): Promise<WithFallbackResult<ManusTask>> {\n const body: Record<string, unknown> = {\n task_id: taskId,\n event_id: eventId,\n };\n if (input) body.input = input;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.confirmAction\", apiKey, body),\n keys,\n );\n}\n\n/** POST /v2/task.stop */\nexport async function stopTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"task.stop\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** POST /v2/task.delete */\nexport async function deleteTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"task.delete\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** POST /v2/task.update */\nexport async function updateTask(\n keys: ManusKeys,\n taskId: string,\n opts: {\n title?: string;\n shareVisibility?: \"private\" | \"team\" | \"public\";\n },\n): Promise<WithFallbackResult<ManusApiResponse>> {\n const body: Record<string, unknown> = { task_id: taskId };\n if (opts.title !== undefined) body.title = opts.title;\n if (opts.shareVisibility) body.share_visibility = opts.shareVisibility;\n\n return withFallback(\n (apiKey) => manusPost<ManusApiResponse>(\"task.update\", apiKey, body),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// PROJECT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/project.create */\nexport async function createProject(\n keys: ManusKeys,\n opts: {\n name: string;\n description?: string;\n instruction?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & { project?: ManusProject }>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { project?: ManusProject }>(\n \"project.create\",\n apiKey,\n opts,\n ),\n keys,\n );\n}\n\n/** GET /v2/project.list */\nexport async function listProjects(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusProject[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusProject[] }>(\n \"project.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// FILE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/file.upload (multipart/form-data) */\nexport async function uploadFile(\n keys: ManusKeys,\n file: Blob | ArrayBuffer,\n filename: string,\n): Promise<WithFallbackResult<ManusApiResponse & { file?: ManusFile }>> {\n return withFallback(async (apiKey) => {\n const formData = new FormData();\n const blob =\n file instanceof Blob ? file : new Blob([file]);\n formData.append(\"file\", blob, filename);\n\n const res = await fetch(`${MANUS_API_BASE}/file.upload`, {\n method: \"POST\",\n headers: { \"x-manus-api-key\": apiKey },\n body: formData,\n });\n const data = (await res.json()) as ManusApiResponse & {\n file?: ManusFile;\n };\n return { _httpStatus: res.status, data, key_used: \"primary\" as const };\n }, keys);\n}\n\n/** GET /v2/file.detail */\nexport async function getFileDetail(\n keys: ManusKeys,\n fileId: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { file?: ManusFileDetail }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { file?: ManusFileDetail }>(\n \"file.detail\",\n apiKey,\n { file_id: fileId },\n ),\n keys,\n );\n}\n\n/** POST /v2/file.delete */\nexport async function deleteFile(\n keys: ManusKeys,\n fileId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"file.delete\", apiKey, { file_id: fileId }),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// CONNECTOR & SKILL ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/connector.list */\nexport async function listConnectors(\n keys: ManusKeys,\n projectId?: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusConnectorInfo[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusConnectorInfo[] }>(\n \"connector.list\",\n apiKey,\n projectId ? { project_id: projectId } : undefined,\n ),\n keys,\n );\n}\n\n/** GET /v2/skill.list */\nexport async function listSkills(\n keys: ManusKeys,\n projectId?: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusSkillInfo[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusSkillInfo[] }>(\n \"skill.list\",\n apiKey,\n projectId ? { project_id: projectId } : undefined,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// AGENT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/agent.list */\nexport async function listAgents(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusAgent[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusAgent[] }>(\n \"agent.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n/** GET /v2/agent.detail */\nexport async function getAgentDetail(\n keys: ManusKeys,\n agentId: string,\n): Promise<WithFallbackResult<ManusApiResponse & { agent?: ManusAgent }>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { agent?: ManusAgent }>(\n \"agent.detail\",\n apiKey,\n { agent_id: agentId },\n ),\n keys,\n );\n}\n\n/** POST /v2/agent.update */\nexport async function updateAgent(\n keys: ManusKeys,\n agentId: string,\n opts: {\n nickname?: string;\n description?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & { agent?: ManusAgent }>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { agent?: ManusAgent }>(\n \"agent.update\",\n apiKey,\n { agent_id: agentId, ...opts },\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// BROWSER CLIENT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/browser.onlineList */\nexport async function listOnlineBrowsers(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusBrowserClient[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusBrowserClient[] }>(\n \"browser.onlineList\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// WEBHOOK ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/webhook.create */\nexport async function createWebhook(\n keys: ManusKeys,\n url: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { webhook?: ManusWebhook }>\n> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { webhook?: ManusWebhook }>(\n \"webhook.create\",\n apiKey,\n { url },\n ),\n keys,\n );\n}\n\n/** GET /v2/webhook.list */\nexport async function listWebhooks(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusWebhook[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusWebhook[] }>(\n \"webhook.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n/** POST /v2/webhook.delete */\nexport async function deleteWebhook(\n keys: ManusKeys,\n webhookId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"webhook.delete\", apiKey, {\n webhook_id: webhookId,\n }),\n keys,\n );\n}\n\n/** GET /v2/webhook.publicKey */\nexport async function getWebhookPublicKey(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { public_key?: string }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { public_key?: string }>(\n \"webhook.publicKey\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// USAGE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/usage.list */\nexport async function listUsage(\n keys: ManusKeys,\n opts?: { limit?: number; cursor?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: ManusUsageRecord[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: ManusUsageRecord[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >(\"usage.list\", apiKey, {\n limit: opts?.limit,\n cursor: opts?.cursor,\n }),\n keys,\n );\n}\n\n/** GET /v2/usage.teamStatistic */\nexport async function getTeamStatistic(\n keys: ManusKeys,\n opts?: { startDate?: string; endDate?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: {\n daily_statistics?: ManusDailyStatistic[];\n total_credits?: number;\n };\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: {\n daily_statistics?: ManusDailyStatistic[];\n total_credits?: number;\n };\n }\n >(\"usage.teamStatistic\", apiKey, {\n start_date: opts?.startDate,\n end_date: opts?.endDate,\n }),\n keys,\n );\n}\n\n/** GET /v2/usage.teamLog */\nexport async function getTeamLog(\n keys: ManusKeys,\n opts?: {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n sortBy?: string;\n isAsc?: boolean;\n },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: ManusTeamUsageLog[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: ManusTeamUsageLog[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >(\"usage.teamLog\", apiKey, {\n limit: opts?.limit,\n cursor: opts?.cursor,\n start_date: opts?.startDate,\n end_date: opts?.endDate,\n sort_by: opts?.sortBy,\n is_asc: opts?.isAsc,\n }),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// WEBSITE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/website.status */\nexport async function getWebsiteStatus(\n keys: ManusKeys,\n opts: { taskId?: string; websiteId?: string },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & Record<string, unknown>>(\n \"website.status\",\n apiKey,\n {\n task_id: opts.taskId,\n website_id: opts.websiteId,\n },\n ),\n keys,\n );\n}\n\n/** GET /v2/website.listCheckpoints */\nexport async function listWebsiteCheckpoints(\n keys: ManusKeys,\n opts: { taskId?: string; websiteId?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n website_id?: string;\n checkpoints?: ManusWebsiteCheckpoint[];\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n website_id?: string;\n checkpoints?: ManusWebsiteCheckpoint[];\n }\n >(\"website.listCheckpoints\", apiKey, {\n task_id: opts.taskId,\n website_id: opts.websiteId,\n }),\n keys,\n );\n}\n\n/** POST /v2/website.publish */\nexport async function publishWebsite(\n keys: ManusKeys,\n opts: {\n taskId?: string;\n websiteId?: string;\n visibility?: \"public\" | \"team\" | \"private\";\n },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n const body: Record<string, unknown> = {};\n if (opts.taskId) body.task_id = opts.taskId;\n if (opts.websiteId) body.website_id = opts.websiteId;\n if (opts.visibility) body.visibility = opts.visibility;\n\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & Record<string, unknown>>(\n \"website.publish\",\n apiKey,\n body,\n ),\n keys,\n );\n}\n\n/** POST /v2/website.update */\nexport async function updateWebsite(\n keys: ManusKeys,\n opts: {\n taskId?: string;\n websiteId?: string;\n versionId?: string;\n customDomain?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n const body: Record<string, unknown> = {};\n if (opts.taskId) body.task_id = opts.taskId;\n if (opts.websiteId) body.website_id = opts.websiteId;\n if (opts.versionId) body.version_id = opts.versionId;\n if (opts.customDomain) body.custom_domain = opts.customDomain;\n\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & Record<string, unknown>>(\n \"website.update\",\n apiKey,\n body,\n ),\n keys,\n );\n}\n","/**\n * Carrier MCP — Stripe Connect tools (Phase 16).\n *\n * Provides AI-agent access to the operator Stripe Connect layer.\n * All tools call the Stripe API directly using STRIPE_SECRET_KEY from env.\n * The connected account ID is looked up from CARRIER_USERS KV\n * under key `stripe_account:<operatorId>`.\n *\n * Tools registered here:\n * stripe_connect_status — read-only: account status + capabilities\n * stripe_connect_payouts — read-only: list recent payouts\n * stripe_connect_balance — read-only: available + pending balance\n * stripe_connect_refund — write (HARD_BLOCK): refund a charge\n * stripe_connect_dispute_list — read-only: list active disputes\n * radar_review_list — read-only: list pending Radar reviews\n * radar_review_approve — admin (HARD_BLOCK): approve a review\n * radar_review_decline — admin (HARD_BLOCK): decline/close a review\n * radar_value_list_add — admin (HARD_BLOCK): add to block/allow list\n * radar_rule_toggle — admin: documented stub (Stripe API limitation)\n *\n * HARD_BLOCK pattern: destructive tools require a confirm_token stored in\n * OAUTH_KV with a 5-min TTL (same pattern as pricing-tools.ts).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport * as Sentry from \"@sentry/cloudflare\";\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport { writeAudit } from \"./audit.js\";\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nexport interface StripeConnectToolContext {\n env: Env;\n props: CarrierProps;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Hard-block confirm token stored in KV with 5-min TTL. */\nasync function verifyConfirmToken(\n env: Env,\n sub: string,\n toolName: string,\n token: string,\n): Promise<boolean> {\n const key = `confirm:${sub}:${toolName}`;\n const stored = await env.OAUTH_KV.get(key);\n if (!stored || stored !== token) return false;\n await env.OAUTH_KV.delete(key); // single-use\n return true;\n}\n\nasync function issueConfirmToken(env: Env, sub: string, toolName: string): Promise<string> {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n const token = Array.from(bytes).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n const key = `confirm:${sub}:${toolName}`;\n await env.OAUTH_KV.put(key, token, { expirationTtl: 300 }); // 5 min TTL\n return token;\n}\n\ntype ToolResult = { content: Array<{ type: \"text\"; text: string }>; isError?: boolean };\n\nfunction ok(text: string): ToolResult {\n return { content: [{ type: \"text\", text }] };\n}\n\nfunction err(text: string): ToolResult {\n return { isError: true, content: [{ type: \"text\", text }] };\n}\n\n/** Call Stripe REST API (GET). */\nasync function stripeGet<T = unknown>(\n stripeKey: string,\n path: string,\n connectedAccountId?: string,\n): Promise<{ ok: boolean; status: number; data: T }> {\n const headers: Record<string, string> = { Authorization: `Bearer ${stripeKey}` };\n if (connectedAccountId) headers[\"Stripe-Account\"] = connectedAccountId;\n const res = await fetch(`https://api.stripe.com${path}`, { headers });\n const data = (await res.json()) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n/** Call Stripe REST API (POST, form-encoded). */\nasync function stripePost<T = unknown>(\n stripeKey: string,\n path: string,\n params: Record<string, string>,\n connectedAccountId?: string,\n): Promise<{ ok: boolean; status: number; data: T }> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n };\n if (connectedAccountId) headers[\"Stripe-Account\"] = connectedAccountId;\n const res = await fetch(`https://api.stripe.com${path}`, {\n method: \"POST\",\n headers,\n body: new URLSearchParams(params).toString(),\n });\n const data = (await res.json()) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n/** Doc + registry merge — mirrors the tool inventory in this file's header comment. */\nexport const STRIPE_CONNECT_TOOL_SCOPES: Record<string, ToolScope> = {\n stripe_connect_status: \"read\",\n stripe_connect_payouts: \"read\",\n stripe_connect_balance: \"read\",\n stripe_connect_refund: \"write\",\n stripe_connect_dispute_list: \"read\",\n radar_review_list: \"read\",\n radar_review_approve: \"admin\",\n radar_review_decline: \"admin\",\n radar_value_list_add: \"admin\",\n radar_rule_toggle: \"admin\",\n};\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerStripeConnectTools(\n server: McpServer,\n ctx: StripeConnectToolContext,\n): void {\n const { env, props } = ctx;\n const operatorId = props.org_id ?? props.sub;\n const kvKey = `stripe_account:${operatorId}`;\n\n /** Look up the operator's connected Stripe account ID from KV. */\n async function getAccountId(): Promise<string | null> {\n return env.CARRIER_USERS.get(kvKey);\n }\n\n // -------------------------------------------------------------------------\n // stripe_connect_status\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_status\",\n \"Read-only: returns the Stripe Connect account status, capabilities, and requirements for the authenticated operator.\",\n {\n operator_id: z\n .string()\n .optional()\n .describe(\"Override operator_id (admin use). Defaults to caller's org/user.\"),\n },\n async ({ operator_id }) => {\n const opId = operator_id ?? operatorId;\n const opKvKey = operator_id ? `stripe_account:${operator_id}` : kvKey;\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const accountId = await env.CARRIER_USERS.get(opKvKey);\n if (!accountId) {\n return ok(JSON.stringify({ status: \"not_connected\", operator_id: opId }));\n }\n\n const result = await stripeGet<{\n id: string;\n charges_enabled: boolean;\n payouts_enabled: boolean;\n details_submitted: boolean;\n requirements: unknown;\n capabilities: unknown;\n default_currency: string;\n settings?: { payouts?: { schedule?: { interval: string; delay_days: number } } };\n }>(stripeKey, `/v1/accounts/${accountId}`);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n const a = result.data;\n const status = a.charges_enabled && a.details_submitted ? \"active\" : \"pending\";\n\n writeAudit(env, {\n tool_name: \"stripe_connect_status\",\n ocs_method: \"stripe.account.read\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({\n status,\n operator_id: opId,\n account_id: accountId,\n charges_enabled: a.charges_enabled,\n payouts_enabled: a.payouts_enabled,\n details_submitted: a.details_submitted,\n requirements: a.requirements,\n capabilities: a.capabilities,\n default_currency: a.default_currency,\n payout_schedule: a.settings?.payouts?.schedule,\n }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_payouts\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_payouts\",\n \"Read-only: list recent payouts for the operator's connected Stripe account.\",\n {\n limit: z.number().int().min(1).max(50).default(10).describe(\"Number of payouts to return.\"),\n status: z\n .enum([\"pending\", \"paid\", \"failed\", \"canceled\", \"in_transit\"])\n .optional()\n .describe(\"Filter by payout status.\"),\n },\n async ({ limit, status }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (status) params.set(\"status\", status);\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n amount: number;\n currency: string;\n status: string;\n arrival_date: number;\n automatic: boolean;\n created: number;\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/payouts?${params.toString()}`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_payouts\",\n ocs_method: \"stripe.payouts.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ payouts: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_balance\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_balance\",\n \"Read-only: returns the current available and pending balance per currency for the operator's connected Stripe account.\",\n {},\n async () => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const result = await stripeGet<{\n available: Array<{ amount: number; currency: string }>;\n pending: Array<{ amount: number; currency: string }>;\n }>(stripeKey, `/v1/balance`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_balance\",\n ocs_method: \"stripe.balance.read\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({\n account_id: accountId,\n available: result.data.available ?? [],\n pending: result.data.pending ?? [],\n }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_refund (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_refund\",\n \"Admin: issue a refund on a charge via the operator's connected Stripe account. Requires confirm_token (call without token first to get one).\",\n {\n charge_id: z.string().min(1).describe(\"Stripe charge ID (ch_...).\"),\n amount_cents: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\"Partial refund amount in cents. Omit for full refund.\"),\n reason: z.enum([\"duplicate\", \"fraudulent\", \"requested_by_customer\"]).optional(),\n confirm_token: z\n .string()\n .optional()\n .describe(\"Confirmation token from previous call. Required to execute.\"),\n },\n async ({ charge_id, amount_cents, reason, confirm_token }) => {\n const start = Date.now();\n const toolName = \"stripe_connect_refund\";\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Refund ${amount_cents ? `${amount_cents} cents on` : \"(full) on\"} charge ${charge_id} requires confirmation.\\n` +\n `confirm_token: ${token}\\n` +\n `Call again with confirm_token=\"${token}\" to execute. Token expires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) {\n return err(\"Invalid or expired confirm_token. Call without token to get a new one.\");\n }\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params: Record<string, string> = { charge: charge_id };\n if (amount_cents) params.amount = String(amount_cents);\n if (reason) params.reason = reason;\n\n const result = await stripePost<{\n id: string;\n amount: number;\n currency: string;\n reason: string | null;\n status: string;\n }>(stripeKey, \"/v1/refunds\", params, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.refund.create\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Refund issued: ${result.data.id} — status: ${result.data.status}`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_dispute_list\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_dispute_list\",\n \"Read-only: list active disputes for the operator's connected Stripe account.\",\n {\n limit: z.number().int().min(1).max(50).default(10),\n status: z\n .string()\n .optional()\n .describe(\"Filter by dispute status (e.g. needs_response, under_review).\"),\n },\n async ({ limit, status }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (status) params.set(\"status\", status);\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n charge: string;\n amount: number;\n currency: string;\n status: string;\n reason: string;\n evidence_details: { due_by: number | null };\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/disputes?${params.toString()}`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_dispute_list\",\n ocs_method: \"stripe.disputes.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ disputes: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_list\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_list\",\n \"Read-only: list pending Radar reviews requiring manual platform decision.\",\n {\n open_only: z.boolean().default(true).describe(\"If true, only returns open (undecided) reviews.\"),\n limit: z.number().int().min(1).max(50).default(10),\n },\n async ({ open_only, limit }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (open_only) params.set(\"open\", \"true\");\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n charge: string | { id: string };\n reason: string | null;\n opened_reason: string | null;\n closed_reason: string | null;\n created: number;\n closed: boolean;\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/radar/reviews?${params.toString()}`);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"radar_review_list\",\n ocs_method: \"stripe.radar.reviews.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ reviews: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_approve (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_approve\",\n \"Admin: approve a Radar review, allowing the charge to proceed. Requires confirm_token.\",\n {\n review_id: z.string().min(1).describe(\"Stripe Radar review ID (prv_...).\"),\n confirm_token: z.string().optional(),\n },\n async ({ review_id, confirm_token }) => {\n const toolName = \"radar_review_approve\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Approving review ${review_id} allows the charge to proceed.\\n` +\n `confirm_token: ${token}\\nCall again with confirm_token=\"${token}\" to execute. Expires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const result = await stripePost<{ id: string; closed: boolean }>(\n stripeKey,\n `/v1/radar/reviews/${review_id}/approve`,\n {},\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.review.approve\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Review ${review_id} approved. Charge will proceed.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_decline (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_decline\",\n \"Admin: decline a Radar review, blocking/closing the charge. Requires confirm_token.\",\n {\n review_id: z.string().min(1),\n confirm_token: z.string().optional(),\n },\n async ({ review_id, confirm_token }) => {\n const toolName = \"radar_review_decline\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Declining review ${review_id} will close/block the charge.\\n` +\n `confirm_token: ${token}\\nExpires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n // Stripe closes a review by approving it with close_reason=fraudulent\n // or by calling close on the underlying charge. The /approve endpoint\n // with a reason is the supported path for platform-level decline.\n const result = await stripePost<{ id: string; closed: boolean }>(\n stripeKey,\n `/v1/radar/reviews/${review_id}/approve`,\n { reason: \"fraudulent\" },\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.review.decline\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Review ${review_id} declined.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_value_list_add (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_value_list_add\",\n \"Admin: add an item (email, IP, card fingerprint, country code) to a Stripe Radar block/allow list. Requires confirm_token.\",\n {\n value_list_id: z.string().min(1).describe(\"Stripe Radar value list ID (rsl_...).\"),\n value: z\n .string()\n .min(1)\n .describe(\"The value to add (email, IP address, country code, etc.).\"),\n confirm_token: z.string().optional(),\n },\n async ({ value_list_id, value, confirm_token }) => {\n const toolName = \"radar_value_list_add\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Adding \"${value}\" to list ${value_list_id} will affect future charge decisions.\\n` +\n `confirm_token: ${token}\\nExpires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const result = await stripePost<{ id: string; value: string }>(\n stripeKey,\n \"/v1/radar/value_list_items\",\n { value_list: value_list_id, value },\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.value_list.add\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Added \"${value}\" to Radar list ${value_list_id}.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_rule_toggle\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_rule_toggle\",\n \"Admin: enable or disable a Stripe Radar rule. NOTE: Stripe does not expose rule CRUD via the public API — this tool returns Dashboard instructions.\",\n {\n rule_id: z.string().min(1).describe(\"Stripe Radar rule ID.\"),\n enabled: z.boolean().describe(\"true = enable, false = disable.\"),\n },\n async ({ rule_id, enabled }) => {\n // Stripe Radar rules are not manageable via the REST API — only the Dashboard.\n return ok(\n `Stripe Radar does not expose rule enable/disable via the public API.\\n` +\n `To ${enabled ? \"enable\" : \"disable\"} rule ${rule_id}:\\n` +\n `1. Open https://dashboard.stripe.com/radar/rules\\n` +\n `2. Find rule ${rule_id} and toggle it ${enabled ? \"on\" : \"off\"}.\\n\\n` +\n `Note: If you need this automated, use the Radar for Platforms beta — contact Stripe support at https://support.stripe.com.`,\n );\n },\n );\n}\n","import type { Env, AuditRow } from \"./types.js\";\n\n/**\n * Fire-and-forget Analytics Engine write.\n * Never await — AE writes are non-blocking and best-effort.\n *\n * Schema:\n * blobs[0] = tool_name\n * blobs[1] = ocs_method\n * blobs[2] = status ('ok' | 'error' | 'scope_denied' | 'dry_run')\n * blobs[3] = dry_run ('0' | '1')\n * blobs[4] = sub (user email)\n * blobs[5] = manus_task_id (empty when not a Manus dispatch)\n * blobs[6] = manus_profile (empty when absent)\n * blobs[7] = manus_key_used: \"primary\" | \"fallback\" (empty when absent)\n * doubles[0] = duration_ms\n * doubles[1] = ocs_status_code (0 = success, -1 = network error)\n * indexes[0] = reseller_id (string; enables per-reseller filtering in SQL queries)\n *\n * Query example (Workers Analytics Engine SQL API):\n * SELECT blob1 AS tool, SUM(_sample_interval) AS calls\n * FROM carrier_mcp_audit\n * WHERE timestamp > NOW() - INTERVAL '7' DAY\n * GROUP BY tool ORDER BY calls DESC\n *\n * Note: use SUM(_sample_interval) not COUNT(*) — AE downsamples at high volume.\n */\nexport function writeAudit(\n env: Env,\n row: AuditRow & { sub: string; reseller_id: number },\n): void {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n row.tool_name,\n row.ocs_method,\n row.status,\n row.dry_run ? \"1\" : \"0\",\n row.sub,\n row.manus_task_id ?? \"\",\n row.manus_profile ?? \"\",\n row.manus_key_used ?? \"\",\n ],\n doubles: [row.duration_ms, row.ocs_status_code ?? 0],\n indexes: [String(row.reseller_id)],\n });\n}\n"],"mappings":"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L,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA;AAAA,EAGL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA;AAAA,EAGL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA;AAAA,EAGL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAA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","names":["baseUrl","token","result","token","err","server","z","token","err","server","z","z","DRY_RUN_FIELD","z","server","token","result","client","z","token","err","server","z","z","server","result","err","z","err","server","z","token","z","registerAppTool","registerAppResource","RESOURCE_MIME_TYPE","safeCallWithToken","err","server","registerAppResource","RESOURCE_MIME_TYPE","registerAppTool","z","token","result","z","registerAppTool","registerAppResource","RESOURCE_MIME_TYPE","safeCallWithToken","err","server","registerAppResource","RESOURCE_MIME_TYPE","registerAppTool","z","token","result","newBalance","structured","server","z","server","z","currentMonth","firstDayNextMonth","currentMonth","currentMonth","firstDayNextMonth","resolveUserTier","resolveUserTier","props","props","token","server","result","err","z","z","token","err","server","z","result","err","z","baseUrl","noManusKeyError","result","err","server","z","z","MANUS_API_BASE","MANUS_API_BASE","server","z","result","err","z","Sentry","token","server","props","z","result","token"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/tools.ts","../src/client.ts","../src/billing.ts","../src/intelligence.ts","../../../packages/ocs-spec/ocs-methods.json","../../../packages/ocs-spec/src/mcc-iso.ts","../../../packages/ocs-spec/src/index.ts","../src/tools-backlog.ts","../src/tools-carrier-ask.ts","../src/list-recent-ocs-events.ts","../src/apps/fleet-health-app.ts","../src/apps/provisioning-wizard.ts","../src/apps/app-state.ts","../src/apps/balance-topup.ts","../src/apps/index.ts","../src/prompts.ts","../src/tools-pricing.ts","../src/credits.ts","../src/billing-thresholds.ts","../src/pricing-tools.ts","../src/projects-tools.ts","../src/tools-ui-agent-schedule.ts","../src/manus-common.ts","../src/manus-schedule.ts","../src/manus-usage.ts","../src/tools-ui-agent.ts","../src/clerk.ts","../src/tools-ui-agent-ask.ts","../src/manus-webhook.ts","../src/manus-client.ts","../src/stripe-connect-tools.ts","../src/audit.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Carrier MCP — single-user stdio entry point (MCPB / DXT bundle target).\n *\n * Reads CARRIER_OCS_API_TOKEN from env; calls OCS directly with that token.\n * No OAuth, no Workers — for local Claude Desktop installs via the .mcpb bundle.\n *\n * For multi-user deployments, use the remote OAuth endpoint at mcp.carrier.llc/mcp.\n *\n * Tool registry MUST mirror agent.ts exactly so that generate-docs / verify-fidelity\n * produce the same tool list as the deployed Worker.\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { registerAllTools } from \"./tools.js\";\nimport { registerIntelligenceTools } from \"./intelligence.js\";\nimport { registerAllBacklogTools } from \"./tools-backlog.js\";\nimport { registerAllCarrierAskTools } from \"./tools-carrier-ask.js\";\nimport { registerListRecentOcsEventsTool } from \"./list-recent-ocs-events.js\";\nimport { registerAllApps } from \"./apps/index.js\";\nimport { registerAllPrompts } from \"./prompts.js\";\nimport { registerAllPricingTools } from \"./tools-pricing.js\";\nimport { registerScheduleAndUsageTools } from \"./tools-ui-agent-schedule.js\";\nimport { registerAllUiAgentTools } from \"./tools-ui-agent.js\";\nimport { registerUiAgentAskTools } from \"./tools-ui-agent-ask.js\";\nimport { registerStripeConnectTools } from \"./stripe-connect-tools.js\";\nimport type { CarrierProps, AuditRow, Env } from \"./types.js\";\n\nconst baseUrl =\n process.env.CARRIER_OCS_BASE_URL ??\n process.env.ESIMVAULT_BASE_URL ??\n \"https://ocs.esimvault.cloud\";\nconst token =\n process.env.CARRIER_OCS_API_TOKEN ?? process.env.ESIMVAULT_API_TOKEN;\n\nif (!token) {\n console.error(\n \"ERROR: CARRIER_OCS_API_TOKEN (or legacy ESIMVAULT_API_TOKEN) must be set.\",\n );\n process.exit(1);\n}\n\n// Minimal env shim — stdio mode never touches KV/R2/AE/secrets at runtime.\n// CF-only bindings (OAUTH_KV, OCS_EVENT_ROUTING, ASSETS, CARRIER_USERS, DOWNLOADS)\n// are stubbed so that tool *registration* succeeds; their handlers would error if\n// actually invoked in stdio mode (acceptable — these tools require the Workers runtime).\nconst stdioEnv = {\n CARRIER_OCS_BASE_URL: baseUrl,\n CARRIER_TOKEN_ENCRYPTION_KEY: \"\",\n SENTRY_DSN: \"\",\n CLERK_PUBLISHABLE_KEY: \"\",\n CLERK_SECRET_KEY: \"\",\n CLERK_WEBHOOK_SECRET: \"\",\n AUDIT_LOG: { writeDataPoint: (_: unknown) => undefined },\n OAUTH_KV: null,\n OCS_EVENT_ROUTING: null,\n ASSETS: null,\n CARRIER_USERS: null,\n DOWNLOADS: null,\n MANUS_API_KEY: \"\",\n STRIPE_SECRET_KEY: \"\",\n} as unknown as Env;\n\nconst props: CarrierProps = {\n sub: \"stdio@local\",\n reseller_id: 0,\n reseller_name: \"stdio\",\n tier: \"enterprise\",\n scope: [\"read\", \"write\", \"admin\"],\n};\n\nconst audit = (_row: AuditRow): void => {\n // no-op in stdio mode\n};\n\nconst getUserToken = async (_sub: string): Promise<string> => token;\n\nconst toolCtx = { env: stdioEnv, props, audit, getUserToken };\n\nconst server = new McpServer(\n { name: \"carrier-mcp\", version: \"0.2.4\" },\n {\n instructions:\n \"Carrier MCP — single-user stdio mode. Full tool registry (mirrors the deployed Worker).\",\n },\n);\n\n// v1: 43 OCS API wrappers\nregisterAllTools(server, toolCtx);\n// v1 intelligence: 8 AI composite tools\nregisterIntelligenceTools(server, toolCtx);\n// v1.1 backlog: 8 confirmed-live OCS methods\nregisterAllBacklogTools(server, toolCtx);\n// NL router: carrier_ask + carrier_ask_describe\nregisterAllCarrierAskTools(server, toolCtx);\n// OCS event ring-buffer tool\nregisterListRecentOcsEventsTool(server, stdioEnv);\n// v1.2 MCP Apps (fleet-health, provisioning-wizard, balance-topup)\nregisterAllApps(server, toolCtx);\n// Pricing + projects tools\nregisterAllPricingTools(server, toolCtx);\n// UI agent schedule + usage tools\nregisterScheduleAndUsageTools(server, toolCtx);\n// UI agent write tools\nregisterAllUiAgentTools(server, toolCtx);\n// UI agent ask/reply tools\nregisterUiAgentAskTools(server, toolCtx);\n// Stripe Connect + Radar tools\nregisterStripeConnectTools(server, { env: stdioEnv, props });\nregisterAllPrompts(server);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n","/**\n * Carrier MCP — OCS tool registrations (43 tools).\n *\n * All 43 OCS v1 methods are exposed as MCP tools. Each is wrapped with:\n * - Scope enforcement (read / write / admin)\n * - Dry-run short-circuit for destructive tools (no OCS call)\n * - Sentry error capture\n * - Audit hook into Analytics Engine\n * - Per-user token resolution via getUserToken(sub)\n *\n * Scope assignments live in TOOL_SCOPES below; must match packages/ocs-spec/ocs-methods.json.\n *\n * PR #10 schema fixes applied:\n * Fix #1: getSimProviderStatus — ICCID → simId lookup → bare integer\n * Fix #2: hlrGetBitrate — ICCID → IMSI lookup → { imsi }\n * Fix #3: hlrSetBitrate — ICCID → IMSI + bitrate → limit rename → { imsi, limit }\n * Fix #4: subscriberUsageOverPeriod — { subscriber: { iccid }, period: { start, end } }\n * Fix #5: subscriberNetworkEventsOverPeriod — same nested shape\n * Fix #6: modifySubscriberStatus — { subscriber, newStatus }\n * Fix #7: modifySubscriberBalance — { subscriber, amount } or { subscriber, setBalance }\n * Fix #8: changeSimStatus — ICCID → simId + simStatus → newStatus\n * Fix #9: modifySubscriberContactInfo — firstName+lastName → name, email→mail, phone→phone\n * Fix #10: setSubscriberTrafficRestrictions — typed booleans, not JSON string\n * Fix #11: sendMtSms — ICCID→IMSI, message→text, sender→senderId\n * Fix #12: listSponsor — bare integer (resellerId)\n * Fix #13: listSteeringList — bare integer (resellerId)\n * Fix #14: getCustomerTariff — bare integer + response key listTariffRule\n * Fix #15: listDetailedLocationZone — bare integer (resellerId)\n * Fix #16: modifySubscriberSteeringList — { subscriber, steeringListId }\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport * as Sentry from \"@sentry/cloudflare\";\nimport { OcsClient, OcsApiError } from \"./client.js\";\nimport type { Env, CarrierProps, AuditRow, ToolScope } from \"./types.js\";\nimport { checkCallQuota, recordUsage, UPGRADE_URL } from \"./billing.js\";\n\nexport interface ToolContext {\n env: Env;\n props: CarrierProps;\n audit: (row: AuditRow) => void;\n getUserToken: (sub: string) => Promise<string>;\n}\n\n// Scope metadata per tool — all 43 tools declared here.\n// Must stay in sync with ocs-methods.json from packages/ocs-spec.\nexport const TOOL_SCOPES: Record<string, ToolScope> = {\n // --- read ---\n list_reseller_accounts: \"read\",\n get_reseller_info: \"read\",\n esim_status_per_account: \"read\",\n list_sponsors: \"read\",\n list_steering_lists: \"read\",\n get_subscriber: \"read\",\n list_subscribers: \"read\",\n get_sim_provider_status: \"read\",\n get_subscriber_location: \"read\",\n hlr_get_bitrate: \"read\",\n list_subscriber_packages: \"read\",\n list_package_templates: \"read\",\n list_location_zones: \"read\",\n list_detailed_location_zones: \"read\",\n list_destination_prefixes: \"read\",\n subscriber_usage: \"read\",\n subscriber_network_events: \"read\",\n subscriber_active_period: \"read\",\n get_tariff: \"read\",\n list_network_profiles: \"read\",\n // --- intelligence composites ---\n detect_country_entry: \"read\",\n // --- write ---\n modify_subscriber_balance: \"write\",\n modify_subscriber_status: \"write\",\n modify_subscriber_contact_info: \"write\",\n set_subscriber_traffic_restrictions: \"write\",\n modify_subscriber_steering_list: \"write\",\n move_subscriber_range_to_account: \"write\",\n hlr_set_bitrate: \"write\",\n assign_package: \"write\",\n assign_recurring_package: \"write\",\n modify_package_limits: \"write\",\n modify_package_expiry: \"write\",\n modify_package_status: \"write\",\n stop_resume_recurring_package: \"write\",\n create_package_template: \"write\",\n create_location_zone: \"write\",\n // --- admin ---\n modify_account_balance: \"admin\", // corrected per ocs-spec PR #6\n change_sim_status: \"admin\",\n delete_subscriber_package: \"admin\",\n clean_all_packages: \"admin\",\n modify_template_core: \"admin\",\n modify_template_recurring: \"admin\",\n modify_template_throttling: \"admin\",\n send_sms: \"admin\",\n};\n\nexport const DESTRUCTIVE_TOOLS = new Set([\n \"modify_account_balance\",\n \"modify_subscriber_balance\",\n \"modify_subscriber_status\",\n \"change_sim_status\",\n \"modify_subscriber_contact_info\",\n \"set_subscriber_traffic_restrictions\",\n \"modify_subscriber_steering_list\",\n \"move_subscriber_range_to_account\",\n \"hlr_set_bitrate\",\n \"assign_package\",\n \"assign_recurring_package\",\n \"modify_package_limits\",\n \"modify_package_expiry\",\n \"modify_package_status\",\n \"stop_resume_recurring_package\",\n \"delete_subscriber_package\",\n \"clean_all_packages\",\n \"modify_template_core\",\n \"modify_template_recurring\",\n \"modify_template_throttling\",\n \"create_package_template\",\n \"create_location_zone\",\n \"send_sms\",\n // v1.1 backlog — same dry_run contract as v1 write/admin tools (tools-backlog.ts)\n \"affect_subscriber_phone_number\",\n \"modify_subscriber_mobile_plan\",\n \"modify_subscriber_package_active_period\",\n \"modify_subscriber_voip_plan\",\n \"push_steering_to_subscriber\",\n \"reset_subscriber_gz_counter\",\n]);\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n/**\n * Wraps a tool handler with scope enforcement, dry-run short-circuit,\n * Sentry capture, and audit logging.\n */\nexport function wrapHandler<T extends Record<string, unknown>>(\n toolName: string,\n ocsMethod: string,\n requiredScope: ToolScope,\n ctx: ToolContext,\n handler: (args: T, token: string) => Promise<ToolResult>,\n) {\n return async (args: T & { dry_run?: boolean }): Promise<ToolResult> => {\n const start = Date.now();\n const isDryRun = args.dry_run === true;\n\n // Scope enforcement\n if (!ctx.props.scope.includes(requiredScope)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Scope denied: tool '${toolName}' requires '${requiredScope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Billing quota check (Phase 7 — v1.1)\n // Enterprise is unlimited; free/pro are gate-checked against KV counter.\n const quota = await checkCallQuota(ctx.env, ctx.props.sub, ctx.props.tier);\n if (!quota.allowed) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"quota_exceeded\",\n dry_run: isDryRun,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: [\n `Quota exceeded: your ${quota.tier} plan has reached the safety limit of 100,000 regular tool calls/month.`,\n `This limit exists to prevent runaway automation. Resets ${quota.resetAt}.`,\n `Upgrade to Pro for unlimited calls at ${UPGRADE_URL}`,\n ].join(\" \"),\n },\n ],\n };\n }\n\n // Dry-run short-circuit for destructive tools\n if (isDryRun && DESTRUCTIVE_TOOLS.has(toolName)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"dry_run\",\n dry_run: true,\n duration_ms: 0,\n });\n return {\n content: [\n {\n type: \"text\",\n text: `[dry_run=true] Would execute '${toolName}' (OCS method '${ocsMethod}') with args: ${JSON.stringify(args)}. No changes made.`,\n },\n ],\n };\n }\n\n let result: ToolResult;\n try {\n const token = await ctx.getUserToken(ctx.props.sub);\n result = await handler(args, token);\n } catch (err) {\n try {\n Sentry.captureException(err, {\n tags: {\n tool: toolName,\n feature: \"mcp\",\n reseller_id: String(ctx.props.reseller_id),\n },\n });\n } catch {\n // Sentry may not be initialised in tests — swallow.\n }\n const message = err instanceof Error ? err.message : String(err);\n const ocsCode = err instanceof OcsApiError ? err.code : undefined;\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: \"error\",\n dry_run: isDryRun,\n duration_ms: Date.now() - start,\n ...(ocsCode !== undefined ? { ocs_status_code: ocsCode } : {}),\n });\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${message}` }],\n };\n }\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: ocsMethod,\n status: result.isError ? \"error\" : \"ok\",\n dry_run: isDryRun,\n duration_ms: Date.now() - start,\n });\n\n // Record usage on successful (non-error, non-dry-run) calls.\n // Fire-and-forget — never blocks the response.\n if (!result.isError && !isDryRun) {\n recordUsage(ctx.env, ctx.props.sub, ctx.props.tier);\n }\n\n return result;\n };\n}\n\n// ---------------------------------------------------------------------------\n// OCS call helper — accepts explicit token (no module-level singleton).\n// Fix: params broadened to accept bare scalar for methods that expect it\n// (listSponsor, listSteeringList, getCustomerTariff, listDetailedLocationZone,\n// getSimProviderStatus).\n// ---------------------------------------------------------------------------\nasync function ocsCall<T = Record<string, unknown>>(\n env: Env,\n token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<ToolResult> {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call<T>(method, params);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Request-scoped subscriber lookup cache (ICCID → subscriber record).\n// Prevents N+1 lookups when tools need simId or IMSI from the same subscriber.\n// Fix #1, #2, #3, #8, #11 depend on this resolver.\n// ---------------------------------------------------------------------------\ntype SubscriberRecord = Record<string, unknown>;\n\nexport async function resolveSubscriberByIccid(\n env: Env,\n token: string,\n iccid: string,\n cache: Map<string, SubscriberRecord>,\n): Promise<SubscriberRecord> {\n const hit = cache.get(iccid);\n if (hit) return hit;\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const record = await client.call<SubscriberRecord>(\"getSingleSubscriber\", { iccid });\n cache.set(iccid, record);\n return record;\n}\n\n// ---------------------------------------------------------------------------\n// Fetch the token owner's reseller ID via getResellerInfo.\n// Used for bare-integer OCS methods: listSponsor, listSteeringList,\n// getCustomerTariff, listDetailedLocationZone.\n// Fix #12, #13, #14, #15.\n// ---------------------------------------------------------------------------\nexport async function getDefaultResellerId(env: Env, token: string): Promise<number> {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const info = await client.call<{ id?: number }>(\"getResellerInfo\", {});\n const id = info?.id;\n if (typeof id !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return id;\n}\n\n// Shorthand: build the destructive-tool annotation + dry_run schema field\nconst DRY_RUN_FIELD = {\n dry_run: z\n .boolean()\n .optional()\n .describe(\n \"If true, do not call OCS — return the would-be request for confirmation\",\n ),\n};\n\nexport function registerAllTools(server: McpServer, ctx: ToolContext): void {\n // =========================================================================\n // 1. RESELLER TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_reseller_accounts\",\n {\n title: \"List Reseller Accounts\",\n description:\n \"Use this to enumerate all accounts (sub-resellers or customer accounts) under a reseller. \" +\n \"Returns each account's name, ID, current balance, package-only flag, and account type. \" +\n \"Params: `resellerId` (integer, optional — omit to list accounts under the token owner's reseller). \" +\n \"Returns: array of account records, each containing `accountId`, `name`, `balance`, `type`. \" +\n \"Do NOT use this to fetch a single subscriber's details — use `get_subscriber` instead. \" +\n \"Do NOT use this to check eSIM activation counts — use `esim_status_per_account` for that.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Filter to a specific reseller by ID (omit for token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_reseller_accounts\",\n \"listResellerAccount\",\n TOOL_SCOPES[\"list_reseller_accounts\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.resellerId = resellerId;\n return ocsCall(ctx.env, token, \"listResellerAccount\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_account_balance\",\n {\n title: \"Modify Account Balance\",\n description:\n \"Use this to adjust or set the monetary balance on a reseller account. \" +\n \"'adapt' mode adds (positive amount) or subtracts (negative amount) from the current balance; \" +\n \"'set' mode replaces the balance with the exact amount. Every change is logged as a transaction. \" +\n \"Params: `accountId` (integer account ID from `list_reseller_accounts`), `amount` (number), \" +\n \"`mode` ('adapt' | 'set'). \" +\n \"Returns: updated account balance record with the transaction ID. \" +\n \"Do NOT use this to modify a subscriber's personal balance — use `modify_subscriber_balance` instead. \" +\n \"Always call `list_reseller_accounts` first to confirm the target accountId before executing.\",\n inputSchema: {\n accountId: z.number().describe(\"The account ID to modify\"),\n amount: z.number().describe(\"Amount to add (adapt) or set to (set)\"),\n mode: z\n .enum([\"adapt\", \"set\"])\n .describe(\"'adapt' adds/subtracts, 'set' replaces the balance\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_account_balance\",\n \"modifyAccountBalance\",\n TOOL_SCOPES[\"modify_account_balance\"]!,\n ctx,\n async ({ accountId, amount, mode }, token) => {\n const params: Record<string, unknown> = { accountId };\n if (mode === \"adapt\") params.adaptBalance = amount;\n else params.setBalance = amount;\n return ocsCall(ctx.env, token, \"modifyAccountBalance\", params);\n },\n ),\n );\n\n server.registerTool(\n \"get_reseller_info\",\n {\n title: \"Get Reseller Info\",\n description:\n \"Use this to retrieve full details for a reseller: main info, traffic configuration, \" +\n \"charging info, contact info, and active pricing plans. \" +\n \"Params: `resellerId` (integer, optional — omit to return the token owner's reseller). \" +\n \"Returns: reseller object with `id`, `name`, `balance`, `pricingPlan`, `contactInfo`, and more. \" +\n \"Do NOT use this to list all accounts under a reseller — use `list_reseller_accounts` for that.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit for token owner)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_reseller_info\",\n \"getResellerInfo\",\n TOOL_SCOPES[\"get_reseller_info\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.resellerId = resellerId;\n return ocsCall(ctx.env, token, \"getResellerInfo\", params);\n },\n ),\n );\n\n server.registerTool(\n \"esim_status_per_account\",\n {\n title: \"eSIM Status Per Account\",\n description:\n \"Use this to get eSIM status counts broken down by account: active, suspended, inventory \" +\n \"(not yet activated), and other states. Good for fleet health dashboards and capacity planning. \" +\n \"OCS requires either `accountId` OR `resellerId`. If both omitted, the token owner's reseller is resolved automatically. \" +\n \"Params: `accountId` (integer, optional — for a single account), `resellerId` (integer, optional — for all accounts under a specific reseller). \" +\n \"Returns: array of per-account objects with `accountId`, `active`, `suspended`, `inventory`, `other`. \" +\n \"Do NOT use this to check a single subscriber's status — use `get_subscriber` for that. \" +\n \"Do NOT use this for billing or balance checks — use `list_reseller_accounts` for balances.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter to a specific account\"),\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"esim_status_per_account\",\n \"esimStatusPerAccount\",\n TOOL_SCOPES[\"esim_status_per_account\"]!,\n ctx,\n async ({ accountId, resellerId }, token) => {\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) {\n params.accountId = accountId;\n } else {\n params.resellerId = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n }\n return ocsCall(ctx.env, token, \"esimStatusPerAccount\", params);\n },\n ),\n );\n\n // Fix #12: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_sponsors\",\n {\n title: \"List Sponsors\",\n description:\n \"Use this to list all sponsor networks (eSIM sponsor carriers) available to this reseller. \" +\n \"A sponsor defines which physical network infrastructure backs a given eSIM profile. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of sponsor records with `sponsorId`, `name`, and coverage metadata. \" +\n \"Do NOT use this to list steering lists or network profiles — those are separate concepts. \" +\n \"Use `list_steering_lists` to see operator preference configurations.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_sponsors\",\n \"listSponsor\",\n TOOL_SCOPES[\"list_sponsors\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listSponsor\", id);\n },\n ),\n );\n\n // Fix #13: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_steering_lists\",\n {\n title: \"List Steering Lists\",\n description:\n \"Use this to retrieve all network steering lists configured for this reseller. \" +\n \"A steering list is a named configuration of excluded and priority mobile operators that \" +\n \"controls which networks an eSIM prefers to roam onto — the primary mechanism for network \" +\n \"quality optimisation and cost control. Call this before `modify_subscriber_steering_list` \" +\n \"to obtain valid steering list IDs. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of steering list records with `steeringListId`, `name`, and configured operators. \" +\n \"Do NOT use this to assign a steering list to a subscriber — use `modify_subscriber_steering_list`. \" +\n \"Do NOT use this to push a steering change to a device — use `push_steering_to_subscriber` after assignment.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_steering_lists\",\n \"listSteeringList\",\n TOOL_SCOPES[\"list_steering_lists\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listSteeringList\", id);\n },\n ),\n );\n\n // =========================================================================\n // 2. SUBSCRIBER TOOLS\n // =========================================================================\n\n server.registerTool(\n \"get_subscriber\",\n {\n title: \"Get Single Subscriber\",\n description:\n \"Use this as the primary lookup for a single subscriber by ICCID or MSISDN. \" +\n \"Returns the complete subscriber record: status, balance, assigned account, contact info, \" +\n \"IMSI, simId, steering list, active pricing plan, and traffic restriction flags. \" +\n \"Params: `iccid` (20-digit ICC identifier, optional) OR `msisdn` (E.164 phone number, optional) — \" +\n \"provide at least one. \" +\n \"Optional: `with_gz_counter` (boolean) — when true, includes `greenZoneCounter` in the response: \" +\n \"{ subscriberId, volumeOnGZ (bytes consumed on reseller whitelist hosts/IPs after bundle depletion), \" +\n \"lastResetDate, lastUpdateDate }. Omit or set false to skip the GZ counter (default). \" +\n \"Returns: full subscriber object. Key fields: `status` (ACTIVE/SUSPENDED/TERMINATED), \" +\n \"`balance`, `imsi`, `simId`, `steeringListId`. \" +\n \"Do NOT use this for bulk lookups — use `list_subscribers` with filters for that.\",\n inputSchema: {\n iccid: z.string().optional().describe(\"The ICCID of the subscriber\"),\n msisdn: z\n .string()\n .optional()\n .describe(\"The MSISDN (phone number) of the subscriber\"),\n with_gz_counter: z\n .boolean()\n .optional()\n .describe(\n \"When true, include greenZoneCounter { subscriberId, volumeOnGZ (bytes), lastResetDate, lastUpdateDate } — tracks bytes consumed on reseller whitelist hosts/IPs after bundle depletion\",\n ),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber\",\n \"getSingleSubscriber\",\n TOOL_SCOPES[\"get_subscriber\"]!,\n ctx,\n async ({ iccid, msisdn, with_gz_counter }, token) => {\n const params: Record<string, unknown> = {};\n if (iccid) params.iccid = iccid;\n if (msisdn) params.msisdn = msisdn;\n if (with_gz_counter === true) params.withGzCounter = true;\n return ocsCall(ctx.env, token, \"getSingleSubscriber\", params);\n },\n ),\n );\n\n server.registerTool(\n \"list_subscribers\",\n {\n title: \"List Subscribers\",\n description:\n \"Use this to list subscribers with optional filters and pagination. Good for fleet enumeration, \" +\n \"bulk status checks, and finding subscribers by account or status. \" +\n \"OCS REQUIRES at least one search key — provide exactly one of: `imsi`, `iccid`, `activationCode`, \" +\n \"`accountId`, or `msisdn`. Calling with no key will be rejected before reaching OCS. \" +\n \"Params: `imsi` (string), `iccid` (string), `activationCode` (string), `accountId` (integer), \" +\n \"`msisdn` (string), `status` (string, e.g. 'ACTIVE'/'SUSPENDED'), `offset` (integer, pagination — default 0), \" +\n \"`limit` (integer, max results — always set to avoid unbounded fetches; recommended max 100 per call). \" +\n \"Returns: array of subscriber summary records with ICCID, status, and account. \" +\n \"Do NOT use this to fetch full details for a specific subscriber — use `get_subscriber` for that.\",\n inputSchema: z\n .object({\n imsi: z.string().optional().describe(\"Filter by IMSI\"),\n iccid: z.string().optional().describe(\"Filter by ICCID\"),\n activationCode: z\n .string()\n .optional()\n .describe(\"Filter by activation code\"),\n accountId: z.number().optional().describe(\"Filter by account ID\"),\n msisdn: z.string().optional().describe(\"Filter by MSISDN\"),\n status: z.string().optional().describe(\"Filter by status\"),\n offset: z.number().optional().describe(\"Pagination offset\"),\n limit: z.number().optional().describe(\"Max results to return\"),\n })\n .refine(\n (d) =>\n d.imsi !== undefined ||\n d.iccid !== undefined ||\n d.activationCode !== undefined ||\n d.accountId !== undefined ||\n d.msisdn !== undefined,\n {\n message:\n \"Provide at least one of: imsi, iccid, activationCode, accountId, msisdn\",\n },\n ),\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_subscribers\",\n \"listSubscriber\",\n TOOL_SCOPES[\"list_subscribers\"]!,\n ctx,\n async (args, token) => {\n // OCS listSubscriber does not accept `limit` — strip it before forwarding.\n // We keep `limit` in the inputSchema as a UX hint so callers can express intent.\n const params: Record<string, unknown> = {};\n if (args.imsi) params.imsi = args.imsi;\n if (args.iccid) params.iccid = args.iccid;\n if (args.activationCode) params.activationCode = args.activationCode;\n if (args.accountId !== undefined) params.accountId = args.accountId;\n if (args.msisdn) params.msisdn = args.msisdn;\n if (args.status) params.status = args.status;\n if (args.offset !== undefined) params.offset = args.offset;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const raw = await client.call<unknown>(\"listSubscriber\", params);\n const limit = args.limit;\n const payload =\n Array.isArray(raw) && typeof limit === \"number\" && limit >= 0\n ? raw.slice(0, limit)\n : raw;\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n },\n ),\n );\n\n // Fix #7: OCS expects { subscriber, amount } or { subscriber, setBalance } not { iccid, adaptBalance|setBalance }\n server.registerTool(\n \"modify_subscriber_balance\",\n {\n title: \"Modify Subscriber Balance\",\n description:\n \"Use this to adjust or set the monetary balance for an individual subscriber. \" +\n \"'adapt' mode adds (positive) or subtracts (negative) from the current balance; \" +\n \"'set' mode replaces the balance with the exact amount provided. \" +\n \"Params: `iccid` (subscriber identifier), `amount` (number), `mode` ('adapt' | 'set'). \" +\n \"Returns: updated subscriber balance. \" +\n \"Do NOT use this to modify an account-level balance — use `modify_account_balance` for that. \" +\n \"Always call `get_subscriber` first to capture the current balance before adjusting.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n amount: z.number().describe(\"Amount to add (adapt) or set to (set)\"),\n mode: z\n .enum([\"adapt\", \"set\"])\n .describe(\"'adapt' adds/subtracts, 'set' replaces\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_balance\",\n \"modifySubscriberBalance\",\n TOOL_SCOPES[\"modify_subscriber_balance\"]!,\n ctx,\n async ({ iccid, amount, mode }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n if (mode === \"adapt\") params.amount = amount;\n else params.setBalance = amount;\n return ocsCall(ctx.env, token, \"modifySubscriberBalance\", params);\n },\n ),\n );\n\n // Fix #6: OCS expects { subscriber, newStatus } not { iccid, status }\n server.registerTool(\n \"modify_subscriber_status\",\n {\n title: \"Modify Subscriber Status\",\n description:\n \"Use this to change the OCS lifecycle status of a subscriber. \" +\n \"Common transitions: ACTIVE → SUSPENDED (pause without losing packages), \" +\n \"SUSPENDED → ACTIVE (reactivate), ACTIVE/SUSPENDED → TERMINATED (irreversible). \" +\n \"WARNING: TERMINATED status is permanent — the subscriber record cannot be reactivated. \" +\n \"⚠ Setting status to END_OF_LIFE is irreversible. The subscriber becomes read-only (OCS error 17 on subsequent mutations). Confirm before calling. \" +\n \"Params: `iccid` (subscriber identifier), `status` (new status string, e.g. 'ACTIVE', \" +\n \"'SUSPENDED', 'TERMINATED', 'END_OF_LIFE'). \" +\n \"Returns: updated subscriber record with the new status. \" +\n \"Do NOT use this to disable the SIM card at the network level — use `change_sim_status` for that. \" +\n \"Always call `get_subscriber` first to confirm current status before modifying.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n status: z.string().describe(\"New status value\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_status\",\n \"modifySubscriberStatus\",\n TOOL_SCOPES[\"modify_subscriber_status\"]!,\n ctx,\n async ({ iccid, status }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberStatus\", {\n subscriber: iccid,\n newStatus: status,\n }),\n ),\n );\n\n // Fix #8: OCS expects { simId, newStatus } not { iccid, simStatus }.\n // Resolve ICCID → simId via getSingleSubscriber, then send { simId, newStatus }.\n server.registerTool(\n \"change_sim_status\",\n {\n title: \"Change SIM Status\",\n description:\n \"Use this to change the physical SIM/eSIM card status at the SIM provider level, \" +\n \"independent of the OCS subscriber lifecycle status. \" +\n \"Statuses: ENABLED (normal operation), DISABLED (blocked at network level, subscriber cannot connect), \" +\n \"DELETED (irrecoverably removes the SIM profile — use only to decommission). \" +\n \"WARNING: DELETED is irreversible. Always use `dry_run=true` first. \" +\n \"Internally resolves ICCID → numeric simId via a getSingleSubscriber call before forwarding to OCS. \" +\n \"Params: `iccid` (subscriber identifier), `simStatus` ('ENABLED' | 'DISABLED' | 'DELETED'). \" +\n \"Returns: updated SIM record with new status. \" +\n \"Do NOT use this to change the subscriber's OCS lifecycle status — use `modify_subscriber_status`. \" +\n \"Do NOT confuse DISABLED (reversible) with DELETED (irreversible).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n simStatus: z.string().describe(\"New SIM status (e.g. ENABLED, DISABLED, DELETED)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"change_sim_status\",\n \"changeSimStatus\",\n TOOL_SCOPES[\"change_sim_status\"]!,\n ctx,\n async ({ iccid, simStatus }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const simId = Number(sub.simId ?? sub.sim_id ?? sub.id);\n if (simId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve simId for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"changeSimStatus\", {\n simId: Number(simId),\n newStatus: simStatus,\n });\n },\n ),\n );\n\n // Fix #1: OCS expects bare Long (simId integer) not { iccid }.\n // Resolve ICCID → simId via getSingleSubscriber, then send bare integer.\n server.registerTool(\n \"get_sim_provider_status\",\n {\n title: \"Get SIM Provider Status\",\n description:\n \"Use this to check the physical SIM/eSIM card status at the SIM provider level \" +\n \"(ENABLED, DISABLED, DELETED) — distinct from the OCS subscriber status. \" +\n \"Useful when `get_subscriber` shows ACTIVE but connectivity is broken; the SIM may be \" +\n \"DISABLED at the provider level. Internally resolves ICCID → numeric simId. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: provider status object with `simStatus`, `activationDate`, `lastStatusChange`. \" +\n \"Do NOT use this to change the SIM status — use `change_sim_status` for that.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_sim_provider_status\",\n \"getSimProviderStatus\",\n TOOL_SCOPES[\"get_sim_provider_status\"]!,\n ctx,\n async ({ iccid }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const simId = Number(sub.simId ?? sub.sim_id ?? sub.id);\n if (simId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve simId for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"getSimProviderStatus\", Number(simId));\n },\n ),\n );\n\n server.registerTool(\n \"get_subscriber_location\",\n {\n title: \"Get Subscriber Location\",\n description:\n \"Returns last-known location from subscriber's most recent cell tower usage. Complementary to GeoSense get_subscriber_location_by_cell_id — use this when you have the subscriber id, use the cell-id variant when you have raw cell parameters.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber_location\",\n \"getSubscriberLocation\",\n TOOL_SCOPES[\"get_subscriber_location\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"getSubscriberLocation\", { iccid }),\n ),\n );\n\n // Fix #9: OCS expects { subscriber, name, company, phone, mail }\n // not { iccid, firstName, lastName, email, phoneNumber }\n server.registerTool(\n \"modify_subscriber_contact_info\",\n {\n title: \"Modify Subscriber Contact Info\",\n description:\n \"Use this to update the contact details stored on a subscriber record in OCS. \" +\n \"Only the fields you provide are updated — omitted fields are left unchanged. \" +\n \"Params: `iccid` (subscriber identifier), `firstName` (optional), `lastName` (optional), \" +\n \"`company` (optional), `email` (optional), `phoneNumber` (optional). \" +\n \"Returns: updated subscriber contact record. \" +\n \"Do NOT use this to change subscriber status, balance, or traffic flags — those have dedicated tools.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n firstName: z.string().optional().describe(\"First name\"),\n lastName: z.string().optional().describe(\"Last name\"),\n company: z.string().optional().describe(\"Company name\"),\n email: z.string().optional().describe(\"Email address\"),\n phoneNumber: z.string().optional().describe(\"Phone number\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_contact_info\",\n \"modifySubscriberContactInfo\",\n TOOL_SCOPES[\"modify_subscriber_contact_info\"]!,\n ctx,\n async ({ iccid, firstName, lastName, company, email, phoneNumber }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n const nameParts = [firstName, lastName].filter(Boolean);\n if (nameParts.length > 0) params.name = nameParts.join(\" \");\n if (company !== undefined) params.company = company;\n if (phoneNumber !== undefined) params.phone = phoneNumber;\n if (email !== undefined) params.mail = email;\n return ocsCall(ctx.env, token, \"modifySubscriberContactInfo\", params);\n },\n ),\n );\n\n // Fix #10: OCS expects { subscriber, mtcAllowed, smsMoAllowed, dataAllowed, mocAllowed }\n // Drop JSON-string antipattern; use typed booleans directly.\n server.registerTool(\n \"set_subscriber_traffic_restrictions\",\n {\n title: \"Set Traffic Restrictions\",\n description:\n \"Use this to enable or disable individual traffic types for a subscriber: mobile data, \" +\n \"voice calls (mobile-originated and mobile-terminated), and SMS. Omit any flag to leave \" +\n \"it unchanged. Changes take effect immediately at the OCS level. \" +\n \"Params: `iccid` (subscriber identifier), `dataAllowed` (boolean, controls data traffic), \" +\n \"`mocAllowed` (boolean, controls outbound calls), `mtcAllowed` (boolean, controls inbound calls), \" +\n \"`smsMoAllowed` (boolean, controls outbound SMS). \" +\n \"Returns: updated traffic restriction record for the subscriber. \" +\n \"Do NOT use this to throttle bandwidth — use `hlr_set_bitrate` for speed limiting. \" +\n \"Do NOT use this to suspend the subscriber entirely — use `modify_subscriber_status` (SUSPENDED) instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n mtcAllowed: z.boolean().optional().describe(\"Allow mobile-terminated calls\"),\n smsMoAllowed: z.boolean().optional().describe(\"Allow SMS mobile-originated\"),\n dataAllowed: z.boolean().optional().describe(\"Allow data traffic\"),\n mocAllowed: z.boolean().optional().describe(\"Allow mobile-originated calls\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"set_subscriber_traffic_restrictions\",\n \"setSubscriberTrafficRestrictions\",\n TOOL_SCOPES[\"set_subscriber_traffic_restrictions\"]!,\n ctx,\n async ({ iccid, mtcAllowed, smsMoAllowed, dataAllowed, mocAllowed }, token) => {\n const params: Record<string, unknown> = { subscriber: iccid };\n if (mtcAllowed !== undefined) params.mtcAllowed = mtcAllowed;\n if (smsMoAllowed !== undefined) params.smsMoAllowed = smsMoAllowed;\n if (dataAllowed !== undefined) params.dataAllowed = dataAllowed;\n if (mocAllowed !== undefined) params.mocAllowed = mocAllowed;\n return ocsCall(ctx.env, token, \"setSubscriberTrafficRestrictions\", params);\n },\n ),\n );\n\n // Fix #16: OCS expects { subscriber, steeringListId } not { iccid, steeringListId }\n server.registerTool(\n \"modify_subscriber_steering_list\",\n {\n title: \"Modify Subscriber Steering List\",\n description:\n \"Use this to assign or remove a network steering list on a specific subscriber, controlling \" +\n \"which mobile operators the subscriber's eSIM prefers to connect to. Steering lists are \" +\n \"managed separately — call `list_steering_lists` to get valid IDs. \" +\n \"This operates at the SUBSCRIBER level only. After assigning, call `push_steering_to_subscriber` \" +\n \"to push the change to the physical device immediately; without that call the device continues \" +\n \"using the old operator preference list until next re-registration. \" +\n \"Params: `iccid` (subscriber identifier), `steeringListId` (integer from `list_steering_lists`, \" +\n \"or null/0 to remove the current steering list). \" +\n \"Returns: updated subscriber record confirming the new steeringListId. \" +\n \"Do NOT use this for account-level steering (no MCP tool yet — gap G-03, awaiting eSIMVault input).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n steeringListId: z.number().describe(\"The steering list ID to assign\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_steering_list\",\n \"modifySubscriberSteeringList\",\n TOOL_SCOPES[\"modify_subscriber_steering_list\"]!,\n ctx,\n async ({ iccid, steeringListId }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberSteeringList\", {\n subscriber: iccid,\n steeringListId,\n }),\n ),\n );\n\n server.registerTool(\n \"move_subscriber_range_to_account\",\n {\n title: \"Move Subscribers to Account\",\n description:\n \"Use this to move a contiguous ICCID range of subscribers to a different account. \" +\n \"Useful for bulk subscriber migrations between accounts or during account restructuring. \" +\n \"Params: `iccidFrom` (start ICCID of range, inclusive), `iccidTo` (end ICCID of range, inclusive), \" +\n \"`accountId` (target account ID from `list_reseller_accounts`). \" +\n \"Returns: OCS confirmation of the range move with affected subscriber count. \" +\n \"Do NOT use this for a single subscriber move — provide identical iccidFrom and iccidTo. \" +\n \"Always call `list_subscribers` on the range first to verify the correct subscribers are included.\",\n inputSchema: {\n iccidFrom: z.string().describe(\"Start ICCID of range\"),\n iccidTo: z.string().describe(\"End ICCID of range\"),\n accountId: z.number().describe(\"Target account ID\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"move_subscriber_range_to_account\",\n \"moveSubscriberRangeToAccount\",\n TOOL_SCOPES[\"move_subscriber_range_to_account\"]!,\n ctx,\n async ({ iccidFrom, iccidTo, accountId }, token) =>\n ocsCall(ctx.env, token, \"moveSubscriberRangeToAccount\", {\n iccidFrom,\n iccidTo,\n accountId,\n }),\n ),\n );\n\n // Fix #3: OCS expects { imsi, limit } not { iccid, bitrate }.\n // Resolve ICCID → IMSI via getSingleSubscriber; rename bitrate → limit.\n // B2.4: added bitrate_string string-enum alternative; refine ensures at least one of (bitrate, bitrate_string).\n server.registerTool(\n \"hlr_set_bitrate\",\n {\n title: \"Set HLR Bitrate\",\n description:\n \"Use this to set a hard bandwidth cap for a subscriber at the HLR (Home Location Register) level. \" +\n \"This is a network-level throttle applied regardless of package allowance — use it to enforce \" +\n \"fair-use speed limits or to throttle heavy users without suspending service. \" +\n \"Provide at least one of `bitrate` (numeric bps) or `bitrate_string` (OCS string enum); \" +\n \"when both are provided, `bitrate_string` is used. \" +\n \"String enum values: KB_32, KB_64, KB_128, KB_256, KB_384, KB_512, KB_1024, KB_2048, KB_3072, \" +\n \"KB_5120, KB_7680, KB_10240, KB_20480, KB_51200, KB_102400, UNLIMITED. \" +\n \"Numeric equivalents: 256000 (256 kbps throttle), 1000000 (1 Mbps), 0 (remove limit). \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup. \" +\n \"Params: `iccid` (subscriber identifier), `bitrate` (integer, bits-per-second) OR \" +\n \"`bitrate_string` (string enum from the list above). \" +\n \"Returns: HLR confirmation with the applied bitrate. \" +\n \"Do NOT use this to block data entirely — use `set_subscriber_traffic_restrictions` with `dataAllowed=false`. \" +\n \"Do NOT use this to change throttling thresholds on a package template — use `modify_template_throttling`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n bitrate: z.number().optional().describe(\"Max bitrate in bps (numeric form; use 0 to remove limit)\"),\n bitrate_string: z\n .enum([\n \"KB_32\", \"KB_64\", \"KB_128\", \"KB_256\", \"KB_384\", \"KB_512\",\n \"KB_1024\", \"KB_2048\", \"KB_3072\", \"KB_5120\", \"KB_7680\",\n \"KB_10240\", \"KB_20480\", \"KB_51200\", \"KB_102400\", \"UNLIMITED\",\n ])\n .optional()\n .describe(\"Max bitrate as OCS string enum (alternative to numeric `bitrate`)\"),\n dry_run: z\n .boolean()\n .optional()\n .describe(\"If true, do not call OCS — return the would-be request for confirmation\"),\n })\n .refine(\n (d) => d.bitrate !== undefined || d.bitrate_string !== undefined,\n { message: \"Provide at least one of `bitrate` (number) or `bitrate_string` (string enum)\" },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"hlr_set_bitrate\",\n \"hlrSetBitrate\",\n TOOL_SCOPES[\"hlr_set_bitrate\"]!,\n ctx,\n async ({ iccid, bitrate, bitrate_string }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n const limit = bitrate_string !== undefined ? bitrate_string : bitrate;\n return ocsCall(ctx.env, token, \"hlrSetBitrate\", { imsi, limit });\n },\n ),\n );\n\n // Fix #2: OCS expects { imsi } not { iccid }.\n // Resolve ICCID → IMSI via getSingleSubscriber.\n server.registerTool(\n \"hlr_get_bitrate\",\n {\n title: \"Get HLR Bitrate\",\n description:\n \"Use this to read the current HLR-level bandwidth cap applied to a subscriber. \" +\n \"A non-zero value means the subscriber is throttled to that speed regardless of package allowance. \" +\n \"A zero or null response means no HLR-level cap is in effect. \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: object with `bitrate` (integer, bits-per-second) or null if no limit is set. \" +\n \"Do NOT use this to check package data allowance limits — use `list_subscriber_packages` for that.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"hlr_get_bitrate\",\n \"hlrGetBitrate\",\n TOOL_SCOPES[\"hlr_get_bitrate\"]!,\n ctx,\n async ({ iccid }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n return ocsCall(ctx.env, token, \"hlrGetBitrate\", { imsi });\n },\n ),\n );\n\n // =========================================================================\n // 3. PACKAGE TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_subscriber_packages\",\n {\n title: \"List Subscriber Packages\",\n description:\n \"Use this to retrieve all prepaid packages currently assigned to a subscriber. \" +\n \"Returns each package's allowance (data/voice/SMS), consumed usage, expiry date, status, and packageId. \" +\n \"Always call this before any package modification tool (`modify_package_limits`, \" +\n \"`modify_package_expiry`, `modify_package_status`, `delete_subscriber_package`) to confirm \" +\n \"the correct packageId and current state. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: array of package records with `packageId`, `name`, `status`, `dataLimit`, `dataUsed`, \" +\n \"`expirationDate`, `recurring` flag. \" +\n \"Do NOT use this to browse the product catalog — use `list_package_templates` for that.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_subscriber_packages\",\n \"listSubscriberPrepaidPackages\",\n TOOL_SCOPES[\"list_subscriber_packages\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n ),\n );\n\n server.registerTool(\n \"assign_package\",\n {\n title: \"Assign Package to Subscriber\",\n description:\n \"Use this to assign a one-time prepaid data/voice package to a subscriber from an existing template. \" +\n \"The package is active immediately (or at first usage, depending on template settings). \" +\n \"Params: `iccid` (subscriber identifier), `packageTemplateId` (integer from `list_package_templates`), \" +\n \"`account_for_subs` (integer, optional — when provided instead of resolving a subscriber, OCS auto-selects \" +\n \"a free eSIM from that account and assigns the package; this is the bulk auto-provisioning path). \" +\n \"Returns: created package record with `packageId`, `startDate`, `endDate`, and allowances. \" +\n \"Do NOT use this for packages that should auto-renew — use `assign_recurring_package` instead. \" +\n \"Do NOT use this to provision a new subscriber end-to-end — consider `provision_esim_wizard` \" +\n \"for a guided flow with dry-run preview.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageTemplateId: z\n .number()\n .describe(\"The package template ID to assign\"),\n account_for_subs: z\n .number()\n .optional()\n .describe(\n \"Account ID — when provided, OCS auto-selects a free eSIM from this account for bulk provisioning\",\n ),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"assign_package\",\n \"affectPackageToSubscriber\",\n TOOL_SCOPES[\"assign_package\"]!,\n ctx,\n async ({ iccid, packageTemplateId, account_for_subs }, token) => {\n // accountForSubs is an alternative to subscriber per OCS — never send both.\n if (account_for_subs !== undefined) {\n return ocsCall(ctx.env, token, \"affectPackageToSubscriber\", {\n packageTemplateId,\n accountForSubs: account_for_subs,\n });\n }\n // OCS affectPackageToSubscriber wants a SubscriberId object {iccid}, not a bare integer.\n return ocsCall(ctx.env, token, \"affectPackageToSubscriber\", {\n subscriber: { iccid },\n packageTemplateId,\n });\n },\n ),\n );\n\n server.registerTool(\n \"assign_recurring_package\",\n {\n title: \"Assign Recurring Package\",\n description:\n \"Use this to assign an auto-renewing prepaid package to a subscriber. The package renews \" +\n \"automatically based on the template's periodicity settings, reducing churn from manual renewal. \" +\n \"Params: `iccid` (subscriber identifier), `packageTemplateId` (integer from `list_package_templates` \" +\n \"— must be a template configured with recurring/periodicity settings), \" +\n \"`activation_at_first_use` (boolean, optional — when true, package activates on the subscriber's \" +\n \"first network usage rather than immediately; mutually exclusive with `start_time_utc`), \" +\n \"`start_time_utc` (ISO 8601 UTC datetime, optional — schedules a specific activation start; \" +\n \"mutually exclusive with `activation_at_first_use`). \" +\n \"Returns: created recurring package record with `packageId` and renewal schedule. \" +\n \"Do NOT use this for one-time packages — use `assign_package` instead. \" +\n \"To pause or cancel auto-renewal without deleting the package, use `stop_resume_recurring_package`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageTemplateId: z.number().describe(\"The package template ID\"),\n activation_at_first_use: z\n .boolean()\n .optional()\n .describe(\n \"When true, package activates on first network usage (mutually exclusive with start_time_utc)\",\n ),\n start_time_utc: z\n .string()\n .optional()\n .describe(\n \"Scheduled activation datetime in ISO 8601 UTC format (mutually exclusive with activation_at_first_use)\",\n ),\n dry_run: z\n .boolean()\n .optional()\n .describe(\"If true, do not call OCS — return the would-be request for confirmation\"),\n })\n .refine(\n (d) => !(d.activation_at_first_use === true && d.start_time_utc !== undefined),\n {\n message:\n \"activation_at_first_use and start_time_utc are mutually exclusive — choose one\",\n },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"assign_recurring_package\",\n \"affectRecurringPackageToSubscriber\",\n TOOL_SCOPES[\"assign_recurring_package\"]!,\n ctx,\n async ({ iccid, packageTemplateId, activation_at_first_use, start_time_utc }, token) => {\n // Fix #18: OCS affectRecurringPackageToSubscriber expects integer subscriberId, not ICCID string.\n // Resolve ICCID → numeric id via getSingleSubscriber before calling OCS.\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const subscriberId = sub.id ?? sub.subscriberId;\n if (subscriberId === undefined) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve subscriberId for ICCID ${iccid}` }],\n };\n }\n const params: Record<string, unknown> = {\n subscriber: Number(subscriberId),\n packageTemplateId,\n };\n if (activation_at_first_use === true) params.activationAtFirstUse = true;\n if (start_time_utc !== undefined) params.startTimeUTC = start_time_utc;\n return ocsCall(ctx.env, token, \"affectRecurringPackageToSubscriber\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_package_limits\",\n {\n title: \"Modify Package Limits\",\n description:\n \"Use this to change the data, voice, or SMS allowance ceilings on an already-assigned subscriber package. \" +\n \"Useful for mid-cycle top-ups or corrections without assigning a new package. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`limits` (JSON string with the limit fields to change, e.g. {\\\"dataLimit\\\": 5368709120}). \" +\n \"Returns: updated package record with new limits. \" +\n \"Do NOT use this to change the package template (affecting future subscribers) — use `modify_template_core`. \" +\n \"Do NOT use this to change expiry — use `modify_package_expiry`. \" +\n \"Always call `list_subscriber_packages` first to confirm the correct packageId.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n limits: z.string().describe(\"New limits as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_limits\",\n \"modifySubscriberPrepaidPackageLimits\",\n TOOL_SCOPES[\"modify_package_limits\"]!,\n ctx,\n async ({ iccid, packageId, limits }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageLimits\", {\n iccid,\n packageId,\n ...(JSON.parse(limits) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_package_expiry\",\n {\n title: \"Modify Package Expiry Date\",\n description:\n \"Use this to extend or shorten the expiry date of an active prepaid package on a subscriber. \" +\n \"Useful when a subscriber's trip is longer than expected or for promotional extensions. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`expirationDate` (ISO 8601 date string, e.g. '2026-06-01' or '2026-06-01T23:59:59' — absolute date), \" +\n \"`validity_days` (integer, optional — number of days from now; passed to OCS as `newValidityDuration`; \" +\n \"provide either `expirationDate` OR `validity_days`, not both). \" +\n \"Returns: updated package record with the new expiry date. \" +\n \"Do NOT use this to change when a package becomes active — use `modify_subscriber_package_active_period`. \" +\n \"Do NOT use this to change data allowances — use `modify_package_limits`.\",\n inputSchema: z\n .object({\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n expirationDate: z\n .string()\n .optional()\n .describe(\"New expiry date (ISO 8601 format, absolute)\"),\n validity_days: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Number of days from now until expiry (alternative to expirationDate)\"),\n ...DRY_RUN_FIELD,\n })\n .refine(\n (d) => d.expirationDate !== undefined || d.validity_days !== undefined,\n {\n message:\n \"Provide at least one of `expirationDate` (absolute) or `validity_days` (relative)\",\n },\n )\n .refine(\n (d) => !(d.expirationDate !== undefined && d.validity_days !== undefined),\n {\n message:\n \"`expirationDate` and `validity_days` are mutually exclusive — choose one\",\n },\n ),\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_expiry\",\n \"modifySubscriberPrepaidPackageExpDate\",\n TOOL_SCOPES[\"modify_package_expiry\"]!,\n ctx,\n async ({ iccid, packageId, expirationDate, validity_days }, token) => {\n const params: Record<string, unknown> = { iccid, packageId };\n if (expirationDate !== undefined) params.expirationDate = expirationDate;\n if (validity_days !== undefined) params.newValidityDuration = validity_days;\n return ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageExpDate\", params);\n },\n ),\n );\n\n server.registerTool(\n \"modify_package_status\",\n {\n title: \"Modify Package Status\",\n description:\n \"Use this to activate or deactivate a specific prepaid package on a subscriber without \" +\n \"removing it. A deactivated package retains its allowances and can be reactivated later. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`status` (new package status string, e.g. 'ACTIVE', 'INACTIVE'). \" +\n \"Returns: updated package record with the new status. \" +\n \"Do NOT use this to delete a package — use `delete_subscriber_package` for permanent removal. \" +\n \"Do NOT use this to change the subscriber's overall account status — use `modify_subscriber_status`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The active package ID\"),\n status: z.string().describe(\"New package status\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_package_status\",\n \"modifySubscriberPrepaidPackageStatus\",\n TOOL_SCOPES[\"modify_package_status\"]!,\n ctx,\n async ({ iccid, packageId, status }, token) =>\n ocsCall(ctx.env, token, \"modifySubscriberPrepaidPackageStatus\", {\n iccid,\n packageId,\n status,\n }),\n ),\n );\n\n server.registerTool(\n \"stop_resume_recurring_package\",\n {\n title: \"Stop/Resume Recurring Package\",\n description:\n \"Use this to pause or restart the auto-renewal cycle of a recurring package without removing it. \" +\n \"'stop' halts future renewals (subscriber keeps current period until expiry); \" +\n \"'resume' re-enables auto-renewal from the next renewal date. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`), \" +\n \"`action` ('stop' | 'resume'). \" +\n \"Returns: updated recurring package record with new renewal state. \" +\n \"Do NOT use this to permanently delete a recurring package — use `delete_subscriber_package`. \" +\n \"Do NOT confuse this with `modify_package_status` (which activates/deactivates a package for usage).\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The recurring package ID\"),\n action: z\n .enum([\"stop\", \"resume\"])\n .describe(\"Whether to stop or resume\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"stop_resume_recurring_package\",\n \"stopResumeSubsRecurringPackage\",\n TOOL_SCOPES[\"stop_resume_recurring_package\"]!,\n ctx,\n async ({ iccid, packageId, action }, token) =>\n ocsCall(ctx.env, token, \"stopResumeSubsRecurringPackage\", {\n iccid,\n packageId,\n action,\n }),\n ),\n );\n\n server.registerTool(\n \"delete_subscriber_package\",\n {\n title: \"Delete Subscriber Package\",\n description:\n \"Use this to permanently remove a single prepaid package from a subscriber. \" +\n \"This is irreversible — the package record and any unused allowance are deleted. \" +\n \"Always call `list_subscriber_packages` first to confirm the correct packageId and snapshot \" +\n \"the current state. Use `dry_run=true` on the first call. \" +\n \"Params: `iccid` (subscriber identifier), `packageId` (integer from `list_subscriber_packages`). \" +\n \"Returns: OCS confirmation of deletion. \" +\n \"Do NOT use this to remove ALL packages at once — use `clean_all_packages` for that (requires separate confirm). \" +\n \"Do NOT use this to pause a package — use `modify_package_status` to deactivate it instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n packageId: z.number().describe(\"The package ID to delete\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"delete_subscriber_package\",\n \"deleteSubscriberPackage\",\n TOOL_SCOPES[\"delete_subscriber_package\"]!,\n ctx,\n async ({ iccid, packageId }, token) =>\n ocsCall(ctx.env, token, \"deleteSubscriberPackage\", { iccid, packageId }),\n ),\n );\n\n server.registerTool(\n \"clean_all_packages\",\n {\n title: \"Clean All Subscriber Packages\",\n description:\n \"DANGEROUS: Removes ALL prepaid packages from a subscriber in a single irreversible operation. \" +\n \"There is no undo. Typical use: resetting a subscriber to zero before re-provisioning a new package series. \" +\n \"REQUIRED workflow: (1) call `list_subscriber_packages` to snapshot what will be deleted; \" +\n \"(2) call this tool with `dry_run=true` to preview; (3) get explicit user confirmation; \" +\n \"(4) call again with `dry_run=false`. \" +\n \"Params: `iccid` (subscriber identifier), `dry_run` (boolean — MUST be true on first call). \" +\n \"Returns: list of packages that were (or would be) deleted. \" +\n \"Do NOT use this to remove a single package — use `delete_subscriber_package` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"clean_all_packages\",\n \"cleanSubscriberAllPackages\",\n TOOL_SCOPES[\"clean_all_packages\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"cleanSubscriberAllPackages\", { iccid }),\n ),\n );\n\n // =========================================================================\n // 4. PACKAGE TEMPLATE TOOLS\n // =========================================================================\n\n server.registerTool(\n \"list_package_templates\",\n {\n title: \"List Package Templates\",\n description:\n \"Use this to browse the product catalog of prepaid package templates available for assignment. \" +\n \"Returns each template's name, data/voice/SMS limits, pricing, validity period, location zone, \" +\n \"and recurring configuration. Call this before `assign_package` or `assign_recurring_package` \" +\n \"to obtain valid `packageTemplateId` values. \" +\n \"Params: `accountId` (integer, optional — filter templates visible to a specific account). \" +\n \"Returns: array of template records with `templateId`, `name`, `dataLimit`, `price`, \" +\n \"`validityDays`, `locationZoneId`, `recurring`. \" +\n \"Do NOT use this to list packages assigned to a specific subscriber — use `list_subscriber_packages`.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter templates by account ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_package_templates\",\n \"listPrepaidPackageTemplate\",\n TOOL_SCOPES[\"list_package_templates\"]!,\n ctx,\n async ({ accountId }, token) => {\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) params.accountId = accountId;\n return ocsCall(ctx.env, token, \"listPrepaidPackageTemplate\", params);\n },\n ),\n );\n\n server.registerTool(\n \"create_package_template\",\n {\n title: \"Create Package Template\",\n description:\n \"Use this to create a new prepaid package template in the product catalog. Templates define \" +\n \"allowances, pricing, location zones, validity, and throttling thresholds that are reused each \" +\n \"time the template is assigned to a subscriber. \" +\n \"Params: `template` (full template configuration as a JSON string — fields include `name`, \" +\n \"`dataLimit` in bytes, `price`, `validityDays`, `locationZoneId`, `recurring`, `throttlingActive`). \" +\n \"Returns: created template record with the new `templateId`. \" +\n \"Do NOT use this to modify an existing template — use `modify_template_core`. \" +\n \"After creation, call `list_package_templates` to confirm the template is visible.\",\n inputSchema: {\n template: z\n .string()\n .describe(\"Full template configuration as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"create_package_template\",\n \"createPrepaidPackageTemplate\",\n TOOL_SCOPES[\"create_package_template\"]!,\n ctx,\n async ({ template }, token) =>\n ocsCall(\n ctx.env,\n token,\n \"createPrepaidPackageTemplate\",\n JSON.parse(template) as Record<string, unknown>,\n ),\n ),\n );\n\n server.registerTool(\n \"modify_template_core\",\n {\n title: \"Modify Template Core Settings\",\n description:\n \"Use this to change the core fields of an existing package template: name, data/voice/SMS limits, \" +\n \"pricing, validity period, and location zone. Changes affect future package assignments from this \" +\n \"template but do NOT retroactively change packages already assigned to subscribers. \" +\n \"Params: `templateId` (integer from `list_package_templates`), `changes` (JSON string with fields \" +\n \"to modify, e.g. {\\\"name\\\": \\\"Europe 5GB\\\", \\\"dataLimit\\\": 5368709120}). \" +\n \"Returns: updated template record. \" +\n \"Do NOT use this to modify throttling thresholds — use `modify_template_throttling`. \" +\n \"Do NOT use this to modify recurring/renewal settings — use `modify_template_recurring`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z.string().describe(\"Core fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_core\",\n \"modifyPPTCore\",\n TOOL_SCOPES[\"modify_template_core\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTCore\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_template_recurring\",\n {\n title: \"Modify Template Recurring Settings\",\n description:\n \"Use this to change the auto-renewal configuration of a package template: periodicity \" +\n \"(daily/weekly/monthly), occurrence count, and renewal trigger conditions. Changes affect \" +\n \"future assignments and existing recurring packages assigned from this template. \" +\n \"Params: `templateId` (integer from `list_package_templates`), `changes` (JSON string with \" +\n \"recurring fields, e.g. {\\\"periodicity\\\": \\\"monthly\\\", \\\"occurrences\\\": 12}). \" +\n \"Returns: updated template record with new recurring settings. \" +\n \"Do NOT use this to stop an individual subscriber's recurring renewal — use `stop_resume_recurring_package`. \" +\n \"Do NOT use this to change core template fields like data limits — use `modify_template_core`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z\n .string()\n .describe(\"Recurring fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_recurring\",\n \"modifyPPTRecurring\",\n TOOL_SCOPES[\"modify_template_recurring\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTRecurring\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"modify_template_throttling\",\n {\n title: \"Modify Template Throttling\",\n description:\n \"Use this to change the bandwidth throttling thresholds on a package template. \" +\n \"WARNING: changes apply immediately to ALL existing subscriber packages created from this template, \" +\n \"not just future ones. Setting a lower threshold will NOT retroactively throttle subscribers \" +\n \"already below the new threshold (the system does not re-check existing usage). \" +\n \"Params: `templateId` (integer), `changes` (JSON string with throttling fields, e.g. \" +\n \"{\\\"throttlingActive\\\": true, \\\"firstThresholdPercent\\\": 80, \\\"firstThresholdLimitKbps\\\": 1024, \" +\n \"\\\"errorAction\\\": \\\"continue_unthrottled\\\"}). \" +\n \"Returns: updated template record with new throttling configuration. \" +\n \"Do NOT use this to throttle a single subscriber — use `hlr_set_bitrate` instead. \" +\n \"Do NOT use this to change core package limits — use `modify_template_core`.\",\n inputSchema: {\n templateId: z.number().describe(\"The template ID\"),\n changes: z\n .string()\n .describe(\"Throttling fields to modify as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_template_throttling\",\n \"modifyPPTThrottling\",\n TOOL_SCOPES[\"modify_template_throttling\"]!,\n ctx,\n async ({ templateId, changes }, token) =>\n ocsCall(ctx.env, token, \"modifyPPTThrottling\", {\n templateId,\n ...(JSON.parse(changes) as Record<string, unknown>),\n }),\n ),\n );\n\n server.registerTool(\n \"list_location_zones\",\n {\n title: \"List Location Zone Elements\",\n description:\n \"Use this to list countries and networks within a specific location zone. \" +\n \"WARNING: this method has a known Jackson deserialization bug in the upstream OCS API that \" +\n \"may return malformed responses. Prefer `list_detailed_location_zones` for reliable results. \" +\n \"Params: `locationZoneId` (integer, optional — filter to a specific zone). \" +\n \"Returns: array of zone element records with country and operator entries. \" +\n \"Do NOT use this for reliable zone data — use `list_detailed_location_zones` instead. \" +\n \"Do NOT use this to create zones — use `create_location_zone`.\",\n inputSchema: {\n locationZoneId: z.number().optional().describe(\"Filter by zone ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_location_zones\",\n \"listLocationZoneElement\",\n TOOL_SCOPES[\"list_location_zones\"]!,\n ctx,\n async ({ locationZoneId }, token) => {\n const params: Record<string, unknown> = {};\n if (locationZoneId !== undefined) params.locationZoneId = locationZoneId;\n return ocsCall(ctx.env, token, \"listLocationZoneElement\", params);\n },\n ),\n );\n\n // Fix #15: OCS expects bare integer (resellerId), not {}\n server.registerTool(\n \"list_detailed_location_zones\",\n {\n title: \"List Detailed Location Zones\",\n description:\n \"Use this as the preferred way to list location zones with full detail: included countries, \" +\n \"operator networks, zone IDs, and names. This is the working alternative to `list_location_zones` \" +\n \"which has a known upstream deserialization bug. Use `locationZoneId` values from this response \" +\n \"when creating or editing package templates. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of zone objects each containing `locationZoneId`, `name`, `countries`, and `operators`. \" +\n \"Do NOT use `list_location_zones` when you need reliable data — always use this tool instead.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_detailed_location_zones\",\n \"listDetailedLocationZone\",\n TOOL_SCOPES[\"list_detailed_location_zones\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"listDetailedLocationZone\", id);\n },\n ),\n );\n\n server.registerTool(\n \"list_destination_prefixes\",\n {\n title: \"List Destination List Prefixes\",\n description:\n \"Use this to list the phone number prefixes (country dialling codes) within a specific \" +\n \"named destination list. Destination lists control which countries a subscriber may call on \" +\n \"voice/SMS packages. You must already know the `destinationListId` to use this tool. \" +\n \"Params: `destinationListId` (integer, optional — omit to list all known prefixes). \" +\n \"Returns: array of prefix records with country code and E.164 prefix. \" +\n \"Do NOT use this to discover the destination list catalog — use `list_destination_lists` for that. \" +\n \"For data-only eSIM products without MOC voice, destination lists are irrelevant.\",\n inputSchema: {\n destinationListId: z\n .number()\n .optional()\n .describe(\"Filter by destination list ID\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_destination_prefixes\",\n \"listDestinationListPrefix\",\n TOOL_SCOPES[\"list_destination_prefixes\"]!,\n ctx,\n async ({ destinationListId }, token) => {\n const params: Record<string, unknown> = {};\n if (destinationListId !== undefined)\n params.destinationListId = destinationListId;\n return ocsCall(ctx.env, token, \"listDestinationListPrefix\", params);\n },\n ),\n );\n\n server.registerTool(\n \"create_location_zone\",\n {\n title: \"Create Location Zone\",\n description:\n \"Use this to create a new location zone — a named collection of countries and operators \" +\n \"that defines where a package can be used. Location zones are required when creating package \" +\n \"templates. Use `list_network_profiles` to find valid operator identifiers to include. \" +\n \"Params: `zone` (full zone configuration as a JSON string — fields include `name`, `countries` \" +\n \"(array of ISO country codes), `operators` (array of MCC-MNC strings)). \" +\n \"Returns: created zone record with the new `locationZoneId`. \" +\n \"Do NOT use this to modify an existing zone — no edit tool exists yet (gap G-19, pending eSIMVault). \" +\n \"After creation, verify with `list_detailed_location_zones`.\",\n inputSchema: {\n zone: z.string().describe(\"Zone configuration as JSON string\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"create_location_zone\",\n \"createLocationZone\",\n TOOL_SCOPES[\"create_location_zone\"]!,\n ctx,\n async ({ zone }, token) =>\n ocsCall(\n ctx.env,\n token,\n \"createLocationZone\",\n JSON.parse(zone) as Record<string, unknown>,\n ),\n ),\n );\n\n // =========================================================================\n // 5. STATISTICS TOOLS\n // =========================================================================\n\n // Fix #4: OCS expects { subscriber: { iccid }, period: { start, end } }\n // not { iccid, startDate, endDate }\n server.registerTool(\n \"subscriber_usage\",\n {\n title: \"Subscriber Usage Over Period\",\n description:\n \"Use this to retrieve daily data, voice, and SMS usage for a subscriber over a date range. \" +\n \"Hard limit: maximum 7 days per query — do not exceed or OCS will return an error. \" +\n \"Params: `iccid` (subscriber identifier), `startDate` (YYYY-MM-DD, inclusive), \" +\n \"`endDate` (YYYY-MM-DD, inclusive, max 7 days from start). \" +\n \"Returns: array of daily usage records. Each record contains a `usageType` integer code: \" +\n \"1=MOC (mobile-originated call), 15=MTC (mobile-terminated call), \" +\n \"21=MO-SMS (outbound SMS), 22=MT-SMS (inbound SMS), \" +\n \"33=Data, 40=MOC VoIP, 41=MTC VoIP. \" +\n \"Do NOT use this for event-level network activity — use `subscriber_network_events` for attach/detach events. \" +\n \"Do NOT use this to check current package allowances — use `list_subscriber_packages`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n startDate: z.string().describe(\"Start date (YYYY-MM-DD, inclusive)\"),\n endDate: z\n .string()\n .describe(\n \"End date (YYYY-MM-DD, inclusive, max 7 days from start)\",\n ),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_usage\",\n \"subscriberUsageOverPeriod\",\n TOOL_SCOPES[\"subscriber_usage\"]!,\n ctx,\n async ({ iccid, startDate, endDate }, token) =>\n ocsCall(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: startDate, end: endDate },\n }),\n ),\n );\n\n // Fix #5: same nested shape as subscriberUsageOverPeriod\n server.registerTool(\n \"subscriber_network_events\",\n {\n title: \"Subscriber Network Events\",\n description:\n \"Use this to retrieve timestamped network events for a subscriber: attach, detach, location \" +\n \"updates, and handovers between operators. Useful for connectivity troubleshooting, roaming \" +\n \"activity verification, and fraud pattern detection. Max 7 days per query. \" +\n \"Params: `iccid` (subscriber identifier), `startDate` (YYYY-MM-DD, inclusive), \" +\n \"`endDate` (YYYY-MM-DD, inclusive, max 7 days from start). \" +\n \"Returns: array of event records with `timestamp`, `eventType`, `country`, `operator`, `mccMnc`. \" +\n \"Do NOT use this for daily usage volumes — use `subscriber_usage` for data/voice/SMS byte counts. \" +\n \"For real-time events (last 24h), prefer `list_recent_ocs_events` which reads from the ring buffer.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID\"),\n startDate: z.string().describe(\"Start date (YYYY-MM-DD, inclusive)\"),\n endDate: z.string().describe(\"End date (YYYY-MM-DD, inclusive)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_network_events\",\n \"subscriberNetworkEventsOverPeriod\",\n TOOL_SCOPES[\"subscriber_network_events\"]!,\n ctx,\n async ({ iccid, startDate, endDate }, token) =>\n ocsCall(ctx.env, token, \"subscriberNetworkEventsOverPeriod\", {\n subscriber: { iccid },\n period: { start: startDate, end: endDate },\n }),\n ),\n );\n\n server.registerTool(\n \"subscriber_active_period\",\n {\n title: \"Get Subscriber Active Period\",\n description:\n \"Use this to retrieve the lifetime activity window for a subscriber: the date of first usage \" +\n \"and the date of last usage. Useful for churn analysis, dormancy detection, and subscriber \" +\n \"lifetime value calculations. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: object with `firstUseDate` and `lastUseDate` (ISO 8601 strings). \" +\n \"Do NOT use this to check current package status — use `list_subscriber_packages`. \" +\n \"Do NOT use this for detailed daily usage patterns — use `subscriber_usage`.\",\n inputSchema: { iccid: z.string().describe(\"The subscriber ICCID\") },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"subscriber_active_period\",\n \"getSubscriberActivePeriod\",\n TOOL_SCOPES[\"subscriber_active_period\"]!,\n ctx,\n async ({ iccid }, token) =>\n ocsCall(ctx.env, token, \"getSubscriberActivePeriod\", { iccid }),\n ),\n );\n\n // =========================================================================\n // 6. MISC TOOLS (tariff, SMS, network profiles)\n // =========================================================================\n\n // Fix #14: OCS expects bare integer (resellerId); response key is listTariffRule.\n server.registerTool(\n \"get_tariff\",\n {\n title: \"Get Customer Tariff\",\n description:\n \"Use this to retrieve the complete tariff table for a reseller: per-country, per-traffic-type \" +\n \"(data/voice/SMS) wholesale rates. Useful for cost analysis, margin calculations, and identifying \" +\n \"expensive roaming countries before steering decisions. \" +\n \"Params: `resellerId` (integer, optional — omit to use the token owner's reseller). \" +\n \"Returns: array of tariff rules, each with `country`, `trafficType`, `rate`, and `currency`. \" +\n \"Response key in OCS is `listTariffRule`. \" +\n \"Do NOT use this to assign a pricing plan to a subscriber — use `modify_subscriber_mobile_plan`. \" +\n \"This shows the RESELLER's wholesale cost, not what end-users are charged.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_tariff\",\n \"getCustomerTariff\",\n TOOL_SCOPES[\"get_tariff\"]!,\n ctx,\n async ({ resellerId }, token) => {\n const id = resellerId ?? (await getDefaultResellerId(ctx.env, token));\n return ocsCall(ctx.env, token, \"getCustomerTariff\", id);\n },\n ),\n );\n\n // Fix #11: OCS expects { imsi, msisdn, text, senderId? }\n // not { iccid, msisdn, message, sender }\n // Resolve ICCID → IMSI; rename message → text, sender → senderId.\n server.registerTool(\n \"send_sms\",\n {\n title: \"Send MT SMS\",\n description:\n \"Use this to send a mobile-terminated (MT) SMS to a subscriber. Useful for service notifications, \" +\n \"package expiry alerts, and support messages sent programmatically from the platform. \" +\n \"Internally resolves ICCID → IMSI via a getSingleSubscriber lookup before forwarding to OCS. \" +\n \"Params: `iccid` (subscriber identifier), `msisdn` (E.164 phone number of the subscriber), \" +\n \"`message` (SMS text content, max 160 chars for single SMS in GSM-7 encoding), \" +\n \"`sender` (optional sender ID or phone number displayed on the device). \" +\n \"⚠ Messages containing non-GSM-7 characters (any emoji, é, ñ, Chinese, Arabic, Hebrew, etc.) \" +\n \"trigger UCS-2 encoding which limits a single SMS to 70 characters instead of 160. \" +\n \"Plan for multi-part splits accordingly. \" +\n \"Returns: OCS delivery confirmation. \" +\n \"Do NOT use this for bulk SMS campaigns — this sends one message per call and is rate-limited. \" +\n \"Requires admin scope.\",\n inputSchema: {\n iccid: z.string().describe(\"The target subscriber ICCID\"),\n msisdn: z.string().describe(\"The target MSISDN\"),\n message: z.string().describe(\"SMS text content\"),\n sender: z.string().optional().describe(\"Sender ID/number (senderId in OCS)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"send_sms\",\n \"sendMtSms\",\n TOOL_SCOPES[\"send_sms\"]!,\n ctx,\n async ({ iccid, msisdn, message, sender }, token) => {\n const cache = new Map<string, SubscriberRecord>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n const imsi = sub.imsi;\n if (typeof imsi !== \"string\" || imsi.length === 0) {\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: Could not resolve IMSI for ICCID ${iccid}` }],\n };\n }\n const params: Record<string, unknown> = { imsi, msisdn, text: message };\n if (sender) params.senderId = sender;\n return ocsCall(ctx.env, token, \"sendMtSms\", params);\n },\n ),\n );\n\n server.registerTool(\n \"list_network_profiles\",\n {\n title: \"List Network Profiles\",\n description:\n \"Use this to list all network profiles available to this reseller. A network profile defines \" +\n \"the roaming configuration and operator partnerships for eSIM provisioning. Use profile IDs \" +\n \"when creating location zones or configuring steering lists. \" +\n \"Params: none. \" +\n \"Returns: array of profile records with `profileId`, `name`, and coverage metadata. \" +\n \"Do NOT use this to list operator steering configurations — use `list_steering_lists` for that.\",\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_network_profiles\",\n \"listNetworkProfile\",\n TOOL_SCOPES[\"list_network_profiles\"]!,\n ctx,\n async (_args, token) => ocsCall(ctx.env, token, \"listNetworkProfile\"),\n ),\n );\n}\n","/**\n * eSIMVault OCS API client.\n * All requests are POST to /v1?token=<api_key> with JSON body { methodName: <params> }.\n * Responses: { status: { code, msg }, methodName: { ...data } }.\n *\n * params may be a plain object OR a bare scalar (number/string) for OCS methods that\n * expect a primitive as the request value rather than a nested object (e.g. listSponsor,\n * listSteeringList, getCustomerTariff, listDetailedLocationZone, getSimProviderStatus).\n */\n\nexport interface OcsStatus {\n code: number;\n msg: string;\n}\n\nexport interface OcsResponse<T = Record<string, unknown>> {\n status: OcsStatus;\n [method: string]: T | OcsStatus;\n}\n\nexport class OcsApiError extends Error {\n constructor(\n public readonly code: number,\n message: string,\n public readonly method: string,\n ) {\n super(`[${method}] OCS error ${code}: ${message}`);\n this.name = \"OcsApiError\";\n }\n}\n\nexport class OcsClient {\n private readonly baseUrl: string;\n private readonly token: string;\n\n constructor(baseUrl: string, token: string) {\n this.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n this.token = token;\n }\n\n async call<T = Record<string, unknown>>(\n method: string,\n params: Record<string, unknown> | number | string = {},\n ): Promise<T> {\n const url = `${this.baseUrl}/v1?token=${this.token}`;\n const body = JSON.stringify({ [method]: params });\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body,\n });\n\n if (!res.ok) {\n throw new OcsApiError(res.status, `HTTP ${res.status} ${res.statusText}`, method);\n }\n\n const json = (await res.json()) as OcsResponse<T>;\n\n if (json.status?.code !== 0) {\n throw new OcsApiError(json.status?.code ?? -1, json.status?.msg ?? \"Unknown error\", method);\n }\n\n // getCustomerTariff response is keyed as \"listTariffRule\" not \"getCustomerTariff\"\n if (method === \"getCustomerTariff\" && json[\"listTariffRule\"] !== undefined) {\n return json[\"listTariffRule\"] as T;\n }\n\n // GeoSense: live OCS returns coordinates under \"subscriberLocation\", not the method name\n if (method === \"getSubscriberLocationByCellId\") {\n const byMethod = json[method] as T | undefined;\n if (byMethod !== undefined) {\n return byMethod;\n }\n if (json[\"subscriberLocation\"] !== undefined) {\n return json[\"subscriberLocation\"] as T;\n }\n }\n\n // Return the method-specific payload\n return (json[method] as T) ?? (json as unknown as T);\n }\n}\n\nlet _client: OcsClient | null = null;\n\nexport function getClient(): OcsClient {\n if (!_client) {\n const baseUrl = process.env.ESIMVAULT_BASE_URL;\n const token = process.env.ESIMVAULT_API_TOKEN;\n if (!baseUrl || !token) {\n throw new Error(\n \"Missing ESIMVAULT_BASE_URL or ESIMVAULT_API_TOKEN environment variables. \" +\n \"Set them before starting the MCP server.\",\n );\n }\n _client = new OcsClient(baseUrl, token);\n }\n return _client;\n}\n\n/**\n * Fetch the token owner's reseller ID via getResellerInfo.\n * Used as a fallback when bare-integer methods are called without an explicit resellerId.\n */\nexport async function getDefaultResellerId(): Promise<number> {\n const info = await getClient().call<{ id?: number }>(\"getResellerInfo\", {});\n const id = info?.id;\n if (typeof id !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return id;\n}\n","/**\n * Carrier MCP — Billing v2.0 (Phase 15 — Clerk Billing GA Migration)\n *\n * Tier model:\n * free — 5,000 tool calls/mo, read scope only, no Stripe product\n * pro — 50,000 tool calls/mo, read+write+intelligence, $49/mo\n * enterprise — unlimited tool calls, read+write+admin, $499/mo, custom rate limits, SSO\n *\n * Storage layout (CARRIER_USERS KV):\n * key: user:<sub> value: UserRecord (tier field drives all gate checks)\n * key: usage:<sub>:<yyyymm> value: JSON { calls: number } (TTL: 35 days)\n *\n * Analytics Engine (carrier_mcp_audit dataset) is the source of truth for usage\n * rollups — KV counter is a fast hot path for quota checks.\n *\n * BILLING_PRIMARY feature flag (Doppler carrier/prd):\n * \"clerk\" → Clerk Billing is authoritative; KV is a cache/fallback.\n * Portal redirects to Clerk-hosted billing page.\n * Stripe webhook still runs (dual-write period; kept for 1 billing cycle).\n * \"stripe\" → (default) Direct Stripe path; Clerk plan claim is a session-layer overlay.\n *\n * IMPORTANT: This module NEVER charges a card. It only:\n * 1. Gates tool calls based on tier + call count.\n * 2. Records usage records to Stripe Metered Billing (for Pro overages, Stripe-primary only).\n * 3. Redirects users to the appropriate Billing Portal (Clerk or Stripe).\n */\n\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const TIER_CALL_LIMITS: Record<Tier, number> = {\n free: 5_000,\n pro: 50_000,\n enterprise: Infinity,\n};\n\nexport const UPGRADE_URL = \"https://mcp.carrier.llc/upgrade\";\n\nexport type Tier = \"free\" | \"pro\" | \"enterprise\";\nexport type ScopeToken = \"read\" | \"write\" | \"admin\";\n\n// Intelligence scope is a virtual scope — Pro users can call intelligence tools\n// because those tools are registered under \"read\" or \"write\" scope internally.\nexport const TIER_SCOPES: Record<Tier, ScopeToken[]> = {\n free: [\"read\"],\n pro: [\"read\", \"write\"],\n enterprise: [\"read\", \"write\", \"admin\"],\n};\n\n// ---------------------------------------------------------------------------\n// Phase 15 — BILLING_PRIMARY feature flag\n// ---------------------------------------------------------------------------\n\n/**\n * \"clerk\" → Clerk Billing is the authoritative source.\n * \"stripe\" → (default) Direct Stripe path; Clerk plan claim is a session overlay only.\n *\n * Cutover recommendation: flip to \"clerk\" after one full billing cycle of\n * dual-write validation confirming KV ↔ Clerk plan parity for all active subscribers.\n */\nexport type BillingPrimary = \"clerk\" | \"stripe\";\n\nexport function getBillingPrimary(env: Env): BillingPrimary {\n const raw = (env as Env & { BILLING_PRIMARY?: string }).BILLING_PRIMARY;\n return raw === \"clerk\" ? \"clerk\" : \"stripe\";\n}\n\n// ---------------------------------------------------------------------------\n// getUserTier\n// ---------------------------------------------------------------------------\n\n/**\n * Read the tier stored in the user's KV record.\n * Falls back to \"free\" if the record is missing or malformed.\n * When BILLING_PRIMARY=clerk this becomes a cache/fallback only.\n */\nexport async function getUserTier(env: Env, sub: string): Promise<Tier> {\n // stdio mode: no CF Workers KV available — treat as free tier (callers will gate).\n if (!env.CARRIER_USERS) return \"free\";\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(\n () => null,\n );\n if (\n raw &&\n typeof raw === \"object\" &&\n \"tier\" in raw &&\n (raw as { tier: string }).tier in TIER_CALL_LIMITS\n ) {\n return (raw as { tier: Tier }).tier;\n }\n return \"free\";\n}\n\n/**\n * Phase 15 — Resolve the effective tier.\n *\n * BILLING_PRIMARY=clerk: Clerk session plan claim is primary; KV is the fallback.\n * BILLING_PRIMARY=stripe (default): KV is canonical; Clerk plan is an overlay\n * (used to catch Clerk-driven downgrades like plan cancellations).\n *\n * In both modes: clerkPlan ?? fallbackTier — the function is the same; the\n * caller decides which value to pass as fallbackTier based on BILLING_PRIMARY.\n */\nexport function resolveTierFromClerk(\n clerkPlan: Tier | undefined,\n fallbackTier: Tier,\n): Tier {\n return clerkPlan ?? fallbackTier;\n}\n\n// ---------------------------------------------------------------------------\n// Portal URL resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Phase 15 — Build the Clerk-hosted billing portal URL.\n * Activated as primary when BILLING_PRIMARY=clerk.\n */\nexport function buildClerkBillingPortalUrl(env: Env, returnUrl: string): string {\n const base =\n env.CLERK_BILLING_PORTAL_URL ?? \"https://accounts.carrier.llc/user/billing\";\n const url = new URL(base);\n url.searchParams.set(\"redirect_url\", returnUrl);\n return url.toString();\n}\n\n/**\n * Phase 15 — Resolve the billing portal URL based on BILLING_PRIMARY.\n * This is the single entry point for all portal redirects (oauth/index.ts,\n * console billing routes, etc.).\n *\n * BILLING_PRIMARY=clerk → Clerk-hosted portal (buildClerkBillingPortalUrl)\n * BILLING_PRIMARY=stripe → Stripe portal (createBillingPortalSession) with\n * Clerk portal as fallback when Stripe is unconfigured\n */\nexport async function resolveBillingPortalUrl(\n env: Env,\n sub: string,\n returnUrl: string,\n): Promise<string | null> {\n const primary = getBillingPrimary(env);\n\n if (primary === \"clerk\") {\n return buildClerkBillingPortalUrl(env, returnUrl);\n }\n\n // BILLING_PRIMARY=stripe — try Stripe first, fall back to Clerk portal\n const stripePortalUrl = await createBillingPortalSession(env, sub, returnUrl);\n if (stripePortalUrl) return stripePortalUrl;\n\n return buildClerkBillingPortalUrl(env, returnUrl);\n}\n\n// ---------------------------------------------------------------------------\n// getScopeForTier\n// ---------------------------------------------------------------------------\n\nexport function getScopeForTier(tier: Tier): ScopeToken[] {\n return TIER_SCOPES[tier];\n}\n\n// ---------------------------------------------------------------------------\n// checkCallQuota\n// ---------------------------------------------------------------------------\n\nexport interface QuotaResult {\n allowed: boolean;\n remaining: number;\n resetAt: string; // ISO 8601 first day of next month\n tier: Tier;\n}\n\n/**\n * Returns current-month usage from KV hot counter.\n * Enterprise users always get allowed=true / remaining=Infinity.\n */\nexport async function checkCallQuota(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<QuotaResult> {\n const limit = TIER_CALL_LIMITS[tier];\n const resetAt = firstDayNextMonth();\n\n if (tier === \"enterprise\") {\n return { allowed: true, remaining: Infinity, resetAt, tier };\n }\n\n // stdio mode: no CF Workers KV available — allow unbounded calls locally.\n if (!env.CARRIER_USERS) {\n return { allowed: true, remaining: Infinity, resetAt, tier };\n }\n\n const month = currentMonth();\n const usageKey = `usage:${sub}:${month}`;\n const raw = await env.CARRIER_USERS.get(usageKey, \"json\").catch(() => null);\n const calls: number =\n raw && typeof raw === \"object\" && \"calls\" in raw\n ? Number((raw as { calls: number }).calls)\n : 0;\n\n const remaining = Math.max(0, limit - calls);\n return {\n allowed: calls < limit,\n remaining,\n resetAt,\n tier,\n };\n}\n\n// ---------------------------------------------------------------------------\n// recordUsage\n// ---------------------------------------------------------------------------\n\nexport function recordUsage(env: Env, sub: string, tier: Tier): void {\n // stdio mode: no CF Workers KV available — telemetry is a no-op locally.\n // Without this guard the async IIFE below crashes the Node process with\n // \"Cannot read properties of null (reading 'get')\" after returning the\n // tool result, breaking subsequent JSON-RPC calls over stdin.\n if (!env.CARRIER_USERS) return;\n\n (async () => {\n const month = currentMonth();\n const usageKey = `usage:${sub}:${month}`;\n\n const raw = await env.CARRIER_USERS.get(usageKey, \"json\").catch(() => null);\n const prev: number =\n raw && typeof raw === \"object\" && \"calls\" in raw\n ? Number((raw as { calls: number }).calls)\n : 0;\n const next = prev + 1;\n\n await env.CARRIER_USERS.put(\n usageKey,\n JSON.stringify({ calls: next, updated_at: new Date().toISOString() }),\n { expirationTtl: 35 * 24 * 60 * 60 },\n );\n\n // Push Stripe usage record only when Stripe is the primary billing source.\n // When BILLING_PRIMARY=clerk, Clerk Billing handles metering natively.\n if (tier === \"pro\" && next % 100 === 0 && getBillingPrimary(env) === \"stripe\") {\n await pushStripeUsageRecord(env, sub, 100).catch(() => {\n // Non-fatal — nightly rollup will reconcile.\n });\n }\n })();\n}\n\n// ---------------------------------------------------------------------------\n// pushStripeUsageRecord (internal — Stripe-primary mode only)\n// ---------------------------------------------------------------------------\n\nasync function pushStripeUsageRecord(\n env: Env,\n sub: string,\n quantity: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string })\n .STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n if (!env.CARRIER_USERS) return;\n\n const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);\n if (!subItemId) return;\n\n const body = new URLSearchParams({\n quantity: String(quantity),\n timestamp: String(Math.floor(Date.now() / 1000)),\n action: \"increment\",\n });\n\n await fetch(\n `https://api.stripe.com/v1/subscription_items/${subItemId}/usage_records`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n}\n\n// ---------------------------------------------------------------------------\n// createBillingPortalSession (Stripe — kept for dual-write period)\n// ---------------------------------------------------------------------------\n\n/**\n * Create a Stripe Billing Portal session URL for the given customer.\n * Used by /oauth/billing route when BILLING_PRIMARY=stripe.\n * Kept during the dual-write period; will be removed after Clerk-primary cutover.\n *\n * Returns null if Stripe is not configured or the user has no Stripe customer record.\n */\nexport async function createBillingPortalSession(\n env: Env,\n sub: string,\n returnUrl: string,\n): Promise<string | null> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string })\n .STRIPE_SECRET_KEY;\n if (!stripeKey) return null;\n if (!env.CARRIER_USERS) return null;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return null;\n\n const body = new URLSearchParams({\n customer: customerId,\n return_url: returnUrl,\n });\n\n const resp = await fetch(\n \"https://api.stripe.com/v1/billing_portal/sessions\",\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n if (!resp.ok) return null;\n const data = (await resp.json()) as { url?: string };\n return data.url ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction currentMonth(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction firstDayNextMonth(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 1;\n if (m === 12) {\n return new Date(Date.UTC(y + 1, 0, 1)).toISOString();\n }\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { mccToIso } from \"@carrier/ocs-spec\";\nimport { OcsClient } from \"./client.js\";\nimport { getDefaultResellerId, type ToolContext } from \"./tools.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function safeCall<T = Record<string, unknown>>(\n env: { CARRIER_OCS_BASE_URL: string },\n token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n const client = new OcsClient(env.CARRIER_OCS_BASE_URL, token);\n const data = await client.call<T>(method, params);\n return { data, error: null };\n } catch (err) {\n return { data: null, error: err instanceof Error ? err.message : String(err) };\n }\n}\n\n/**\n * OCS listSubscriber requires one of: accountId/activationCode/imsiPrefix/iccidPrefix/msisdnPrefix.\n * 'status' is NOT a valid filter. Fan out across reseller accounts when none provided.\n */\nasync function fetchActiveSubscribers(\n env: { CARRIER_OCS_BASE_URL: string },\n token: string,\n accountId: number | undefined,\n resellerId: number,\n): Promise<{ data: Record<string, unknown>[] | null; error: string | null }> {\n let accountIds: number[];\n if (accountId !== undefined) {\n accountIds = [accountId];\n } else {\n const accountsResult = await safeCall<{ reseller?: Array<{ account?: Array<{ id: number }> }> }>(\n env,\n token,\n \"listResellerAccount\",\n { resellerId },\n );\n if (accountsResult.error) return { data: null, error: accountsResult.error };\n const reseller = accountsResult.data?.reseller ?? [];\n accountIds = reseller.flatMap((r) => (r.account ?? []).map((a) => a.id));\n if (accountIds.length === 0) return { data: [], error: null };\n }\n\n const aggregated: Record<string, unknown>[] = [];\n for (const acctId of accountIds) {\n const subResult = await safeCall<Record<string, unknown> | Record<string, unknown>[]>(\n env,\n token,\n \"listSubscriber\",\n { accountId: acctId },\n );\n if (subResult.error) return { data: null, error: subResult.error };\n const raw = subResult.data;\n const list = Array.isArray(raw)\n ? raw\n : ((raw as { subscriberList?: Record<string, unknown>[] } | null)?.subscriberList ?? []);\n aggregated.push(...list);\n }\n\n const active = aggregated.filter((s) => String(s.status ?? \"\").toUpperCase() === \"ACTIVE\");\n return { data: active, error: null };\n}\n\nfunction formatBytes(bytes: number): string {\n if (bytes === 0) return \"0 B\";\n const units = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i]}`;\n}\n\nfunction daysUntil(dateStr: string): number {\n const now = new Date();\n const target = new Date(dateStr);\n return Math.ceil((target.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));\n}\n\nfunction toISODate(d: Date): string {\n return d.toISOString().split(\"T\")[0];\n}\n\ntype ToolResult = { content: Array<{ type: \"text\"; text: string }>; isError?: boolean };\n\nfunction result(text: string, isError = false): ToolResult {\n return { content: [{ type: \"text\" as const, text }], ...(isError ? { isError: true } : {}) };\n}\n\n// ---------------------------------------------------------------------------\n// 1. DIAGNOSE SUBSCRIBER — \"why is this subscriber offline?\"\n// ---------------------------------------------------------------------------\n\nexport function registerIntelligenceTools(server: McpServer, ctx: ToolContext) {\n server.registerTool(\"diagnose_subscriber\", {\n title: \"Diagnose Subscriber Issues\",\n description:\n \"Smart diagnostic that chains multiple API calls to analyze why a subscriber \" +\n \"may be offline, throttled, or having connectivity issues. Returns a structured \" +\n \"diagnosis with root cause analysis and recommended actions.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to diagnose\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const findings: string[] = [];\n const actions: string[] = [];\n let severity: \"critical\" | \"warning\" | \"info\" | \"healthy\" = \"healthy\";\n\n // 1. Get subscriber details\n const sub = await safeCall<Record<string, unknown>>(ctx.env, token, \"getSingleSubscriber\", { iccid });\n if (sub.error) return result(`Failed to fetch subscriber: ${sub.error}`, true);\n if (!sub.data) return result(\"Subscriber not found\", true);\n\n const status = String(sub.data.status ?? \"\").toUpperCase();\n const balance = Number(sub.data.balance ?? 0);\n\n // Check OCS status\n if (status !== \"ACTIVE\") {\n findings.push(`OCS status is ${status} (not ACTIVE)`);\n actions.push(`Reactivate subscriber via modify_subscriber_status`);\n severity = \"critical\";\n }\n\n // Check balance\n if (balance <= 0) {\n findings.push(`Balance is ${balance} — subscriber may be blocked from usage`);\n actions.push(`Top up balance via modify_subscriber_balance`);\n if (severity !== \"critical\") severity = \"warning\";\n }\n\n // 2. Check SIM provider status — OCS expects bare simId (Long), resolve from subscriber record\n const simId = sub.data.simId ?? sub.data.sim_id ?? sub.data.id;\n const sim = simId !== undefined\n ? await safeCall<Record<string, unknown>>(ctx.env, token, \"getSimProviderStatus\", Number(simId))\n : { data: null, error: null };\n if (sim.data) {\n const simStatus = String(sim.data.simStatus ?? sim.data.status ?? \"\").toUpperCase();\n if (simStatus && ![\"ENABLED\", \"ACTIVE\", \"ACTIVATED\"].includes(simStatus)) {\n findings.push(`SIM provider status is ${simStatus} — SIM may be disabled at network level`);\n actions.push(`Enable SIM via change_sim_status`);\n severity = \"critical\";\n }\n }\n\n // 3. Check packages\n const pkgs = await safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid });\n if (pkgs.data && Array.isArray(pkgs.data)) {\n const activePkgs = pkgs.data.filter((p: Record<string, unknown>) =>\n String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n if (activePkgs.length === 0) {\n findings.push(\"No active packages — subscriber has no data/voice/SMS allowance\");\n actions.push(\"Assign a package via assign_package\");\n severity = \"critical\";\n } else {\n // Check for depleted packages\n for (const pkg of activePkgs) {\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n if (dataLimit > 0 && dataUsed >= dataLimit) {\n findings.push(\n `Package \"${pkg.name ?? pkg.packageTemplateId}\" data depleted: ` +\n `${formatBytes(dataUsed)} / ${formatBytes(dataLimit)}`\n );\n actions.push(\"Assign additional package or increase limits via modify_package_limits\");\n if (severity !== \"critical\") severity = \"warning\";\n }\n\n // Check expiry\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n if (expiry) {\n const days = daysUntil(expiry);\n if (days < 0) {\n findings.push(`Package \"${pkg.name ?? pkg.packageTemplateId}\" expired ${Math.abs(days)} days ago`);\n actions.push(\"Remove expired package and assign a new one\");\n if (severity !== \"critical\") severity = \"warning\";\n } else if (days <= 3) {\n findings.push(`Package \"${pkg.name ?? pkg.packageTemplateId}\" expires in ${days} day(s)`);\n actions.push(\"Consider renewing or assigning a recurring package\");\n if (severity === \"healthy\") severity = \"info\";\n }\n }\n }\n }\n }\n\n // 4. Check recent network events (last 2 days)\n const now = new Date();\n const twoDaysAgo = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000);\n const events = await safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberNetworkEventsOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(twoDaysAgo), end: toISODate(now) },\n });\n if (events.data && Array.isArray(events.data)) {\n if (events.data.length === 0) {\n findings.push(\"No network events in last 48 hours — device may be powered off or out of coverage\");\n if (severity === \"healthy\") severity = \"warning\";\n } else {\n const lastEvent = events.data[events.data.length - 1];\n const lastType = String(lastEvent.eventType ?? lastEvent.type ?? \"unknown\");\n findings.push(`Last network event: ${lastType} at ${lastEvent.timestamp ?? lastEvent.date ?? \"unknown\"}`);\n }\n }\n\n // 5. Check HLR bitrate — OCS expects { imsi }, resolve from subscriber record\n const imsiForBitrate = typeof sub.data.imsi === \"string\" ? sub.data.imsi : null;\n const bitrate = imsiForBitrate\n ? await safeCall<Record<string, unknown>>(ctx.env, token, \"hlrGetBitrate\", { imsi: imsiForBitrate })\n : { data: null, error: null };\n if (bitrate.data) {\n const rate = Number(bitrate.data.bitrate ?? bitrate.data.maxBitrate ?? 0);\n if (rate > 0 && rate < 1000000) {\n findings.push(`HLR bitrate throttled to ${(rate / 1000).toFixed(0)} kbps`);\n actions.push(\"Increase bitrate via hlr_set_bitrate if throttling is unintended\");\n if (severity === \"healthy\") severity = \"info\";\n }\n }\n\n // Build report\n if (findings.length === 0) {\n findings.push(\"No issues detected — subscriber appears healthy\");\n }\n\n const report = [\n `# Subscriber Diagnosis: ${iccid}`,\n ``,\n `## Severity: ${severity.toUpperCase()}`,\n ``,\n `## Findings`,\n ...findings.map((f, i) => `${i + 1}. ${f}`),\n ``,\n ...(actions.length > 0 ? [\n `## Recommended Actions`,\n ...actions.map((a, i) => `${i + 1}. ${a}`),\n ] : []),\n ``,\n `## Raw Status`,\n `- OCS Status: ${status}`,\n `- Balance: ${balance}`,\n `- Active Packages: ${pkgs.data && Array.isArray(pkgs.data) ? pkgs.data.filter((p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\").length : \"unknown\"}`,\n ].join(\"\\n\");\n\n return result(report);\n });\n\n // ---------------------------------------------------------------------------\n // 2. FLEET HEALTH — single-call fleet overview\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"fleet_health\", {\n title: \"Fleet Health Dashboard\",\n description:\n \"Aggregates eSIM status counts, low-balance accounts, and provides a \" +\n \"fleet-wide health summary in a single call. Identifies accounts that \" +\n \"need attention.\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account (omit for all)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n // OCS requires resellerId for both calls; resolve once from token owner.\n const resellerId = await getDefaultResellerId(ctx.env, token).catch(() => undefined);\n const [statusResult, accountsResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"esimStatusPerAccount\",\n accountId !== undefined\n ? { accountId }\n : resellerId !== undefined\n ? { resellerId }\n : {},\n ),\n safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"listResellerAccount\",\n resellerId !== undefined ? { resellerId } : {},\n ),\n ]);\n\n const sections: string[] = [\"# Fleet Health Dashboard\\n\"];\n\n // OCS responses are wrapped: esimStatusPerAccount → { account: [{sponsor:[{esim:{status:[...]}}]}] },\n // listResellerAccount → { reseller: [{account:[...]}] }. Unwrap to flat per-account arrays.\n const statusRaw = statusResult.data as { account?: Record<string, unknown>[] } | Record<string, unknown>[] | null;\n const statusAccounts: Record<string, unknown>[] = Array.isArray(statusRaw)\n ? statusRaw\n : (statusRaw?.account ?? []);\n const statusOk = statusResult.data !== null && (statusAccounts.length > 0 || statusResult.error === null);\n\n // OCS eSIM status shape: { statusNum: 0|1|2|3, statusStr: \"Free\"|\"Activated\"|\"Suspended\"|\"Released\", count }\n // statusNum canonical: 0=Free (inventory, not yet activated), 1=Activated, 2=Suspended, 3=Released/other.\n const countByState = (account: Record<string, unknown>): { active: number; suspended: number; inventory: number; other: number } => {\n const sponsors = (account.sponsor as Array<Record<string, unknown>> | undefined) ?? [];\n let active = 0, suspended = 0, inventory = 0, other = 0;\n for (const sp of sponsors) {\n const esim = (sp.esim as Record<string, unknown> | undefined) ?? {};\n const statuses = (esim.status as Array<Record<string, unknown>> | undefined) ?? [];\n for (const s of statuses) {\n const count = Number(s.count ?? 0);\n const num = s.statusNum;\n if (typeof num === \"number\") {\n if (num === 1) active += count;\n else if (num === 2) suspended += count;\n else if (num === 0) inventory += count;\n else other += count;\n continue;\n }\n const str = String(s.statusStr ?? s.name ?? \"\").toUpperCase();\n if (str === \"ACTIVATED\" || str === \"ACTIVE\") active += count;\n else if (str === \"SUSPENDED\") suspended += count;\n else if (str === \"FREE\" || str === \"INVENTORY\" || str === \"NOT_ACTIVATED\" || str === \"AVAILABLE\") inventory += count;\n else other += count;\n }\n }\n return { active, suspended, inventory, other };\n };\n\n let totalActive = 0, totalSuspended = 0, totalInventory = 0, totalOther = 0;\n\n if (statusOk) {\n for (const account of statusAccounts) {\n const hasSponsors = Array.isArray(account.sponsor);\n if (hasSponsors) {\n const c = countByState(account);\n totalActive += c.active;\n totalSuspended += c.suspended;\n totalInventory += c.inventory;\n totalOther += c.other;\n } else {\n totalActive += Number(account.active ?? 0);\n totalSuspended += Number(account.suspended ?? 0);\n totalInventory += Number(account.inventory ?? account.notActivated ?? 0);\n totalOther += Number(account.other ?? account.terminated ?? 0);\n }\n }\n\n const total = totalActive + totalSuspended + totalInventory + totalOther;\n const utilization = total > 0 ? ((totalActive / total) * 100).toFixed(1) : \"0\";\n\n sections.push(`## eSIM Fleet Status`);\n if (total === 0) {\n sections.push(`No eSIMs provisioned across ${statusAccounts.length} account(s).`);\n } else {\n sections.push(`| Metric | Count | % |`);\n sections.push(`|--------|-------|---|`);\n sections.push(`| Active | ${totalActive} | ${((totalActive / total) * 100).toFixed(1)}% |`);\n sections.push(`| Suspended | ${totalSuspended} | ${((totalSuspended / total) * 100).toFixed(1)}% |`);\n sections.push(`| Inventory | ${totalInventory} | ${((totalInventory / total) * 100).toFixed(1)}% |`);\n sections.push(`| Other | ${totalOther} | ${((totalOther / total) * 100).toFixed(1)}% |`);\n sections.push(`| **Total** | **${total}** | |`);\n sections.push(`\\n**Fleet Utilization: ${utilization}%**`);\n\n if (totalSuspended > totalActive * 0.1) {\n sections.push(`\\nHigh suspension rate (${totalSuspended} suspended vs ${totalActive} active)`);\n }\n }\n } else {\n sections.push(`## eSIM Fleet Status`);\n sections.push(`Unavailable: ${statusResult.error ?? \"esimStatusPerAccount returned no data\"}`);\n }\n\n // Account balances + health flags — unwrap { reseller: [{account: [...]}] }\n const accountsRaw = accountsResult.data as\n | { reseller?: Array<{ account?: Record<string, unknown>[] }> }\n | Record<string, unknown>[]\n | null;\n const accounts: Record<string, unknown>[] = Array.isArray(accountsRaw)\n ? accountsRaw\n : (accountsRaw?.reseller ?? []).flatMap((r) => r.account ?? []);\n const accountsOk = accountsResult.data !== null && (accounts.length > 0 || accountsResult.error === null);\n\n if (accountsOk) {\n const lowBalance = accounts.filter(\n (a) => Number(a.balance ?? 0) < 10,\n );\n const packageOnlyZero = accounts.filter(\n (a) => Boolean(a.packageOnly) && Number(a.balance ?? 0) <= 0,\n );\n\n sections.push(`\\n## Account Summary`);\n sections.push(`- Total accounts: ${accounts.length}`);\n sections.push(`- Low balance (< 10): ${lowBalance.length}`);\n sections.push(`- Package-only with 0 balance: ${packageOnlyZero.length}`);\n\n if (lowBalance.length > 0) {\n sections.push(`\\n### Low Balance Accounts (< 10)`);\n sections.push(`| Account | Balance | packageOnly |`);\n sections.push(`|---------|---------|-------------|`);\n for (const a of lowBalance) {\n sections.push(`| ${a.name ?? a.accountId ?? \"?\"} | ${Number(a.balance ?? 0).toFixed(2)} | ${a.packageOnly ? \"yes\" : \"no\"} |`);\n }\n }\n\n // Health verdict\n const critical = packageOnlyZero.length;\n const warning = lowBalance.length - critical;\n const healthy = accounts.length - lowBalance.length;\n sections.push(`\\n## Fleet Health Verdict`);\n sections.push(`- Healthy: ${healthy}`);\n sections.push(`- Warning (low balance, not package-only-zero): ${Math.max(warning, 0)}`);\n sections.push(`- Critical (package-only and 0 balance): ${critical}`);\n if (accounts.length === 0) {\n sections.push(`\\nNo accounts found under this reseller.`);\n } else if (critical > 0) {\n sections.push(`\\nAction: top up package-only accounts at 0 balance to keep packages assignable.`);\n } else if (lowBalance.length === 0) {\n sections.push(`\\nAll accounts healthy.`);\n }\n } else {\n sections.push(`\\n## Account Summary`);\n sections.push(`Unavailable: ${accountsResult.error ?? \"listResellerAccount returned no data\"}`);\n }\n\n // Surface aggregated errors if both upstream calls failed\n if (!statusOk && !accountsOk) {\n sections.push(`\\n## Errors`);\n if (statusResult.error) sections.push(`- esimStatusPerAccount: ${statusResult.error}`);\n if (accountsResult.error) sections.push(`- listResellerAccount: ${accountsResult.error}`);\n return result(sections.join(\"\\n\"), true);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 3. USAGE ANOMALY DETECTION\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"detect_usage_anomalies\", {\n title: \"Detect Usage Anomalies\",\n description:\n \"Analyzes a subscriber's recent usage patterns over the last 7 days to detect \" +\n \"anomalies: sudden spikes, unusual off-hours activity, or consumption rates that \" +\n \"would exhaust the package before expiry.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to analyze\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [usageResult, pkgResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n ]);\n\n if (usageResult.error) return result(`Failed to fetch usage: ${usageResult.error}`, true);\n\n const sections: string[] = [`# Usage Anomaly Report: ${iccid}\\n`];\n const anomalies: string[] = [];\n\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length > 0) {\n // Extract daily data volumes\n const dailyData: { date: string; bytes: number }[] = [];\n\n for (const entry of usageResult.data) {\n const bytes = Number(entry.dataBytes ?? entry.dataVolume ?? entry.totalData ?? 0);\n const date = String(entry.date ?? entry.day ?? \"?\");\n dailyData.push({ date, bytes });\n }\n\n if (dailyData.length >= 2) {\n // Calculate stats\n const volumes = dailyData.map(d => d.bytes);\n const mean = volumes.reduce((a, b) => a + b, 0) / volumes.length;\n const stdDev = Math.sqrt(volumes.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / volumes.length);\n\n sections.push(`## Daily Usage (Last 7 Days)`);\n sections.push(`| Date | Data | vs Average |`);\n sections.push(`|------|------|-----------|`);\n\n for (const d of dailyData) {\n const deviation = mean > 0 ? ((d.bytes - mean) / mean * 100).toFixed(0) : \"0\";\n const flag = d.bytes > mean + 2 * stdDev ? \" SPIKE\" :\n d.bytes > mean + stdDev ? \" HIGH\" : \"\";\n sections.push(`| ${d.date} | ${formatBytes(d.bytes)} | ${deviation}%${flag} |`);\n\n if (d.bytes > mean + 2 * stdDev) {\n anomalies.push(`Spike on ${d.date}: ${formatBytes(d.bytes)} (${deviation}% above average)`);\n }\n }\n\n sections.push(`\\n**Average daily usage: ${formatBytes(mean)}**`);\n sections.push(`**Std deviation: ${formatBytes(stdDev)}**`);\n\n // Burn rate analysis against active packages\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n for (const pkg of activePkgs) {\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const remaining = dataLimit - dataUsed;\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n\n if (remaining > 0 && expiry && mean > 0) {\n const daysLeft = daysUntil(expiry);\n const daysToExhaust = remaining / mean;\n\n sections.push(`\\n## Burn Rate: ${pkg.name ?? pkg.packageTemplateId}`);\n sections.push(`- Remaining: ${formatBytes(remaining)} of ${formatBytes(dataLimit)}`);\n sections.push(`- Days until expiry: ${daysLeft}`);\n sections.push(`- At current rate, data exhausts in: ${daysToExhaust.toFixed(1)} days`);\n\n if (daysToExhaust < daysLeft * 0.5) {\n anomalies.push(\n `Package \"${pkg.name ?? pkg.packageTemplateId}\" will run out ` +\n `${(daysLeft - daysToExhaust).toFixed(0)} days before expiry at current consumption`\n );\n }\n }\n }\n }\n }\n } else {\n sections.push(\"No usage data available for the last 7 days.\");\n }\n\n if (anomalies.length > 0) {\n sections.push(`\\n## Anomalies Detected`);\n anomalies.forEach((a, i) => sections.push(`${i + 1}. ${a}`));\n } else {\n sections.push(`\\n## No anomalies detected — usage appears normal.`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 4. PACKAGE OPTIMIZER — recommend better-fit packages\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"optimize_package\", {\n title: \"Package Optimization Advisor\",\n description:\n \"Compares a subscriber's actual usage against their current package and all \" +\n \"available templates. Recommends better-fit packages to reduce waste or prevent \" +\n \"overages. Calculates potential savings.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to optimize\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [usageResult, pkgResult, templatesResult] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listPrepaidPackageTemplate\", {}),\n ]);\n\n const sections: string[] = [`# Package Optimization: ${iccid}\\n`];\n\n // Calculate average daily usage\n let avgDailyData = 0;\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length > 0) {\n const totalData = usageResult.data.reduce(\n (sum: number, e: Record<string, unknown>) =>\n sum + Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0),\n 0\n );\n avgDailyData = totalData / usageResult.data.length;\n sections.push(`## Current Usage Pattern`);\n sections.push(`- Average daily data: ${formatBytes(avgDailyData)}`);\n sections.push(`- Projected monthly: ${formatBytes(avgDailyData * 30)}`);\n }\n\n // Current packages\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n if (activePkgs.length > 0) {\n sections.push(`\\n## Current Active Packages`);\n for (const pkg of activePkgs) {\n const dataLimit = Number(pkg.dataLimit ?? pkg.dataAllowance ?? 0);\n const dataUsed = Number(pkg.dataUsed ?? pkg.dataConsumed ?? 0);\n const utilization = dataLimit > 0 ? ((dataUsed / dataLimit) * 100).toFixed(1) : \"N/A\";\n const price = Number(pkg.price ?? pkg.cost ?? 0);\n\n sections.push(`\\n### ${pkg.name ?? pkg.packageTemplateId}`);\n sections.push(`- Data: ${formatBytes(dataUsed)} / ${formatBytes(dataLimit)} (${utilization}% used)`);\n if (price > 0) sections.push(`- Price: ${price.toFixed(2)}`);\n\n const expiry = String(pkg.expirationDate ?? pkg.endDate ?? \"\");\n if (expiry) sections.push(`- Expires: ${expiry} (${daysUntil(expiry)} days)`);\n\n // Flag waste\n if (dataLimit > 0 && Number(utilization) < 30) {\n sections.push(`- LOW UTILIZATION — subscriber is using less than 30% of allowance`);\n } else if (Number(utilization) > 90) {\n sections.push(`- NEAR LIMIT — subscriber at risk of running out`);\n }\n }\n }\n }\n\n // Recommend templates\n if (templatesResult.data && Array.isArray(templatesResult.data) && avgDailyData > 0) {\n // Score templates by fit\n const scored = templatesResult.data\n .map((t: Record<string, unknown>) => {\n const limit = Number(t.dataLimit ?? t.dataAllowance ?? 0);\n const validity = Number(t.validityDays ?? t.duration ?? 30);\n const price = Number(t.price ?? t.cost ?? 0);\n const projectedUsage = avgDailyData * validity;\n\n // Fit score: penalize both waste (too much data) and shortage (too little)\n const ratio = limit > 0 ? projectedUsage / limit : 0;\n const fitScore = 1 - Math.abs(1 - ratio); // 1.0 = perfect fit, 0 = terrible\n const costPerGB = limit > 0 && price > 0 ? price / (limit / (1024 * 1024 * 1024)) : Infinity;\n\n const name = String(t.name ?? t.templateId ?? \"?\");\n return { name, limit, validity, price, projectedUsage, fitScore, costPerGB, ratio };\n })\n .filter((t) => t.fitScore > 0.3 && t.limit > 0)\n .sort((a, b) => b.fitScore - a.fitScore)\n .slice(0, 5);\n\n if (scored.length > 0) {\n sections.push(`\\n## Recommended Packages (by usage fit)`);\n sections.push(`| Template | Data | Validity | Price | Fit | Projected Use |`);\n sections.push(`|----------|------|----------|-------|-----|--------------|`);\n\n for (const t of scored) {\n const fitLabel = t.fitScore > 0.8 ? \"GREAT\" : t.fitScore > 0.6 ? \"GOOD\" : \"OK\";\n sections.push(\n `| ${t.name} | ${formatBytes(t.limit)} | ` +\n `${t.validity}d | ${t.price > 0 ? t.price.toFixed(2) : \"?\"} | ` +\n `${fitLabel} (${(t.fitScore * 100).toFixed(0)}%) | ${formatBytes(t.projectedUsage)} |`\n );\n }\n }\n } else if (avgDailyData === 0) {\n sections.push(`\\n*No usage data available — cannot recommend packages without usage history.*`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 5. CHURN RISK SCORING\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"churn_risk\", {\n title: \"Churn Risk Assessment\",\n description:\n \"Analyzes a subscriber's usage trends, package status, balance, and activity \" +\n \"to produce a churn risk score (0-100) with contributing factors and retention \" +\n \"recommendations.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID to assess\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ iccid }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n const [subResult, usageResult, pkgResult, activeResult] = await Promise.all([\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSingleSubscriber\", { iccid }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberActivePeriod\", { iccid }),\n ]);\n\n let riskScore = 0;\n const factors: { factor: string; impact: number; detail: string }[] = [];\n\n // Factor 1: Usage trend (declining usage = higher risk)\n if (usageResult.data && Array.isArray(usageResult.data) && usageResult.data.length >= 3) {\n const volumes = usageResult.data.map(\n (e: Record<string, unknown>) => Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0)\n );\n const firstHalf = volumes.slice(0, Math.floor(volumes.length / 2));\n const secondHalf = volumes.slice(Math.floor(volumes.length / 2));\n const avgFirst = firstHalf.reduce((a: number, b: number) => a + b, 0) / firstHalf.length;\n const avgSecond = secondHalf.reduce((a: number, b: number) => a + b, 0) / secondHalf.length;\n\n if (avgFirst > 0) {\n const trend = (avgSecond - avgFirst) / avgFirst;\n if (trend < -0.5) {\n const impact = 30;\n riskScore += impact;\n factors.push({ factor: \"Declining usage\", impact, detail: `Usage dropped ${Math.abs(trend * 100).toFixed(0)}% week-over-week` });\n } else if (trend < -0.2) {\n const impact = 15;\n riskScore += impact;\n factors.push({ factor: \"Moderately declining usage\", impact, detail: `Usage dropped ${Math.abs(trend * 100).toFixed(0)}%` });\n }\n }\n } else if (!usageResult.data || (Array.isArray(usageResult.data) && usageResult.data.length === 0)) {\n riskScore += 25;\n factors.push({ factor: \"No recent usage\", impact: 25, detail: \"Zero data activity in last 7 days\" });\n }\n\n // Factor 2: Package status\n if (pkgResult.data && Array.isArray(pkgResult.data)) {\n const activePkgs = pkgResult.data.filter(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n if (activePkgs.length === 0) {\n riskScore += 20;\n factors.push({ factor: \"No active packages\", impact: 20, detail: \"Subscriber has no active data packages\" });\n } else {\n // Check if all packages are near expiry\n const allExpiringSoon = activePkgs.every((p: Record<string, unknown>) => {\n const expiry = String(p.expirationDate ?? p.endDate ?? \"\");\n return expiry && daysUntil(expiry) <= 5;\n });\n if (allExpiringSoon) {\n riskScore += 15;\n factors.push({ factor: \"All packages expiring soon\", impact: 15, detail: \"No package renewal in sight\" });\n }\n\n // Check if no recurring packages\n const hasRecurring = activePkgs.some(\n (p: Record<string, unknown>) => p.recurring === true || p.isRecurring === true\n );\n if (!hasRecurring) {\n riskScore += 10;\n factors.push({ factor: \"No recurring packages\", impact: 10, detail: \"Manual renewal required — higher churn risk\" });\n }\n }\n }\n\n // Factor 3: Balance\n if (subResult.data) {\n const balance = Number(subResult.data.balance ?? 0);\n if (balance <= 0) {\n riskScore += 15;\n factors.push({ factor: \"Zero balance\", impact: 15, detail: \"Cannot purchase new packages\" });\n }\n }\n\n // Factor 4: Subscriber age (newer = higher risk)\n if (activeResult.data) {\n const firstUse = String(activeResult.data.firstUseDate ?? activeResult.data.activationDate ?? \"\");\n if (firstUse) {\n const daysSinceFirst = Math.abs(daysUntil(firstUse));\n if (daysSinceFirst < 30) {\n riskScore += 10;\n factors.push({ factor: \"New subscriber\", impact: 10, detail: `Only ${daysSinceFirst} days since first use` });\n }\n }\n }\n\n // Cap at 100\n riskScore = Math.min(riskScore, 100);\n\n // Risk level\n const level = riskScore >= 70 ? \"HIGH\" : riskScore >= 40 ? \"MEDIUM\" : \"LOW\";\n\n // Build report\n const sections = [\n `# Churn Risk Assessment: ${iccid}`,\n ``,\n `## Risk Score: ${riskScore}/100 (${level})`,\n ``,\n `${\"█\".repeat(Math.floor(riskScore / 5))}${\"░\".repeat(20 - Math.floor(riskScore / 5))}`,\n ``,\n ];\n\n if (factors.length > 0) {\n sections.push(`## Contributing Factors`);\n sections.push(`| Factor | Impact | Detail |`);\n sections.push(`|--------|--------|--------|`);\n factors.sort((a, b) => b.impact - a.impact);\n for (const f of factors) {\n sections.push(`| ${f.factor} | +${f.impact} | ${f.detail} |`);\n }\n }\n\n // Retention recommendations\n sections.push(`\\n## Retention Recommendations`);\n if (riskScore >= 70) {\n sections.push(\"1. **Immediate outreach** — contact subscriber with special offer\");\n sections.push(\"2. Assign a complimentary small data package to re-engage\");\n sections.push(\"3. Set up a recurring package to reduce renewal friction\");\n } else if (riskScore >= 40) {\n sections.push(\"1. Monitor usage for next 7 days\");\n sections.push(\"2. Consider proactive package renewal notification (via send_sms)\");\n sections.push(\"3. Ensure package fits usage pattern (run optimize_package)\");\n } else {\n sections.push(\"1. No immediate action required\");\n sections.push(\"2. Continue monitoring via regular fleet_health checks\");\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 6. NETWORK COVERAGE AUDIT — \"am I on the right networks?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"audit_network_coverage\", {\n title: \"Network Coverage Audit\",\n description:\n \"Analyzes which networks your subscribers are actually connecting to in a given \" +\n \"country or across all countries. Compares against your steering lists to identify \" +\n \"mismatches — subscribers roaming on expensive or non-preferred networks. \" +\n \"Use this to answer: 'Am I using the right networks in country X?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n limit: z.number().optional().describe(\"Max subscribers to sample (default 50)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId, limit: sampleLimit }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const maxSample = sampleLimit ?? 50;\n\n // OCS listSubscriber requires accountId. Fan out across accounts.\n const resellerId = await getDefaultResellerId(ctx.env, token);\n const [subsResult, steeringResult] = await Promise.all([\n fetchActiveSubscribers(ctx.env, token, accountId, resellerId),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSteeringList\", resellerId),\n ]);\n\n if (subsResult.error) return result(`Failed to fetch subscribers: ${subsResult.error}`, true);\n\n const sections: string[] = [`# Network Coverage Audit\\n`];\n\n // Build steering list lookup\n const steeringMap = new Map<number, Record<string, unknown>>();\n if (steeringResult.data && Array.isArray(steeringResult.data)) {\n for (const sl of steeringResult.data) {\n steeringMap.set(Number(sl.steeringListId ?? sl.id), sl);\n }\n sections.push(`## Steering Lists: ${steeringMap.size} configured`);\n }\n\n // Sample subscriber locations and networks\n const countryStats = new Map<string, {\n count: number;\n networks: Map<string, number>;\n subscribers: string[];\n }>();\n\n if (subsResult.data && Array.isArray(subsResult.data)) {\n const subs = subsResult.data.slice(0, maxSample);\n sections.push(`## Sampling ${subs.length} active subscribers\\n`);\n\n // Fetch locations in batches of 10\n const batchSize = 10;\n\n for (let i = 0; i < subs.length; i += batchSize) {\n const batch = subs.slice(i, i + batchSize);\n const locations = await Promise.all(\n batch.map((s: Record<string, unknown>) =>\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", {\n iccid: String(s.iccid ?? \"\"),\n })\n )\n );\n\n for (let j = 0; j < batch.length; j++) {\n const loc = locations[j];\n if (loc.data) {\n const country = String(loc.data.country ?? loc.data.countryCode ?? \"Unknown\");\n const network = String(loc.data.network ?? loc.data.operator ?? loc.data.mccMnc ?? \"Unknown\");\n const iccid = String(batch[j].iccid ?? \"\");\n\n if (!countryStats.has(country)) {\n countryStats.set(country, { count: 0, networks: new Map(), subscribers: [] });\n }\n const stat = countryStats.get(country)!;\n stat.count++;\n stat.networks.set(network, (stat.networks.get(network) ?? 0) + 1);\n stat.subscribers.push(iccid);\n }\n }\n }\n }\n\n // Report by country\n if (countryStats.size > 0) {\n sections.push(`## Network Distribution by Country`);\n\n const sorted = [...countryStats.entries()].sort((a, b) => b[1].count - a[1].count);\n\n for (const [country, stat] of sorted) {\n sections.push(`\\n### ${country} (${stat.count} subscribers)`);\n sections.push(`| Network | Subscribers | % |`);\n sections.push(`|---------|------------|---|`);\n\n const networksSorted = [...stat.networks.entries()].sort((a, b) => b[1] - a[1]);\n for (const [network, count] of networksSorted) {\n sections.push(`| ${network} | ${count} | ${((count / stat.count) * 100).toFixed(0)}% |`);\n }\n\n if (networksSorted.length > 3) {\n sections.push(`\\n${networksSorted.length} different networks in ${country} — possible steering fragmentation`);\n }\n }\n } else {\n sections.push(\"No location data available for sampled subscribers.\");\n }\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 7. MARKETING INTELLIGENCE — \"which countries should I target?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"marketing_intelligence\", {\n title: \"Marketing Intelligence Report\",\n description:\n \"Analyzes your subscriber base to identify high-growth markets, underserved regions, \" +\n \"and revenue concentration. Answers: 'Which countries should I target with marketing?' \" +\n \"and 'Where are my most valuable subscribers?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const params: Record<string, unknown> = {};\n if (accountId !== undefined) params.accountId = accountId;\n\n const [subsResult, templatesResult, resellerId] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriber\", params),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listPrepaidPackageTemplate\", {}),\n getDefaultResellerId(ctx.env, token),\n ]);\n const zonesResult = await safeCall<Record<string, unknown>[]>(\n ctx.env,\n token,\n \"listDetailedLocationZone\",\n resellerId,\n );\n\n const sections: string[] = [`# Marketing Intelligence Report\\n`];\n\n // Subscriber distribution by location\n if (subsResult.data && Array.isArray(subsResult.data)) {\n const total = subsResult.data.length;\n sections.push(`## Fleet Size: ${total} subscribers sampled\\n`);\n\n // Get locations for a sample\n const sample = subsResult.data.slice(0, 100);\n const countryData = new Map<string, {\n subscribers: number;\n activePackages: number;\n totalBalance: number;\n }>();\n\n const batchSize = 10;\n for (let i = 0; i < sample.length; i += batchSize) {\n const batch = sample.slice(i, i + batchSize);\n const locations = await Promise.all(\n batch.map((s: Record<string, unknown>) =>\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", {\n iccid: String(s.iccid ?? \"\"),\n })\n )\n );\n\n for (let j = 0; j < batch.length; j++) {\n const loc = locations[j];\n const sub = batch[j];\n const country = loc.data\n ? String(loc.data.country ?? loc.data.countryCode ?? \"Unknown\")\n : \"Unknown\";\n\n if (!countryData.has(country)) {\n countryData.set(country, { subscribers: 0, activePackages: 0, totalBalance: 0 });\n }\n const cd = countryData.get(country)!;\n cd.subscribers++;\n cd.totalBalance += Number(sub.balance ?? 0);\n }\n }\n\n if (countryData.size > 0) {\n const sorted = [...countryData.entries()].sort((a, b) => b[1].subscribers - a[1].subscribers);\n\n sections.push(`## Subscriber Concentration by Country`);\n sections.push(`| Country | Subscribers | % of Fleet | Avg Balance |`);\n sections.push(`|---------|-----------|------------|-------------|`);\n\n for (const [country, data] of sorted) {\n const pct = ((data.subscribers / sample.length) * 100).toFixed(1);\n const avgBal = (data.totalBalance / data.subscribers).toFixed(2);\n sections.push(`| ${country} | ${data.subscribers} | ${pct}% | ${avgBal} |`);\n }\n\n // Insights\n sections.push(`\\n## Market Insights`);\n\n // Top market\n const topMarket = sorted[0];\n if (topMarket) {\n sections.push(`- **Strongest market**: ${topMarket[0]} (${topMarket[1].subscribers} subscribers)`);\n if (topMarket[1].subscribers / sample.length > 0.5) {\n sections.push(` Revenue concentration risk — >50% of fleet in one market`);\n }\n }\n\n // High-value markets (high avg balance)\n const highValue = sorted\n .filter(([, d]) => d.subscribers >= 3)\n .sort((a, b) => (b[1].totalBalance / b[1].subscribers) - (a[1].totalBalance / a[1].subscribers))\n .slice(0, 3);\n\n if (highValue.length > 0) {\n sections.push(`\\n### High-Value Markets (by avg balance)`);\n for (const [country, data] of highValue) {\n sections.push(`- **${country}**: avg balance ${(data.totalBalance / data.subscribers).toFixed(2)} (${data.subscribers} subs)`);\n }\n }\n\n // Underserved (1-2 subscribers — early traction)\n const emerging = sorted.filter(([, d]) => d.subscribers >= 1 && d.subscribers <= 3);\n if (emerging.length > 0) {\n sections.push(`\\n### Emerging Markets (early traction, 1-3 subscribers)`);\n sections.push(`These markets show initial demand — consider targeted campaigns:`);\n for (const [country, data] of emerging) {\n sections.push(`- ${country}: ${data.subscribers} subscriber(s)`);\n }\n }\n }\n }\n\n // Available coverage vs actual usage\n if (zonesResult.data && Array.isArray(zonesResult.data)) {\n sections.push(`\\n## Coverage Catalog`);\n sections.push(`- Location zones available: ${zonesResult.data.length}`);\n }\n\n if (templatesResult.data && Array.isArray(templatesResult.data)) {\n sections.push(`- Package templates available: ${templatesResult.data.length}`);\n\n // Price analysis\n const prices = templatesResult.data\n .map((t: Record<string, unknown>) => Number(t.price ?? t.cost ?? 0))\n .filter((p: number) => p > 0);\n\n if (prices.length > 0) {\n const avgPrice = prices.reduce((a: number, b: number) => a + b, 0) / prices.length;\n const minPrice = Math.min(...prices);\n const maxPrice = Math.max(...prices);\n sections.push(`\\n### Pricing Range`);\n sections.push(`- Min: ${minPrice.toFixed(2)} | Avg: ${avgPrice.toFixed(2)} | Max: ${maxPrice.toFixed(2)}`);\n }\n }\n\n sections.push(`\\n## Recommended Actions`);\n sections.push(`1. Run \\`audit_network_coverage\\` to verify network quality in top markets`);\n sections.push(`2. Run \\`high_cost_subscribers\\` to identify margin pressure`);\n sections.push(`3. Consider creating regional package templates for emerging markets`);\n\n return result(sections.join(\"\\n\"));\n });\n\n // ---------------------------------------------------------------------------\n // 8. HIGH COST SUBSCRIBERS — \"who's costing me money?\"\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"high_cost_subscribers\", {\n title: \"High Cost Subscriber Report\",\n description:\n \"Identifies subscribers with disproportionately high data consumption relative \" +\n \"to their package value. Finds subscribers burning through data at rates that \" +\n \"erode margins. Answers: 'Which subscribers are costing me money?'\",\n inputSchema: {\n accountId: z.number().optional().describe(\"Filter to a specific account\"),\n limit: z.number().optional().describe(\"Max subscribers to analyze (default 100)\"),\n thresholdPct: z.number().optional().describe(\"Usage % threshold to flag (default 80)\"),\n },\n annotations: { readOnlyHint: true },\n }, async ({ accountId, limit: maxLimit, thresholdPct }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const sampleSize = maxLimit ?? 100;\n const threshold = thresholdPct ?? 80;\n\n // OCS listSubscriber requires accountId. Fan out across accounts.\n const resellerId = await getDefaultResellerId(ctx.env, token);\n const subsResult = await fetchActiveSubscribers(ctx.env, token, accountId, resellerId);\n if (subsResult.error) return result(`Failed to fetch subscribers: ${subsResult.error}`, true);\n if (!subsResult.data || subsResult.data.length === 0) return result(\"No subscribers found\", true);\n\n const sections: string[] = [`# High Cost Subscriber Report\\n`];\n const now = new Date();\n const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);\n\n type SubscriberCost = {\n iccid: string;\n dailyAvgBytes: number;\n packageDataLimit: number;\n packagePrice: number;\n utilizationPct: number;\n costPerGB: number;\n daysToExhaust: number;\n country: string;\n };\n\n const highCostSubs: SubscriberCost[] = [];\n\n // Analyze in batches\n const batchSize = 5;\n const subs = subsResult.data.slice(0, sampleSize);\n\n for (let i = 0; i < subs.length; i += batchSize) {\n const batch = subs.slice(i, i + batchSize);\n\n await Promise.all(\n batch.map(async (sub: Record<string, unknown>) => {\n const iccid = String(sub.iccid ?? \"\");\n\n const [usage, pkgs, loc] = await Promise.all([\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"subscriberUsageOverPeriod\", {\n subscriber: { iccid },\n period: { start: toISODate(weekAgo), end: toISODate(now) },\n }),\n safeCall<Record<string, unknown>[]>(ctx.env, token, \"listSubscriberPrepaidPackages\", { iccid }),\n safeCall<Record<string, unknown>>(ctx.env, token, \"getSubscriberLocation\", { iccid }),\n ]);\n\n // Calculate daily avg\n let dailyAvgBytes = 0;\n if (usage.data && Array.isArray(usage.data) && usage.data.length > 0) {\n const totalBytes = usage.data.reduce(\n (sum: number, e: Record<string, unknown>) =>\n sum + Number(e.dataBytes ?? e.dataVolume ?? e.totalData ?? 0),\n 0\n );\n dailyAvgBytes = totalBytes / usage.data.length;\n }\n\n // Get active package info\n if (pkgs.data && Array.isArray(pkgs.data)) {\n const activePkg = pkgs.data.find(\n (p: Record<string, unknown>) => String(p.status ?? \"\").toUpperCase() === \"ACTIVE\"\n );\n\n if (activePkg && dailyAvgBytes > 0) {\n const dataLimit = Number(activePkg.dataLimit ?? activePkg.dataAllowance ?? 0);\n const dataUsed = Number(activePkg.dataUsed ?? activePkg.dataConsumed ?? 0);\n const price = Number(activePkg.price ?? activePkg.cost ?? 0);\n const utilizationPct = dataLimit > 0 ? (dataUsed / dataLimit) * 100 : 0;\n const remaining = dataLimit - dataUsed;\n const daysToExhaust = dailyAvgBytes > 0 ? remaining / dailyAvgBytes : Infinity;\n const costPerGB = price > 0 && dataUsed > 0\n ? price / (dataUsed / (1024 * 1024 * 1024))\n : 0;\n\n const country = loc.data\n ? String(loc.data.country ?? loc.data.countryCode ?? \"?\")\n : \"?\";\n\n if (utilizationPct >= threshold || daysToExhaust < 3) {\n highCostSubs.push({\n iccid,\n dailyAvgBytes,\n packageDataLimit: dataLimit,\n packagePrice: price,\n utilizationPct,\n costPerGB,\n daysToExhaust,\n country,\n });\n }\n }\n }\n })\n );\n }\n\n // Sort by utilization (highest first)\n highCostSubs.sort((a, b) => b.utilizationPct - a.utilizationPct);\n\n sections.push(`Analyzed ${subs.length} active subscribers (threshold: ${threshold}% usage)\\n`);\n\n if (highCostSubs.length === 0) {\n sections.push(`No subscribers above ${threshold}% package utilization. Fleet margins look healthy.`);\n } else {\n sections.push(`## ${highCostSubs.length} High-Cost Subscribers Found\\n`);\n sections.push(`| ICCID | Country | Daily Avg | Usage % | Days Left | Cost/GB |`);\n sections.push(`|-------|---------|-----------|---------|-----------|---------|`);\n\n let totalDailyBytes = 0;\n for (const s of highCostSubs) {\n totalDailyBytes += s.dailyAvgBytes;\n sections.push(\n `| ${s.iccid.slice(-8)}... | ${s.country} | ${formatBytes(s.dailyAvgBytes)} | ` +\n `${s.utilizationPct.toFixed(0)}% | ${s.daysToExhaust === Infinity ? \"inf\" : s.daysToExhaust.toFixed(1)} | ` +\n `${s.costPerGB > 0 ? s.costPerGB.toFixed(2) : \"?\"} |`\n );\n }\n\n sections.push(`\\n## Summary`);\n sections.push(`- High-cost subscribers: ${highCostSubs.length} / ${subs.length} (${((highCostSubs.length / subs.length) * 100).toFixed(1)}%)`);\n sections.push(`- Combined daily data burn: ${formatBytes(totalDailyBytes)}`);\n\n // Country breakdown\n const byCountry = new Map<string, number>();\n for (const s of highCostSubs) {\n byCountry.set(s.country, (byCountry.get(s.country) ?? 0) + 1);\n }\n const countrySorted = [...byCountry.entries()].sort((a, b) => b[1] - a[1]);\n if (countrySorted.length > 0) {\n sections.push(`\\n### By Country`);\n for (const [country, count] of countrySorted) {\n sections.push(`- ${country}: ${count} high-cost subscriber(s)`);\n }\n }\n\n sections.push(`\\n## Recommended Actions`);\n sections.push(`1. Review tariff rates for top countries via \\`get_tariff\\``);\n sections.push(`2. Consider throttling heavy users via \\`hlr_set_bitrate\\``);\n sections.push(`3. Run \\`optimize_package\\` on flagged ICCIDs to find better-fit plans`);\n sections.push(`4. Negotiate better wholesale rates for high-volume countries`);\n }\n\n return result(sections.join(\"\\n\"));\n });\n // ---------------------------------------------------------------------------\n // 9. DETECT COUNTRY ENTRY — cheap MCC-based location change detection\n // ---------------------------------------------------------------------------\n\n server.registerTool(\"detect_country_entry\", {\n title: \"Detect Country Entry\",\n description:\n \"Detects when a subscriber has entered a new country by reading \" +\n \"networkInfo.lastMcc from getSingleSubscriber (one cheap OCS call — \" +\n \"avoids the per-call cost of getSubscriberLocationByCellId). Resolves \" +\n \"MCC → ISO 3166-1 alpha-2 and optionally diffs against a caller-supplied \" +\n \"expectedCountry to return countryChanged. Designed for downstream \" +\n \"country-entry upsell workflows (e.g. mango.talk SMS/push offers). \" +\n \"COST NOTE: This tool makes exactly one OCS call per invocation. \" +\n \"Consumers running polling crons MUST enforce their own rate floor — \" +\n \"this layer provides no throttle.\",\n inputSchema: {\n subscriber: z\n .union([\n z.object({ subscriberId: z.number() }).describe(\"Internal subscriber ID\"),\n z.object({ imsi: z.string() }).describe(\"IMSI\"),\n z.object({ iccid: z.string() }).describe(\"ICCID\"),\n z.object({ msisdn: z.string() }).describe(\"MSISDN / phone number\"),\n z.object({ multiImsi: z.string() }).describe(\"Multi-IMSI identifier\"),\n z.object({ activationCode: z.string() }).describe(\"eSIM activation code\"),\n ])\n .describe(\"Subscriber identifier (use exactly one field)\"),\n expectedCountry: z\n .string()\n .length(2)\n .transform((code) => code.toUpperCase())\n .optional()\n .describe(\n \"Caller\\u2019s last-known ISO 3166-1 alpha-2 country for this subscriber \" +\n \"(e.g. \\\"RU\\\"). When provided, countryChanged is included in the response.\",\n ),\n },\n annotations: { readOnlyHint: true },\n }, async ({ subscriber, expectedCountry }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n\n // getSingleSubscriber accepts any of subscriberId | imsi | iccid | msisdn |\n // multiImsi | activationCode — pass the discriminated union value directly.\n const sub = await safeCall<Record<string, unknown>>(\n ctx.env,\n token,\n \"getSingleSubscriber\",\n subscriber as Record<string, unknown>,\n );\n\n if (sub.error) return result(`Failed to fetch subscriber: ${sub.error}`, true);\n if (!sub.data) return result(\"Subscriber not found\", true);\n\n const subscriberId =\n sub.data.subscriberId ??\n sub.data.id ??\n (\"subscriberId\" in subscriber\n ? (subscriber as { subscriberId: number }).subscriberId\n : undefined);\n\n const networkInfo = sub.data.networkInfo as Record<string, unknown> | null | undefined;\n\n if (networkInfo === null || networkInfo === undefined || typeof networkInfo !== \"object\") {\n return result(\n JSON.stringify({ status: \"no_location_data\", subscriberId: subscriberId ?? null }),\n );\n }\n\n const lastMcc =\n networkInfo.lastMcc != null ? Number(networkInfo.lastMcc) : null;\n const lastMnc =\n networkInfo.lastMnc != null ? Number(networkInfo.lastMnc) : null;\n const lastSeenAtUtc =\n networkInfo.time != null ? String(networkInfo.time) : null;\n\n if (lastMcc === null || isNaN(lastMcc)) {\n return result(\n JSON.stringify({ status: \"no_location_data\", subscriberId: subscriberId ?? null }),\n );\n }\n\n const currentCountry = mccToIso(lastMcc);\n const mccUnresolved = currentCountry === null;\n\n const response: Record<string, unknown> = {\n subscriberId: subscriberId ?? null,\n currentCountry,\n currentMcc: lastMcc,\n currentMnc: lastMnc,\n lastSeenAtUtc,\n ...(mccUnresolved ? { mccUnresolved: true } : {}),\n };\n\n if (expectedCountry !== undefined) {\n response.expectedCountry = expectedCountry;\n // null = cannot determine (MCC unresolved); true/false = definitive diff\n response.countryChanged = currentCountry !== null\n ? currentCountry !== expectedCountry\n : null;\n }\n\n return result(JSON.stringify(response, null, 2));\n });\n\n}\n","{\n \"version\": \"1.0.0\",\n \"captured_at\": \"2026-05-10T20:55:08.779899+00:00\",\n \"sources\": {\n \"live_docs_url\": \"https://docs.esimvault.cloud/ocs-api\",\n \"server_source_repo\": \"auroracapital/esimmcp.com\",\n \"server_source_commit\": \"8793971\",\n \"server_source_branch\": \"feat/intelligence-tools@e200c42 merged to main via restore-mcp-to-main PR#31\",\n \"notes\": \"Live docs SPA rendered via Kapture (2026-05-10). Server is a strict subset of live docs (43/52 methods). Zero server→live drift confirmed. 9 live-only methods are v1.1 backlog.\"\n },\n \"v1_methods\": [\n {\n \"name\": \"list_reseller_accounts\",\n \"ocs_method\": \"listResellerAccount\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all accounts across all resellers\",\n \"params\": {\n \"resellerId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_reseller_info\",\n \"ocs_method\": \"getResellerInfo\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"Retrieve reseller details\",\n \"params\": {\n \"resellerId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"esim_status_per_account\",\n \"ocs_method\": \"esimStatusPerAccount\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"eSIM status breakdown per account\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_sponsors\",\n \"ocs_method\": \"listSponsor\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all sponsor networks\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_steering_lists\",\n \"ocs_method\": \"listSteeringList\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"description\": \"List all network steering lists\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_account_balance\",\n \"ocs_method\": \"modifyAccountBalance\",\n \"category\": \"reseller\",\n \"scope\": \"admin\",\n \"description\": \"Adjust or set reseller account balance\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": true },\n \"amount\": { \"type\": \"number\", \"required\": true },\n \"mode\": { \"type\": \"enum[adapt,set]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber\",\n \"ocs_method\": \"getSingleSubscriber\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get full subscriber details by ICCID or MSISDN\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": false },\n \"msisdn\": { \"type\": \"string\", \"required\": false },\n \"with_gz_counter\": { \"type\": \"boolean\", \"required\": false, \"ocs_field\": \"withGzCounter\", \"description\": \"When true, include greenZoneCounter { subscriberId, volumeOnGZ (bytes), lastResetDate, lastUpdateDate } in response\" }\n },\n \"response\": {\n \"greenZoneCounter\": { \"type\": \"object\", \"present_when\": \"with_gz_counter=true\", \"fields\": { \"subscriberId\": \"number\", \"volumeOnGZ\": \"number (bytes)\", \"lastResetDate\": \"string (ISO8601)\", \"lastUpdateDate\": \"string (ISO8601)\" } }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_subscribers\",\n \"ocs_method\": \"listSubscriber\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"List subscribers with optional filters\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false },\n \"status\": { \"type\": \"string\", \"required\": false },\n \"offset\": { \"type\": \"number\", \"required\": false },\n \"limit\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_balance\",\n \"ocs_method\": \"modifySubscriberBalance\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Adjust or set subscriber balance\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"amount\": { \"type\": \"number\", \"required\": true },\n \"mode\": { \"type\": \"enum[adapt,set]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_status\",\n \"ocs_method\": \"modifySubscriberStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change subscriber OCS status\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"status\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"change_sim_status\",\n \"ocs_method\": \"changeSimStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change SIM status at provider level\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"simStatus\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_sim_provider_status\",\n \"ocs_method\": \"getSimProviderStatus\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Check SIM provider-level status\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber_location\",\n \"ocs_method\": \"getSubscriberLocation\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get last known subscriber location\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_contact_info\",\n \"ocs_method\": \"modifySubscriberContactInfo\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Update subscriber contact info\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"firstName\": { \"type\": \"string\", \"required\": false },\n \"lastName\": { \"type\": \"string\", \"required\": false },\n \"email\": { \"type\": \"string\", \"required\": false },\n \"phoneNumber\": { \"type\": \"string\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"set_subscriber_traffic_restrictions\",\n \"ocs_method\": \"setSubscriberTrafficRestrictions\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Configure traffic restrictions for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"restrictions\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_steering_list\",\n \"ocs_method\": \"modifySubscriberSteeringList\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Change network steering list for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"steeringListId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"move_subscriber_range_to_account\",\n \"ocs_method\": \"moveSubscriberRangeToAccount\",\n \"category\": \"subscriber\",\n \"scope\": \"admin\",\n \"description\": \"Move subscriber range to another account\",\n \"params\": {\n \"iccidFrom\": { \"type\": \"string\", \"required\": true },\n \"iccidTo\": { \"type\": \"string\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"hlr_set_bitrate\",\n \"ocs_method\": \"hlrSetBitrate\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"description\": \"Set HLR bitrate for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"bitrate\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"hlr_get_bitrate\",\n \"ocs_method\": \"hlrGetBitrate\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"description\": \"Get HLR bitrate for a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_subscriber_packages\",\n \"ocs_method\": \"listSubscriberPrepaidPackages\",\n \"category\": \"packages\",\n \"scope\": \"read\",\n \"description\": \"List all prepaid packages assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"assign_package\",\n \"ocs_method\": \"affectPackageToSubscriber\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Assign prepaid package template to subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageTemplateId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"assign_recurring_package\",\n \"ocs_method\": \"affectRecurringPackageToSubscriber\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Assign recurring prepaid package to subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageTemplateId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_limits\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageLimits\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Change data/voice/SMS limits on active package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"limits\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_expiry\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageExpDate\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Change expiration date of active package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"expirationDate\": { \"type\": \"string(ISO8601)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_package_status\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageStatus\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Activate or deactivate a subscriber package\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"status\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"stop_resume_recurring_package\",\n \"ocs_method\": \"stopResumeSubsRecurringPackage\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"description\": \"Stop or resume recurring package auto-renewal\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true },\n \"action\": { \"type\": \"enum[stop,resume]\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"delete_subscriber_package\",\n \"ocs_method\": \"deleteSubscriberPackage\",\n \"category\": \"packages\",\n \"scope\": \"admin\",\n \"description\": \"Remove a package from a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"packageId\": { \"type\": \"number\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"clean_all_packages\",\n \"ocs_method\": \"cleanSubscriberAllPackages\",\n \"category\": \"packages\",\n \"scope\": \"admin\",\n \"description\": \"Remove ALL packages from a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_package_templates\",\n \"ocs_method\": \"listPrepaidPackageTemplate\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List all prepaid package templates\",\n \"params\": {\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"create_package_template\",\n \"ocs_method\": \"createPrepaidPackageTemplate\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Create a new prepaid package template\",\n \"params\": {\n \"template\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_core\",\n \"ocs_method\": \"modifyPPTCore\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify core settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_recurring\",\n \"ocs_method\": \"modifyPPTRecurring\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify recurring settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_template_throttling\",\n \"ocs_method\": \"modifyPPTThrottling\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Modify throttling settings of a package template\",\n \"params\": {\n \"templateId\": { \"type\": \"number\", \"required\": true },\n \"changes\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_location_zones\",\n \"ocs_method\": \"listLocationZoneElement\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List countries/networks in a location zone\",\n \"params\": {\n \"locationZoneId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_detailed_location_zones\",\n \"ocs_method\": \"listDetailedLocationZone\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"Get detailed location zone definitions\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_destination_prefixes\",\n \"ocs_method\": \"listDestinationListPrefix\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"description\": \"List phone number prefixes in destination lists\",\n \"params\": {\n \"destinationListId\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"create_location_zone\",\n \"ocs_method\": \"createLocationZone\",\n \"category\": \"templates\",\n \"scope\": \"admin\",\n \"description\": \"Create a new location zone\",\n \"params\": {\n \"zone\": { \"type\": \"string(JSON)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_usage\",\n \"ocs_method\": \"subscriberUsageOverPeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get daily usage for a subscriber (max 7 days)\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_network_events\",\n \"ocs_method\": \"subscriberNetworkEventsOverPeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get network events for a subscriber (max 7 days)\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"subscriber_active_period\",\n \"ocs_method\": \"getSubscriberActivePeriod\",\n \"category\": \"statistics\",\n \"scope\": \"read\",\n \"description\": \"Get subscriber active period\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_tariff\",\n \"ocs_method\": \"getCustomerTariff\",\n \"category\": \"tariff\",\n \"scope\": \"read\",\n \"description\": \"Retrieve customer tariff/pricing table\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"send_sms\",\n \"ocs_method\": \"sendMtSms\",\n \"category\": \"messaging\",\n \"scope\": \"write\",\n \"description\": \"Send MT SMS to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"msisdn\": { \"type\": \"string\", \"required\": true },\n \"message\": { \"type\": \"string\", \"required\": true },\n \"sender\": { \"type\": \"string\", \"required\": false }\n },\n \"response\": {},\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_network_profiles\",\n \"ocs_method\": \"listNetworkProfile\",\n \"category\": \"network\",\n \"scope\": \"read\",\n \"description\": \"List all available network profiles\",\n \"params\": {},\n \"response\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n }\n ],\n \"v1_intelligence_methods\": [\n {\n \"name\": \"diagnose_subscriber\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"AI diagnostic: chains 5 OCS calls to diagnose connectivity issues\",\n \"wraps\": [\"getSingleSubscriber\", \"getSimProviderStatus\", \"listSubscriberPrepaidPackages\", \"subscriberNetworkEventsOverPeriod\", \"hlrGetBitrate\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"fleet_health\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Single-call fleet overview: accounts, eSIM counts, low-balance alerts\",\n \"wraps\": [\"listResellerAccount\", \"esimStatusPerAccount\", \"listSubscriberPrepaidPackages\"],\n \"params\": {},\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"detect_usage_anomalies\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Detect abnormal usage patterns across subscribers\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"optimize_package\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Package optimization: match subscriber usage to best template\",\n \"wraps\": [\"getSingleSubscriber\", \"listSubscriberPrepaidPackages\", \"subscriberUsageOverPeriod\", \"listPrepaidPackageTemplate\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"churn_risk\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Identify subscribers at risk of churn based on usage patterns\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\", \"getSubscriberActivePeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"audit_network_coverage\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Audit network coverage and steering effectiveness\",\n \"wraps\": [\"listDetailedLocationZone\", \"listSteeringList\", \"getSubscriberLocation\"],\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"marketing_intelligence\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Marketing insights: segment analysis, upsell opportunities\",\n \"wraps\": [\"listResellerAccount\", \"esimStatusPerAccount\", \"listPrepaidPackageTemplate\", \"subscriberUsageOverPeriod\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"high_cost_subscribers\",\n \"category\": \"intelligence\",\n \"scope\": \"read\",\n \"description\": \"Identify highest-cost subscribers for cost optimization\",\n \"wraps\": [\"listSubscriber\", \"subscriberUsageOverPeriod\", \"getCustomerTariff\"],\n \"params\": {\n \"startDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"endDate\": { \"type\": \"string(YYYY-MM-DD)\", \"required\": true },\n \"accountId\": { \"type\": \"number\", \"required\": false }\n },\n \"verified_against_server\": true,\n \"verified_against_live_docs\": false\n }\n ],\n \"v1_1_backlog\": [\n {\n \"name\": \"affect_subscriber_phone_number\",\n \"ocs_method\": \"affectSubscriberFakePhoneNumber / affectSubscriberRealPhoneNumber\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Assign a fake or real MSISDN to a subscriber — single MCP tool wraps both OCS methods via phone_type param\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"phone_number\": { \"type\": \"string(E.164)\", \"required\": true },\n \"phone_type\": { \"type\": \"enum[fake,real]\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"get_subscriber_location_by_cell_id\",\n \"ocs_method\": \"getSubscriberLocationByCellId\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"status\": \"implemented\",\n \"description\": \"Resolve a cell tower tuple (radioType + MCC + MNC + LAC + optional cellId) to lat/lon via Bridge4IP GeoSense. No subscriber identifier required — caller supplies cell params directly.\",\n \"params\": {\n \"radio_type\": { \"type\": \"enum[2G,3G,4G,5G,NB-IoT]\", \"required\": true },\n \"mcc\": { \"type\": \"integer\", \"required\": true },\n \"mnc\": { \"type\": \"integer\", \"required\": true },\n \"lac\": { \"type\": \"integer\", \"required\": true },\n \"cell_id\": { \"type\": \"integer\", \"required\": false },\n \"signal_strength\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {\n \"latitude\": { \"type\": \"number\" },\n \"longitude\": { \"type\": \"number\" },\n \"accuracy\": { \"type\": \"integer\", \"notes\": \"median error in meters at 50% confidence\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"list_destination_lists\",\n \"ocs_method\": \"listDetailedDestinationList\",\n \"category\": \"templates\",\n \"scope\": \"read\",\n \"status\": \"implemented\",\n \"description\": \"List all destination lists with full detail (prefix sets for voice/SMS routing control)\",\n \"params\": {},\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_mobile_plan\",\n \"ocs_method\": \"modifySubscriberMobilePlan\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the mobile plan assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"mobile_plan_id\": { \"type\": \"number\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_package_active_period\",\n \"ocs_method\": \"modifySubscriberPrepaidPackageActivePeriod\",\n \"category\": \"packages\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the active period (start/end dates) of a prepaid package on a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"package_id\": { \"type\": \"number\", \"required\": true },\n \"start_date\": { \"type\": \"string(ISO8601)\", \"required\": false },\n \"end_date\": { \"type\": \"string(ISO8601)\", \"required\": false }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"modify_subscriber_voip_plan\",\n \"ocs_method\": \"modifySubscriberVoipPlan\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Change the VoIP plan assigned to a subscriber\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true },\n \"voip_plan_id\": { \"type\": \"number\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"push_steering_to_subscriber\",\n \"ocs_method\": \"pushSteeringToSubs\",\n \"category\": \"subscriber\",\n \"scope\": \"write\",\n \"status\": \"implemented\",\n \"description\": \"Push the current steering list configuration down to the subscriber's SIM — required after modifying steering to take effect\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"reset_subscriber_gz_counter\",\n \"ocs_method\": \"resetSubsGzCounter\",\n \"category\": \"subscriber\",\n \"scope\": \"admin\",\n \"status\": \"implemented\",\n \"description\": \"Reset the Green Zone (Greenzone) volume counter for a subscriber — tracks bytes consumed on reseller whitelist after bundle depletion. Irreversible, use only for reprovisioning or billing disputes.\",\n \"params\": {\n \"iccid\": { \"type\": \"string\", \"required\": true }\n },\n \"annotations\": \"destructiveHint\",\n \"verified_against_server\": true,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"resolve_cell_location\",\n \"ocs_method\": \"getSubscriberLocationByCellId\",\n \"category\": \"subscriber\",\n \"scope\": \"read\",\n \"status\": \"stubbed\",\n \"audit_pr\": \"feat/ocs-feature-audit\",\n \"audit_stub_id\": \"S-03\",\n \"description\": \"Resolve a raw cell tower tuple (radioType + MCC + MNC + LAC + optional cellId) to lat/lon via Bridge4IP GeoSense. Does NOT require a subscriber identifier — caller supplies cell params directly. Lower-level primitive than get_subscriber_location_by_cell_id. Needed for Relay LU webhook consumer.\",\n \"params\": {\n \"radio_type\": { \"type\": \"enum[2G,3G,4G,5G,NB-IoT]\", \"required\": true },\n \"mcc\": { \"type\": \"integer\", \"required\": true },\n \"mnc\": { \"type\": \"integer\", \"required\": true },\n \"lac\": { \"type\": \"integer\", \"required\": true },\n \"cell_id\": { \"type\": \"integer\", \"required\": false },\n \"signal_strength\": { \"type\": \"integer\", \"required\": false }\n },\n \"response\": {\n \"latitude\": { \"type\": \"number\" },\n \"longitude\": { \"type\": \"number\" },\n \"accuracy\": { \"type\": \"integer\", \"notes\": \"median error in meters at 50% confidence\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"blocked_by\": \"confirm Relay LU payload shape with Bridge4IP NOC\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": true\n },\n {\n \"name\": \"carrier_webhook_config\",\n \"ocs_method\": \"getResellerInfo\",\n \"category\": \"reseller\",\n \"scope\": \"read\",\n \"status\": \"stubbed\",\n \"audit_pr\": \"feat/ocs-feature-audit\",\n \"audit_stub_id\": \"S-04\",\n \"description\": \"Read-only view of Bridge4IP webhook and relay flag state from getResellerInfo.trafficInfo. Surfaces relayLU, relayGy, relayCallSms, relayVoIP booleans + notification webhook types. Relay LU is the key flag for event-driven country-change detection (vs polling). Relay endpoint config is OCS portal UI-only.\",\n \"params\": {\n \"reseller_id\": { \"type\": \"number\", \"required\": false }\n },\n \"response\": {\n \"relay_lu\": { \"type\": \"boolean\", \"notes\": \"Update Location relay active — closest to country-change signal\" },\n \"relay_gy\": { \"type\": \"boolean\", \"notes\": \"Mobile data usage relay active\" },\n \"relay_voip\": { \"type\": \"boolean\", \"notes\": \"VoIP usage relay active\" },\n \"relay_calls_sms\": { \"type\": \"boolean\", \"notes\": \"Calls + SMS relay active\" },\n \"notification_webhooks\": { \"type\": \"array\", \"notes\": \"Active notification types: prepaid_usage, low_credit, esim_status, recurring_packages\" }\n },\n \"annotations\": \"readOnlyHint\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": true\n }\n ],\n \"v1_app_methods\": [\n {\n \"name\": \"fleet_health_app\",\n \"category\": \"apps\",\n \"scope\": \"read\",\n \"description\": \"MCP App: Fleet Health Dashboard — rendered chart UI wrapping the fleet_health composite. Read-only, no destructive ops.\",\n \"min_tier\": \"free\",\n \"destructive\": false,\n \"ui_resource_uri\": \"ui://fleet-health-dashboard\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"provision_esim_wizard\",\n \"category\": \"apps\",\n \"scope\": \"write\",\n \"description\": \"MCP App: eSIM Provisioning Wizard — 3-step wizard UI. Destructive on step 3 (confirm). Pro tier minimum.\",\n \"min_tier\": \"pro\",\n \"destructive\": true,\n \"destructive_step\": 3,\n \"ui_resource_uri\": \"ui://esim-provisioning-wizard\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n },\n {\n \"name\": \"balance_topup_form\",\n \"category\": \"apps\",\n \"scope\": \"admin\",\n \"description\": \"MCP App: Balance Top-up Form — single-field destructive form with dry_run preview. Enterprise only, MFA-gated.\",\n \"min_tier\": \"enterprise\",\n \"destructive\": true,\n \"mfa_gated\": true,\n \"ui_resource_uri\": \"ui://balance-topup-form\",\n \"verified_against_server\": false,\n \"verified_against_live_docs\": false\n }\n ]\n}\n","/**\n * ITU-T E.212 Mobile Country Code (MCC) → ISO 3166-1 alpha-2 mapping.\n *\n * Source: ITU-T E.212 (11/2019) + Wikipedia \"Mobile country code\" article.\n * Used by detect_country_entry intelligence composite and mango.talk country-watch cron.\n */\nexport const MCC_TO_ISO: Record<number, string> = {\n // Europe\n 202: \"GR\", // Greece\n 204: \"NL\", // Netherlands\n 206: \"BE\", // Belgium\n 208: \"FR\", // France\n 212: \"MC\", // Monaco\n 213: \"AD\", // Andorra\n 214: \"ES\", // Spain\n 216: \"HU\", // Hungary\n 218: \"BA\", // Bosnia and Herzegovina\n 219: \"HR\", // Croatia\n 220: \"RS\", // Serbia\n 221: \"XK\", // Kosovo\n 222: \"IT\", // Italy\n 225: \"VA\", // Vatican City\n 226: \"RO\", // Romania\n 228: \"CH\", // Switzerland\n 230: \"CZ\", // Czech Republic\n 231: \"SK\", // Slovakia\n 232: \"AT\", // Austria\n 234: \"GB\", // United Kingdom\n 235: \"GB\", // United Kingdom\n 238: \"DK\", // Denmark\n 240: \"SE\", // Sweden\n 242: \"NO\", // Norway\n 244: \"FI\", // Finland\n 246: \"LT\", // Lithuania\n 247: \"LV\", // Latvia\n 248: \"EE\", // Estonia\n 250: \"RU\", // Russia\n 255: \"UA\", // Ukraine\n 257: \"BY\", // Belarus\n 259: \"MD\", // Moldova\n 260: \"PL\", // Poland\n 262: \"DE\", // Germany\n 266: \"GI\", // Gibraltar\n 268: \"PT\", // Portugal\n 270: \"LU\", // Luxembourg\n 272: \"IE\", // Ireland\n 274: \"IS\", // Iceland\n 276: \"AL\", // Albania\n 278: \"MT\", // Malta\n 280: \"CY\", // Cyprus\n 282: \"GE\", // Georgia\n 283: \"AM\", // Armenia\n 284: \"BG\", // Bulgaria\n 286: \"TR\", // Turkey\n 288: \"FO\", // Faroe Islands\n 289: \"GE\", // Abkhazia (Georgia)\n 290: \"GL\", // Greenland\n 292: \"SM\", // San Marino\n 293: \"SI\", // Slovenia\n 294: \"MK\", // North Macedonia\n 295: \"LI\", // Liechtenstein\n 297: \"ME\", // Montenegro\n\n // Commonwealth of Independent States / Former USSR\n 401: \"KZ\", // Kazakhstan\n 402: \"BT\", // Bhutan\n 404: \"IN\", // India\n 405: \"IN\", // India\n 406: \"IN\", // India\n 410: \"PK\", // Pakistan\n 412: \"AF\", // Afghanistan\n 413: \"LK\", // Sri Lanka\n 414: \"MM\", // Myanmar\n 415: \"LB\", // Lebanon\n 416: \"JO\", // Jordan\n 417: \"SY\", // Syria\n 418: \"IQ\", // Iraq\n 419: \"KW\", // Kuwait\n 420: \"SA\", // Saudi Arabia\n 421: \"YE\", // Yemen\n 422: \"OM\", // Oman\n 424: \"AE\", // United Arab Emirates\n 425: \"IL\", // Israel\n 426: \"BH\", // Bahrain\n 427: \"QA\", // Qatar\n 428: \"MN\", // Mongolia\n 429: \"NP\", // Nepal\n 430: \"AE\", // United Arab Emirates\n 431: \"AE\", // United Arab Emirates\n 432: \"IR\", // Iran\n 434: \"UZ\", // Uzbekistan\n 436: \"TJ\", // Tajikistan\n 437: \"KG\", // Kyrgyzstan\n 438: \"TM\", // Turkmenistan\n 440: \"JP\", // Japan\n 441: \"JP\", // Japan\n 450: \"KR\", // South Korea\n 452: \"VN\", // Vietnam\n 454: \"HK\", // Hong Kong\n 455: \"MO\", // Macau\n 456: \"KH\", // Cambodia\n 457: \"LA\", // Laos\n 460: \"CN\", // China\n 461: \"CN\", // China\n 466: \"TW\", // Taiwan\n 467: \"KP\", // North Korea\n 470: \"BD\", // Bangladesh\n 472: \"MV\", // Maldives\n 502: \"MY\", // Malaysia\n 505: \"AU\", // Australia\n 510: \"ID\", // Indonesia\n 514: \"TL\", // East Timor\n 515: \"PH\", // Philippines\n 520: \"TH\", // Thailand\n 525: \"SG\", // Singapore\n 528: \"BN\", // Brunei\n 530: \"NZ\", // New Zealand\n 536: \"NR\", // Nauru\n 537: \"PG\", // Papua New Guinea\n 539: \"TO\", // Tonga\n 540: \"SB\", // Solomon Islands\n 541: \"VU\", // Vanuatu\n 542: \"FJ\", // Fiji\n 544: \"AS\", // American Samoa\n 545: \"KI\", // Kiribati\n 546: \"NC\", // New Caledonia\n 547: \"PF\", // French Polynesia\n 548: \"CK\", // Cook Islands\n 549: \"WS\", // Samoa\n 550: \"FM\", // Micronesia\n 551: \"MH\", // Marshall Islands\n 552: \"PW\", // Palau\n 553: \"TV\", // Tuvalu\n 555: \"NU\", // Niue\n\n // Africa (ITU-T E.212)\n 602: \"EG\", // Egypt\n 603: \"DZ\", // Algeria\n 604: \"MA\", // Morocco\n 605: \"TN\", // Tunisia\n 606: \"LY\", // Libya\n 607: \"GM\", // Gambia\n 608: \"SN\", // Senegal\n 609: \"MR\", // Mauritania\n 610: \"ML\", // Mali\n 611: \"GN\", // Guinea\n 612: \"CI\", // Côte d'Ivoire\n 613: \"BF\", // Burkina Faso\n 614: \"NE\", // Niger\n 615: \"TG\", // Togo\n 616: \"BJ\", // Benin\n 617: \"MU\", // Mauritius\n 618: \"LR\", // Liberia\n 619: \"SL\", // Sierra Leone\n 620: \"GH\", // Ghana\n 621: \"NG\", // Nigeria\n 622: \"TD\", // Chad\n 623: \"CF\", // Central African Republic\n 624: \"CM\", // Cameroon\n 625: \"CV\", // Cape Verde\n 626: \"ST\", // São Tomé and Príncipe\n 627: \"GQ\", // Equatorial Guinea\n 628: \"GA\", // Gabon\n 629: \"CG\", // Republic of the Congo\n 630: \"CD\", // Democratic Republic of the Congo\n 631: \"AO\", // Angola\n 632: \"GW\", // Guinea-Bissau\n 633: \"SC\", // Seychelles\n 634: \"SD\", // Sudan\n 635: \"RW\", // Rwanda\n 636: \"ET\", // Ethiopia\n 637: \"SO\", // Somalia\n 638: \"DJ\", // Djibouti\n 639: \"KE\", // Kenya\n 640: \"TZ\", // Tanzania\n 641: \"UG\", // Uganda\n 642: \"BI\", // Burundi\n 643: \"MZ\", // Mozambique\n 645: \"ZM\", // Zambia\n 646: \"MG\", // Madagascar\n 647: \"RE\", // Réunion / French Indian Ocean\n 648: \"ZW\", // Zimbabwe\n 649: \"NA\", // Namibia\n 650: \"MW\", // Malawi\n 651: \"LS\", // Lesotho\n 652: \"BW\", // Botswana\n 653: \"SZ\", // Eswatini\n 654: \"KM\", // Comoros\n 655: \"ZA\", // South Africa\n 657: \"ER\", // Eritrea\n 658: \"SH\", // Saint Helena\n 659: \"SS\", // South Sudan\n 702: \"BZ\", // Belize\n 704: \"GT\", // Guatemala\n 706: \"SV\", // El Salvador\n 708: \"HN\", // Honduras\n 710: \"NI\", // Nicaragua\n 712: \"CR\", // Costa Rica\n 714: \"PA\", // Panama\n 716: \"PE\", // Peru\n 722: \"AR\", // Argentina\n 724: \"BR\", // Brazil\n 730: \"CL\", // Chile\n 732: \"CO\", // Colombia\n 734: \"VE\", // Venezuela\n 736: \"BO\", // Bolivia\n 738: \"GY\", // Guyana\n 740: \"EC\", // Ecuador\n 742: \"GF\", // French Guiana\n 744: \"PY\", // Paraguay\n 746: \"SR\", // Suriname\n 748: \"UY\", // Uruguay\n 750: \"FK\", // Falkland Islands\n\n // North America, Caribbean\n 302: \"CA\", // Canada\n 308: \"PM\", // Saint Pierre and Miquelon\n 310: \"US\", // United States\n 311: \"US\", // United States\n 312: \"US\", // United States\n 313: \"US\", // United States\n 314: \"US\", // United States\n 315: \"US\", // United States\n 316: \"US\", // United States\n 330: \"PR\", // Puerto Rico\n 332: \"VI\", // U.S. Virgin Islands\n 334: \"MX\", // Mexico\n 338: \"JM\", // Jamaica\n 340: \"GP\", // Guadeloupe\n 342: \"BB\", // Barbados\n 344: \"AG\", // Antigua and Barbuda\n 346: \"KY\", // Cayman Islands\n 348: \"VG\", // British Virgin Islands\n 350: \"BM\", // Bermuda\n 352: \"GD\", // Grenada\n 354: \"MS\", // Montserrat\n 356: \"KN\", // Saint Kitts and Nevis\n 358: \"LC\", // Saint Lucia\n 360: \"VC\", // Saint Vincent and the Grenadines\n 362: \"CW\", // Curaçao / Netherlands Antilles\n 363: \"AW\", // Aruba\n 364: \"BS\", // Bahamas\n 365: \"AI\", // Anguilla\n 366: \"DM\", // Dominica\n 368: \"CU\", // Cuba\n 370: \"DO\", // Dominican Republic\n 372: \"HT\", // Haiti\n 374: \"TT\", // Trinidad and Tobago\n 376: \"TC\", // Turks and Caicos Islands\n\n // Special / Test MCCs\n 999: \"XX\", // Test network\n 901: \"XX\", // International / satellite\n};\n\n/**\n * Resolve an MCC (Mobile Country Code, ITU-T E.212) to ISO 3166-1 alpha-2.\n * Returns null for unknown MCCs.\n */\nexport function mccToIso(mcc: number | string | null | undefined): string | null {\n if (mcc == null) return null;\n let n: number;\n if (typeof mcc === \"string\") {\n const trimmed = mcc.trim();\n if (trimmed === \"\" || !/^\\d+$/.test(trimmed)) return null;\n n = parseInt(trimmed, 10);\n } else {\n n = mcc;\n }\n if (!Number.isFinite(n)) return null;\n return MCC_TO_ISO[n] ?? null;\n}\n\n/**\n * Reverse: get all MCCs for a given ISO 3166-1 alpha-2 country code.\n */\nexport function isoToMccs(iso: string): number[] {\n const upper = iso.toUpperCase();\n return Object.entries(MCC_TO_ISO)\n .filter(([, v]) => v === upper)\n .map(([k]) => Number(k));\n}\n","import methodsJson from \"../ocs-methods.json\" with { type: \"json\" };\n\nexport { MCC_TO_ISO, mccToIso, isoToMccs } from \"./mcc-iso.js\";\n\nexport type OcsScope = \"read\" | \"write\" | \"admin\";\n\nexport interface OcsParam {\n type: string;\n required: boolean;\n}\n\nexport interface OcsMethod {\n name: string;\n ocs_method: string;\n category: string;\n scope: OcsScope;\n description: string;\n params: Record<string, OcsParam>;\n response: Record<string, unknown>;\n annotations: string;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsIntelligenceMethod {\n name: string;\n category: \"intelligence\";\n scope: OcsScope;\n description: string;\n wraps: string[];\n params: Record<string, OcsParam>;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsBacklogMethod {\n name: string;\n ocs_method: string;\n category: string;\n scope: OcsScope;\n source: string;\n rationale: string;\n}\n\n/**\n * v1.2 — MCP App registry entry.\n *\n * Documents server-rendered UI surfaces (resourceUri + tier gating) without\n * a corresponding OCS REST method. Listed in `ocs-methods.json#v1_app_methods`\n * so the nightly fidelity reconcile script doesn't flag the app tool names\n * (e.g. `fleet_health_app`) as drift.\n */\nexport interface OcsAppMethod {\n name: string;\n category: \"apps\";\n scope: OcsScope;\n description: string;\n min_tier: \"free\" | \"pro\" | \"enterprise\";\n destructive: boolean;\n destructive_step?: number;\n mfa_gated?: boolean;\n ui_resource_uri: string;\n verified_against_server: boolean;\n verified_against_live_docs: boolean;\n}\n\nexport interface OcsSpec {\n version: string;\n captured_at: string;\n sources: {\n live_docs_url: string;\n server_source_repo: string;\n server_source_commit: string;\n server_source_branch: string;\n notes: string;\n };\n v1_methods: OcsMethod[];\n v1_intelligence_methods: OcsIntelligenceMethod[];\n v1_1_backlog: OcsBacklogMethod[];\n /** v1.2c — registered MCP App tools; excluded from OCS drift detection. */\n v1_app_methods: OcsAppMethod[];\n}\n\n// Cast via `unknown` because TypeScript's strict `as` check considers the\n// inferred JSON shape and the declared OcsSpec insufficiently overlapping\n// once optional/variant fields are present across method entries.\nexport const ocsSpec: OcsSpec = methodsJson as unknown as OcsSpec;\nexport const ocsMethods: OcsMethod[] = ocsSpec.v1_methods;\nexport const ocsIntelligenceMethods: OcsIntelligenceMethod[] = ocsSpec.v1_intelligence_methods;\nexport const ocsBacklog: OcsBacklogMethod[] = ocsSpec.v1_1_backlog;\nexport const ocsAppMethods: OcsAppMethod[] = ocsSpec.v1_app_methods;\n\nexport function getMethodScope(name: string): OcsScope | undefined {\n const v1 = ocsSpec.v1_methods.find((m) => m.name === name);\n if (v1) return v1.scope;\n const intel = ocsSpec.v1_intelligence_methods.find((m) => m.name === name);\n if (intel) return intel.scope;\n return undefined;\n}\n\nexport function getMethodsByScope(scope: OcsScope): OcsMethod[] {\n return ocsSpec.v1_methods.filter((m) => m.scope === scope);\n}\n\nexport function getAllMethodNames(): string[] {\n return [\n ...ocsSpec.v1_methods.map((m) => m.name),\n ...ocsSpec.v1_intelligence_methods.map((m) => m.name),\n ];\n}\n","/**\n * Carrier MCP — v1.1 backlog tool registrations (9 tools) + v1.2 audit stubs (3 tools).\n *\n * These are OCS methods confirmed live in the eSIMVault API docs but not yet\n * exposed in the v1 server. All 9 v1.1 tools are wired here to close coverage gaps\n * identified in the 2026-05-12 forensic audit (mango/.planning/research/03-carrier-llc-audit.md).\n *\n * v1.2 AUDIT STUBS (feat/ocs-feature-audit, 2026-05-20):\n * Registered but throw NotImplementedError — implementation in follow-up PRs.\n * These stubs are intentionally NOT added to BACKLOG_TOOL_SCOPES or to the\n * carrier_ask tool registry until implemented. The registerAllBacklogTools function\n * conditionally registers them only when CARRIER_AUDIT_STUBS_ENABLED=true.\n * Stubs: carrier_webhook_config (resolve_cell_location removed — merged into get_subscriber_location_by_cell_id)\n * See: docs/research/bridge4ip-ocs-api/UNUSED-FEATURES.md\n *\n * Scope assignments (v1.1):\n * write — affect_subscriber_phone_number, modify_subscriber_mobile_plan,\n * modify_subscriber_package_active_period, modify_subscriber_voip_plan,\n * push_steering_to_subscriber\n * read — get_subscriber_location_by_cell_id, list_destination_lists,\n * resolve_cell_location, carrier_webhook_config\n * admin — reset_subscriber_gz_counter\n *\n * Schema notes:\n * - All ICCID-accepting tools use the subscriber-record lookup cache pattern\n * (resolveSubscriberByIccid) for IMSI resolution where required.\n * - pushSteeringToSubs is listed as \"write\" in the live docs; marked write here\n * pending confirmation from eSIMVault support (gap G-04).\n * - resetSubsGzCounter is admin-scoped; usage counter resets are irreversible.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { OcsClient } from \"./client.js\";\nimport {\n wrapHandler,\n resolveSubscriberByIccid,\n getDefaultResellerId,\n type ToolContext,\n} from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\n\nconst DRY_RUN_FIELD = {\n dry_run: z\n .boolean()\n .optional()\n .describe(\n \"If true, do not call OCS — return the would-be request for confirmation\",\n ),\n};\n\n/** Scope lookup for the v1.1 backlog tools + implemented v1.2 tools. */\nexport const BACKLOG_TOOL_SCOPES: Record<string, ToolScope> = {\n affect_subscriber_phone_number: \"write\",\n carrier_webhook_config: \"read\",\n get_subscriber_location_by_cell_id: \"read\",\n list_destination_lists: \"read\",\n modify_subscriber_mobile_plan: \"write\",\n modify_subscriber_package_active_period: \"write\",\n modify_subscriber_voip_plan: \"write\",\n push_steering_to_subscriber: \"write\",\n reset_subscriber_gz_counter: \"admin\",\n};\n\nexport function registerAllBacklogTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // 1. AFFECT SUBSCRIBER PHONE NUMBER\n // OCS methods: affectSubscriberFakePhoneNumber / affectSubscriberRealPhoneNumber\n // Gap: G-08 (MEDIUM). Merges two OCS methods behind one MCP tool.\n // =========================================================================\n server.registerTool(\n \"affect_subscriber_phone_number\",\n {\n title: \"Assign Phone Number to Subscriber\",\n description:\n \"Use this to assign a phone number (MSISDN) to a subscriber. Supports both fake/test MSISDNs \" +\n \"and real production MSISDNs via the `phone_type` parameter. Required for MSISDN assignment \" +\n \"workflows before activating voice services. \" +\n \"Params: `iccid` (subscriber identifier), `phone_number` (E.164 format, e.g. +31612345678), \" +\n \"`phone_type` ('fake' for test/dev, 'real' for production). \" +\n \"Returns: updated subscriber record with the new MSISDN. \" +\n \"Do NOT use this to check a subscriber's current MSISDN — use `get_subscriber` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n phone_number: z\n .string()\n .describe(\"E.164 phone number to assign (e.g. +31612345678)\"),\n phone_type: z\n .enum([\"fake\", \"real\"])\n .describe(\n \"'fake' assigns a test/dev MSISDN (affectSubscriberFakePhoneNumber in OCS); \" +\n \"'real' assigns a production MSISDN (affectSubscriberRealPhoneNumber in OCS)\",\n ),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"affect_subscriber_phone_number\",\n \"affectSubscriberFakePhoneNumber/affectSubscriberRealPhoneNumber\",\n BACKLOG_TOOL_SCOPES[\"affect_subscriber_phone_number\"]!,\n ctx,\n async ({ iccid, phone_number, phone_type }: { iccid: string; phone_number: string; phone_type: string }, token: string) => {\n const ocsMethod =\n phone_type === \"fake\"\n ? \"affectSubscriberFakePhoneNumber\"\n : \"affectSubscriberRealPhoneNumber\";\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(ocsMethod, { subscriber: iccid, phoneNumber: phone_number });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 2. GET SUBSCRIBER LOCATION BY CELL ID\n // OCS method: getSubscriberLocationByCellId (Bridge4IP GeoSense)\n // Gap: G-09 (MEDIUM). Takes a cell tuple — no subscriber identifier needed.\n // =========================================================================\n server.registerTool(\n \"get_subscriber_location_by_cell_id\",\n {\n title: \"Get Location by Cell ID (GeoSense)\",\n description:\n \"Powered by Bridge4IP GeoSense — cell-level location resolution with sub-cell accuracy where available. \" +\n \"Use this to resolve a cell tower tuple (radio type + MCC + MNC + LAC + optional cellId) \" +\n \"to a latitude/longitude estimate. \" +\n \"No subscriber identifier required — caller supplies cell parameters directly. \" +\n \"Useful for fraud detection, roaming cost attribution, and network troubleshooting when \" +\n \"you have raw cell info from an external source (e.g. a Relay LU webhook event). \" +\n \"Params: `radio_type` ('2G'|'3G'|'4G'|'5G'|'NB-IoT'), `mcc` (int), `mnc` (int), \" +\n \"`lac` (int), `cell_id` (int, optional but strongly recommended for accuracy), \" +\n \"`signal_strength` (number dBm, optional). \" +\n \"Returns: { latitude, longitude, accuracy } — accuracy is median error in meters at 50% confidence. \" +\n \"Without cell_id accuracy degrades significantly (>10 km). \" +\n \"Do NOT use this for bulk fleet location sweeps — one OCS call per cell tower; \" +\n \"use `audit_network_coverage` for fleet-level analysis instead.\",\n inputSchema: {\n radio_type: z\n .enum([\"2G\", \"3G\", \"4G\", \"5G\", \"NB-IoT\"])\n .describe(\"Radio access technology type\"),\n mcc: z.number().int().describe(\"Mobile Country Code (e.g. 250 for Russia, 234 for UK)\"),\n mnc: z.number().int().describe(\"Mobile Network Code\"),\n lac: z.number().int().describe(\"Location Area Code\"),\n cell_id: z\n .number()\n .int()\n .optional()\n .describe(\"Cell tower ID — strongly recommended for accuracy\"),\n signal_strength: z\n .number()\n .optional()\n .describe(\"Signal strength in dBm (e.g. -89). Optional, improves accuracy.\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"get_subscriber_location_by_cell_id\",\n \"getSubscriberLocationByCellId\",\n BACKLOG_TOOL_SCOPES[\"get_subscriber_location_by_cell_id\"]!,\n ctx,\n async (\n {\n radio_type,\n mcc,\n mnc,\n lac,\n cell_id,\n signal_strength,\n }: {\n radio_type: \"2G\" | \"3G\" | \"4G\" | \"5G\" | \"NB-IoT\";\n mcc: number;\n mnc: number;\n lac: number;\n cell_id?: number;\n signal_strength?: number;\n },\n token: string,\n ) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const params: Record<string, unknown> = { radioType: radio_type, mcc, mnc, lac };\n if (cell_id !== undefined) params.cellId = cell_id;\n if (signal_strength !== undefined) params.signalStrength = signal_strength;\n const result = await client.call(\"getSubscriberLocationByCellId\", params);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 3. LIST DESTINATION LISTS\n // OCS method: listDetailedDestinationList\n // Gap: G-13 (MEDIUM). The existing list_destination_prefixes only reads\n // prefixes WITHIN a known list ID; this tool returns the list catalog itself.\n // =========================================================================\n server.registerTool(\n \"list_destination_lists\",\n {\n title: \"List Destination Lists\",\n description:\n \"Use this to retrieve the full catalog of destination lists available to this reseller. \" +\n \"A destination list is a named set of phone number prefixes (country codes) that control \" +\n \"which numbers a subscriber may call on a voice/SMS package. \" +\n \"Returns: array of destination list records, each with `id`, `name`, and prefix count. \" +\n \"Do NOT use this to read the prefixes inside a specific list — use `list_destination_prefixes` \" +\n \"with a known `destinationListId` for that. \" +\n \"Do NOT use this for data-only eSIM products without MOC voice; destination lists only \" +\n \"apply to packages with voice/SMS allowances.\",\n inputSchema: {\n resellerId: z\n .number()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"list_destination_lists\",\n \"listDetailedDestinationList\",\n BACKLOG_TOOL_SCOPES[\"list_destination_lists\"]!,\n ctx,\n async ({ resellerId }: { resellerId?: number }, token: string) => {\n const id =\n resellerId ??\n (await (async () => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const info = await client.call<{ id?: number }>(\"getResellerInfo\", {});\n const resolvedId = info?.id;\n if (typeof resolvedId !== \"number\") {\n throw new Error(\"Could not determine resellerId from getResellerInfo\");\n }\n return resolvedId;\n })());\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\"listDetailedDestinationList\", id);\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 4. MODIFY SUBSCRIBER MOBILE PLAN\n // OCS method: modifySubscriberMobilePlan\n // Gap: G-06 (HIGH). Needed to change which pricing plan a subscriber is billed under.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_mobile_plan\",\n {\n title: \"Modify Subscriber Mobile Plan\",\n description:\n \"Use this to change the mobile pricing plan assigned to a specific subscriber. \" +\n \"The mobile plan determines per-country rates for data, voice, and SMS. Changing the plan \" +\n \"takes effect immediately on the next OCS rating cycle. \" +\n \"Params: `iccid` (subscriber identifier), `mobile_plan_id` (integer plan ID — obtain valid \" +\n \"plan IDs from the OCS reseller settings or `get_tariff`). \" +\n \"Returns: updated subscriber record confirming the new plan assignment. \" +\n \"Do NOT use this to change package allowances — use `modify_package_limits` for that. \" +\n \"Do NOT use this to change account-level pricing — this only affects the individual subscriber.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n mobile_plan_id: z\n .number()\n .describe(\"The mobile pricing plan ID to assign to this subscriber\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_mobile_plan\",\n \"modifySubscriberMobilePlan\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_mobile_plan\"]!,\n ctx,\n async ({ iccid, mobile_plan_id }: { iccid: string; mobile_plan_id: number }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberMobilePlan\",\n { subscriber: iccid, mobilePlanId: mobile_plan_id },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 5. MODIFY SUBSCRIBER PACKAGE ACTIVE PERIOD\n // OCS method: modifySubscriberPrepaidPackageActivePeriod\n // Gap: G-07 (HIGH). Controls when a package becomes active on a subscriber.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_package_active_period\",\n {\n title: \"Modify Subscriber Package Active Period\",\n description:\n \"Use this to change the start and/or end date of a prepaid package's active period for a \" +\n \"specific subscriber. This controls WHEN the package runs, not what it contains. \" +\n \"Useful for scheduling packages in advance (e.g. activate on arrival date) or extending \" +\n \"a package that would otherwise expire while the subscriber is still travelling. \" +\n \"Params: `iccid` (subscriber identifier), `package_id` (from `list_subscriber_packages`), \" +\n \"`start_date` (ISO 8601 date, optional), `end_date` (ISO 8601 date, optional). \" +\n \"Returns: updated package record with new active period. \" +\n \"Do NOT use this to change a package's data/voice allowance — use `modify_package_limits`. \" +\n \"Do NOT use this to change the expiry date of a package — use `modify_package_expiry`.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n package_id: z\n .number()\n .describe(\"The subscriber package ID (from list_subscriber_packages)\"),\n start_date: z\n .string()\n .optional()\n .describe(\"New start date in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)\"),\n end_date: z\n .string()\n .optional()\n .describe(\"New end date in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDTHH:mm:ss)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_package_active_period\",\n \"modifySubscriberPrepaidPackageActivePeriod\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_package_active_period\"]!,\n ctx,\n async ({ iccid, package_id, start_date, end_date }: { iccid: string; package_id: number; start_date?: string; end_date?: string }, token: string) => {\n const params: Record<string, unknown> = { subscriber: iccid, packageId: package_id };\n if (start_date !== undefined) params.startDate = start_date;\n if (end_date !== undefined) params.endDate = end_date;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberPrepaidPackageActivePeriod\",\n params,\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 6. MODIFY SUBSCRIBER VOIP PLAN\n // OCS method: modifySubscriberVoipPlan\n // Gap: G-11 (MEDIUM). Parallel to modify_subscriber_mobile_plan for VoIP.\n // =========================================================================\n server.registerTool(\n \"modify_subscriber_voip_plan\",\n {\n title: \"Modify Subscriber VoIP Plan\",\n description:\n \"Use this to change the VoIP pricing plan assigned to a specific subscriber. \" +\n \"VoIP plans control billing rates for VoIP calls made through the OCS platform, \" +\n \"separate from the standard mobile plan's call rates. \" +\n \"Params: `iccid` (subscriber identifier), `voip_plan_id` (integer VoIP plan ID from \" +\n \"the OCS reseller settings). \" +\n \"Returns: updated subscriber record confirming the new VoIP plan. \" +\n \"Do NOT use this for mobile (non-VoIP) plan changes — use `modify_subscriber_mobile_plan`. \" +\n \"For data-only eSIM products without VoIP services this tool has no effect.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n voip_plan_id: z\n .number()\n .describe(\"The VoIP pricing plan ID to assign to this subscriber\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"modify_subscriber_voip_plan\",\n \"modifySubscriberVoipPlan\",\n BACKLOG_TOOL_SCOPES[\"modify_subscriber_voip_plan\"]!,\n ctx,\n async ({ iccid, voip_plan_id }: { iccid: string; voip_plan_id: number }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"modifySubscriberVoipPlan\",\n { subscriber: iccid, voipPlanId: voip_plan_id },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 7. PUSH STEERING TO SUBSCRIBER\n // OCS method: pushSteeringToSubs\n // Gap: G-04 (HIGH). Must be called AFTER modify_subscriber_steering_list\n // to push the new OPLMN list to the physical device.\n // =========================================================================\n server.registerTool(\n \"push_steering_to_subscriber\",\n {\n title: \"Push Steering List to Subscriber Device\",\n description:\n \"Use this AFTER `modify_subscriber_steering_list` to actively push the updated OPLMN \" +\n \"(operator preference list) to the subscriber's physical eSIM/SIM. \" +\n \"Without this call, the steering list assignment change is recorded in OCS but the device \" +\n \"continues using the old operator preference list until it performs a network re-registration. \" +\n \"This is required for immediate operator switching (e.g. steering a subscriber away from \" +\n \"an expensive roaming partner in real time). \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: push confirmation from OCS with delivery status. \" +\n \"Do NOT call this without first calling `modify_subscriber_steering_list` — pushing without \" +\n \"an assigned steering list is a no-op and wastes an OCS call.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"push_steering_to_subscriber\",\n \"pushSteeringToSubs\",\n BACKLOG_TOOL_SCOPES[\"push_steering_to_subscriber\"]!,\n ctx,\n async ({ iccid }: { iccid: string }, token: string) => {\n const cache = new Map<string, Record<string, unknown>>();\n const sub = await resolveSubscriberByIccid(ctx.env, token, iccid, cache);\n // OCS pushSteeringToSubs expects subscriber identifier — ICCID confirmed\n // from live docs. Passing the full subscriber object as fallback.\n const subscriberId = sub.id ?? sub.subscriberId ?? iccid;\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\n \"pushSteeringToSubs\",\n { subscriber: subscriberId },\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 8. RESET SUBSCRIBER GZ COUNTER\n // OCS method: resetSubsGzCounter\n // Gap: G-10 (MEDIUM). Resets usage counters — used after billing disputes.\n // Admin scope — irreversible operation.\n // =========================================================================\n server.registerTool(\n \"reset_subscriber_gz_counter\",\n {\n title: \"Reset Subscriber Green Zone Counter\",\n description:\n \"ADMIN: Use this to reset the Green Zone (Greenzone) volume counter for a subscriber. \" +\n \"The Green Zone counter tracks bytes consumed on the reseller-defined whitelist of \" +\n \"hosts/IPs after the subscriber's bundle is depleted — NOT the Diameter Gz/Gy accounting \" +\n \"interface. Typically used after a billing dispute or test-cycle reset. \" +\n \"This operation is IRREVERSIBLE — volumeOnGZ is permanently zeroed. \" +\n \"Params: `iccid` (subscriber identifier). \" +\n \"Returns: new counter state with volumeOnGZ (bytes, normally 0 after reset), \" +\n \"lastResetDate, lastUpdateDate. \" +\n \"Always call `get_subscriber` with `with_gz_counter=true` first to capture the snapshot. \" +\n \"Do NOT use this to pause data usage — use `set_subscriber_traffic_restrictions` with \" +\n \"`dataAllowed=false` instead.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID (20-digit ICC identifier)\"),\n ...DRY_RUN_FIELD,\n },\n annotations: { destructiveHint: true },\n },\n wrapHandler(\n \"reset_subscriber_gz_counter\",\n \"resetSubsGzCounter\",\n BACKLOG_TOOL_SCOPES[\"reset_subscriber_gz_counter\"]!,\n ctx,\n async ({ iccid }: { iccid: string }, token: string) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n const result = await client.call(\"resetSubsGzCounter\", { subscriber: iccid });\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n\n // =========================================================================\n // 10. CARRIER WEBHOOK CONFIG — reads relay + notification flags from\n // getResellerInfo.trafficInfo and getResellerInfo.notificationInfo.\n // Audit gap S-04 in UNUSED-FEATURES.md — now implemented.\n //\n // trafficInfo shape (live probe against reseller 1170, 2026-05-21):\n // { relayGy: boolean, relayCallSms: boolean, relayLU: boolean, relayVoIP: boolean }\n // notificationInfo shape: passed through as-is (z.record(z.unknown())) because\n // the exact keys vary by OCS configuration and are not documented upstream.\n // =========================================================================\n\n // carrier_webhook_config is now a real tool — registered unconditionally\n // (no CARRIER_AUDIT_STUBS_ENABLED guard needed after implementation).\n server.registerTool(\n \"carrier_webhook_config\",\n {\n title: \"Carrier Webhook / Relay Flag Status\",\n description:\n \"Use this to check the current Bridge4IP webhook and relay flag configuration for \" +\n \"this reseller. Returns the active state of all four traffic relay flags: \" +\n \"Relay LU (Update Location — cell tower changes, closest to country-change signal), \" +\n \"Relay Gy (mobile data usage events), Relay VoIP (VoIP usage events), \" +\n \"Relay calls+SMS (call and SMS events). \" +\n \"Also returns which notification webhooks are enabled (prepaid package usage threshold, \" +\n \"reseller low credit, ES2 eSIM status, recurring packages) as a passthrough object. \" +\n \"All relay/notification configuration is done in the OCS portal UI — this tool is \" +\n \"READ-ONLY and reflects current state. \" +\n \"Relay LU is the highest-value flag: when active, Bridge4IP pushes real-time Update \" +\n \"Location events (mcc, mnc, lac, cellId) to the configured HTTP endpoint.\",\n inputSchema: {\n reseller_id: z\n .number()\n .int()\n .optional()\n .describe(\"Reseller ID (omit to use the token owner's reseller)\"),\n },\n annotations: { readOnlyHint: true },\n },\n wrapHandler(\n \"carrier_webhook_config\",\n \"getResellerInfo\",\n BACKLOG_TOOL_SCOPES[\"carrier_webhook_config\"]!,\n ctx,\n async ({ reseller_id }, token) => {\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n // Resolve reseller ID: explicit arg → token owner's reseller\n let resellerId = reseller_id;\n if (resellerId === undefined) {\n resellerId = await getDefaultResellerId(ctx.env, token);\n }\n\n const params: Record<string, unknown> = {};\n if (resellerId !== undefined) params.id = resellerId;\n\n const raw = await client.call<{\n id?: number;\n trafficInfo?: {\n relayGy?: boolean;\n relayCallSms?: boolean;\n relayLU?: boolean;\n relayVoIP?: boolean;\n };\n notificationInfo?: Record<string, unknown>;\n }>(\"getResellerInfo\", params);\n\n const traffic = raw.trafficInfo ?? {};\n const notification = raw.notificationInfo ?? {};\n\n const result = {\n resellerId: raw.id ?? resellerId,\n traffic: {\n relayGy: traffic.relayGy === true,\n relayCallSms: traffic.relayCallSms === true,\n relayLU: traffic.relayLU === true,\n relayVoIP: traffic.relayVoIP === true,\n },\n notification,\n };\n\n return {\n content: [{ type: \"text\" as const, text: JSON.stringify(result, null, 2) }],\n };\n },\n ),\n );\n}\n","/**\n * Carrier MCP — carrier_ask + carrier_ask_describe (v2.0 live routing).\n *\n * IMPLEMENTATION STATUS: LIVE (Phase 2)\n * carrier_ask now routes via Claude Haiku 4.5 on AWS Bedrock tool-use.\n * The router receives the full TOOL_REGISTRY as its tool catalog and returns\n * a single tool_use block identifying the best matching tool + extracted params.\n *\n * ACTIVATION:\n * - Requires AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY in Doppler carrier/dev+stg+prd.\n * - Set CARRIER_ASK_ENABLED=true in Doppler to activate per-env.\n * - Without the credentials/flag, carrier_ask gracefully degrades to routing_pending.\n *\n * DESIGN CHOICES:\n * - Router model: Claude Haiku 4.5 on Bedrock (us.anthropic.claude-haiku-4-5-20251001-v1:0).\n * - Auth: SigV4 via aws4fetch — no AWS SDK bundle (CF Worker compatible).\n * - tool_choice: { type: \"any\" } — forces a tool_use response.\n * - Ambiguous/no-match: sentinel \"carrier_clarify\" tool for Haiku to signal.\n * - HARD_BLOCK_TOOLS: always return confirm_token; never auto-execute.\n * - Confirm token TTL: 120s. Single-use (deleted on consume).\n * - Intent hashing: SHA-256, hex. Not stored verbatim (PII guard).\n * - Audit log: Analytics Engine, fire-and-forget. Extended schema for router.\n * - Rate-limit (429): returns friendly retry hint, never crashes.\n *\n * SAFETY FLOORS (non-negotiable):\n * - Resolved tool name validated against TOOL_REGISTRY — no hallucination.\n * - HARD_BLOCK_TOOLS always require confirm_token round-trip.\n * - No-match / ambiguous: structured response, never fabricated tool call.\n */\n\nimport { AwsClient } from \"aws4fetch\";\nimport { z } from \"zod\";\nimport { sha256 } from \"@noble/hashes/sha256\";\nimport { bytesToHex } from \"@noble/hashes/utils\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { TOOL_SCOPES, DESTRUCTIVE_TOOLS, type ToolContext, wrapHandler } from \"./tools.js\";\nimport { BACKLOG_TOOL_SCOPES } from \"./tools-backlog.js\";\n\n// ---------------------------------------------------------------------------\n// Tool registry — complete list of all MCP tool names known at build time.\n// Resolved tool names are validated against this set before returning to caller.\n// ---------------------------------------------------------------------------\nconst TOOL_REGISTRY: ReadonlySet<string> = new Set([\n // v1 OCS tools (43)\n ...Object.keys(TOOL_SCOPES),\n // v1.1 backlog tools\n ...Object.keys(BACKLOG_TOOL_SCOPES),\n // intelligence composites (8)\n \"diagnose_subscriber\",\n \"fleet_health\",\n \"detect_usage_anomalies\",\n \"optimize_package\",\n \"churn_risk\",\n \"audit_network_coverage\",\n \"marketing_intelligence\",\n \"high_cost_subscribers\",\n // event ring buffer (1)\n \"list_recent_ocs_events\",\n // MCP App tools (3)\n \"fleet_health_app\",\n \"provision_esim_wizard\",\n \"balance_topup_form\",\n // router tools (self-reference)\n \"carrier_ask\",\n \"carrier_ask_describe\",\n]);\n\n// Tools that MUST NEVER auto-execute from a natural-language intent.\n// Always require confirm_token round-trip regardless of confidence.\nconst HARD_BLOCK_TOOLS: ReadonlySet<string> = new Set([\n \"clean_all_packages\",\n \"delete_subscriber_package\",\n \"modify_account_balance\",\n \"modify_subscriber_status\",\n \"change_sim_status\",\n \"reset_subscriber_gz_counter\",\n]);\n\n// ---------------------------------------------------------------------------\n// Confirm token helpers\n// ---------------------------------------------------------------------------\nconst CONFIRM_TOKEN_TTL_SECONDS = 120;\nconst CONFIRM_TOKEN_PREFIX = \"carrier_ask_confirm:\";\n\nfunction generateConfirmToken(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return bytesToHex(bytes);\n}\n\nasync function storeConfirmToken(\n kv: KVNamespace,\n token: string,\n payload: Record<string, unknown>,\n): Promise<void> {\n await kv.put(\n `${CONFIRM_TOKEN_PREFIX}${token}`,\n JSON.stringify(payload),\n { expirationTtl: CONFIRM_TOKEN_TTL_SECONDS },\n );\n}\n\nasync function consumeConfirmToken(\n kv: KVNamespace,\n token: string,\n): Promise<Record<string, unknown> | null> {\n const raw = await kv.get(`${CONFIRM_TOKEN_PREFIX}${token}`, \"text\");\n if (!raw) return null;\n await kv.delete(`${CONFIRM_TOKEN_PREFIX}${token}`);\n return JSON.parse(raw) as Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Intent hashing — SHA-256, hex-encoded.\n// ---------------------------------------------------------------------------\nexport function hashIntent(intent: string): string {\n return bytesToHex(sha256(new TextEncoder().encode(intent)));\n}\n\n// ---------------------------------------------------------------------------\n// Routing result shape\n// ---------------------------------------------------------------------------\ntype RouteResult =\n | {\n match: \"confirmed\";\n resolved_tool: string;\n resolved_params: Record<string, unknown>;\n confidence: number;\n confirm_required: false;\n execution_note: string;\n }\n | {\n match: \"pending_confirm\";\n resolved_tool: string;\n resolved_params: Record<string, unknown>;\n confidence: number;\n confirm_required: true;\n confirm_token: string;\n confirm_expires_in_seconds: number;\n dry_run_preview?: string;\n safety_note: string;\n }\n | {\n match: \"ambiguous\";\n candidates: Array<{ tool: string; reason: string }>;\n clarifying_question: string;\n }\n | {\n match: \"none\";\n closest: Array<{ tool: string; reason: string }>;\n suggestion: string;\n }\n | {\n match: \"routing_pending\";\n intent_received: string;\n note: string;\n scaffold_version: string;\n }\n | {\n match: \"rate_limited\";\n retry_after_seconds: number;\n suggestion: string;\n };\n\n// ---------------------------------------------------------------------------\n// Bedrock request/response types (Bedrock converse-compatible, tool-use subset)\n// ---------------------------------------------------------------------------\ninterface BedrockTool {\n name: string;\n description: string;\n input_schema: {\n type: \"object\";\n properties: Record<string, unknown>;\n required?: string[];\n };\n}\n\ninterface BedrockPayload {\n anthropic_version: \"bedrock-2023-05-31\";\n max_tokens: number;\n system: string;\n messages: Array<{ role: \"user\" | \"assistant\"; content: string }>;\n tools: BedrockTool[];\n tool_choice: { type: \"any\" };\n}\n\ninterface BedrockToolUseBlock {\n type: \"tool_use\";\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface BedrockTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface BedrockResponse {\n content: Array<BedrockToolUseBlock | BedrockTextBlock>;\n stop_reason: string;\n}\n\n// ---------------------------------------------------------------------------\n// Router tool catalog for Bedrock.\n// Sentinel \"carrier_clarify\" signals ambiguity without hallucinating a match.\n// ---------------------------------------------------------------------------\nconst ROUTER_TOOLS: BedrockTool[] = [\n {\n name: \"carrier_clarify\",\n description:\n \"Use ONLY when the intent is genuinely ambiguous and you cannot determine a single best-matching tool. \" +\n \"Provide 1-3 candidate tools and a clarifying question.\",\n input_schema: {\n type: \"object\" as const,\n properties: {\n candidates: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n tool: { type: \"string\" },\n reason: { type: \"string\" },\n },\n required: [\"tool\", \"reason\"],\n },\n },\n clarifying_question: { type: \"string\" },\n },\n required: [\"candidates\", \"clarifying_question\"],\n },\n },\n {\n name: \"list_reseller_accounts\",\n description: \"List all reseller accounts. Intent: 'show my accounts', 'list resellers', 'what accounts do I have'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_reseller_info\",\n description: \"Get info about a specific reseller. Intent: 'reseller info', 'account details for reseller X'.\",\n input_schema: { type: \"object\" as const, properties: { reseller_id: { type: \"number\" } } },\n },\n {\n name: \"esim_status_per_account\",\n description: \"Show eSIM counts by status per account. Intent: 'esim overview', 'how many esims active per account'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_subscriber\",\n description: \"Look up a single subscriber by ICCID or MSISDN. Intent: 'get subscriber', 'look up ICCID', 'find SIM 8931...'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, msisdn: { type: \"string\" } } },\n },\n {\n name: \"list_subscribers\",\n description: \"List subscribers in an account. Intent: 'list subscribers', 'show all SIMs', 'subscribers in account X'.\",\n input_schema: { type: \"object\" as const, properties: { account_id: { type: \"number\" }, page: { type: \"number\" } } },\n },\n {\n name: \"subscriber_usage\",\n description: \"Show data usage for a subscriber (max 7 days). Intent: 'how much data did X use', 'usage for subscriber', 'data consumption'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, start: { type: \"string\" }, end: { type: \"string\" } } },\n },\n {\n name: \"subscriber_network_events\",\n description: \"Show network events (attach/detach/roaming) for a subscriber. Intent: 'network events', 'connection history', 'roaming events'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, start: { type: \"string\" }, end: { type: \"string\" } } },\n },\n {\n name: \"list_subscriber_packages\",\n description: \"List active packages for a subscriber. Intent: 'what packages does subscriber have', 'show data packages', 'subscriber plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_package_templates\",\n description: \"List available package templates. Intent: 'what packages can I assign', 'show product catalog', 'available data plans'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"assign_package\",\n description: \"Assign a one-time data package to a subscriber. Intent: 'assign package', 'give subscriber X the Y plan', 'add data package'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageTemplateId: { type: \"number\" } } },\n },\n {\n name: \"assign_recurring_package\",\n description: \"Set up auto-renewing recurring package for a subscriber. Intent: 'monthly plan', 'recurring package', 'auto-renew data'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageTemplateId: { type: \"number\" } } },\n },\n {\n name: \"modify_package_limits\",\n description: \"Change data/voice/SMS limits on an existing package. Intent: 'change package limit', 'update data cap', 'modify plan limits'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"modify_package_expiry\",\n description: \"Change the expiry date of a subscriber package. Intent: 'extend package', 'change expiry', 'push package end date'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, expiryDate: { type: \"string\" } } },\n },\n {\n name: \"modify_package_status\",\n description: \"Activate or pause a specific package. Intent: 'pause package', 'activate package', 'suspend data plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, status: { type: \"string\" } } },\n },\n {\n name: \"stop_resume_recurring_package\",\n description: \"Stop or resume a recurring package. Intent: 'cancel auto-renew', 'stop recurring', 'resume monthly plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" }, action: { type: \"string\" } } },\n },\n {\n name: \"delete_subscriber_package\",\n description: \"DESTRUCTIVE: Delete a package from a subscriber. Intent: 'delete package', 'remove plan from subscriber'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"clean_all_packages\",\n description: \"DESTRUCTIVE: Remove ALL packages from a subscriber. Irreversible. Intent: 'reset packages', 'clean all plans', 'wipe packages'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_status\",\n description: \"DESTRUCTIVE if terminating: Change subscriber status (ACTIVE/SUSPENDED/TERMINATED). Intent: 'suspend subscriber', 'pause SIM', 'terminate', 'reactivate'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, status: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_balance\",\n description: \"Add or set credit balance for a subscriber. Intent: 'top up subscriber', 'add credit', 'set subscriber balance'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, amount: { type: \"number\" } } },\n },\n {\n name: \"modify_account_balance\",\n description: \"DESTRUCTIVE: Modify account-level balance. Intent: 'adjust account balance', 'add account credit'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { accountId: { type: \"number\" }, amount: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_contact_info\",\n description: \"Update subscriber contact details. Intent: 'update subscriber name', 'change email for SIM', 'fix contact info'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, name: { type: \"string\" }, email: { type: \"string\" } } },\n },\n {\n name: \"set_subscriber_traffic_restrictions\",\n description: \"Enable or disable voice/SMS/data restrictions. Intent: 'block data for subscriber', 'restrict voice', 'data-only SIM'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_steering_list\",\n description: \"Set preferred network steering list for a subscriber. Intent: 'change network preference', 'steer to operator X', 'preferred network'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, steeringListId: { type: \"number\" } } },\n },\n {\n name: \"push_steering_to_subscriber\",\n description: \"Push network steering config to subscriber device. Intent: 'push steering', 'apply network config', 'force network update'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"move_subscriber_range_to_account\",\n description: \"Move a range of subscribers to a different account. Intent: 'move subscribers', 'transfer SIMs to account'.\",\n input_schema: { type: \"object\" as const, properties: { accountId: { type: \"number\" } } },\n },\n {\n name: \"hlr_get_bitrate\",\n description: \"Get current HLR bitrate cap for a subscriber. Intent: 'what speed is subscriber throttled to', 'get bitrate', 'check speed cap'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"hlr_set_bitrate\",\n description: \"Set or remove HLR speed cap (throttle). Intent: 'throttle subscriber', 'set speed limit', 'cap to 256kbps', 'remove throttle'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, bitrate: { type: \"number\" } } },\n },\n {\n name: \"change_sim_status\",\n description: \"DESTRUCTIVE: Change physical SIM card status. Intent: 'deactivate SIM', 'delete SIM card', 'suspend card'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, status: { type: \"string\" } } },\n },\n {\n name: \"send_sms\",\n description: \"Send SMS to a subscriber. Intent: 'send text to subscriber', 'SMS ICCID X', 'message subscriber'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, message: { type: \"string\" } } },\n },\n {\n name: \"get_sim_provider_status\",\n description: \"Get SIM provider / eSIM profile status. Intent: 'SIM provider status', 'eSIM profile downloaded?', 'check profile status'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"get_subscriber_location\",\n description: \"Get approximate subscriber location. Intent: 'where is subscriber', 'subscriber location', 'locate SIM'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"get_subscriber_location_by_cell_id\",\n description: \"Get granular subscriber location by cell tower. Intent: 'cell-level location', 'cell tower for subscriber', 'exact location'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_steering_lists\",\n description: \"List available network steering lists. Intent: 'show steering lists', 'available networks', 'what network profiles exist'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_network_profiles\",\n description: \"List network profiles. Intent: 'list network profiles', 'show network configs'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_location_zones\",\n description: \"List location zones. Intent: 'list zones', 'show coverage zones'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_detailed_location_zones\",\n description: \"List detailed location zones with coordinates. Intent: 'detailed zones', 'zone coordinates', 'coverage map'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_destination_prefixes\",\n description: \"List destination number prefixes. Intent: 'list prefixes', 'routing prefixes', 'number ranges'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_destination_lists\",\n description: \"List destination lists for voice/SMS routing. Intent: 'destination lists', 'routing lists'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"list_sponsors\",\n description: \"List sponsor accounts. Intent: 'list sponsors', 'show sponsor accounts'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"get_tariff\",\n description: \"Get tariff/rate rules. Intent: 'what are my rates', 'tariff info', 'pricing rules'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"create_package_template\",\n description: \"Create a new package template. Intent: 'create package', 'new product', 'add package template'.\",\n input_schema: { type: \"object\" as const, properties: { name: { type: \"string\" } } },\n },\n {\n name: \"create_location_zone\",\n description: \"Create a new location zone. Intent: 'create zone', 'add location zone', 'new coverage zone'.\",\n input_schema: { type: \"object\" as const, properties: { name: { type: \"string\" } } },\n },\n {\n name: \"modify_template_core\",\n description: \"Modify core settings of a package template. Intent: 'edit package template', 'change template name/settings'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"modify_template_recurring\",\n description: \"Modify recurring billing settings of a template. Intent: 'change template renewal', 'edit recurring settings'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"modify_template_throttling\",\n description: \"Modify throttling settings of a template. Intent: 'change template speed', 'edit throttle on template'.\",\n input_schema: { type: \"object\" as const, properties: { templateId: { type: \"number\" } } },\n },\n {\n name: \"subscriber_active_period\",\n description: \"Get or set the active period for a subscriber. Intent: 'active period', 'subscriber validity', 'SIM activation window'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"list_recent_ocs_events\",\n description: \"List recent OCS events for a subscriber (last 50, 24h window). Intent: 'recent events', 'event history', 'OCS log'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"affect_subscriber_phone_number\",\n description: \"Assign or unassign a phone number to a subscriber. Intent: 'assign phone number', 'give SIM a number', 'remove number'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, msisdn: { type: \"string\" } } },\n },\n {\n name: \"modify_subscriber_mobile_plan\",\n description: \"Change the mobile plan for a subscriber. Intent: 'change mobile plan', 'switch plan', 'update rate plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, planId: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_package_active_period\",\n description: \"Modify the active period of a subscriber's package. Intent: 'extend package period', 'change package dates'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" }, packageId: { type: \"number\" } } },\n },\n {\n name: \"modify_subscriber_voip_plan\",\n description: \"Change VoIP plan for a subscriber. Intent: 'change voip plan', 'update voice plan'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"reset_subscriber_gz_counter\",\n description: \"DESTRUCTIVE: Reset a subscriber's guaranteed zone counter. Irreversible. Intent: 'reset gz counter', 'clear gz usage'. Requires confirm_token.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"diagnose_subscriber\",\n description: \"Run composite diagnostic on a subscriber. Intent: 'why is subscriber offline', 'diagnose SIM', 'troubleshoot ICCID'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"fleet_health\",\n description: \"Show overall fleet health (active/suspended/churned counts, alerts). Intent: 'fleet status', 'how is my fleet', 'health overview', 'how many esims active'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"detect_usage_anomalies\",\n description: \"Detect unusual data usage patterns across the fleet. Intent: 'usage anomalies', 'abnormal data use', 'spike detection'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"optimize_package\",\n description: \"Suggest package optimizations for a subscriber based on usage. Intent: 'optimize package', 'right-size plan', 'package recommendation'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"churn_risk\",\n description: \"Identify subscribers at risk of churning. Intent: 'churn risk', 'at-risk subscribers', 'who might leave'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"audit_network_coverage\",\n description: \"Audit network coverage for subscriber or fleet. Intent: 'coverage audit', 'network coverage check', 'coverage gaps'.\",\n input_schema: { type: \"object\" as const, properties: { iccid: { type: \"string\" } } },\n },\n {\n name: \"marketing_intelligence\",\n description: \"Get marketing intelligence: usage trends, popular packages, growth metrics. Intent: 'marketing data', 'growth report', 'popular plans'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"high_cost_subscribers\",\n description: \"List subscribers generating highest costs. Intent: 'high cost subscribers', 'most expensive SIMs', 'cost outliers'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"fleet_health_app\",\n description: \"Open the fleet health MCP App UI. Intent: 'open fleet dashboard app', 'fleet health UI'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"provision_esim_wizard\",\n description: \"Open the eSIM provisioning wizard app. Intent: 'provision esim', 'new esim wizard', 'onboard esim'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"balance_topup_form\",\n description: \"Open the balance top-up form app. Intent: 'top up balance', 'add credit form', 'balance topup'.\",\n input_schema: { type: \"object\" as const, properties: {} },\n },\n {\n name: \"carrier_ask_describe\",\n description: \"Get documentation for a specific carrier tool. Intent: 'describe tool X', 'how does assign_package work', 'tool documentation'.\",\n input_schema: { type: \"object\" as const, properties: { tool_name: { type: \"string\" } } },\n },\n];\n\n// System prompt for the Haiku router\nconst ROUTER_SYSTEM_PROMPT = `You are a carrier fleet operations router. Your job is to map a user's natural-language intent to exactly ONE tool from the Carrier MCP tool registry.\n\nRules:\n1. Pick the single best-matching tool. Never pick carrier_ask (the router itself).\n2. Extract any parameters mentioned in the intent (ICCID, account IDs, amounts, etc.) as the tool's input.\n3. Use carrier_clarify ONLY when genuinely ambiguous — when multiple tools are equally likely and you need more information.\n4. DESTRUCTIVE tools are flagged in their descriptions — still pick them if they match; the safety layer handles the confirm flow.\n5. Only include params explicitly mentioned in the intent.\n6. Context fields (iccid, account_id, reseller_id) from the routing context take precedence.`;\n\n// RouteResult variant from _routeIntent (confirm_token is \"\" placeholder; caller fills it)\ntype RoutedResult =\n | Extract<RouteResult, { match: \"confirmed\" }>\n | Extract<RouteResult, { match: \"pending_confirm\" }>\n | Extract<RouteResult, { match: \"ambiguous\" }>\n | Extract<RouteResult, { match: \"none\" }>\n | Extract<RouteResult, { match: \"routing_pending\" }>\n | Extract<RouteResult, { match: \"rate_limited\" }>;\n\n// ---------------------------------------------------------------------------\n// Default Bedrock config\n// ---------------------------------------------------------------------------\nconst DEFAULT_REGION = \"us-east-1\";\nconst DEFAULT_MODEL_ID = \"us.anthropic.claude-haiku-4-5-20251001-v1:0\";\n\n// ---------------------------------------------------------------------------\n// callBedrock — SigV4-signed InvokeModel via aws4fetch.\n// Exported for testing (mock globalThis.fetch or AwsClient in tests).\n// ---------------------------------------------------------------------------\nexport async function callBedrock(\n env: { AWS_ACCESS_KEY_ID: string; AWS_SECRET_ACCESS_KEY: string; AWS_REGION?: string; BEDROCK_MODEL_ID?: string },\n payload: BedrockPayload,\n): Promise<BedrockResponse> {\n const region = env.AWS_REGION ?? DEFAULT_REGION;\n const modelId = env.BEDROCK_MODEL_ID ?? DEFAULT_MODEL_ID;\n\n const aws = new AwsClient({\n accessKeyId: env.AWS_ACCESS_KEY_ID,\n secretAccessKey: env.AWS_SECRET_ACCESS_KEY,\n region,\n service: \"bedrock\",\n });\n\n const url = `https://bedrock-runtime.${region}.amazonaws.com/model/${encodeURIComponent(modelId)}/invoke`;\n\n const resp = await aws.fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", Accept: \"application/json\" },\n body: JSON.stringify(payload),\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n // 429 → surface as a structured rate-limit signal\n if (resp.status === 429) {\n const retryAfter = resp.headers.get(\"retry-after\");\n const err = new Error(`Bedrock rate limit: ${body}`) as Error & { isRateLimit: true; retryAfter: string | null };\n err.isRateLimit = true;\n err.retryAfter = retryAfter;\n throw err;\n }\n throw new Error(`Bedrock invoke failed: ${resp.status} ${body}`);\n }\n\n return (await resp.json()) as BedrockResponse;\n}\n\n// ---------------------------------------------------------------------------\n// _routeIntent — core routing logic via Claude Haiku 4.5 on Bedrock.\n// Exported for testing (mock callBedrock or globalThis.fetch in tests).\n// ---------------------------------------------------------------------------\nexport async function _routeIntent(\n intent: string,\n context: { iccid?: string; account_id?: number; reseller_id?: number },\n env: ToolContext[\"env\"],\n): Promise<RoutedResult> {\n // Feature flag gate\n if (env.CARRIER_ASK_ENABLED !== \"true\" || !env.AWS_ACCESS_KEY_ID || !env.AWS_SECRET_ACCESS_KEY) {\n return {\n match: \"routing_pending\",\n intent_received: intent,\n note:\n \"carrier_ask routing engine is not yet activated. \" +\n \"Add AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY to Doppler carrier/dev+stg+prd and set CARRIER_ASK_ENABLED=true.\",\n scaffold_version: \"v2.0-bedrock\",\n };\n }\n\n // Merge context into user message (omit keys with undefined — JSON.stringify drops them)\n const definedContext = Object.fromEntries(\n Object.entries(context).filter(([, value]) => value !== undefined),\n );\n const contextNote =\n Object.keys(definedContext).length > 0\n ? `\\n\\nPre-resolved context: ${JSON.stringify(definedContext)}`\n : \"\";\n const userMessage = `${intent}${contextNote}`;\n\n const payload: BedrockPayload = {\n anthropic_version: \"bedrock-2023-05-31\",\n max_tokens: 512,\n system: ROUTER_SYSTEM_PROMPT,\n messages: [{ role: \"user\", content: userMessage }],\n tools: ROUTER_TOOLS,\n tool_choice: { type: \"any\" },\n };\n\n let response: BedrockResponse;\n try {\n response = await callBedrock({\n AWS_ACCESS_KEY_ID: env.AWS_ACCESS_KEY_ID,\n AWS_SECRET_ACCESS_KEY: env.AWS_SECRET_ACCESS_KEY,\n AWS_REGION: env.AWS_REGION,\n BEDROCK_MODEL_ID: env.BEDROCK_MODEL_ID,\n }, payload);\n } catch (err) {\n if (err instanceof Error && (err as Error & { isRateLimit?: boolean }).isRateLimit) {\n const retryAfter = (err as Error & { retryAfter: string | null }).retryAfter;\n const parsedSeconds = retryAfter ? parseInt(retryAfter, 10) : 60;\n return {\n match: \"rate_limited\",\n retry_after_seconds: Number.isFinite(parsedSeconds) ? parsedSeconds : 60,\n suggestion: \"Bedrock rate limit reached. Please retry after the indicated delay.\",\n };\n }\n throw err;\n }\n\n // Extract tool_use block\n const toolUseBlock = response.content.find(\n (block): block is BedrockToolUseBlock => block.type === \"tool_use\",\n );\n\n if (!toolUseBlock) {\n return {\n match: \"none\",\n closest: [],\n suggestion:\n \"Could not determine the right tool for this intent. Try rephrasing or use carrier_ask_describe to explore available tools.\",\n };\n }\n\n const { name: resolvedTool, input } = toolUseBlock;\n const resolvedParams = (input ?? {}) as Record<string, unknown>;\n\n // Clarification sentinel\n if (resolvedTool === \"carrier_clarify\") {\n const candidates = (resolvedParams.candidates ?? []) as Array<{ tool: string; reason: string }>;\n const clarifyingQuestion = typeof resolvedParams.clarifying_question === \"string\"\n ? resolvedParams.clarifying_question\n : \"Could you clarify your intent?\";\n return {\n match: \"ambiguous\",\n candidates,\n clarifying_question: clarifyingQuestion,\n };\n }\n\n // Hallucination guard\n if (!TOOL_REGISTRY.has(resolvedTool)) {\n return {\n match: \"none\",\n closest: [],\n suggestion: `Router returned unknown tool '${resolvedTool}'. Please try rephrasing your intent.`,\n };\n }\n\n // HARD_BLOCK: require confirm_token\n if (HARD_BLOCK_TOOLS.has(resolvedTool)) {\n return {\n match: \"pending_confirm\",\n resolved_tool: resolvedTool,\n resolved_params: resolvedParams,\n confidence: 0.95,\n confirm_required: true,\n confirm_token: \"\", // filled by caller after storeConfirmToken\n confirm_expires_in_seconds: CONFIRM_TOKEN_TTL_SECONDS,\n safety_note:\n `'${resolvedTool}' is a protected destructive operation. ` +\n \"Re-call carrier_ask with the returned confirm_token to execute.\",\n };\n }\n\n // Safe read/write tool\n return {\n match: \"confirmed\",\n resolved_tool: resolvedTool,\n resolved_params: resolvedParams,\n confidence: 0.95,\n confirm_required: false,\n execution_note:\n `Call '${resolvedTool}' directly with resolved_params to execute. ` +\n \"carrier_ask does not auto-execute — the caller makes the explicit tool call.\",\n };\n}\n\n// ---------------------------------------------------------------------------\n// Audit log write for carrier_ask routing events.\n// ---------------------------------------------------------------------------\nfunction writeCarrierAskAudit(\n env: ToolContext[\"env\"],\n row: {\n intent_hash: string;\n match: string;\n resolved_tool: string;\n confirm_token_state: \"none\" | \"issued\" | \"redeemed\" | \"expired\";\n status: \"ok\" | \"error\";\n latency_ms: number;\n sub: string;\n reseller_id: number;\n },\n): void {\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"carrier_ask\", // blob[0] tool_name\n row.resolved_tool, // blob[1] resolved tool (or \"none\")\n row.status, // blob[2] ok | error\n row.match, // blob[3] match type\n row.intent_hash, // blob[4] SHA-256 of intent\n row.confirm_token_state, // blob[5] confirm token state\n row.sub, // blob[6] user subject\n ],\n doubles: [row.latency_ms],\n indexes: [String(row.reseller_id)],\n });\n } catch {\n // Never let audit failure propagate\n }\n}\n\n// ---------------------------------------------------------------------------\n// registerAllCarrierAskTools — registers carrier_ask + carrier_ask_describe\n// ---------------------------------------------------------------------------\nexport function registerAllCarrierAskTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // carrier_ask — natural-language router\n // =========================================================================\n server.registerTool(\n \"carrier_ask\",\n {\n title: \"Natural Language Carrier Tool Router\",\n description:\n \"Use this when you want to perform a carrier operation but don't know which specific tool to call. \" +\n \"Describe your intent in plain language and carrier_ask will identify the correct tool(s) and \" +\n \"suggest the required parameters. For simple read intents, it executes directly and returns results. \" +\n \"For destructive operations it returns a confirm_token that you must pass in a second call. \" +\n \"Params: `intent` (string — natural language description of what you want to do), \" +\n \"`context` (optional: iccid, account_id, reseller_id if already known). \" +\n \"Returns: RouteResult — confirmed | pending_confirm | ambiguous | none. \" +\n \"Do NOT use this when you know the right tool — direct calls are faster and cheaper.\",\n inputSchema: {\n intent: z\n .string()\n .min(3)\n .describe(\n \"Natural-language description of the operation to perform \" +\n \"(e.g. 'suspend ICCID 89316 until next month', 'show fleet health', \" +\n \"'assign Europe 5GB package to subscriber 89316...')\",\n ),\n context: z\n .object({\n iccid: z.string().optional().describe(\"Subscriber ICCID if already known\"),\n account_id: z.number().optional().describe(\"Account ID if already known\"),\n reseller_id: z.number().optional().describe(\"Reseller ID if already known\"),\n })\n .optional()\n .describe(\"Optional pre-resolved context to improve routing accuracy\"),\n confirm_token: z\n .string()\n .optional()\n .describe(\n \"One-time token from a previous carrier_ask call with confirm_required=true. \" +\n \"Providing this executes the previously staged destructive operation.\",\n ),\n },\n },\n wrapHandler(\n \"carrier_ask\",\n \"[carrier_ask]\",\n \"read\",\n ctx,\n async (args, _token) => {\n const { intent, context = {}, confirm_token } = args;\n const intentHash = hashIntent(intent);\n const start = Date.now();\n\n // ------------------------------------------------------------------\n // Confirm token redemption path\n // ------------------------------------------------------------------\n if (confirm_token) {\n const staged = await consumeConfirmToken(ctx.env.OAUTH_KV, confirm_token);\n if (!staged) {\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: \"confirm_expired\",\n resolved_tool: \"none\",\n confirm_token_state: \"expired\",\n status: \"error\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"confirm_token_expired\",\n message:\n `Confirm token '${confirm_token}' has expired or was already used. ` +\n `Tokens expire after ${CONFIRM_TOKEN_TTL_SECONDS}s. Re-issue the original intent to get a new token.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const resolvedTool = staged.resolved_tool as string;\n if (!TOOL_REGISTRY.has(resolvedTool)) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"invalid_tool\",\n message: `Staged tool '${resolvedTool}' is not in the tool registry.`,\n }),\n },\n ],\n isError: true,\n };\n }\n\n writeCarrierAskAudit(ctx.env, {\n intent_hash:\n typeof staged.intent_hash === \"string\" ? staged.intent_hash : intentHash,\n match: \"confirm_executed\",\n resolved_tool: resolvedTool,\n confirm_token_state: \"redeemed\",\n status: \"ok\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n match: \"confirm_executed\",\n resolved_tool: resolvedTool,\n resolved_params: staged.resolved_params,\n note:\n \"Confirm token accepted. Call the resolved_tool directly with resolved_params \" +\n \"to execute the operation. carrier_ask does not auto-execute — the caller must \" +\n \"make the explicit tool call.\",\n }),\n },\n ],\n };\n }\n\n // ------------------------------------------------------------------\n // Main routing path\n // ------------------------------------------------------------------\n let route: RoutedResult;\n\n try {\n route = await _routeIntent(intent, context, ctx.env);\n } catch (err) {\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: \"error\",\n resolved_tool: \"none\",\n confirm_token_state: \"none\",\n status: \"error\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"routing_error\",\n message:\n err instanceof Error\n ? err.message\n : \"An unexpected error occurred during routing.\",\n }),\n },\n ],\n isError: true,\n };\n }\n\n // Issue confirm token for HARD_BLOCK results\n let finalRoute: RouteResult = route as RouteResult;\n let confirmTokenState: \"none\" | \"issued\" = \"none\";\n\n if (route.match === \"pending_confirm\") {\n const token = generateConfirmToken();\n await storeConfirmToken(ctx.env.OAUTH_KV, token, {\n resolved_tool: route.resolved_tool,\n resolved_params: route.resolved_params,\n intent_hash: intentHash,\n issued_at: new Date().toISOString(),\n });\n finalRoute = { ...route, confirm_token: token } as RouteResult;\n confirmTokenState = \"issued\";\n }\n\n const resolvedToolForAudit: string =\n (route.match === \"confirmed\" || route.match === \"pending_confirm\")\n ? route.resolved_tool\n : \"none\";\n\n writeCarrierAskAudit(ctx.env, {\n intent_hash: intentHash,\n match: route.match,\n resolved_tool: resolvedToolForAudit,\n confirm_token_state: confirmTokenState,\n status: \"ok\",\n latency_ms: Date.now() - start,\n sub: ctx.props.sub,\n reseller_id: ctx.props.reseller_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(finalRoute, null, 2),\n },\n ],\n };\n },\n ),\n );\n\n // =========================================================================\n // carrier_ask_describe — drill-down companion\n // =========================================================================\n server.registerTool(\n \"carrier_ask_describe\",\n {\n title: \"Describe a Carrier Tool\",\n description:\n \"Get full documentation for any registered Carrier MCP tool: description, \" +\n \"parameters, 2-3 example invocations, required scope, destructive flag, and guidance. \" +\n \"Params: `tool_name` (exact MCP tool name, e.g. 'assign_package'). \" +\n \"Returns: structured tool metadata. Does NOT execute the tool.\",\n inputSchema: {\n tool_name: z\n .string()\n .describe(\"The exact MCP tool name to describe (e.g. 'assign_package', 'hlr_set_bitrate')\"),\n },\n },\n wrapHandler(\n \"carrier_ask_describe\",\n \"[carrier_ask_describe]\",\n \"read\",\n ctx,\n async ({ tool_name }, _token) => {\n if (!TOOL_REGISTRY.has(tool_name)) {\n const closest = [...TOOL_REGISTRY]\n .filter((name) => name.includes(tool_name.split(\"_\")[0] ?? \"\") || tool_name.includes(name.split(\"_\")[0] ?? \"\"))\n .slice(0, 5);\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"tool_not_found\",\n tool_name,\n message: `'${tool_name}' is not a registered Carrier MCP tool.`,\n did_you_mean: closest.length > 0 ? closest : undefined,\n total_registered: TOOL_REGISTRY.size,\n }),\n },\n ],\n isError: true,\n };\n }\n\n const allScopes = { ...TOOL_SCOPES, ...BACKLOG_TOOL_SCOPES };\n const scope = allScopes[tool_name as keyof typeof allScopes] ?? \"read\";\n const isDestructive = DESTRUCTIVE_TOOLS.has(tool_name);\n const isHardBlock = HARD_BLOCK_TOOLS.has(tool_name);\n\n const doc = {\n tool_name,\n scope,\n destructive: isDestructive,\n hard_block: isHardBlock,\n hard_block_note: isHardBlock\n ? \"This tool is in the HARD_BLOCK list: carrier_ask will never auto-execute it. \" +\n \"It always requires an explicit confirm_token redemption.\"\n : undefined,\n dry_run_supported: isDestructive,\n examples: buildExamples(tool_name),\n note:\n \"Full parameter descriptions are available in the tool's inputSchema. \" +\n \"Call the tool with no arguments to trigger the MCP schema introspection response.\",\n };\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify(doc, null, 2),\n },\n ],\n };\n },\n ),\n );\n}\n\n// ---------------------------------------------------------------------------\n// buildExamples — curated invocation examples for high-traffic tools.\n// ---------------------------------------------------------------------------\nfunction buildExamples(toolName: string): Array<{ intent: string; params: Record<string, unknown> }> {\n const examples: Record<string, Array<{ intent: string; params: Record<string, unknown> }>> = {\n assign_package: [\n { intent: \"Give subscriber 89316... the Europe 5GB package\", params: { iccid: \"89316...\", packageTemplateId: 42 } },\n { intent: \"Assign a one-time data package to this eSIM\", params: { iccid: \"89316...\", packageTemplateId: 42 } },\n ],\n assign_recurring_package: [\n { intent: \"Set up monthly auto-renewal for subscriber 89316...\", params: { iccid: \"89316...\", packageTemplateId: 55 } },\n ],\n modify_subscriber_status: [\n { intent: \"Pause Maya's subscription for 2 months\", params: { iccid: \"89316...\", status: \"SUSPENDED\" } },\n { intent: \"Reactivate subscriber 89316...\", params: { iccid: \"89316...\", status: \"ACTIVE\" } },\n ],\n hlr_set_bitrate: [\n { intent: \"Throttle ICCID 89316... to 256kbps\", params: { iccid: \"89316...\", bitrate: 256000 } },\n { intent: \"Remove speed cap from subscriber 89316...\", params: { iccid: \"89316...\", bitrate: 0 } },\n ],\n modify_subscriber_steering_list: [\n { intent: \"Connect this eSIM to the best network in Italy\", params: { iccid: \"89316...\", steeringListId: 7 } },\n ],\n push_steering_to_subscriber: [\n { intent: \"Push the new steering config to the device\", params: { iccid: \"89316...\" } },\n ],\n clean_all_packages: [\n { intent: \"Reset all packages for subscriber 89316... before reprovisioning\", params: { iccid: \"89316...\", dry_run: true } },\n ],\n fleet_health: [\n { intent: \"Show me the fleet status overview\", params: {} },\n { intent: \"How many eSIMs are active right now\", params: {} },\n ],\n diagnose_subscriber: [\n { intent: \"Why is subscriber 89316... offline?\", params: { iccid: \"89316...\" } },\n ],\n };\n\n return examples[toolName] ?? [\n { intent: `Call ${toolName} for subscriber 89316...`, params: { iccid: \"89316...\" } },\n ];\n}\n\n// Export for TOOL_INVENTORY generation and reconcile script\nexport { TOOL_REGISTRY, HARD_BLOCK_TOOLS };\n","/**\n * Carrier MCP — Tool: list_recent_ocs_events\n *\n * Reads the per-ICCID ring-buffer written by the OCS webhook receiver\n * (ocs-webhook.ts → storeEvent). Key pattern:\n * events:<reseller_id>:<iccid>:evt:<padded_ts>:<event_id> (primary, per-event)\n * events:<reseller_id>:<iccid> (legacy batch, read-compat)\n *\n * The reseller_id is resolved via the `iccid:<iccid>` routing entry; falls back\n * to 0 when no routing entry exists (same convention as the writer).\n *\n * Annotations: readOnlyHint, idempotentHint, NOT openWorldHint (closed KV read).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Re-use types from the receiver (kept local to avoid circular imports)\n// ---------------------------------------------------------------------------\n\ninterface OcsEventStored {\n event_id: string;\n event_type: string;\n iccid: string;\n occurred_at: number;\n payload: Record<string, unknown>;\n /** Optional fields that may be present on enriched events */\n subscriber_id?: number;\n account_id?: number;\n reseller_id?: number;\n}\n\ninterface IccidRoutingEntry {\n reseller_id: number;\n user_key: string;\n}\n\ninterface StoredEventBatch {\n events: OcsEventStored[];\n updated_at: string;\n}\n\n// ---------------------------------------------------------------------------\n// Input schema\n// ---------------------------------------------------------------------------\n\nconst ALLOWED_EVENT_TYPES = [\n \"esim.activated\",\n \"esim.disabled\",\n \"package.expiry_warning\",\n \"location.changed\",\n \"balance.low\",\n] as const;\n\nexport const listRecentOcsEventsSchema = {\n iccid: z\n .string()\n .regex(/^\\d{19,20}$/)\n .describe(\"ICCID, 19 or 20 digits, ITU-T E.118 format\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(20)\n .describe(\"Max events to return, newest first\"),\n event_types: z\n .array(z.enum(ALLOWED_EVENT_TYPES))\n .optional()\n .describe(\"Filter to specific event types\"),\n since: z\n .string()\n .datetime()\n .optional()\n .describe(\"ISO-8601 timestamp; only events after this point\"),\n};\n\n// ---------------------------------------------------------------------------\n// Core reader — exported for tests\n// ---------------------------------------------------------------------------\n\nexport interface OcsEventOutput {\n event_id: string;\n event_type: string;\n timestamp: string;\n subscriber_id?: number;\n account_id?: number;\n reseller_id?: number;\n data: Record<string, unknown>;\n}\n\nexport interface ListRecentOcsEventsResult {\n iccid: string;\n events: OcsEventOutput[];\n total_in_buffer: number;\n filtered_count: number;\n buffer_oldest_event_timestamp: string | null;\n buffer_newest_event_timestamp: string | null;\n}\n\nexport async function listRecentOcsEvents(\n iccid: string,\n limit: number,\n eventTypes: readonly string[] | undefined,\n since: string | undefined,\n kv: Env[\"OCS_EVENT_ROUTING\"],\n): Promise<ListRecentOcsEventsResult> {\n // 1. Resolve reseller_id from routing entry (fall back to 0, same as writer)\n const routingRaw = (await kv.get(\n `iccid:${iccid}`,\n \"json\",\n )) as IccidRoutingEntry | null;\n const resellerId = routingRaw?.reseller_id ?? 0;\n\n const ringKey = `events:${resellerId}:${iccid}`;\n const itemPrefix = `${ringKey}:evt:`;\n\n // 2. Collect all per-event keys from ring-buffer (primary format)\n const fromItems: OcsEventStored[] = [];\n let listCursor: string | undefined;\n do {\n const listed = await kv.list({ prefix: itemPrefix, cursor: listCursor });\n for (const k of listed.keys) {\n const raw = await kv.get(k.name, \"text\");\n if (!raw) continue;\n try {\n fromItems.push(JSON.parse(raw) as OcsEventStored);\n } catch {\n // skip corrupt entries\n }\n }\n listCursor = listed.list_complete ? undefined : listed.cursor;\n } while (listCursor !== undefined);\n\n // 3. Legacy batch key (backwards compat with events written before per-event format)\n const legacy = (await kv.get(ringKey, \"json\")) as StoredEventBatch | null;\n\n // 4. Merge — de-duplicate by event_id; per-event items win over legacy batch\n const merged = new Map<string, OcsEventStored>();\n for (const e of legacy?.events ?? []) {\n merged.set(e.event_id, e);\n }\n for (const e of fromItems) {\n merged.set(e.event_id, e);\n }\n\n // 5. Sort by occurred_at ascending (oldest first for slicing, then we reverse)\n const allSorted = [...merged.values()].sort((a, b) => {\n if (a.occurred_at !== b.occurred_at) return a.occurred_at - b.occurred_at;\n return a.event_id.localeCompare(b.event_id);\n });\n\n const totalInBuffer = allSorted.length;\n const bufferOldest =\n allSorted.length > 0\n ? new Date(allSorted[0]!.occurred_at * 1000).toISOString()\n : null;\n const bufferNewest =\n allSorted.length > 0\n ? new Date(allSorted[allSorted.length - 1]!.occurred_at * 1000).toISOString()\n : null;\n\n // 6. Apply filters\n const sinceMs = since ? new Date(since).getTime() : null;\n\n const filtered = allSorted.filter((e) => {\n if (sinceMs !== null && e.occurred_at * 1000 <= sinceMs) return false;\n if (eventTypes && eventTypes.length > 0 && !eventTypes.includes(e.event_type))\n return false;\n return true;\n });\n\n const filteredCount = filtered.length;\n\n // 7. Newest first, slice to limit\n const sliced = filtered.slice(-limit).reverse();\n\n const events: OcsEventOutput[] = sliced.map((e) => {\n const out: OcsEventOutput = {\n event_id: e.event_id,\n event_type: e.event_type,\n timestamp: new Date(e.occurred_at * 1000).toISOString(),\n data: e.payload,\n };\n if (e.subscriber_id !== undefined) out.subscriber_id = e.subscriber_id;\n if (e.account_id !== undefined) out.account_id = e.account_id;\n if (e.reseller_id !== undefined) out.reseller_id = e.reseller_id;\n return out;\n });\n\n return {\n iccid,\n events,\n total_in_buffer: totalInBuffer,\n filtered_count: filteredCount,\n buffer_oldest_event_timestamp: bufferOldest,\n buffer_newest_event_timestamp: bufferNewest,\n };\n}\n\n// ---------------------------------------------------------------------------\n// MCP tool registration\n// ---------------------------------------------------------------------------\n\nexport function registerListRecentOcsEventsTool(\n server: McpServer,\n env: Env,\n): void {\n server.registerTool(\n \"list_recent_ocs_events\",\n {\n title: \"List Recent OCS Events\",\n description:\n \"Return the last N OCS events buffered for a given ICCID. Events include eSIM activations, disable, package expiry warnings, location changes, and balance alerts. Buffer holds up to 50 events per ICCID, 24h TTL. Use this when a user asks 'what happened to ICCID X recently' or 'why did subscriber Y go offline'.\",\n inputSchema: listRecentOcsEventsSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n openWorldHint: false,\n },\n },\n async (args) => {\n const { iccid, limit, event_types, since } = args as {\n iccid: string;\n limit: number;\n event_types?: Array<(typeof ALLOWED_EVENT_TYPES)[number]>;\n since?: string;\n };\n\n try {\n const result = await listRecentOcsEvents(\n iccid,\n limit,\n event_types,\n since,\n env.OCS_EVENT_ROUTING,\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error reading OCS event buffer: ${message}` }],\n };\n }\n },\n );\n}\n","/**\n * v1.2a — Fleet Health Dashboard MCP App\n *\n * Registers a UI-enabled tool `fleet_health_app` that returns structured data\n * for rendering charts in the sandboxed iframe view, alongside the\n * `ui://fleet-health-dashboard` resource that serves the HTML panel.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport type { ToolContext } from \"../tools.js\";\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport interface FleetHealthStructuredContent {\n utilization: number;\n totalActive: number;\n totalSuspended: number;\n totalInventory: number;\n totalOther: number;\n totalAccounts: number;\n lowBalanceCount: number;\n accountList: Array<{\n name: string;\n balance: number;\n active: number;\n suspended: number;\n inventory: number;\n other: number;\n }>;\n // Required by MCP SDK tool callback return type (`structuredContent`\n // is typed as `{ [key: string]: unknown }`).\n [key: string]: unknown;\n}\n\nexport function registerFleetHealthApp(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // ── Resource ─────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"Fleet Health Dashboard\",\n \"ui://fleet-health-dashboard\",\n {\n description:\n \"Interactive Fleet Health Dashboard — eSIM status charts, account breakdown, low-balance alerts.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\"https://internal/views/fleet-health/index.html\"),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Dashboard unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://fleet-health-dashboard\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n _meta: {\n ui: {\n csp: {\n resourceDomains: [\"https://cdn.jsdelivr.net\"],\n },\n },\n },\n },\n ],\n };\n },\n );\n\n // ── Tool ─────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"fleet_health_app\",\n {\n title: \"Fleet Health Dashboard\",\n description:\n \"Renders an interactive Fleet Health Dashboard with eSIM status charts, top-10 account breakdown, and low-balance alerts. Returns structuredContent for the chart panel.\",\n inputSchema: {\n accountId: z\n .number()\n .optional()\n .describe(\"Filter to a specific account (omit for all)\"),\n },\n annotations: { readOnlyHint: true },\n _meta: {\n ui: {\n resourceUri: \"ui://fleet-health-dashboard\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n async ({ accountId }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n const [statusResult, accountsResult] = await Promise.all([\n safeCallWithToken<Record<string, unknown>[]>(\n client,\n token,\n \"esimStatusPerAccount\",\n accountId !== undefined ? { accountId } : {},\n ),\n safeCallWithToken<Record<string, unknown>[]>(\n client,\n token,\n \"listResellerAccount\",\n {},\n ),\n ]);\n\n let totalActive = 0;\n let totalSuspended = 0;\n let totalInventory = 0;\n let totalOther = 0;\n const accountList: FleetHealthStructuredContent[\"accountList\"] = [];\n\n if (statusResult.data && Array.isArray(statusResult.data)) {\n for (const account of statusResult.data) {\n const active = Number(account[\"active\"] ?? 0);\n const suspended = Number(account[\"suspended\"] ?? 0);\n const inventory = Number(\n account[\"inventory\"] ?? account[\"notActivated\"] ?? 0,\n );\n const other = Number(\n account[\"other\"] ?? account[\"terminated\"] ?? 0,\n );\n totalActive += active;\n totalSuspended += suspended;\n totalInventory += inventory;\n totalOther += other;\n accountList.push({\n name: String(account[\"name\"] ?? account[\"accountId\"] ?? \"?\"),\n balance: 0,\n active,\n suspended,\n inventory,\n other,\n });\n }\n }\n\n // Merge balance data from accounts list\n if (accountsResult.data && Array.isArray(accountsResult.data)) {\n for (const a of accountsResult.data) {\n const aName = String(a[\"name\"] ?? a[\"accountId\"] ?? \"?\");\n const entry = accountList.find((e) => e.name === aName);\n if (entry) {\n entry.balance = Number(a[\"balance\"] ?? 0);\n }\n }\n }\n\n const total = totalActive + totalSuspended + totalInventory + totalOther;\n const utilization =\n total > 0\n ? Math.round((totalActive / total) * 1000) / 10\n : 0;\n\n const totalAccounts =\n accountsResult.data && Array.isArray(accountsResult.data)\n ? accountsResult.data.length\n : accountList.length;\n\n const lowBalanceCount =\n accountsResult.data && Array.isArray(accountsResult.data)\n ? accountsResult.data.filter((a) => Number(a[\"balance\"] ?? 0) < 10)\n .length\n : 0;\n\n // Sort accountList by total eSIMs descending for top-10 bar chart\n const sortedAccounts = [...accountList]\n .sort(\n (a, b) =>\n b.active + b.suspended + b.inventory + b.other -\n (a.active + a.suspended + a.inventory + a.other),\n )\n .slice(0, 10);\n\n const errors = [statusResult.error, accountsResult.error]\n .filter(Boolean)\n .join(\"; \");\n\n const summaryLines = [\n `Fleet Utilization: ${utilization}%`,\n `Active: ${totalActive} | Suspended: ${totalSuspended} | Inventory: ${totalInventory} | Other: ${totalOther}`,\n `Total Accounts: ${totalAccounts} | Low Balance (<10): ${lowBalanceCount}`,\n ...(errors ? [`Errors: ${errors}`] : []),\n ];\n\n const structuredContent: FleetHealthStructuredContent = {\n utilization,\n totalActive,\n totalSuspended,\n totalInventory,\n totalOther,\n totalAccounts,\n lowBalanceCount,\n accountList: sortedAccounts,\n };\n\n return {\n content: [{ type: \"text\" as const, text: summaryLines.join(\"\\n\") }],\n structuredContent,\n };\n },\n );\n}\n","/**\n * v1.2b — eSIM Provisioning Wizard MCP App\n *\n * 3-step wizard: select subscriber → select package → confirm + execute.\n * Tier-gated: pro and enterprise only (free tier is skipped).\n * Step 2→3 fetches package template details for preview; step 3 (confirm) calls affectPackageToSubscriber.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport { getDefaultResellerId, type ToolContext } from \"../tools.js\";\nimport {\n loadWizardSession,\n saveWizardSession,\n deleteWizardSession,\n} from \"./app-state.js\";\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nfunction generateWizardId(): string {\n const arr = new Uint8Array(4);\n crypto.getRandomValues(arr);\n return Array.from(arr)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\n// ── Registration ──────────────────────────────────────────────────────────────\n\nexport function registerProvisioningWizard(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // Tier guard — free tier does not get this wizard\n if (ctx.props.tier === \"free\") return;\n\n // ── Resource ───────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"eSIM Provisioning Wizard\",\n \"ui://esim-provisioning-wizard\",\n {\n description:\n \"3-step eSIM provisioning wizard — pick subscriber, pick package, confirm + execute.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\n \"https://internal/views/provisioning-wizard/index.html\",\n ),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Provisioning wizard unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://esim-provisioning-wizard\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n _meta: { ui: {} },\n },\n ],\n };\n },\n );\n\n // ── Tool ───────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"provision_esim_wizard\",\n {\n title: \"eSIM Provisioning Wizard\",\n description:\n \"Interactive 3-step wizard to provision an eSIM: select subscriber, choose package template, preview (dry_run) and confirm execution.\",\n inputSchema: {\n step: z\n .enum([\"init\", \"select-package\", \"preview\", \"confirm\"])\n .describe(\"Current wizard step\"),\n wizardId: z\n .string()\n .optional()\n .describe(\"Wizard session ID (absent on init)\"),\n subscriber_iccid: z\n .string()\n .optional()\n .describe(\"Subscriber ICCID (required for select-package)\"),\n package_template_id: z\n .number()\n .optional()\n .describe(\"Package template ID (required for preview)\"),\n },\n _meta: {\n ui: {\n resourceUri: \"ui://esim-provisioning-wizard\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n async ({ step, wizardId, subscriber_iccid, package_template_id }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n // ── init ────────────────────────────────────────────────────────────────\n if (step === \"init\") {\n const newWizardId = generateWizardId();\n const subscribersResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listResellerAccount\",\n {},\n );\n\n const session = {\n step: \"select-subscriber\" as const,\n dry_run: false,\n initiated_at: new Date().toISOString(),\n };\n await saveWizardSession(\n ctx.env,\n ctx.props.sub,\n newWizardId,\n session,\n );\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Wizard started (id: ${newWizardId}). Select a subscriber to provision.`,\n },\n ],\n structuredContent: {\n wizardId: newWizardId,\n step: \"select-subscriber\",\n subscribers: subscribersResult.data ?? [],\n error: subscribersResult.error,\n },\n };\n }\n\n // All subsequent steps require a wizardId\n if (!wizardId) {\n return {\n content: [{ type: \"text\" as const, text: \"Missing wizardId.\" }],\n isError: true,\n };\n }\n\n // ── select-package ──────────────────────────────────────────────────────\n if (step === \"select-package\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"select-subscriber\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected select-subscriber, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n if (!subscriber_iccid) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"subscriber_iccid is required for select-package step.\",\n },\n ],\n isError: true,\n };\n }\n\n // OCS method is listPrepaidPackageTemplate; requires resellerId param.\n const resellerIdForTemplates = await getDefaultResellerId(ctx.env, token);\n const packagesResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listPrepaidPackageTemplate\",\n { resellerId: resellerIdForTemplates },\n );\n\n const updated = {\n ...session,\n step: \"select-package\" as const,\n subscriber_iccid,\n };\n await saveWizardSession(ctx.env, ctx.props.sub, wizardId, updated);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Subscriber ${subscriber_iccid} selected. Choose a package template.`,\n },\n ],\n structuredContent: {\n wizardId,\n step: \"select-package\",\n subscriber_iccid,\n packages: packagesResult.data ?? [],\n error: packagesResult.error,\n },\n };\n }\n\n // ── preview ─────────────────────────────────────────────────────────────\n if (step === \"preview\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"select-package\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected select-package, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n if (package_template_id === undefined) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"package_template_id is required for preview step.\",\n },\n ],\n isError: true,\n };\n }\n\n // Fix #19: modifyAccountPackage does not exist in OCS v1.\n // Preview step fetches the package template details (read-only) to show\n // the operator what will be assigned before confirm executes the real call.\n const previewResult = await safeCallWithToken<unknown[]>(\n client,\n token,\n \"listPrepaidPackageTemplate\",\n {},\n );\n\n const list = previewResult.data;\n let preview: unknown = null;\n if (Array.isArray(list)) {\n preview =\n list.find((item) => {\n if (!item || typeof item !== \"object\") return false;\n const rec = item as Record<string, unknown>;\n const tid = rec.templateId ?? rec.packageTemplateId;\n return Number(tid) === package_template_id;\n }) ?? null;\n } else if (list && typeof list === \"object\") {\n const rec = list as Record<string, unknown>;\n const tid = rec.templateId ?? rec.packageTemplateId;\n if (Number(tid) === package_template_id) preview = list;\n }\n\n const updated = {\n ...session,\n step: \"confirm\" as const,\n package_template_id,\n dry_run: true,\n };\n await saveWizardSession(ctx.env, ctx.props.sub, wizardId, updated);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Preview ready. Review changes and confirm to proceed.`,\n },\n ],\n structuredContent: {\n wizardId,\n step: \"confirm\",\n subscriber_iccid: session.subscriber_iccid,\n package_template_id,\n preview,\n previewError: previewResult.error,\n },\n };\n }\n\n // ── confirm ─────────────────────────────────────────────────────────────\n if (step === \"confirm\") {\n const session = await loadWizardSession(\n ctx.env,\n ctx.props.sub,\n wizardId,\n );\n if (!session) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"Wizard session not found or expired.\",\n },\n ],\n isError: true,\n };\n }\n if (session.step !== \"confirm\") {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Invalid step transition: expected confirm, got ${session.step}.`,\n },\n ],\n isError: true,\n };\n }\n\n // Fix #19: modifyAccountPackage does not exist in OCS v1. The correct method\n // for provisioning a package is affectPackageToSubscriber, which expects an\n // integer subscriberId (not ICCID string). Resolve via getSingleSubscriber first.\n const subRecord = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"getSingleSubscriber\",\n { iccid: session.subscriber_iccid },\n );\n if (subRecord.error || !subRecord.data) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: could not resolve subscriber for ICCID ${session.subscriber_iccid}: ${subRecord.error ?? \"empty response\"}`,\n },\n ],\n isError: true,\n };\n }\n const subscriberId = subRecord.data.id ?? subRecord.data.subscriberId;\n if (subscriberId === undefined) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: getSingleSubscriber returned no id for ICCID ${session.subscriber_iccid}`,\n },\n ],\n isError: true,\n };\n }\n const result = await safeCallWithToken(\n client,\n token,\n \"affectPackageToSubscriber\",\n {\n subscriber: Number(subscriberId),\n packageTemplateId: session.package_template_id,\n },\n );\n\n await deleteWizardSession(ctx.env, ctx.props.sub, wizardId);\n\n if (result.error) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Provisioning failed: ${result.error}`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\" as const, text: \"Provisioned.\" }],\n structuredContent: {\n wizardId,\n step: \"done\",\n result: result.data,\n },\n };\n }\n\n return {\n content: [{ type: \"text\" as const, text: `Unknown step: ${step as string}.` }],\n isError: true,\n };\n },\n );\n}\n","/**\n * v1.2b — Wizard Session KV helpers\n *\n * Stores ephemeral 3-step wizard state in CARRIER_USERS KV.\n * Key pattern: app-session:<sub>:<wizardId>\n * TTL: 600 seconds (10 minutes).\n */\n\nimport type { Env } from \"../types.js\";\n\nexport interface WizardSession {\n step: \"select-subscriber\" | \"select-package\" | \"confirm\";\n subscriber_iccid?: string;\n package_template_id?: number;\n dry_run: boolean;\n initiated_at: string;\n}\n\nfunction sessionKey(sub: string, wizardId: string): string {\n return `app-session:${sub}:${wizardId}`;\n}\n\n// In-memory fallback for stdio mode (no KV available).\n// Keys auto-expire after 600s to mirror KV TTL behavior.\nconst inMemorySessions = new Map<string, { session: WizardSession; expiresAt: number }>();\n\nfunction pruneExpired(): void {\n const now = Date.now();\n for (const [key, val] of inMemorySessions.entries()) {\n if (val.expiresAt < now) inMemorySessions.delete(key);\n }\n}\n\nexport async function loadWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n): Promise<WizardSession | null> {\n const key = sessionKey(sub, wizardId);\n if (!env.CARRIER_USERS) {\n pruneExpired();\n return inMemorySessions.get(key)?.session ?? null;\n }\n const raw = await env.CARRIER_USERS.get(key);\n if (!raw) return null;\n try {\n return JSON.parse(raw) as WizardSession;\n } catch {\n return null;\n }\n}\n\nexport async function saveWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n session: WizardSession,\n): Promise<void> {\n const key = sessionKey(sub, wizardId);\n if (!env.CARRIER_USERS) {\n inMemorySessions.set(key, { session, expiresAt: Date.now() + 600_000 });\n return;\n }\n await env.CARRIER_USERS.put(key, JSON.stringify(session), { expirationTtl: 600 });\n}\n\nexport async function deleteWizardSession(\n env: Env,\n sub: string,\n wizardId: string,\n): Promise<void> {\n const key = sessionKey(sub, wizardId);\n if (!env.CARRIER_USERS) {\n inMemorySessions.delete(key);\n return;\n }\n await env.CARRIER_USERS.delete(key);\n}\n","/**\n * v1.2d — Balance Top-up Form MCP App\n *\n * Enterprise-only inline form for adjusting account balances via\n * `modify_account_balance`. Supports preview-only mode before committing.\n * Scoped to `admin` — pairs with MFA gate from PR #46.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport {\n registerAppTool,\n registerAppResource,\n RESOURCE_MIME_TYPE,\n} from \"@modelcontextprotocol/ext-apps/server\";\nimport { OcsClient } from \"../client.js\";\nimport type { ToolContext } from \"../tools.js\";\nimport { wrapHandler, TOOL_SCOPES } from \"../tools.js\";\n\nasync function safeCallWithToken<T = Record<string, unknown>>(\n client: OcsClient,\n _token: string,\n method: string,\n params: Record<string, unknown> | number | string = {},\n): Promise<{ data: T | null; error: string | null }> {\n try {\n return { data: await client.call<T>(method, params), error: null };\n } catch (err) {\n return {\n data: null,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nexport interface BalanceTopupStructuredContent {\n iccid: string;\n delta: number;\n current_balance?: number;\n new_balance?: number;\n preview: boolean;\n success?: boolean;\n}\n\nexport function registerBalanceTopupApp(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // Tier guard — enterprise only\n if (ctx.props.tier !== \"enterprise\") return;\n\n // ── Resource ─────────────────────────────────────────────────────────────\n registerAppResource(\n server,\n \"Balance Top-up Form\",\n \"ui://balance-topup-form\",\n {\n description:\n \"Admin balance top-up form — enter an ICCID and delta amount to preview and commit account balance adjustments. Enterprise only. Requires recent MFA verification.\",\n },\n async () => {\n let html: string;\n try {\n const resp = await ctx.env.ASSETS.fetch(\n new Request(\"https://internal/views/balance-topup/index.html\"),\n );\n html = await resp.text();\n } catch {\n html = \"<html><body><p>Balance top-up form unavailable.</p></body></html>\";\n }\n return {\n contents: [\n {\n uri: \"ui://balance-topup-form\",\n mimeType: RESOURCE_MIME_TYPE,\n text: html,\n },\n ],\n };\n },\n );\n\n // ── Tool ─────────────────────────────────────────────────────────────────\n registerAppTool(\n server,\n \"balance_topup_form\",\n {\n title: \"Balance Top-up Form\",\n description:\n \"Enterprise admin tool: preview or commit an account balance adjustment. Set preview=true to fetch projection (no OCS write); preview=false (default) to execute. Requires admin scope + recent MFA.\",\n inputSchema: {\n iccid: z.string().describe(\"The subscriber ICCID for the account lookup\"),\n delta: z\n .number()\n .describe(\"Amount to add (positive) or deduct (negative) from the account balance\"),\n preview: z\n .boolean()\n .default(true)\n .describe(\"If true, return preview without writing. If false, execute the balance change.\"),\n },\n annotations: { destructiveHint: true },\n _meta: {\n ui: {\n resourceUri: \"ui://balance-topup-form\",\n visibility: [\"model\", \"app\"] as [\"model\", \"app\"],\n },\n },\n },\n wrapHandler(\n \"modify_account_balance\",\n \"modifyAccountBalance\",\n TOOL_SCOPES[\"modify_account_balance\"]!,\n ctx,\n async ({ iccid, delta, preview }: { iccid: string; delta: number; preview?: boolean }) => {\n const token = await ctx.getUserToken(ctx.props.sub);\n const client = new OcsClient(ctx.env.CARRIER_OCS_BASE_URL, token);\n\n if (preview === true) {\n // Preview path — fetch current subscriber balance, return projection\n const result = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"getSingleSubscriber\",\n { iccid },\n );\n\n const currentBalance = result.data\n ? Number(result.data[\"balance\"] ?? result.data[\"accountBalance\"] ?? 0)\n : 0;\n const newBalance = currentBalance + delta;\n\n const structured: BalanceTopupStructuredContent = {\n iccid,\n delta,\n current_balance: currentBalance,\n new_balance: newBalance,\n preview: true,\n };\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `[Preview] ICCID: ${iccid} | Current balance: ${currentBalance} | Delta: ${delta >= 0 ? \"+\" : \"\"}${delta} | New balance: ${newBalance}. No changes made.`,\n },\n ],\n structuredContent: structured,\n };\n }\n\n // Execute path — call modify_account_balance via OCS\n const execResult = await safeCallWithToken<Record<string, unknown>>(\n client,\n token,\n \"modifyAccountBalance\",\n { subscriber: iccid, adaptBalance: delta },\n );\n\n if (execResult.error) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: `Error: ${execResult.error}` }],\n };\n }\n\n const newBalance = execResult.data\n ? Number(execResult.data[\"balance\"] ?? execResult.data[\"newBalance\"] ?? 0)\n : delta;\n\n const structured: BalanceTopupStructuredContent = {\n iccid,\n delta,\n new_balance: newBalance,\n preview: false,\n success: true,\n };\n\n return {\n content: [{ type: \"text\" as const, text: \"Balance updated.\" }],\n structuredContent: structured,\n };\n },\n ),\n );\n}\n","/**\n * MCP Apps barrel — v1.2+\n *\n * Registers all UI-enabled tools and `ui://` HTML resources on every session.\n * Tools carry `_meta.ui.resourceUri` per the MCP Apps spec; MCP-Apps-capable\n * clients (Claude Desktop, Claude.ai with MCP Apps support) render the\n * associated `ui://` resource as a sandboxed iframe. Clients that don't\n * speak MCP Apps simply ignore the `_meta.ui` metadata and call the tool\n * as a normal tool with structured output.\n *\n * Per-app tier gates live INSIDE each register*() function. The previous\n * version of this barrel gated the whole registration block on\n * `getUiCapability` from the client's `initialize` capabilities — that\n * was overly aggressive and hid the tools from clients (including\n * Claude Code) that don't yet advertise `io.modelcontextprotocol/ui`\n * but can still execute structured-output tools.\n *\n * Sub-phase ownership:\n * v1.2a — fleet-health-app\n * v1.2b — provisioning-wizard\n * v1.2d — balance-topup-form\n */\n\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"../tools.js\";\nimport { registerFleetHealthApp } from \"./fleet-health-app.js\";\nimport { registerProvisioningWizard } from \"./provisioning-wizard.js\";\nimport { registerBalanceTopupApp } from \"./balance-topup.js\";\n\nexport {\n registerFleetHealthApp,\n registerProvisioningWizard,\n registerBalanceTopupApp,\n};\n\n/**\n * Register all MCP App tools and resources.\n *\n * Always registers unconditionally — tier gates are enforced inside each\n * register*() function. MCP-Apps-capable clients render the iframes;\n * other clients see the tools as normal structured-output tools.\n */\nexport function registerAllApps(server: McpServer, ctx: ToolContext): void {\n // v1.2a — Fleet Health Dashboard (free+, read scope)\n registerFleetHealthApp(server, ctx);\n\n // v1.2b — eSIM Provisioning Wizard (pro+, write scope; tier-gated internally)\n registerProvisioningWizard(server, ctx);\n\n // v1.2d — Balance Top-up Form (enterprise only, admin scope; tier-gated internally)\n registerBalanceTopupApp(server, ctx);\n}\n","import { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\n\n/**\n * Carrier MCP business prompts (5).\n * Renamed from registerPrompts → registerAllPrompts for consistency.\n */\nexport function registerAllPrompts(server: McpServer): void {\n server.registerPrompt(\n \"fleet_health_report\",\n {\n title: \"Fleet Health Report\",\n description:\n \"Generate a comprehensive fleet health report: account balances, eSIM status breakdown, low-balance alerts, and utilization rates.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier fleet analyst. Generate a health report by:\n\n1. Call list_reseller_accounts to get all accounts and their balances\n2. Call esim_status_per_account for each account to get SIM status breakdowns\n3. Analyze and present:\n - Total eSIMs by status (active, suspended, inventory)\n - Utilization rate (active / total provisioned)\n - Accounts with low balance (< $50) — flag as urgent\n - Accounts with high inactive SIM ratio — flag for cleanup\n - Top accounts by active SIM count\n\nFormat as a structured report with sections, tables, and actionable recommendations.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"subscriber_deep_dive\",\n {\n title: \"Subscriber Deep Dive\",\n description:\n \"Comprehensive analysis of a single subscriber: profile, packages, usage patterns, location history, recommendations.\",\n argsSchema: { iccid: z.string().describe(\"The subscriber ICCID to analyse\") },\n },\n async ({ iccid }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier customer success analyst. Deep-dive into subscriber ${iccid}:\n\n1. Call get_subscriber with ICCID \"${iccid}\" for profile details\n2. Call list_subscriber_packages for their active/expired packages\n3. Call subscriber_usage for the last 7 days to see usage patterns\n4. Call subscriber_network_events for the last 7 days for connectivity\n5. Call get_subscriber_location for current location\n\nAnalyze and present:\n- Subscriber profile summary (status, account, balance, contact)\n- Package utilization: % of data/voice/SMS used vs allowance\n- Usage trends: increasing/decreasing/stable\n- Roaming behavior: which countries/networks\n- Connectivity quality: attach/detach frequency\n- Actionable recommendations:\n - If usage > 80% of allowance → suggest upgrade\n - If usage < 20% → suggest downgrade to prevent churn\n - If frequent network switches → check steering list\n - If low balance → alert for top-up`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"revenue_optimization\",\n {\n title: \"Revenue Optimization Analysis\",\n description:\n \"Analyse accounts and subscribers to find revenue optimization opportunities: underutilized packages, upgrade candidates, churn risks.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier revenue optimization analyst. Find opportunities by:\n\n1. Call list_reseller_accounts for account overview\n2. Call list_package_templates to understand the product catalog\n3. Call get_tariff to understand the cost structure\n4. For top accounts, call list_subscribers and sample subscriber_usage\n\nAnalyze and present:\n- Package template analysis: which templates are most/least popular\n- Pricing gap analysis: cost vs retail price margins\n- Upgrade candidates: subscribers consistently hitting limits\n- Downgrade/churn risks: subscribers with declining usage\n- Geographic opportunities: high-usage zones with limited coverage\n- Recommendations ranked by estimated revenue impact`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"coverage_analysis\",\n {\n title: \"Coverage & Network Analysis\",\n description:\n \"Analyse network coverage, steering lists, and subscriber roaming patterns to optimise connectivity and reduce costs.\",\n },\n async () => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier network coverage analyst. Analyze the fleet's connectivity by:\n\n1. Call list_steering_lists to see network steering configurations\n2. Call list_detailed_location_zones for coverage zone definitions\n3. Call list_sponsors for available sponsor networks\n4. Call list_network_profiles for connectivity configs\n5. Sample subscriber_network_events for active subscribers\n\nAnalyze and present:\n- Coverage map: which zones/countries are covered\n- Steering list effectiveness: are subs connecting to preferred networks?\n- Roaming cost hotspots: countries with high roaming fees\n- Network quality: attach/detach patterns by network\n- Recommendations for steering list optimization`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n \"bulk_operations_planner\",\n {\n title: \"Bulk Operations Planner\",\n description:\n \"Plan bulk operations safely: mass package assignments, account migrations, balance adjustments, or status changes.\",\n argsSchema: { operation: z.string().describe(\"Describe the bulk operation you want to perform\") },\n },\n async ({ operation }) => ({\n messages: [\n {\n role: \"user\",\n content: {\n type: \"text\",\n text: `You are a Carrier operations planner. The user wants to perform this bulk operation:\n\n\"${operation}\"\n\nCreate a safe execution plan:\n1. First, use read-only tools to understand the current state\n2. Identify all affected subscribers/accounts\n3. Estimate the impact (cost, service disruption, reversibility)\n4. Generate a step-by-step plan with:\n - Pre-flight checks\n - Execution order (smallest batch first as canary)\n - Rollback procedure for each step\n - Post-execution verification\n5. List all destructive tool calls that will be needed\n6. Ask for explicit confirmation before any destructive action\n\nNEVER execute destructive operations without confirmation.`,\n },\n },\n ],\n }),\n );\n}\n","/**\n * Carrier MCP — Pricing & Projects Tool Registration\n *\n * Registers 10 new MCP tools:\n * - 5 pricing/billing management tools (credit_balance, configure_billing, etc.)\n * - 5 projects/service management tools (service_catalog, credential_status, etc.)\n *\n * These tools follow the same wrapHandler pattern as OCS tools but skip\n * OCS token resolution (they operate on billing/config data only).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport { checkCallQuota, recordUsage, UPGRADE_URL } from \"./billing.js\";\nimport { PRICING_TOOLS } from \"./pricing-tools.js\";\nimport { PROJECTS_TOOLS } from \"./projects-tools.js\";\nimport { checkCredits, deductCredits } from \"./credits.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\n/**\n * Register all pricing and projects tools on the MCP server.\n * Called from agent.ts init() alongside other tool registrations.\n */\nexport function registerAllPricingTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n const allTools = [...PRICING_TOOLS, ...PROJECTS_TOOLS];\n\n for (const tool of allTools) {\n server.registerTool(\n tool.name,\n {\n title: toolNameToTitle(tool.name),\n description: tool.description,\n inputSchema: buildZodSchema(tool.inputSchema),\n annotations: {\n readOnlyHint: tool.scope === \"read\",\n ...(tool.scope !== \"read\" ? { destructiveHint: false } : {}),\n },\n },\n buildPricingHandler(tool, ctx),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Handler Builder\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nfunction buildPricingHandler(\n tool: (typeof PRICING_TOOLS)[number] | (typeof PROJECTS_TOOLS)[number],\n ctx: ToolContext,\n) {\n return async (args: Record<string, unknown>): Promise<ToolResult> => {\n const start = Date.now();\n\n // Scope enforcement\n if (!ctx.props.scope.includes(tool.scope as \"read\" | \"write\" | \"admin\")) {\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Scope denied: tool '${tool.name}' requires '${tool.scope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Credit check (v2.0 system — runs in parallel with legacy quota check)\n const tier = ctx.props.tier as Tier;\n const creditResult = await checkCredits(ctx.env, ctx.props.sub, tier, tool.scope as \"read\" | \"write\" | \"admin\");\n\n if (!creditResult.allowed) {\n // Fall back to legacy quota check\n const quota = await checkCallQuota(ctx.env, ctx.props.sub, tier);\n if (!quota.allowed) {\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"quota_exceeded\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Credit limit reached. Remaining: ${creditResult.credits_remaining} credits. Resets ${creditResult.reset_at}. Upgrade at ${UPGRADE_URL}`,\n },\n ],\n };\n }\n }\n\n // Execute handler\n try {\n const result = await tool.handler(ctx.env, ctx.props, args);\n\n // Record usage (both systems)\n recordUsage(ctx.env, ctx.props.sub, tier);\n deductCredits(ctx.env, ctx.props.sub, tier, tool.scope as \"read\" | \"write\" | \"admin\");\n\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(result, null, 2),\n },\n ],\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n ctx.audit({\n tool_name: tool.name,\n ocs_method: \"billing\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n return {\n isError: true,\n content: [{ type: \"text\", text: `Error: ${message}` }],\n };\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction toolNameToTitle(name: string): string {\n return name\n .split(\"_\")\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(\" \");\n}\n\n/**\n * Build a zod schema from the JSON Schema-like inputSchema definition.\n * Supports: string, number, boolean, array of numbers.\n */\nfunction buildZodSchema(\n schema: Record<string, unknown>,\n): Record<string, z.ZodTypeAny> {\n const properties = (schema.properties ?? {}) as Record<\n string,\n { type?: string; description?: string; enum?: string[]; items?: { type?: string } }\n >;\n const result: Record<string, z.ZodTypeAny> = {};\n\n for (const [key, prop] of Object.entries(properties)) {\n let field: z.ZodTypeAny;\n\n if (prop.enum) {\n field = z.enum(prop.enum as [string, ...string[]]);\n } else if (prop.type === \"number\") {\n field = z.number();\n } else if (prop.type === \"boolean\") {\n field = z.boolean();\n } else if (prop.type === \"array\") {\n if (prop.items?.type === \"number\") {\n field = z.array(z.number());\n } else {\n field = z.array(z.string());\n }\n } else {\n field = z.string();\n }\n\n // All pricing tool params are optional (no required fields in most cases)\n const required = (schema.required as string[] | undefined) ?? [];\n if (!required.includes(key)) {\n field = field.optional();\n }\n\n if (prop.description) {\n field = field.describe(prop.description);\n }\n\n result[key] = field;\n }\n\n return result;\n}\n","/**\n * Carrier MCP — Credits System v2.0 (Pricing Evolution)\n *\n * Implements credit-based billing inspired by Stripe's Pricing Model Evolution Guide:\n * - Monthly credit allotments per tier (Lovable pattern)\n * - Auto-billed overages when base credits exhausted (Warp pattern)\n * - Credit rollovers for irregular usage (Lovable pattern)\n * - Daily free credits for acquisition (Browserbase/Lovable pattern)\n * - Billing thresholds to prevent bill shock (Hex pattern)\n * - Volume discounts for high-usage customers\n *\n * Storage layout (CARRIER_USERS KV):\n * key: credits:<sub>:<yyyymm> value: CreditLedger\n * key: credits:daily:<sub>:<yyyymmdd> value: DailyFreeCredits\n * key: credits:config:<sub> value: CreditConfig (overrides, thresholds)\n * key: credits:rollover:<sub> value: RolloverBalance\n *\n * Credit economy:\n * 1 tool call = 1 credit (read scope)\n * 1 tool call = 2 credits (write scope)\n * 1 tool call = 5 credits (admin scope)\n * Intelligence composites = 3 credits each\n *\n * Stripe integration:\n * - Overages reported via Stripe Metered Billing (usage_records API)\n * - Billing thresholds trigger Stripe invoice finalization\n * - Credit grants created via Stripe Customer Balance Transactions\n */\n\nimport type { Env } from \"./types.js\";\nimport type { Tier, ScopeToken } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Credit Constants\n// ---------------------------------------------------------------------------\n\n/** Monthly credit allotments per tier */\nexport const TIER_CREDIT_ALLOTMENTS: Record<Tier, number> = {\n free: 5_000,\n pro: 100_000,\n enterprise: Infinity,\n};\n\n/** Daily free credits for all users (acquisition driver) */\nexport const DAILY_FREE_CREDITS = 50;\n\n/** Maximum rollover credits (cap at 2x monthly allotment) */\nexport const ROLLOVER_CAP_MULTIPLIER = 2;\n\n/** Credit cost per scope */\nexport const SCOPE_CREDIT_COSTS: Record<ScopeToken | \"intelligence\", number> = {\n read: 1,\n write: 2,\n admin: 5,\n intelligence: 3,\n};\n\n/** Volume discount tiers (cumulative monthly usage) */\nexport const VOLUME_DISCOUNTS: VolumeDiscountTier[] = [\n { threshold: 50_000, discountPct: 0 },\n { threshold: 100_000, discountPct: 10 },\n { threshold: 250_000, discountPct: 15 },\n { threshold: 500_000, discountPct: 20 },\n { threshold: 1_000_000, discountPct: 25 },\n];\n\n/** Default billing threshold (in cents) — triggers invoice at this spend level */\nexport const DEFAULT_BILLING_THRESHOLD_CENTS = 10_000; // $100\n\n/** Overage price per credit (in cents) — Pro tier */\nexport const OVERAGE_PRICE_PER_CREDIT_CENTS = 0.1; // $0.001 per credit\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface VolumeDiscountTier {\n threshold: number;\n discountPct: number;\n}\n\nexport interface CreditLedger {\n /** Monthly allotment (base + rollover) */\n allotment: number;\n /** Credits consumed this period */\n consumed: number;\n /** Credits from rollovers applied this month */\n rollover_applied: number;\n /** Overage credits consumed beyond allotment */\n overage: number;\n /** Overage amount billed (cents) */\n overage_billed_cents: number;\n /** Whether billing threshold was hit this period */\n threshold_triggered: boolean;\n /** ISO 8601 last updated */\n updated_at: string;\n}\n\nexport interface DailyFreeCredits {\n /** Credits granted today */\n granted: number;\n /** Credits consumed from daily free pool */\n consumed: number;\n /** ISO date (YYYY-MM-DD) */\n date: string;\n}\n\nexport interface CreditConfig {\n /** Custom billing threshold override (cents) */\n billing_threshold_cents: number;\n /** Whether overages are enabled (Pro+) */\n overages_enabled: boolean;\n /** Whether rollovers are enabled (Pro+) */\n rollovers_enabled: boolean;\n /** Custom overage rate override (cents per credit) */\n overage_rate_cents: number;\n /** Volume discount tier override */\n volume_discount_pct: number;\n /** Notification preferences */\n notify_at_pct: number[]; // e.g., [50, 80, 95, 100]\n updated_at: string;\n}\n\nexport interface RolloverBalance {\n /** Unused credits from previous month eligible for rollover */\n credits: number;\n /** Source month (YYYYMM) */\n source_month: string;\n /** Expiry — rollovers expire after 1 month */\n expires_at: string;\n}\n\nexport interface CreditCheckResult {\n allowed: boolean;\n credits_remaining: number;\n daily_free_remaining: number;\n overage_active: boolean;\n overage_amount_cents: number;\n threshold_pct: number;\n tier: Tier;\n volume_discount_pct: number;\n reset_at: string;\n}\n\nexport interface CreditDeductionResult {\n success: boolean;\n credits_deducted: number;\n source: \"allotment\" | \"daily_free\" | \"overage\";\n new_balance: number;\n overage_triggered: boolean;\n threshold_triggered: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Credit Check\n// ---------------------------------------------------------------------------\n\n/**\n * Check if a user has sufficient credits for a tool call.\n * Order of credit consumption:\n * 1. Daily free credits (if available)\n * 2. Monthly allotment (base + rollover)\n * 3. Overage (if enabled for tier)\n */\nexport async function checkCredits(\n env: Env,\n sub: string,\n tier: Tier,\n scope: ScopeToken | \"intelligence\",\n): Promise<CreditCheckResult> {\n const cost = SCOPE_CREDIT_COSTS[scope];\n const month = currentMonth();\n const today = currentDay();\n const resetAt = firstDayNextMonth();\n\n // Enterprise always allowed\n if (tier === \"enterprise\") {\n return {\n allowed: true,\n credits_remaining: Infinity,\n daily_free_remaining: Infinity,\n overage_active: false,\n overage_amount_cents: 0,\n threshold_pct: 0,\n tier,\n volume_discount_pct: 0,\n reset_at: resetAt,\n };\n }\n\n // Load ledger\n const ledger = await getLedger(env, sub, month, tier);\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const config = await getCreditConfig(env, sub, tier);\n\n // Calculate remaining\n const monthlyRemaining = Math.max(0, ledger.allotment - ledger.consumed);\n const dailyFreeRemaining = Math.max(0, dailyFree.granted - dailyFree.consumed);\n const totalRemaining = dailyFreeRemaining + monthlyRemaining;\n\n // Check if allowed\n const overageEnabled = config.overages_enabled && tier !== \"free\";\n const allowed = totalRemaining >= cost || overageEnabled;\n\n // Volume discount\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n\n // Threshold percentage\n const thresholdPct = config.billing_threshold_cents > 0\n ? Math.round((ledger.overage_billed_cents / config.billing_threshold_cents) * 100)\n : 0;\n\n return {\n allowed,\n credits_remaining: monthlyRemaining,\n daily_free_remaining: dailyFreeRemaining,\n overage_active: monthlyRemaining < cost && dailyFreeRemaining < cost && overageEnabled,\n overage_amount_cents: ledger.overage_billed_cents,\n threshold_pct: thresholdPct,\n tier,\n volume_discount_pct: volumeDiscount,\n reset_at: resetAt,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Credit Deduction\n// ---------------------------------------------------------------------------\n\n/**\n * Deduct credits for a tool call. Fire-and-forget in the hot path.\n *\n * Consumption order:\n * 1. Daily free credits first (lowest cost to user)\n * 2. Monthly allotment\n * 3. Overage (auto-billed, Pro+ only)\n */\nexport function deductCredits(\n env: Env,\n sub: string,\n tier: Tier,\n scope: ScopeToken | \"intelligence\",\n): void {\n void (async () => {\n const cost = SCOPE_CREDIT_COSTS[scope];\n const month = currentMonth();\n const today = currentDay();\n\n // Enterprise — no deduction needed\n if (tier === \"enterprise\") return;\n\n // Try daily free credits first\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const dailyRemaining = dailyFree.granted - dailyFree.consumed;\n\n if (dailyRemaining >= cost) {\n // Deduct from daily free pool\n await putDailyFreeCredits(env, sub, today, {\n ...dailyFree,\n consumed: dailyFree.consumed + cost,\n });\n return;\n }\n\n // Deduct from monthly allotment\n const ledger = await getLedger(env, sub, month, tier);\n const monthlyRemaining = ledger.allotment - ledger.consumed;\n\n if (monthlyRemaining >= cost) {\n await putLedger(env, sub, month, {\n ...ledger,\n consumed: ledger.consumed + cost,\n updated_at: new Date().toISOString(),\n });\n return;\n }\n\n // Overage path (Pro+ only)\n const config = await getCreditConfig(env, sub, tier);\n if (!config.overages_enabled || tier === \"free\") return;\n\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n const effectiveRate = OVERAGE_PRICE_PER_CREDIT_CENTS * (1 - volumeDiscount / 100);\n const overageCostCents = Math.round(cost * effectiveRate * 100) / 100;\n\n const updatedLedger: CreditLedger = {\n ...ledger,\n consumed: ledger.consumed + cost,\n overage: ledger.overage + cost,\n overage_billed_cents: ledger.overage_billed_cents + overageCostCents,\n updated_at: new Date().toISOString(),\n };\n\n // Check billing threshold\n if (\n !ledger.threshold_triggered &&\n updatedLedger.overage_billed_cents >= config.billing_threshold_cents\n ) {\n updatedLedger.threshold_triggered = true;\n // Trigger Stripe invoice finalization (async, non-blocking)\n void triggerBillingThreshold(env, sub, updatedLedger.overage_billed_cents);\n }\n\n await putLedger(env, sub, month, updatedLedger);\n\n // Push overage to Stripe at every 100-credit boundary\n if (updatedLedger.overage % 100 === 0) {\n void pushOverageToStripe(env, sub, 100, effectiveRate).catch(() => {});\n }\n })();\n}\n\n// ---------------------------------------------------------------------------\n// Credit Grant (Rollover)\n// ---------------------------------------------------------------------------\n\n/**\n * Calculate and apply rollover credits from previous month.\n * Called by the monthly cron job (scheduled handler).\n *\n * Rules:\n * - Only Pro+ tiers get rollovers\n * - Rollover = min(unused credits, allotment * ROLLOVER_CAP_MULTIPLIER)\n * - Rollovers expire after 1 month (use-it-or-lose-it next cycle)\n */\nexport async function applyMonthlyRollover(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<RolloverBalance | null> {\n if (tier === \"free\") return null;\n\n const prevMonth = previousMonth();\n const prevLedger = await getLedger(env, sub, prevMonth, tier);\n\n const unused = Math.max(0, prevLedger.allotment - prevLedger.consumed);\n if (unused === 0) return null;\n\n const maxRollover = TIER_CREDIT_ALLOTMENTS[tier] * ROLLOVER_CAP_MULTIPLIER;\n const rolloverAmount = Math.min(unused, maxRollover);\n\n const rollover: RolloverBalance = {\n credits: rolloverAmount,\n source_month: prevMonth,\n expires_at: firstDayMonthAfterNext(),\n };\n\n await env.CARRIER_USERS.put(\n `credits:rollover:${sub}`,\n JSON.stringify(rollover),\n { expirationTtl: 62 * 24 * 60 * 60 }, // ~2 months\n );\n\n // Apply to current month's ledger\n const currentMo = currentMonth();\n const currentLedger = await getLedger(env, sub, currentMo, tier);\n await putLedger(env, sub, currentMo, {\n ...currentLedger,\n allotment: currentLedger.allotment + rolloverAmount,\n rollover_applied: rolloverAmount,\n updated_at: new Date().toISOString(),\n });\n\n return rollover;\n}\n\n// ---------------------------------------------------------------------------\n// Volume Discounts\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the applicable volume discount percentage based on cumulative usage.\n */\nexport function resolveVolumeDiscount(consumed: number): number {\n let discount = 0;\n for (const tier of VOLUME_DISCOUNTS) {\n if (consumed >= tier.threshold) {\n discount = tier.discountPct;\n } else {\n break;\n }\n }\n return discount;\n}\n\n// ---------------------------------------------------------------------------\n// Billing Threshold\n// ---------------------------------------------------------------------------\n\n/**\n * Trigger billing threshold — creates a Stripe invoice for accumulated overages.\n * Prevents bill shock by invoicing incrementally (Hex pattern).\n */\nasync function triggerBillingThreshold(\n env: Env,\n sub: string,\n amountCents: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return;\n\n // Create an invoice item for the threshold amount\n const body = new URLSearchParams({\n customer: customerId,\n amount: String(Math.round(amountCents)),\n currency: \"usd\",\n description: `Carrier MCP overage credits (threshold reached)`,\n });\n\n const resp = await fetch(\"https://api.stripe.com/v1/invoiceitems\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!resp.ok) return;\n\n // Create and finalize the invoice\n const invoiceBody = new URLSearchParams({\n customer: customerId,\n auto_advance: \"true\", // Auto-finalize and attempt payment\n \"collection_method\": \"charge_automatically\",\n description: \"Carrier MCP — Overage billing threshold invoice\",\n });\n\n await fetch(\"https://api.stripe.com/v1/invoices\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: invoiceBody.toString(),\n });\n}\n\n/**\n * Push overage usage records to Stripe Metered Billing.\n */\nasync function pushOverageToStripe(\n env: Env,\n sub: string,\n quantity: number,\n ratePerCredit: number,\n): Promise<void> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return;\n\n const subItemId = await env.CARRIER_USERS.get(`stripe_sub_item_id:${sub}`);\n if (!subItemId) return;\n\n const body = new URLSearchParams({\n quantity: String(quantity),\n timestamp: String(Math.floor(Date.now() / 1000)),\n action: \"increment\",\n });\n\n await fetch(\n `https://api.stripe.com/v1/subscription_items/${subItemId}/usage_records`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n // Store rate for reconciliation\n await env.CARRIER_USERS.put(\n `overage_rate:${sub}`,\n JSON.stringify({ rate_cents: ratePerCredit, updated_at: new Date().toISOString() }),\n { expirationTtl: 35 * 24 * 60 * 60 },\n );\n}\n\n// ---------------------------------------------------------------------------\n// KV Helpers\n// ---------------------------------------------------------------------------\n\nasync function getLedger(\n env: Env,\n sub: string,\n month: string,\n tier: Tier,\n): Promise<CreditLedger> {\n const key = `credits:${sub}:${month}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"allotment\" in raw) {\n return raw as CreditLedger;\n }\n // Initialize new ledger for the month\n const allotment = TIER_CREDIT_ALLOTMENTS[tier];\n return {\n allotment,\n consumed: 0,\n rollover_applied: 0,\n overage: 0,\n overage_billed_cents: 0,\n threshold_triggered: false,\n updated_at: new Date().toISOString(),\n };\n}\n\nasync function putLedger(\n env: Env,\n sub: string,\n month: string,\n ledger: CreditLedger,\n): Promise<void> {\n const key = `credits:${sub}:${month}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(ledger), {\n expirationTtl: 65 * 24 * 60 * 60, // ~2 months\n });\n}\n\nasync function getDailyFreeCredits(\n env: Env,\n sub: string,\n day: string,\n): Promise<DailyFreeCredits> {\n const key = `credits:daily:${sub}:${day}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"granted\" in raw) {\n return raw as DailyFreeCredits;\n }\n // Initialize daily free credits\n return {\n granted: DAILY_FREE_CREDITS,\n consumed: 0,\n date: day,\n };\n}\n\nasync function putDailyFreeCredits(\n env: Env,\n sub: string,\n day: string,\n credits: DailyFreeCredits,\n): Promise<void> {\n const key = `credits:daily:${sub}:${day}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(credits), {\n expirationTtl: 2 * 24 * 60 * 60, // 2 days\n });\n}\n\nasync function getCreditConfig(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<CreditConfig> {\n const key = `credits:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"billing_threshold_cents\" in raw) {\n return raw as CreditConfig;\n }\n // Default config\n return {\n billing_threshold_cents: DEFAULT_BILLING_THRESHOLD_CENTS,\n overages_enabled: tier !== \"free\",\n rollovers_enabled: tier !== \"free\",\n overage_rate_cents: OVERAGE_PRICE_PER_CREDIT_CENTS,\n volume_discount_pct: 0,\n notify_at_pct: [50, 80, 95, 100],\n updated_at: new Date().toISOString(),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Admin: Update Credit Config\n// ---------------------------------------------------------------------------\n\n/**\n * Update a user's credit configuration (admin or self-service).\n */\nexport async function updateCreditConfig(\n env: Env,\n sub: string,\n updates: Partial<CreditConfig>,\n): Promise<CreditConfig> {\n const tier = await resolveUserTier(env, sub);\n const current = await getCreditConfig(env, sub, tier);\n const updated: CreditConfig = {\n ...current,\n ...updates,\n updated_at: new Date().toISOString(),\n };\n const key = `credits:config:${sub}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(updated));\n return updated;\n}\n\n/**\n * Get credit usage summary for a user (used by billing UI).\n */\nexport async function getCreditSummary(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<{\n ledger: CreditLedger;\n daily_free: DailyFreeCredits;\n config: CreditConfig;\n rollover: RolloverBalance | null;\n volume_discount_pct: number;\n}> {\n const month = currentMonth();\n const today = currentDay();\n const ledger = await getLedger(env, sub, month, tier);\n const dailyFree = await getDailyFreeCredits(env, sub, today);\n const config = await getCreditConfig(env, sub, tier);\n const rolloverRaw = await env.CARRIER_USERS.get(\n `credits:rollover:${sub}`,\n \"json\",\n ).catch(() => null);\n const rollover = rolloverRaw as RolloverBalance | null;\n const volumeDiscount = resolveVolumeDiscount(ledger.consumed);\n\n return { ledger, daily_free: dailyFree, config, rollover, volume_discount_pct: volumeDiscount };\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Credit Grants\n// ---------------------------------------------------------------------------\n\n/**\n * Issue a credit grant to a customer via Stripe Customer Balance Transactions.\n * Used for promotional credits, referral bonuses, and compensation.\n */\nexport async function issueStripeCredits(\n env: Env,\n sub: string,\n amountCents: number,\n description: string,\n): Promise<boolean> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return false;\n\n const customerId = await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`);\n if (!customerId) return false;\n\n const body = new URLSearchParams({\n amount: String(-Math.abs(amountCents)), // Negative = credit to customer\n currency: \"usd\",\n description,\n });\n\n const resp = await fetch(\n `https://api.stripe.com/v1/customers/${customerId}/balance_transactions`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n return resp.ok;\n}\n\n// ---------------------------------------------------------------------------\n// Internal Helpers\n// ---------------------------------------------------------------------------\n\nasync function resolveUserTier(env: Env, sub: string): Promise<Tier> {\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"tier\" in raw) {\n const t = (raw as { tier: string }).tier;\n if (t === \"pro\" || t === \"enterprise\") return t;\n }\n return \"free\";\n}\n\nfunction currentMonth(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction currentDay(): string {\n const now = new Date();\n return `${now.getUTCFullYear()}${String(now.getUTCMonth() + 1).padStart(2, \"0\")}${String(now.getUTCDate()).padStart(2, \"0\")}`;\n}\n\nfunction previousMonth(): string {\n const now = new Date();\n const d = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() - 1, 1));\n return `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, \"0\")}`;\n}\n\nfunction firstDayNextMonth(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 1;\n if (m === 12) return new Date(Date.UTC(y + 1, 0, 1)).toISOString();\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n\nfunction firstDayMonthAfterNext(): string {\n const now = new Date();\n const y = now.getUTCFullYear();\n const m = now.getUTCMonth() + 2;\n if (m >= 12) return new Date(Date.UTC(y + 1, m - 12, 1)).toISOString();\n return new Date(Date.UTC(y, m, 1)).toISOString();\n}\n","/**\n * Carrier MCP — Billing Thresholds (Hex Pattern)\n *\n * Prevents bill shock by:\n * 1. Triggering invoices at predefined spend levels\n * 2. Sending notifications at configurable usage percentages\n * 3. Hard-stopping overages at a user-defined maximum\n *\n * Integrates with Stripe:\n * - Uses Stripe Billing Thresholds on subscriptions\n * - Creates threshold-triggered invoices for overage accumulation\n * - Sends webhook events for notification dispatch\n *\n * Reference: Hex case study — \"Mitigating the risk of bill shock\"\n * - Invoices trigger automatically at predefined amounts\n * - Acts as spend alerts, preventing unexpected charges\n */\n\nimport type { Env } from \"./types.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ThresholdConfig {\n /** Soft thresholds — trigger notifications (percentage of limit) */\n notification_thresholds: number[];\n /** Hard threshold — stop overages at this amount (cents). 0 = no hard cap */\n hard_cap_cents: number;\n /** Invoice threshold — trigger invoice at this overage amount (cents) */\n invoice_threshold_cents: number;\n /** Whether to auto-pause overages when hard cap is hit */\n auto_pause_on_cap: boolean;\n /** Email for threshold notifications */\n notification_email: string | null;\n /** Webhook URL for threshold events */\n webhook_url: string | null;\n}\n\nexport interface ThresholdEvent {\n type: \"notification\" | \"invoice_triggered\" | \"hard_cap_reached\" | \"overage_paused\";\n sub: string;\n tier: Tier;\n current_spend_cents: number;\n threshold_cents: number;\n pct_of_limit: number;\n timestamp: string;\n}\n\nexport interface ThresholdCheckResult {\n /** Whether the user can continue consuming overage credits */\n overage_allowed: boolean;\n /** Events triggered by this check */\n events: ThresholdEvent[];\n /** Current spend as percentage of hard cap (0 if no cap) */\n spend_pct: number;\n /** Remaining before hard cap (Infinity if no cap) */\n remaining_cents: number;\n}\n\n// ---------------------------------------------------------------------------\n// Default Configs\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_THRESHOLD_CONFIGS: Record<Tier, ThresholdConfig> = {\n free: {\n notification_thresholds: [80, 95, 100],\n hard_cap_cents: 0, // Free tier has no overages\n invoice_threshold_cents: 0,\n auto_pause_on_cap: true,\n notification_email: null,\n webhook_url: null,\n },\n pro: {\n notification_thresholds: [50, 75, 90, 100],\n hard_cap_cents: 50_000, // $500 hard cap default\n invoice_threshold_cents: 10_000, // Invoice every $100\n auto_pause_on_cap: false,\n notification_email: null,\n webhook_url: null,\n },\n enterprise: {\n notification_thresholds: [75, 90],\n hard_cap_cents: 0, // No cap for enterprise\n invoice_threshold_cents: 100_000, // Invoice every $1,000\n auto_pause_on_cap: false,\n notification_email: null,\n webhook_url: null,\n },\n};\n\n// ---------------------------------------------------------------------------\n// Core Functions\n// ---------------------------------------------------------------------------\n\n/**\n * Check billing thresholds before allowing overage consumption.\n * Returns whether overage is still allowed and any triggered events.\n */\nexport async function checkBillingThresholds(\n env: Env,\n sub: string,\n tier: Tier,\n currentSpendCents: number,\n additionalSpendCents: number,\n): Promise<ThresholdCheckResult> {\n const config = await getThresholdConfig(env, sub, tier);\n const events: ThresholdEvent[] = [];\n const projectedSpend = currentSpendCents + additionalSpendCents;\n\n // Check hard cap\n if (config.hard_cap_cents > 0 && projectedSpend >= config.hard_cap_cents) {\n events.push({\n type: \"hard_cap_reached\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.hard_cap_cents,\n pct_of_limit: 100,\n timestamp: new Date().toISOString(),\n });\n\n if (config.auto_pause_on_cap) {\n events.push({\n type: \"overage_paused\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.hard_cap_cents,\n pct_of_limit: 100,\n timestamp: new Date().toISOString(),\n });\n\n return {\n overage_allowed: false,\n events,\n spend_pct: 100,\n remaining_cents: 0,\n };\n }\n }\n\n // Check invoice threshold\n if (config.invoice_threshold_cents > 0) {\n const prevInvoiceCount = Math.floor(currentSpendCents / config.invoice_threshold_cents);\n const newInvoiceCount = Math.floor(projectedSpend / config.invoice_threshold_cents);\n\n if (newInvoiceCount > prevInvoiceCount) {\n events.push({\n type: \"invoice_triggered\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: config.invoice_threshold_cents * newInvoiceCount,\n pct_of_limit: config.hard_cap_cents > 0\n ? Math.round((projectedSpend / config.hard_cap_cents) * 100)\n : 0,\n timestamp: new Date().toISOString(),\n });\n }\n }\n\n // Check notification thresholds\n if (config.hard_cap_cents > 0) {\n for (const pct of config.notification_thresholds) {\n const thresholdAmount = Math.round((pct / 100) * config.hard_cap_cents);\n if (currentSpendCents < thresholdAmount && projectedSpend >= thresholdAmount) {\n events.push({\n type: \"notification\",\n sub,\n tier,\n current_spend_cents: projectedSpend,\n threshold_cents: thresholdAmount,\n pct_of_limit: pct,\n timestamp: new Date().toISOString(),\n });\n }\n }\n }\n\n // Dispatch events (fire-and-forget)\n if (events.length > 0) {\n void dispatchThresholdEvents(env, sub, events, config);\n }\n\n const spendPct = config.hard_cap_cents > 0\n ? Math.round((projectedSpend / config.hard_cap_cents) * 100)\n : 0;\n const remaining = config.hard_cap_cents > 0\n ? Math.max(0, config.hard_cap_cents - projectedSpend)\n : Infinity;\n\n return {\n overage_allowed: true,\n events,\n spend_pct: spendPct,\n remaining_cents: remaining,\n };\n}\n\n/**\n * Get threshold config for a user, with fallback to tier defaults.\n */\nexport async function getThresholdConfig(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<ThresholdConfig> {\n const key = `threshold:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"notification_thresholds\" in raw) {\n return raw as ThresholdConfig;\n }\n return DEFAULT_THRESHOLD_CONFIGS[tier];\n}\n\n/**\n * Update threshold config for a user.\n */\nexport async function updateThresholdConfig(\n env: Env,\n sub: string,\n updates: Partial<ThresholdConfig>,\n): Promise<ThresholdConfig> {\n const tier = await resolveUserTier(env, sub);\n const current = await getThresholdConfig(env, sub, tier);\n const updated: ThresholdConfig = { ...current, ...updates };\n const key = `threshold:config:${sub}`;\n await env.CARRIER_USERS.put(key, JSON.stringify(updated));\n return updated;\n}\n\n/**\n * Set up Stripe subscription billing thresholds.\n * Called when a user upgrades to Pro or changes their threshold config.\n */\nexport async function syncStripeThresholds(\n env: Env,\n sub: string,\n config: ThresholdConfig,\n): Promise<boolean> {\n const stripeKey = (env as Env & { STRIPE_SECRET_KEY?: string }).STRIPE_SECRET_KEY;\n if (!stripeKey) return false;\n\n const subscriptionId = await env.CARRIER_USERS.get(`stripe_subscription_id:${sub}`);\n if (!subscriptionId) return false;\n\n // Update Stripe subscription with billing thresholds\n const body = new URLSearchParams();\n\n if (config.invoice_threshold_cents > 0) {\n body.set(\n \"billing_thresholds[amount_gte]\",\n String(config.invoice_threshold_cents),\n );\n }\n\n const resp = await fetch(\n `https://api.stripe.com/v1/subscriptions/${subscriptionId}`,\n {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n },\n );\n\n return resp.ok;\n}\n\n// ---------------------------------------------------------------------------\n// Event Dispatch\n// ---------------------------------------------------------------------------\n\n/**\n * Dispatch threshold events to configured notification channels.\n */\nasync function dispatchThresholdEvents(\n env: Env,\n sub: string,\n events: ThresholdEvent[],\n config: ThresholdConfig,\n): Promise<void> {\n // Store events in KV for UI display\n const eventsKey = `threshold:events:${sub}`;\n const existingRaw = await env.CARRIER_USERS.get(eventsKey, \"json\").catch(() => null);\n const existing = Array.isArray(existingRaw) ? existingRaw as ThresholdEvent[] : [];\n const allEvents = [...existing, ...events].slice(-50); // Keep last 50 events\n await env.CARRIER_USERS.put(eventsKey, JSON.stringify(allEvents), {\n expirationTtl: 35 * 24 * 60 * 60,\n });\n\n // Webhook dispatch\n if (config.webhook_url) {\n await fetch(config.webhook_url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ events }),\n }).catch(() => {});\n }\n\n // Audit log (Analytics Engine)\n for (const event of events) {\n const ae = (env as Env & { AUDIT_LOG?: { writeDataPoint: (p: unknown) => void } }).AUDIT_LOG;\n if (ae) {\n ae.writeDataPoint({\n blobs: [\n `threshold_${event.type}`,\n sub,\n event.tier,\n ],\n doubles: [event.current_spend_cents, event.threshold_cents],\n indexes: [sub],\n });\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function resolveUserTier(env: Env, sub: string): Promise<Tier> {\n const raw = await env.CARRIER_USERS.get(`user:${sub}`, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"tier\" in raw) {\n const t = (raw as { tier: string }).tier;\n if (t === \"pro\" || t === \"enterprise\") return t;\n }\n return \"free\";\n}\n","/**\n * Carrier MCP — Pricing & Credits MCP Tools\n *\n * Exposes credit management, billing configuration, and usage analytics\n * as MCP tools. These tools allow AI agents and users to:\n * - Check credit balance and usage\n * - Configure billing thresholds\n * - View volume discount status\n * - Manage overage settings\n * - View billing history and projections\n *\n * Inspired by Stripe Projects CLI patterns:\n * - `stripe projects billing show` → credit_balance\n * - `stripe projects upgrade` → upgrade_plan\n * - `stripe projects billing add` → configure_billing\n */\n\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport {\n checkCredits,\n getCreditSummary,\n updateCreditConfig,\n TIER_CREDIT_ALLOTMENTS,\n SCOPE_CREDIT_COSTS,\n VOLUME_DISCOUNTS,\n DAILY_FREE_CREDITS,\n type CreditConfig,\n} from \"./credits.js\";\nimport {\n getThresholdConfig,\n updateThresholdConfig,\n type ThresholdConfig,\n} from \"./billing-thresholds.js\";\nimport type { Tier } from \"./billing.js\";\n\n// ---------------------------------------------------------------------------\n// Tool Definitions (for registration in tools.ts)\n// ---------------------------------------------------------------------------\n\nexport interface PricingToolDef {\n name: string;\n description: string;\n scope: ToolScope;\n inputSchema: Record<string, unknown>;\n handler: (\n env: Env,\n props: CarrierProps,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n}\n\nexport const PRICING_TOOLS: PricingToolDef[] = [\n // -------------------------------------------------------------------------\n // credit_balance — View current credit balance and usage\n // -------------------------------------------------------------------------\n {\n name: \"credit_balance\",\n description:\n \"View your current credit balance, daily free credits, overage status, \" +\n \"volume discount tier, and billing threshold status. Use this to understand \" +\n \"your current usage and remaining capacity before making API calls.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const tier = props.tier as Tier;\n const summary = await getCreditSummary(env, props.sub, tier);\n const creditCheck = await checkCredits(env, props.sub, tier, \"read\");\n\n return {\n tier,\n credits: {\n monthly_allotment: summary.ledger.allotment,\n consumed: summary.ledger.consumed,\n remaining: Math.max(0, summary.ledger.allotment - summary.ledger.consumed),\n rollover_applied: summary.ledger.rollover_applied,\n overage_consumed: summary.ledger.overage,\n overage_billed_cents: summary.ledger.overage_billed_cents,\n },\n daily_free: {\n granted: summary.daily_free.granted,\n consumed: summary.daily_free.consumed,\n remaining: Math.max(0, summary.daily_free.granted - summary.daily_free.consumed),\n },\n volume_discount: {\n current_pct: summary.volume_discount_pct,\n next_tier: getNextVolumeDiscountTier(summary.ledger.consumed),\n },\n billing: {\n overages_enabled: summary.config.overages_enabled,\n threshold_triggered: summary.ledger.threshold_triggered,\n billing_threshold_cents: summary.config.billing_threshold_cents,\n overage_rate_cents: summary.config.overage_rate_cents,\n },\n rollover: summary.rollover\n ? {\n credits: summary.rollover.credits,\n source_month: summary.rollover.source_month,\n expires_at: summary.rollover.expires_at,\n }\n : null,\n reset_at: creditCheck.reset_at,\n credit_costs: SCOPE_CREDIT_COSTS,\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // configure_billing — Update billing preferences\n // -------------------------------------------------------------------------\n {\n name: \"configure_billing\",\n description:\n \"Configure your billing preferences: enable/disable overages, set billing \" +\n \"thresholds (bill shock prevention), configure notification percentages, \" +\n \"and set hard spending caps. Pro and Enterprise tiers only.\",\n scope: \"write\",\n inputSchema: {\n type: \"object\",\n properties: {\n overages_enabled: {\n type: \"boolean\",\n description: \"Enable or disable auto-billed overages when monthly credits are exhausted\",\n },\n billing_threshold_cents: {\n type: \"number\",\n description: \"Amount in cents at which an invoice is automatically generated (e.g., 10000 = $100)\",\n },\n hard_cap_cents: {\n type: \"number\",\n description: \"Maximum overage spend in cents before overages are paused (0 = no cap)\",\n },\n auto_pause_on_cap: {\n type: \"boolean\",\n description: \"Whether to automatically pause overages when hard cap is reached\",\n },\n notify_at_pct: {\n type: \"array\",\n items: { type: \"number\" },\n description: \"Percentage thresholds at which to send notifications (e.g., [50, 80, 95, 100])\",\n },\n notification_email: {\n type: \"string\",\n description: \"Email address for billing threshold notifications\",\n },\n webhook_url: {\n type: \"string\",\n description: \"Webhook URL for billing threshold events\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const tier = props.tier as Tier;\n if (tier === \"free\") {\n return {\n error: \"Billing configuration requires Pro or Enterprise tier\",\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n }\n\n // Update credit config\n const creditUpdates: Partial<CreditConfig> = {};\n if (typeof args.overages_enabled === \"boolean\") {\n creditUpdates.overages_enabled = args.overages_enabled;\n }\n if (typeof args.billing_threshold_cents === \"number\") {\n creditUpdates.billing_threshold_cents = args.billing_threshold_cents;\n }\n if (Array.isArray(args.notify_at_pct)) {\n creditUpdates.notify_at_pct = args.notify_at_pct as number[];\n }\n\n const updatedCreditConfig = Object.keys(creditUpdates).length > 0\n ? await updateCreditConfig(env, props.sub, creditUpdates)\n : await getCreditConfigForSub(env, props.sub, tier);\n\n // Update threshold config\n const thresholdUpdates: Partial<ThresholdConfig> = {};\n if (typeof args.hard_cap_cents === \"number\") {\n thresholdUpdates.hard_cap_cents = args.hard_cap_cents;\n }\n if (typeof args.auto_pause_on_cap === \"boolean\") {\n thresholdUpdates.auto_pause_on_cap = args.auto_pause_on_cap;\n }\n if (typeof args.notification_email === \"string\") {\n thresholdUpdates.notification_email = args.notification_email;\n }\n if (typeof args.webhook_url === \"string\") {\n thresholdUpdates.webhook_url = args.webhook_url;\n }\n\n const updatedThresholdConfig = Object.keys(thresholdUpdates).length > 0\n ? await updateThresholdConfig(env, props.sub, thresholdUpdates)\n : await getThresholdConfig(env, props.sub, tier);\n\n return {\n status: \"updated\",\n credit_config: {\n overages_enabled: updatedCreditConfig.overages_enabled,\n billing_threshold_cents: updatedCreditConfig.billing_threshold_cents,\n overage_rate_cents: updatedCreditConfig.overage_rate_cents,\n notify_at_pct: updatedCreditConfig.notify_at_pct,\n },\n threshold_config: {\n hard_cap_cents: updatedThresholdConfig.hard_cap_cents,\n auto_pause_on_cap: updatedThresholdConfig.auto_pause_on_cap,\n invoice_threshold_cents: updatedThresholdConfig.invoice_threshold_cents,\n notification_email: updatedThresholdConfig.notification_email,\n webhook_url: updatedThresholdConfig.webhook_url,\n },\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // usage_projection — Project future usage and costs\n // -------------------------------------------------------------------------\n {\n name: \"usage_projection\",\n description:\n \"Project your credit usage and costs for the remainder of the billing period \" +\n \"based on current consumption rate. Includes overage cost estimates and \" +\n \"recommendations for plan changes.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n days_to_project: {\n type: \"number\",\n description: \"Number of days to project forward (default: remaining days in month)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const tier = props.tier as Tier;\n const summary = await getCreditSummary(env, props.sub, tier);\n\n const now = new Date();\n const dayOfMonth = now.getUTCDate();\n const daysInMonth = new Date(\n now.getUTCFullYear(),\n now.getUTCMonth() + 1,\n 0,\n ).getUTCDate();\n const daysRemaining = typeof args.days_to_project === \"number\"\n ? args.days_to_project\n : daysInMonth - dayOfMonth;\n\n // Calculate daily burn rate\n const dailyBurnRate = dayOfMonth > 0 ? summary.ledger.consumed / dayOfMonth : 0;\n const projectedTotal = Math.round(summary.ledger.consumed + dailyBurnRate * daysRemaining);\n const projectedOverage = Math.max(0, projectedTotal - summary.ledger.allotment);\n\n // Calculate projected overage cost\n const volumeDiscount = getVolumeDiscountForUsage(projectedTotal);\n const effectiveRate = summary.config.overage_rate_cents * (1 - volumeDiscount / 100);\n const projectedOverageCents = Math.round(projectedOverage * effectiveRate);\n\n // Recommendation\n const recommendation = generateRecommendation(\n tier,\n projectedTotal,\n summary.ledger.allotment,\n projectedOverageCents,\n );\n\n return {\n current_period: {\n day_of_month: dayOfMonth,\n days_in_month: daysInMonth,\n days_remaining: daysRemaining,\n },\n usage: {\n consumed_to_date: summary.ledger.consumed,\n daily_burn_rate: Math.round(dailyBurnRate),\n projected_total: projectedTotal,\n allotment: summary.ledger.allotment,\n },\n overage_projection: {\n projected_overage_credits: projectedOverage,\n projected_overage_cents: projectedOverageCents,\n volume_discount_pct: volumeDiscount,\n effective_rate_cents: effectiveRate,\n },\n recommendation,\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // pricing_plans — View available plans and pricing\n // -------------------------------------------------------------------------\n {\n name: \"pricing_plans\",\n description:\n \"View all available Carrier MCP pricing plans with credit allotments, \" +\n \"features, overage rates, and volume discount tiers. Use this to compare \" +\n \"plans and understand upgrade benefits.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (_env, props) => {\n const currentTier = props.tier as Tier;\n\n return {\n current_plan: currentTier,\n plans: [\n {\n id: \"free\",\n name: \"Free\",\n price_monthly_cents: 0,\n credits_monthly: TIER_CREDIT_ALLOTMENTS.free,\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\"],\n features: [\n \"5,000 monthly credits\",\n \"50 daily free credits\",\n \"Read-only OCS access\",\n \"Basic fleet monitoring\",\n ],\n overages: false,\n rollovers: false,\n volume_discounts: false,\n },\n {\n id: \"pro\",\n name: \"Pro\",\n price_monthly_cents: 4_900,\n credits_monthly: TIER_CREDIT_ALLOTMENTS.pro,\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\", \"write\"],\n features: [\n \"100,000 monthly credits\",\n \"50 daily free credits\",\n \"Read + Write OCS access\",\n \"Intelligence composites\",\n \"Auto-billed overages at $0.001/credit\",\n \"Credit rollovers (unused → next month)\",\n \"Volume discounts (up to 25% off overages)\",\n \"Billing thresholds (bill shock prevention)\",\n \"Configurable hard spending caps\",\n \"Priority support\",\n ],\n overages: true,\n rollovers: true,\n volume_discounts: true,\n overage_rate_cents: 0.1,\n },\n {\n id: \"enterprise\",\n name: \"Enterprise\",\n price_monthly_cents: 49_900,\n credits_monthly: \"unlimited\",\n daily_free_credits: DAILY_FREE_CREDITS,\n scopes: [\"read\", \"write\", \"admin\"],\n features: [\n \"Unlimited credits\",\n \"All OCS scopes (incl. admin)\",\n \"Intelligence composites\",\n \"Custom rate limits\",\n \"SSO / SAML\",\n \"Dedicated support\",\n \"SLA guarantee\",\n \"Custom billing terms\",\n ],\n overages: false,\n rollovers: false,\n volume_discounts: false,\n },\n ],\n volume_discount_tiers: VOLUME_DISCOUNTS,\n credit_costs: SCOPE_CREDIT_COSTS,\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // billing_events — View recent billing threshold events\n // -------------------------------------------------------------------------\n {\n name: \"billing_events\",\n description:\n \"View recent billing threshold events: notifications, invoice triggers, \" +\n \"hard cap alerts, and overage pauses. Useful for monitoring spend and \" +\n \"understanding billing activity.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Maximum number of events to return (default: 20, max: 50)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n const limit = Math.min(\n typeof args.limit === \"number\" ? args.limit : 20,\n 50,\n );\n\n const eventsKey = `threshold:events:${props.sub}`;\n const raw = await env.CARRIER_USERS.get(eventsKey, \"json\").catch(() => null);\n const events = Array.isArray(raw) ? raw.slice(-limit) : [];\n\n return {\n events,\n total: events.length,\n threshold_config: await getThresholdConfig(env, props.sub, props.tier as Tier),\n };\n },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getNextVolumeDiscountTier(\n consumed: number,\n): { threshold: number; discount_pct: number; credits_until: number } | null {\n for (const tier of VOLUME_DISCOUNTS) {\n if (consumed < tier.threshold) {\n return {\n threshold: tier.threshold,\n discount_pct: tier.discountPct,\n credits_until: tier.threshold - consumed,\n };\n }\n }\n return null; // Already at max discount\n}\n\nfunction getVolumeDiscountForUsage(usage: number): number {\n let discount = 0;\n for (const tier of VOLUME_DISCOUNTS) {\n if (usage >= tier.threshold) {\n discount = tier.discountPct;\n } else {\n break;\n }\n }\n return discount;\n}\n\nfunction generateRecommendation(\n tier: Tier,\n projectedTotal: number,\n allotment: number,\n projectedOverageCents: number,\n): { action: string; reason: string; savings_cents?: number } {\n if (tier === \"free\" && projectedTotal > allotment * 0.8) {\n return {\n action: \"upgrade_to_pro\",\n reason:\n \"You're projected to exceed 80% of your free tier credits. \" +\n \"Pro gives you 100,000 credits/month with overages, rollovers, and volume discounts.\",\n };\n }\n\n if (tier === \"pro\" && projectedOverageCents > 4_900) {\n // Overages exceed the cost of Enterprise\n return {\n action: \"upgrade_to_enterprise\",\n reason:\n \"Your projected overage costs exceed the Enterprise plan price. \" +\n \"Enterprise gives unlimited credits at $499/month.\",\n savings_cents: projectedOverageCents - 4_900 + 4_900, // overage + pro fee vs enterprise\n };\n }\n\n if (tier === \"pro\" && projectedTotal < allotment * 0.3) {\n return {\n action: \"no_change\",\n reason:\n \"You're using less than 30% of your Pro allotment. \" +\n \"Unused credits will roll over to next month (up to 2x your allotment).\",\n };\n }\n\n return {\n action: \"no_change\",\n reason: \"Your current plan is well-suited to your usage pattern.\",\n };\n}\n\nasync function getCreditConfigForSub(\n env: Env,\n sub: string,\n tier: Tier,\n): Promise<CreditConfig> {\n const key = `credits:config:${sub}`;\n const raw = await env.CARRIER_USERS.get(key, \"json\").catch(() => null);\n if (raw && typeof raw === \"object\" && \"billing_threshold_cents\" in raw) {\n return raw as CreditConfig;\n }\n return {\n billing_threshold_cents: 10_000,\n overages_enabled: tier !== \"free\",\n rollovers_enabled: tier !== \"free\",\n overage_rate_cents: 0.1,\n volume_discount_pct: 0,\n notify_at_pct: [50, 80, 95, 100],\n updated_at: new Date().toISOString(),\n };\n}\n","/**\n * Carrier MCP — Projects Tools (Stripe Projects CLI Pattern)\n *\n * Implements the Stripe Projects CLI paradigm for Carrier:\n * - Service catalog browsing (carrier ecosystem services)\n * - Credential vault management (API token rotation, env sync)\n * - Billing management via natural language (upgrade/downgrade)\n * - LLM context generation for AI agent workflows\n * - Multi-environment management (dev/staging/prod)\n *\n * These tools enable AI agents to:\n * 1. Discover and provision Carrier services\n * 2. Manage credentials securely\n * 3. Handle billing operations programmatically\n * 4. Generate context for downstream AI workflows\n *\n * Inspired by: `stripe projects init`, `stripe projects add`, `stripe projects catalog`\n */\n\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport type { Tier } from \"./billing.js\";\nimport { TIER_CREDIT_ALLOTMENTS, SCOPE_CREDIT_COSTS } from \"./credits.js\";\n\n// ---------------------------------------------------------------------------\n// Service Catalog\n// ---------------------------------------------------------------------------\n\nexport interface CarrierService {\n id: string;\n name: string;\n category: string;\n description: string;\n tier_required: Tier;\n scopes_required: string[];\n endpoints: string[];\n docs_url: string;\n}\n\nconst CARRIER_SERVICE_CATALOG: CarrierService[] = [\n {\n id: \"mcp\",\n name: \"Carrier MCP\",\n category: \"connectivity\",\n description: \"Model Context Protocol server — 103 natural-language tools for MVNO/eSIM fleet management\",\n tier_required: \"free\",\n scopes_required: [\"read\"],\n endpoints: [\"https://mcp.carrier.llc/mcp\"],\n docs_url: \"https://mcp.carrier.llc/docs\",\n },\n {\n id: \"api\",\n name: \"Carrier REST API\",\n category: \"connectivity\",\n description: \"RESTful HTTP API for programmatic OCS access — same tool surface as MCP over standard REST\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://api.carrier.llc/v1\"],\n docs_url: \"https://api.carrier.llc/docs\",\n },\n {\n id: \"intelligence\",\n name: \"Carrier Intelligence\",\n category: \"analytics\",\n description: \"AI-powered fleet analytics — churn prediction, usage anomalies, coverage optimization, revenue intelligence\",\n tier_required: \"pro\",\n scopes_required: [\"read\"],\n endpoints: [\"https://mcp.carrier.llc/mcp\"],\n docs_url: \"https://mcp.carrier.llc/docs#intelligence\",\n },\n {\n id: \"connect\",\n name: \"Carrier Connect\",\n category: \"marketplace\",\n description: \"MNO/MVNO network marketplace — browse operators, coverage maps, steering list management\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://app.carrier.llc/connect\"],\n docs_url: \"https://mcp.carrier.llc/docs#connect\",\n },\n {\n id: \"atlas\",\n name: \"Carrier Atlas\",\n category: \"coverage\",\n description: \"Global coverage intelligence — real-time network quality, latency maps, operator benchmarks\",\n tier_required: \"enterprise\",\n scopes_required: [\"read\"],\n endpoints: [\"https://atlas.carrier.llc/api/v1\"],\n docs_url: \"https://atlas.carrier.llc/docs\",\n },\n {\n id: \"billing\",\n name: \"Carrier Billing\",\n category: \"billing\",\n description: \"Operator billing engine — CDR ingestion, invoice generation, Stripe Connect payouts\",\n tier_required: \"pro\",\n scopes_required: [\"read\", \"write\"],\n endpoints: [\"https://api.carrier.llc/v1/billing\"],\n docs_url: \"https://api.carrier.llc/docs#billing\",\n },\n {\n id: \"webhooks\",\n name: \"Carrier Webhooks\",\n category: \"integration\",\n description: \"Real-time event delivery — OCS events, billing alerts, threshold notifications via HTTP webhooks\",\n tier_required: \"pro\",\n scopes_required: [\"read\"],\n endpoints: [\"https://api.carrier.llc/v1/webhooks\"],\n docs_url: \"https://api.carrier.llc/docs#webhooks\",\n },\n {\n id: \"console\",\n name: \"Carrier Console\",\n category: \"dashboard\",\n description: \"Visual operator dashboard — fleet management, analytics, billing, onboarding for non-technical operators\",\n tier_required: \"free\",\n scopes_required: [\"read\"],\n endpoints: [\"https://app.carrier.llc\"],\n docs_url: \"https://app.carrier.llc/docs\",\n },\n];\n\n// ---------------------------------------------------------------------------\n// Tool Definitions\n// ---------------------------------------------------------------------------\n\nexport interface ProjectsToolDef {\n name: string;\n description: string;\n scope: ToolScope;\n inputSchema: Record<string, unknown>;\n handler: (\n env: Env,\n props: CarrierProps,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n}\n\nexport const PROJECTS_TOOLS: ProjectsToolDef[] = [\n // -------------------------------------------------------------------------\n // service_catalog — Browse available Carrier services\n // -------------------------------------------------------------------------\n {\n name: \"service_catalog\",\n description:\n \"Browse the Carrier service catalog — discover available services, their \" +\n \"requirements, endpoints, and documentation. Filter by category or tier. \" +\n \"Similar to `stripe projects catalog`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n category: {\n type: \"string\",\n enum: [\"connectivity\", \"analytics\", \"marketplace\", \"coverage\", \"billing\", \"integration\", \"dashboard\"],\n description: \"Filter services by category\",\n },\n tier: {\n type: \"string\",\n enum: [\"free\", \"pro\", \"enterprise\"],\n description: \"Filter services accessible at this tier level\",\n },\n },\n required: [],\n },\n handler: async (_env, props, args) => {\n let services = [...CARRIER_SERVICE_CATALOG];\n\n if (typeof args.category === \"string\") {\n services = services.filter((s) => s.category === args.category);\n }\n\n if (typeof args.tier === \"string\") {\n const tierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n const maxTier = tierOrder[args.tier] ?? 0;\n services = services.filter(\n (s) => (tierOrder[s.tier_required] ?? 0) <= maxTier,\n );\n }\n\n // Mark which services are accessible with current tier\n const currentTierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n const userTierLevel = currentTierOrder[props.tier] ?? 0;\n\n return {\n services: services.map((s) => ({\n ...s,\n accessible: (currentTierOrder[s.tier_required] ?? 0) <= userTierLevel,\n })),\n total: services.length,\n current_tier: props.tier,\n upgrade_url: \"https://mcp.carrier.llc/upgrade\",\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // credential_status — Check credential health and rotation status\n // -------------------------------------------------------------------------\n {\n name: \"credential_status\",\n description:\n \"Check the health and status of your Carrier credentials — API token validity, \" +\n \"encryption status, last rotation date, and expiry warnings. \" +\n \"Similar to `stripe projects env --pull` status check.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const sub = props.sub;\n const orgId = props.org_id;\n\n // stdio mode has no KV — token comes from env vars.\n if (!env.CARRIER_USERS) {\n return {\n credentials: {\n esimvault_token: {\n present: true,\n encrypted: false,\n last_updated: null,\n age_days: null,\n rotation_recommended: false,\n source: \"env-var (stdio)\",\n },\n oauth: { active: false, method: props.auth_method ?? \"stdio\" },\n },\n environment: {\n org_id: orgId ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n },\n recommendations: [\"stdio mode — token managed via ESIMVAULT_API_TOKEN env var, no rotation tracking\"],\n };\n }\n\n // KV key shape mirrors auth.ts: org:<orgId> or user:clerk_<userId>.\n const primaryKey = orgId ? `org:${orgId}` : `user:clerk_${sub}`;\n const legacyKey = orgId ? null : `user:${sub}`;\n\n let record = await env.CARRIER_USERS.get(primaryKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n if (!record && legacyKey) {\n record = await env.CARRIER_USERS.get(legacyKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n }\n\n const hasToken = !!(record && \"esimvault_token_enc\" in record && record.esimvault_token_enc);\n\n // Check OAuth grant status — guard OAUTH_KV (also absent in stdio)\n const oauthKey = `oauth:grant:${sub}`;\n const oauthGrant = env.OAUTH_KV\n ? await env.OAUTH_KV.get(oauthKey, \"json\").catch(() => null) as Record<string, unknown> | null\n : null;\n\n const updatedAt = record && \"updated_at\" in record\n ? record.updated_at as string\n : null;\n\n // Calculate token age\n let tokenAgeDays: number | null = null;\n if (updatedAt) {\n const updated = new Date(updatedAt);\n tokenAgeDays = Math.floor((Date.now() - updated.getTime()) / (1000 * 60 * 60 * 24));\n }\n\n return {\n credentials: {\n esimvault_token: {\n present: hasToken,\n encrypted: hasToken, // All tokens are AES-256-GCM encrypted\n last_updated: updatedAt,\n age_days: tokenAgeDays,\n rotation_recommended: tokenAgeDays !== null && tokenAgeDays > 90,\n },\n oauth: {\n active: !!oauthGrant,\n method: props.auth_method ?? \"oauth\",\n },\n },\n environment: {\n org_id: orgId ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n },\n recommendations: generateCredentialRecommendations(hasToken, tokenAgeDays),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // rotate_credentials — Initiate credential rotation\n // -------------------------------------------------------------------------\n {\n name: \"rotate_credentials\",\n description:\n \"Initiate rotation of your eSIMVault API credentials. Generates a new \" +\n \"encrypted token and invalidates the old one. Requires write scope. \" +\n \"Similar to `stripe projects rotate <service>`.\",\n scope: \"write\",\n inputSchema: {\n type: \"object\",\n properties: {\n new_token: {\n type: \"string\",\n description: \"New eSIMVault API token to encrypt and store. Get from eSIMVault dashboard.\",\n },\n confirm: {\n type: \"boolean\",\n description: \"Confirm rotation — this will replace the current token immediately\",\n },\n },\n required: [\"new_token\", \"confirm\"],\n },\n handler: async (env, props, args) => {\n if (!args.confirm) {\n return {\n status: \"cancelled\",\n message: \"Rotation cancelled — set confirm: true to proceed\",\n };\n }\n\n const newToken = args.new_token as string;\n if (!newToken || newToken.length < 10) {\n return {\n error: \"Invalid token — must be at least 10 characters\",\n };\n }\n\n // Encrypt the new token\n const encryptionKey = (env as Env & { CARRIER_TOKEN_ENCRYPTION_KEY?: string })\n .CARRIER_TOKEN_ENCRYPTION_KEY;\n if (!encryptionKey) {\n return { error: \"Encryption key not configured — contact support\" };\n }\n\n const encrypted = await encryptToken(newToken, encryptionKey);\n const orgId = props.org_id;\n const recordKey = orgId ? `org:${orgId}` : `user:${props.sub}`;\n\n // Update the record\n const existing = await env.CARRIER_USERS.get(recordKey, \"json\").catch(() => null) as Record<string, unknown> | null;\n if (!existing) {\n return { error: \"User record not found\" };\n }\n\n const updated = {\n ...existing,\n esimvault_token_enc: encrypted,\n updated_at: new Date().toISOString(),\n };\n\n await env.CARRIER_USERS.put(recordKey, JSON.stringify(updated));\n\n return {\n status: \"rotated\",\n message: \"Credentials rotated successfully. New token is active immediately.\",\n encrypted: true,\n rotated_at: new Date().toISOString(),\n next_rotation_recommended: new Date(\n Date.now() + 90 * 24 * 60 * 60 * 1000,\n ).toISOString(),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // llm_context — Generate LLM context for AI agent workflows\n // -------------------------------------------------------------------------\n {\n name: \"llm_context\",\n description:\n \"Generate a comprehensive LLM context document describing your Carrier \" +\n \"environment, available tools, current tier, usage patterns, and best \" +\n \"practices. Designed for AI agents that need to understand your setup. \" +\n \"Similar to `stripe projects llm-context`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {\n format: {\n type: \"string\",\n enum: [\"markdown\", \"json\", \"yaml\"],\n description: \"Output format for the context document (default: markdown)\",\n },\n include_examples: {\n type: \"boolean\",\n description: \"Include example tool invocations (default: true)\",\n },\n },\n required: [],\n },\n handler: async (env, props, args) => {\n void env; // used for future expansion\n const format = (args.format as string) ?? \"markdown\";\n const includeExamples = args.include_examples !== false;\n const tier = props.tier as Tier;\n\n // Build context\n const context = {\n project: {\n name: \"Carrier MCP\",\n description: \"Programmable connectivity API control plane for MVNO/eSIM fleet management\",\n version: \"2.0\",\n transport: \"StreamableHTTP\",\n endpoint: \"https://mcp.carrier.llc/mcp\",\n },\n environment: {\n tier,\n scopes: props.scope,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n org_id: props.org_id ?? null,\n auth_method: props.auth_method ?? \"oauth\",\n },\n capabilities: {\n total_tools: 103, // full tool count\n read_tools: 35,\n write_tools: 20,\n admin_tools: 10,\n intelligence_tools: 8,\n pricing_tools: 5,\n projects_tools: 5,\n prompts: 5,\n },\n billing: {\n credits_monthly: TIER_CREDIT_ALLOTMENTS[tier],\n credit_costs: SCOPE_CREDIT_COSTS,\n overages_available: tier !== \"free\",\n volume_discounts_available: tier !== \"free\",\n },\n available_services: CARRIER_SERVICE_CATALOG.filter((s) => {\n const tierOrder: Record<string, number> = { free: 0, pro: 1, enterprise: 2 };\n return (tierOrder[s.tier_required] ?? 0) <= (tierOrder[tier] ?? 0);\n }).map((s) => ({ id: s.id, name: s.name, category: s.category })),\n best_practices: [\n \"Always check credit_balance before batch operations\",\n \"Use intelligence tools for fleet diagnostics before manual investigation\",\n \"Configure billing thresholds to prevent bill shock on overage-enabled plans\",\n \"Rotate credentials every 90 days for security\",\n \"Use carrier_ask when unsure which tool to call\",\n \"Prefer read-scope tools (1 credit) over write-scope (2 credits) when possible\",\n ],\n examples: includeExamples\n ? [\n {\n task: \"Check fleet health\",\n tool: \"fleet_health\",\n description: \"Aggregates eSIM status counts and low-balance accounts\",\n },\n {\n task: \"Diagnose offline subscriber\",\n tool: \"diagnose_subscriber\",\n args: { iccid: \"8944...\" },\n description: \"Chains multiple API calls to analyze connectivity issues\",\n },\n {\n task: \"Check billing status\",\n tool: \"credit_balance\",\n description: \"View current credits, overages, and volume discounts\",\n },\n {\n task: \"Browse available services\",\n tool: \"service_catalog\",\n description: \"Discover Carrier ecosystem services and their requirements\",\n },\n ]\n : [],\n };\n\n if (format === \"json\") {\n return context;\n }\n\n if (format === \"yaml\") {\n return { format: \"yaml\", content: jsonToYaml(context) };\n }\n\n // Markdown format\n return {\n format: \"markdown\",\n content: generateMarkdownContext(context),\n };\n },\n },\n\n // -------------------------------------------------------------------------\n // environment_info — View environment configuration\n // -------------------------------------------------------------------------\n {\n name: \"environment_info\",\n description:\n \"View your Carrier environment configuration — active organization, \" +\n \"reseller details, connected services, and deployment environment. \" +\n \"Similar to `stripe projects status`.\",\n scope: \"read\",\n inputSchema: {\n type: \"object\",\n properties: {},\n required: [],\n },\n handler: async (env, props) => {\n const sub = props.sub;\n const orgId = props.org_id;\n\n // Get org details if available\n let orgDetails: Record<string, unknown> | null = null;\n if (orgId) {\n orgDetails = await env.CARRIER_USERS.get(`org:${orgId}`, \"json\").catch(() => null) as Record<string, unknown> | null;\n }\n\n // Check connected services\n const hasStripe = !!(await env.CARRIER_USERS.get(`stripe_customer_id:${sub}`));\n const hasWebhook = !!(await env.CARRIER_USERS.get(`webhook_url:${sub}`));\n\n return {\n environment: {\n user_sub: sub,\n org_id: orgId ?? null,\n org_name: orgDetails?.name ?? null,\n org_slug: orgDetails?.slug ?? null,\n reseller_id: props.reseller_id,\n reseller_name: props.reseller_name,\n tier: props.tier,\n scopes: props.scope,\n auth_method: props.auth_method ?? \"oauth\",\n },\n connected_services: {\n esimvault: true, // Always connected (required for operation)\n stripe_billing: hasStripe,\n webhooks: hasWebhook,\n carrier_console: true,\n carrier_api: props.tier !== \"free\",\n },\n endpoints: {\n mcp: \"https://mcp.carrier.llc/mcp\",\n api: \"https://api.carrier.llc/v1\",\n console: \"https://app.carrier.llc\",\n billing_portal: \"https://accounts.carrier.llc/user/billing\",\n },\n configuration: {\n ocs_base_url: \"https://ocs.esimvault.cloud\",\n admin_enabled: props.scope.includes(\"admin\"),\n intelligence_enabled: props.tier !== \"free\",\n },\n };\n },\n },\n];\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction generateCredentialRecommendations(\n hasToken: boolean,\n tokenAgeDays: number | null,\n): string[] {\n const recommendations: string[] = [];\n\n if (!hasToken) {\n recommendations.push(\n \"No eSIMVault token configured. Complete setup at https://app.carrier.llc/setup\",\n );\n }\n\n if (tokenAgeDays !== null && tokenAgeDays > 90) {\n recommendations.push(\n `Token is ${tokenAgeDays} days old. Rotate credentials for security (recommended every 90 days).`,\n );\n }\n\n if (tokenAgeDays !== null && tokenAgeDays > 180) {\n recommendations.push(\n \"URGENT: Token is over 180 days old. Immediate rotation strongly recommended.\",\n );\n }\n\n if (recommendations.length === 0) {\n recommendations.push(\"All credentials are healthy. No action needed.\");\n }\n\n return recommendations;\n}\n\nasync function encryptToken(token: string, hexKey: string): Promise<string> {\n const keyBytes = hexToBytes(hexKey);\n const iv = crypto.getRandomValues(new Uint8Array(12));\n const key = await crypto.subtle.importKey(\n \"raw\",\n keyBytes.buffer as ArrayBuffer,\n { name: \"AES-GCM\" },\n false,\n [\"encrypt\"],\n );\n const encoded = new TextEncoder().encode(token);\n const ciphertext = await crypto.subtle.encrypt(\n { name: \"AES-GCM\", iv },\n key,\n encoded,\n );\n // Format: base64(iv:ciphertext+tag)\n const combined = new Uint8Array(iv.length + ciphertext.byteLength);\n combined.set(iv, 0);\n combined.set(new Uint8Array(ciphertext), iv.length);\n return btoa(String.fromCharCode(...combined));\n}\n\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < hex.length; i += 2) {\n bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);\n }\n return bytes;\n}\n\nfunction jsonToYaml(obj: unknown, indent = 0): string {\n const spaces = \" \".repeat(indent);\n if (obj === null || obj === undefined) return `${spaces}null`;\n if (typeof obj === \"string\") return `${spaces}${obj}`;\n if (typeof obj === \"number\" || typeof obj === \"boolean\") return `${spaces}${obj}`;\n if (Array.isArray(obj)) {\n return obj.map((item) => `${spaces}- ${typeof item === \"object\" ? \"\\n\" + jsonToYaml(item, indent + 1) : item}`).join(\"\\n\");\n }\n if (typeof obj === \"object\") {\n return Object.entries(obj as Record<string, unknown>)\n .map(([key, val]) => {\n if (typeof val === \"object\" && val !== null) {\n return `${spaces}${key}:\\n${jsonToYaml(val, indent + 1)}`;\n }\n return `${spaces}${key}: ${val}`;\n })\n .join(\"\\n\");\n }\n return String(obj);\n}\n\nfunction generateMarkdownContext(context: Record<string, unknown>): string {\n const proj = context.project as Record<string, unknown>;\n const envInfo = context.environment as Record<string, unknown>;\n const caps = context.capabilities as Record<string, unknown>;\n const billing = context.billing as Record<string, unknown>;\n const practices = context.best_practices as string[];\n\n return `# Carrier MCP — LLM Context\n\n## Project\n- **Name:** ${proj.name}\n- **Description:** ${proj.description}\n- **Version:** ${proj.version}\n- **Transport:** ${proj.transport}\n- **Endpoint:** ${proj.endpoint}\n\n## Environment\n- **Tier:** ${envInfo.tier}\n- **Scopes:** ${(envInfo.scopes as string[]).join(\", \")}\n- **Reseller:** ${envInfo.reseller_name} (ID: ${envInfo.reseller_id})\n- **Auth:** ${envInfo.auth_method}\n\n## Capabilities\n- Total tools: ${caps.total_tools}\n- Read: ${caps.read_tools} | Write: ${caps.write_tools} | Admin: ${caps.admin_tools}\n- Intelligence: ${caps.intelligence_tools} | Pricing: ${caps.pricing_tools} | Projects: ${caps.projects_tools}\n- Prompts: ${caps.prompts}\n\n## Billing\n- Monthly credits: ${billing.credits_monthly}\n- Credit costs: read=1, write=2, admin=5, intelligence=3\n- Overages: ${billing.overages_available ? \"enabled\" : \"disabled\"}\n- Volume discounts: ${billing.volume_discounts_available ? \"available\" : \"not available\"}\n\n## Best Practices\n${practices.map((p) => `- ${p}`).join(\"\\n\")}\n`;\n}\n","/**\n * Carrier MCP — Manus Scheduled Tasks + Usage Telemetry tools (v1.0.0).\n *\n * NEW TOOLS:\n * ui_agent_schedule_create — create a recurring Manus agent run (cron-based)\n * ui_agent_schedule_list — list the caller's schedules\n * ui_agent_schedule_delete — delete a schedule by ID\n * ui_agent_schedule_pause — pause a schedule\n * ui_agent_schedule_resume — resume a paused schedule\n * ui_agent_usage — current month spend + remaining credits (60s KV cache)\n *\n * SCOPE GATES:\n * - schedule_create / delete / pause / resume: admin only\n * - schedule_list / usage: read\n *\n * CRON SAFETY:\n * - Minimum interval: 5 minutes (rejects * * * * * and sub-5-min step/list expressions)\n *\n * AUDIT:\n * - Every mutating call writes an AE row.\n * - ui_agent_usage emits threshold events when remaining_credits < 1000 (warning) or < 100 (critical).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport {\n createSchedule,\n listSchedules,\n deleteSchedule,\n pauseSchedule,\n resumeSchedule,\n validateCron,\n ManusScheduleError,\n} from \"./manus-schedule.js\";\nimport { getUsage, emitUsageThresholdIfNeeded } from \"./manus-usage.js\";\n\n/** Doc + registry merge — keep aligned with scope checks in registerScheduleAndUsageTools. */\nexport const UI_AGENT_SCHEDULE_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_agent_schedule_create: \"admin\",\n ui_agent_schedule_list: \"read\",\n ui_agent_schedule_delete: \"admin\",\n ui_agent_schedule_pause: \"admin\",\n ui_agent_schedule_resume: \"admin\",\n ui_agent_usage: \"read\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nfunction noManusKeyError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message:\n \"MANUS_API_KEY is not configured on this Carrier MCP deployment. \" +\n \"Schedule and usage tools require a Manus API key. \" +\n \"Contact your Carrier MCP administrator.\",\n }),\n },\n ],\n };\n}\n\nfunction scopeError(toolName: string, required: string, actual: string[]): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: tool '${toolName}' requires '${required}' scope. Your token has: [${actual.join(\", \")}].`,\n },\n ],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\n\nexport function registerScheduleAndUsageTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // ui_agent_schedule_create\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_create\",\n {\n title: \"Create Manus Schedule (UI Agent)\",\n description:\n \"Creates a recurring Manus agent run on a cron schedule. \" +\n \"Use this to automate periodic OCS audits, fleet health checks, or any recurring \" +\n \"browser-automation task. Minimum interval: 5 minutes (*/1, */2, */3, */4 and '* * * * *' are rejected). \" +\n \"Requires admin scope. Returns schedule_id.\",\n inputSchema: {\n name: z.string().describe(\"Human-readable name for this schedule\"),\n cron: z\n .string()\n .describe(\n \"Standard 5-field cron expression (minute hour day month weekday). \" +\n \"Minimum interval: 5 minutes. Example: '0 */6 * * *' = every 6 hours.\",\n ),\n prompt_template: z\n .string()\n .describe(\"Agent prompt/task template the Manus agent will execute on each run\"),\n profile: z\n .string()\n .optional()\n .describe(\"Manus agent profile to use. Defaults to 'manus-1.6-lite'.\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_create\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n const cronError = validateCron(args.cron);\n if (cronError) {\n return {\n isError: true,\n content: [{ type: \"text\" as const, text: JSON.stringify({ error: \"invalid_cron\", message: cronError }) }],\n };\n }\n\n try {\n const result = await createSchedule(ctx.env.MANUS_API_KEY, {\n name: args.name,\n cron: args.cron,\n prompt_template: args.prompt_template,\n agent_profile: args.profile,\n });\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok || !result.schedule_id) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_create_failed\",\n message: result.error?.message ?? \"Manus schedule.create returned ok=false\",\n code: result.error?.code,\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"created\",\n schedule_id: result.schedule_id,\n name: args.name,\n cron: args.cron,\n }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_create\",\n ocs_method: \"[manus:schedule.create]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_list\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_list\",\n {\n title: \"List Manus Schedules\",\n description:\n \"Lists all Manus recurring schedules configured for this API key. \" +\n \"Returns schedule IDs, names, cron expressions, status (active/paused), \" +\n \"and next/last run timestamps.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"read\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_list\", \"read\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await listSchedules(ctx.env.MANUS_API_KEY);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_list_failed\",\n message: result.error?.message ?? \"Manus schedule.list returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ schedules: result.schedules ?? [] }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_list\",\n ocs_method: \"[manus:schedule.list]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_delete\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_delete\",\n {\n title: \"Delete Manus Schedule\",\n description:\n \"Permanently deletes a Manus recurring schedule. \" +\n \"This cannot be undone. Use ui_agent_schedule_pause to temporarily suspend instead. \" +\n \"Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to delete\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_delete\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await deleteSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_delete_failed\",\n message: result.error?.message ?? \"Manus schedule.delete returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"deleted\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_delete\",\n ocs_method: \"[manus:schedule.delete]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_pause\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_pause\",\n {\n title: \"Pause Manus Schedule\",\n description:\n \"Pauses an active Manus recurring schedule. The schedule is preserved and can be \" +\n \"resumed later with ui_agent_schedule_resume. Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to pause\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_pause\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await pauseSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_pause_failed\",\n message: result.error?.message ?? \"Manus schedule.pause returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"paused\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_pause\",\n ocs_method: \"[manus:schedule.pause]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_schedule_resume\n // =========================================================================\n server.registerTool(\n \"ui_agent_schedule_resume\",\n {\n title: \"Resume Manus Schedule\",\n description:\n \"Resumes a paused Manus recurring schedule. Requires admin scope.\",\n inputSchema: {\n schedule_id: z.string().describe(\"ID of the schedule to resume\"),\n },\n },\n async (args): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_schedule_resume\", \"admin\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const result = await resumeSchedule(ctx.env.MANUS_API_KEY, args.schedule_id);\n\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: result.ok ? \"ok\" : \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n\n if (!result.ok) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"schedule_resume_failed\",\n message: result.error?.message ?? \"Manus schedule.resume returned ok=false\",\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ status: \"active\", schedule_id: args.schedule_id }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_schedule_resume\",\n ocs_method: \"[manus:schedule.resume]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n const msg = err instanceof ManusScheduleError\n ? `Manus API error (HTTP ${err.statusCode}): ${err.message}`\n : (err instanceof Error ? err.message : String(err));\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n\n // =========================================================================\n // ui_agent_usage\n // =========================================================================\n server.registerTool(\n \"ui_agent_usage\",\n {\n title: \"Manus Usage & Credits\",\n description:\n \"Returns current month Manus credit spend, remaining balance, and task count. \" +\n \"Result is cached for 60 seconds in KV to avoid rate-limiting the Manus API. \" +\n \"Emits an Analytics Engine event when remaining_credits drops below 1000 (warning) \" +\n \"or 100 (critical). Use this to track Carrier's Manus credit burn.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n const start = Date.now();\n\n if (!ctx.props.scope.includes(\"read\")) {\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return scopeError(\"ui_agent_usage\", \"read\", ctx.props.scope);\n }\n\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n try {\n const { data, from_cache } = await getUsage(ctx.env.MANUS_API_KEY, ctx.env);\n\n // Emit threshold AE event if needed (fire-and-forget)\n emitUsageThresholdIfNeeded(ctx.env, data);\n\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({ ...data, from_cache }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_usage\",\n ocs_method: \"[manus:usage.get]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n });\n const msg = err instanceof Error ? err.message : String(err);\n return { isError: true, content: [{ type: \"text\" as const, text: msg }] };\n }\n },\n );\n}\n","/**\n * Shared Manus HTTP API v2 base URL (dot-notation routes appended, e.g. /usage.get).\n */\nexport const MANUS_API_BASE = \"https://api.manus.ai/v2\";\n","/**\n * Manus Schedule API v2 client.\n *\n * Endpoints (Manus open.manus.ai/docs/v2 dot-notation pattern):\n * POST /v2/schedule.create — create a recurring scheduled agent run\n * GET /v2/schedule.list — list all schedules for this API key\n * POST /v2/schedule.delete — delete a schedule by ID\n * POST /v2/schedule.pause — pause a schedule\n * POST /v2/schedule.resume — resume a paused schedule\n *\n * Auth: `x-manus-api-key` header (same pattern as task.create).\n */\n\nimport { MANUS_API_BASE } from \"./manus-common.js\";\n\n// ---------------------------------------------------------------------------\n// Domain types\n// ---------------------------------------------------------------------------\n\nexport interface ManusSchedule {\n schedule_id: string;\n name: string;\n cron: string;\n status: \"active\" | \"paused\" | string;\n agent_profile?: string;\n prompt_template: string;\n created_at?: string;\n updated_at?: string;\n last_run_at?: string;\n next_run_at?: string;\n}\n\nexport interface ManusScheduleCreateResult {\n ok: boolean;\n schedule_id?: string;\n error?: { code: string; message: string };\n}\n\nexport interface ManusScheduleListResult {\n ok: boolean;\n schedules?: ManusSchedule[];\n error?: { code: string; message: string };\n}\n\nexport interface ManusScheduleActionResult {\n ok: boolean;\n error?: { code: string; message: string };\n}\n\n// ---------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------\n\nexport class ManusScheduleError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n ) {\n super(message);\n this.name = \"ManusScheduleError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Cron validation\n// Minimum interval: 5 minutes. Expands the minute field (lists, ranges,\n// steps, */N) and rejects if any adjacent firing gap (including wrap) is < 5.\n// ---------------------------------------------------------------------------\n\n/**\n * Expands the minute field into sorted unique minutes 0–59, or null if unsupported.\n */\nfunction expandCronMinuteField(minuteField: string): number[] | null {\n if (minuteField === \"*\" || minuteField.includes(\" \")) {\n return null;\n }\n\n const tokens = minuteField.split(\",\").map((t) => t.trim()).filter(Boolean);\n const set = new Set<number>();\n\n for (const token of tokens) {\n const stepWildcard = /^[*]\\/(\\d+)$/.exec(token);\n if (stepWildcard) {\n const step = parseInt(stepWildcard[1] ?? \"0\", 10);\n if (step < 1) return null;\n for (let m = 0; m < 60; m += step) set.add(m);\n continue;\n }\n\n const rangeWithStep = /^(\\d+)-(\\d+)\\/(\\d+)$/.exec(token);\n if (rangeWithStep) {\n const start = parseInt(rangeWithStep[1] ?? \"0\", 10);\n const end = parseInt(rangeWithStep[2] ?? \"0\", 10);\n const step = parseInt(rangeWithStep[3] ?? \"0\", 10);\n if (step < 1 || start > end) return null;\n for (let m = start; m <= end; m += step) set.add(m);\n continue;\n }\n\n const rangeOnly = /^(\\d+)-(\\d+)$/.exec(token);\n if (rangeOnly) {\n const start = parseInt(rangeOnly[1] ?? \"0\", 10);\n const end = parseInt(rangeOnly[2] ?? \"0\", 10);\n if (start > end) return null;\n for (let m = start; m <= end; m++) set.add(m);\n continue;\n }\n\n const single = /^(\\d+)$/.exec(token);\n if (single) {\n set.add(parseInt(single[1] ?? \"0\", 10));\n continue;\n }\n\n return null;\n }\n\n const arr = Array.from(set).sort((a, b) => a - b);\n for (const v of arr) {\n if (v < 0 || v > 59) return null;\n }\n return arr;\n}\n\nfunction minuteFieldViolatesFiveMinuteRule(\n minuteField: string,\n fullCron: string,\n): string | null {\n const minutes = expandCronMinuteField(minuteField);\n if (minutes === null) {\n return (\n `Cron expression rejected: unrecognized or unsupported minute field '${minuteField}'. ` +\n \"Minimum interval is 5 minutes; use lists, ranges with step ≥ 5, or */5 or higher.\"\n );\n }\n if (minutes.length === 0) {\n return `Cron expression rejected: minute field '${minuteField}' expands to no valid minutes.`;\n }\n if (minutes.length === 1) {\n return null;\n }\n\n for (let i = 1; i < minutes.length; i++) {\n const gap = (minutes[i] ?? 0) - (minutes[i - 1] ?? 0);\n if (gap < 5) {\n return (\n `Cron expression rejected: '${fullCron}' implies a ${gap}-minute gap in the minute field. ` +\n \"Minimum allowed interval is 5 minutes.\"\n );\n }\n }\n\n const wrapGap = 60 - (minutes[minutes.length - 1] ?? 0) + (minutes[0] ?? 0);\n if (wrapGap < 5) {\n return (\n `Cron expression rejected: '${fullCron}' implies a ${wrapGap}-minute wraparound gap in the minute field. ` +\n \"Minimum allowed interval is 5 minutes.\"\n );\n }\n\n return null;\n}\n\n/**\n * Returns an error string if the cron expression is invalid or too frequent,\n * or null if it's acceptable.\n *\n * Rules:\n * - Must have exactly 5 fields (standard cron, no seconds).\n * - Minute field must not be `*` (would run every minute).\n * - The minute field is expanded (including star/N steps, a-b ranges, a-b/c\n * range-steps, and comma unions); every gap between consecutive runs within\n * the hour, and the wrap gap to the next hour, must be at least 5 minutes.\n */\nexport function validateCron(cron: string): string | null {\n const parts = cron.trim().split(/\\s+/);\n if (parts.length !== 5) {\n return `Invalid cron expression: expected 5 fields (minute hour day month weekday), got ${parts.length}.`;\n }\n\n const [minuteField] = parts;\n\n if (minuteField === \"*\") {\n return \"Cron expression rejected: '* * * * *' runs every minute. Minimum allowed interval is 5 minutes.\";\n }\n\n return minuteFieldViolatesFiveMinuteRule(minuteField ?? \"\", cron);\n}\n\n// ---------------------------------------------------------------------------\n// API functions\n// ---------------------------------------------------------------------------\n\nexport async function createSchedule(\n apiKey: string,\n params: {\n name: string;\n cron: string;\n prompt_template: string;\n agent_profile?: string;\n },\n): Promise<ManusScheduleCreateResult> {\n const body: Record<string, unknown> = {\n name: params.name,\n cron: params.cron,\n prompt_template: params.prompt_template,\n agent_profile: params.agent_profile ?? \"manus-1.6-lite\",\n interactive_mode: false,\n hide_in_task_list: false,\n };\n\n const res = await fetch(`${MANUS_API_BASE}/schedule.create`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.create failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleCreateResult;\n}\n\nexport async function listSchedules(\n apiKey: string,\n): Promise<ManusScheduleListResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.list`, {\n headers: { \"x-manus-api-key\": apiKey },\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.list failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n const data = (await res.json()) as ManusScheduleListResult | ManusSchedule[];\n // Manus may return a bare array or a wrapped object\n if (Array.isArray(data)) {\n return { ok: true, schedules: data };\n }\n return data;\n}\n\nexport async function deleteSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.delete`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.delete failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n\nexport async function pauseSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.pause`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.pause failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n\nexport async function resumeSchedule(\n apiKey: string,\n scheduleId: string,\n): Promise<ManusScheduleActionResult> {\n const res = await fetch(`${MANUS_API_BASE}/schedule.resume`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ schedule_id: scheduleId }),\n });\n\n if (!res.ok) {\n throw new ManusScheduleError(\n `schedule.resume failed: HTTP ${res.status}`,\n res.status,\n );\n }\n\n return (await res.json()) as ManusScheduleActionResult;\n}\n","/**\n * Manus Usage/Credits API v2 client.\n *\n * Endpoints (open.manus.ai/docs/v2 dot-notation pattern):\n * GET /v2/usage.get — current month's task count + credit spend\n * GET /v2/credits.get — remaining credit balance\n *\n * KV cache key: `manus_usage_cache` — 60-second TTL.\n *\n * Threshold events emitted to Analytics Engine (AUDIT_LOG):\n * remaining_credits < 1000 → warning\n * remaining_credits < 100 → critical\n */\n\nimport { MANUS_API_BASE } from \"./manus-common.js\";\nimport type { Env } from \"./types.js\";\n\nexport class ManusUsageError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number,\n ) {\n super(message);\n this.name = \"ManusUsageError\";\n }\n}\n\n// ---------------------------------------------------------------------------\n// Domain types\n// ---------------------------------------------------------------------------\n\nexport interface ManusUsageData {\n month: string; // \"YYYY-MM\"\n spent_credits: number;\n remaining_credits: number;\n task_count: number;\n}\n\ninterface ManusUsageApiResponse {\n ok?: boolean;\n month?: string;\n spent_credits?: number;\n credits_used?: number; // alternate key some endpoints use\n remaining_credits?: number;\n credits_remaining?: number;\n task_count?: number;\n tasks_run?: number;\n error?: { code: string; message: string };\n}\n\ninterface ManusCreditsApiResponse {\n ok?: boolean;\n remaining_credits?: number;\n credits_remaining?: number;\n balance?: number;\n error?: { code: string; message: string };\n}\n\n// ---------------------------------------------------------------------------\n// KV cache\n// ---------------------------------------------------------------------------\n\nconst CACHE_KEY = \"manus_usage_cache\";\nconst CACHE_TTL_SECONDS = 60;\n\ninterface CachedUsage {\n data: ManusUsageData;\n fetched_at: number; // epoch ms\n}\n\n// ---------------------------------------------------------------------------\n// Threshold constants\n// ---------------------------------------------------------------------------\n\nexport const USAGE_THRESHOLD_WARNING = 1000;\nexport const USAGE_THRESHOLD_CRITICAL = 100;\n\n// ---------------------------------------------------------------------------\n// Fetch from Manus API\n// ---------------------------------------------------------------------------\n\nasync function fetchUsageFromApi(apiKey: string): Promise<ManusUsageData> {\n const now = new Date();\n const month = `${now.getUTCFullYear()}-${String(now.getUTCMonth() + 1).padStart(2, \"0\")}`;\n\n // Fetch usage + credits in parallel\n const [usageRes, creditsRes] = await Promise.all([\n fetch(`${MANUS_API_BASE}/usage.get`, {\n headers: { \"x-manus-api-key\": apiKey },\n }),\n fetch(`${MANUS_API_BASE}/credits.get`, {\n headers: { \"x-manus-api-key\": apiKey },\n }),\n ]);\n\n if (!usageRes.ok && !creditsRes.ok) {\n throw new ManusUsageError(\n `Manus usage APIs failed: usage.get HTTP ${usageRes.status}, credits.get HTTP ${creditsRes.status}`,\n Math.max(usageRes.status, creditsRes.status),\n );\n }\n\n let spentCredits = 0;\n let remainingCredits = 0;\n let taskCount = 0;\n\n if (usageRes.ok) {\n const usageData = (await usageRes.json()) as ManusUsageApiResponse;\n spentCredits = usageData.spent_credits ?? usageData.credits_used ?? 0;\n taskCount = usageData.task_count ?? usageData.tasks_run ?? 0;\n // usage.get may also return remaining_credits\n if (usageData.remaining_credits !== undefined || usageData.credits_remaining !== undefined) {\n remainingCredits = usageData.remaining_credits ?? usageData.credits_remaining ?? 0;\n }\n }\n\n if (creditsRes.ok) {\n const creditsData = (await creditsRes.json()) as ManusCreditsApiResponse;\n // credits.get is the authoritative source for remaining balance\n const fromCreditsApi =\n creditsData.remaining_credits ??\n creditsData.credits_remaining ??\n creditsData.balance;\n if (fromCreditsApi !== undefined) {\n remainingCredits = fromCreditsApi;\n }\n }\n\n return { month, spent_credits: spentCredits, remaining_credits: remainingCredits, task_count: taskCount };\n}\n\n// ---------------------------------------------------------------------------\n// Public: getUsage — with KV cache\n// ---------------------------------------------------------------------------\n\nexport async function getUsage(\n apiKey: string,\n env: Env,\n): Promise<{ data: ManusUsageData; from_cache: boolean }> {\n // Check KV cache\n const cached = await env.CARRIER_USERS.get<CachedUsage>(CACHE_KEY, \"json\");\n const nowMs = Date.now();\n\n if (cached && nowMs - cached.fetched_at < CACHE_TTL_SECONDS * 1000) {\n return { data: cached.data, from_cache: true };\n }\n\n // Fetch fresh data\n const data = await fetchUsageFromApi(apiKey);\n\n // Write to KV with TTL\n await env.CARRIER_USERS.put(\n CACHE_KEY,\n JSON.stringify({ data, fetched_at: nowMs } satisfies CachedUsage),\n { expirationTtl: CACHE_TTL_SECONDS },\n );\n\n return { data, from_cache: false };\n}\n\n// ---------------------------------------------------------------------------\n// Threshold check — emits AE events on warning/critical\n// ---------------------------------------------------------------------------\n\nexport function emitUsageThresholdIfNeeded(\n env: Env,\n data: ManusUsageData,\n): void {\n const { remaining_credits, month, task_count } = data;\n\n if (remaining_credits < USAGE_THRESHOLD_CRITICAL) {\n writeUsageThresholdAudit(env, \"critical\", remaining_credits, month, task_count);\n } else if (remaining_credits < USAGE_THRESHOLD_WARNING) {\n writeUsageThresholdAudit(env, \"warning\", remaining_credits, month, task_count);\n }\n}\n\nfunction writeUsageThresholdAudit(\n env: Env,\n severity: \"warning\" | \"critical\",\n remainingCredits: number,\n month: string,\n taskCount: number,\n): void {\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_usage_threshold\",\n severity,\n month,\n String(taskCount),\n ],\n doubles: [remainingCredits],\n indexes: [\"manus_usage\"],\n });\n } catch (err) {\n console.error(`[manus-usage] threshold audit write failed: ${(err as Error).message}`);\n }\n}\n","/**\n * Carrier MCP — UI-Agent tools (v1.1.1).\n *\n * These tools handle OCS operations that are NOT exposed via the OCS REST API\n * (confirmed by NOC/Bridge4IP on 2026-05-13). Instead of calling OCS JSON-RPC,\n * they spawn a Manus \"lite\" agent that drives the OCS web dashboard via browser\n * automation to complete the operation.\n *\n * Gap IDs covered:\n * G-01 createSteeringList — create a new steering list\n * G-02 buildSteeringList — add/remove operators in a steering list\n * G-03 setSteeringListOnAccount — assign steering list at account level\n * G-05 createAccount — create a new reseller sub-account\n * G-12 destination list CRUD — create/edit/delete destination lists\n * G-18 deletePackageTemplate — delete a package template\n * G-19 editLocationZone/deleteLocationZone — edit or delete location zones\n *\n * AUTH FLOW:\n * OCS portal credentials are stored in Clerk privateMetadata (org or user level).\n * At dispatch time, getOcsPortalCredentials() reads them via the Clerk Backend API.\n * Credentials are passed to the Manus agent prompt — the agent uses them to log\n * into the OCS dashboard before performing the requested operation.\n *\n * MANUS API:\n * Uses v2 task.create with agent_profile \"manus-1.6-lite\", hide_in_task_list true,\n * and structured_output_schema to extract a typed result from the agent's work.\n *\n * SAFETY:\n * - All UI-agent tools require \"write\" or \"admin\" scope.\n * - Destructive operations support dry_run (returns the prompt without dispatching).\n * - Audit log records ui_agent_dispatched status + Manus task_id.\n * - Credentials are never logged or returned in tool output.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport { getOcsPortalCredentials } from \"./clerk.js\";\nimport { MANUS_API_BASE } from \"./manus-common.js\";\n\n// ---------------------------------------------------------------------------\n// Manus API v2 client\n// ---------------------------------------------------------------------------\n\ninterface ManusTaskResult {\n ok: boolean;\n task_id?: string;\n task_url?: string;\n error?: { code: string; message: string };\n}\n\nasync function createManusTask(\n apiKey: string,\n prompt: string,\n title: string,\n outputSchema?: Record<string, unknown>,\n): Promise<ManusTaskResult> {\n const body: Record<string, unknown> = {\n message: { content: prompt },\n agent_profile: \"manus-1.6-lite\",\n hide_in_task_list: true,\n interactive_mode: false,\n title,\n };\n if (outputSchema) {\n body.structured_output_schema = outputSchema;\n }\n\n const res = await fetch(`${MANUS_API_BASE}/task.create`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n return (await res.json()) as ManusTaskResult;\n}\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\nconst OCS_DASHBOARD_DEFAULT = \"https://ocs.esimvault.cloud\";\n\nfunction noCredentialsError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"ocs_portal_not_linked\",\n message:\n \"OCS portal credentials are not configured. An organisation admin must link their OCS portal \" +\n \"login via the Carrier Console settings page (Organisation Profile → OCS Portal) before \" +\n \"UI-agent operations can be dispatched.\",\n action: \"Navigate to https://console.carrier.llc/settings and link your OCS portal credentials.\",\n }),\n },\n ],\n };\n}\n\nfunction noManusKeyError(): ToolResult {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message:\n \"MANUS_API_KEY is not configured on this Carrier MCP deployment. \" +\n \"UI-agent tools require a Manus API key to spawn browser automation agents. \" +\n \"Contact your Carrier MCP administrator.\",\n }),\n },\n ],\n };\n}\n\nfunction buildLoginPreamble(dashboardUrl: string): string {\n return (\n `STEP 1 — LOGIN:\\n` +\n `Navigate to ${dashboardUrl}/login (or the main page if no /login path).\\n` +\n `Enter the OCS portal username and password provided below.\\n` +\n `Wait for the dashboard to fully load after login.\\n` +\n `If already logged in (session cookie persists), skip to STEP 2.\\n\\n`\n );\n}\n\n/**\n * Common structured output schema for UI-agent results.\n */\nconst UI_AGENT_RESULT_SCHEMA = {\n type: \"object\",\n properties: {\n success: { type: \"boolean\", description: \"Whether the operation completed successfully\" },\n summary: { type: \"string\", description: \"Human-readable summary of what was done\" },\n entity_id: { type: \"string\", description: \"ID of the created/modified entity (if applicable)\" },\n error_message: { type: \"string\", description: \"Error description if the operation failed\" },\n screenshots_taken: { type: \"number\", description: \"Number of screenshots captured during the operation\" },\n },\n required: [\"success\", \"summary\"],\n};\n\n// ---------------------------------------------------------------------------\n// UI-Agent tool wrapper — scope enforcement + Clerk creds + Manus dispatch\n// ---------------------------------------------------------------------------\nfunction wrapUiAgentHandler(\n toolName: string,\n gapId: string,\n requiredScope: ToolScope,\n ctx: ToolContext,\n buildPrompt: (args: Record<string, unknown>, dashboardUrl: string) => string,\n) {\n return async (args: Record<string, unknown> & { dry_run?: boolean }): Promise<ToolResult> => {\n const start = Date.now();\n const isDryRun = args.dry_run === true;\n\n // Scope enforcement\n if (!ctx.props.scope.includes(requiredScope)) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: tool '${toolName}' requires '${requiredScope}' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n // Check Manus API key\n if (!ctx.env.MANUS_API_KEY) {\n return noManusKeyError();\n }\n\n // Resolve OCS portal credentials from Clerk privateMetadata\n const clerkUserId = ctx.props.sub.startsWith(\"clerk_\")\n ? ctx.props.sub.slice(6) // strip \"clerk_\" prefix\n : undefined;\n const creds = await getOcsPortalCredentials(ctx.env, ctx.props.org_id, clerkUserId);\n if (!creds) {\n return noCredentialsError();\n }\n\n const dashboardUrl = ctx.env.OCS_DASHBOARD_URL ?? OCS_DASHBOARD_DEFAULT;\n const prompt = buildPrompt(args, dashboardUrl);\n\n // Inject login credentials into the prompt (never logged/returned)\n const fullPrompt =\n `You are a Carrier MCP UI automation agent. Your task is to perform an OCS dashboard operation ` +\n `that is not available via the OCS REST API.\\n\\n` +\n `OCS PORTAL CREDENTIALS (use these to log in — NEVER include them in your output):\\n` +\n ` Username: ${creds.username}\\n` +\n ` Password: ${creds.password}\\n\\n` +\n buildLoginPreamble(dashboardUrl) +\n `STEP 2 — OPERATION:\\n` +\n prompt +\n `\\n\\nSTEP 3 — VERIFICATION:\\n` +\n `After completing the operation, verify the result by checking the dashboard shows the expected state.\\n` +\n `Take a screenshot of the final state for audit purposes.\\n` +\n `Report success or failure with a clear summary.`;\n\n // Dry-run: return the prompt (with credentials redacted) without dispatching\n if (isDryRun) {\n const redactedPrompt = fullPrompt\n .replaceAll(creds.password, \"***REDACTED***\")\n .replaceAll(creds.username, \"***REDACTED***\");\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"dry_run\",\n dry_run: true,\n duration_ms: 0,\n event_type: \"ui_agent_dispatch\",\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n dry_run: true,\n tool: toolName,\n gap_id: gapId,\n agent_prompt_preview: redactedPrompt,\n note: \"No Manus agent was dispatched. Set dry_run=false to execute.\",\n }, null, 2),\n },\n ],\n };\n }\n\n // Dispatch Manus task\n try {\n const result = await createManusTask(\n ctx.env.MANUS_API_KEY,\n fullPrompt,\n `Carrier MCP UI Agent: ${toolName} (${gapId})`,\n UI_AGENT_RESULT_SCHEMA,\n );\n\n if (!result.ok || !result.task_id) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_dispatch_failed\",\n message: result.error?.message ?? \"Failed to create Manus task\",\n code: result.error?.code,\n }),\n },\n ],\n };\n }\n\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"ui_agent_dispatched\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n manus_task_id: result.task_id,\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"ui_agent_dispatched\",\n tool: toolName,\n gap_id: gapId,\n manus_task_id: result.task_id,\n manus_task_url: result.task_url,\n note:\n \"A Manus browser automation agent has been dispatched to perform this operation \" +\n \"on the OCS web dashboard. The agent will log in, execute the operation, and verify \" +\n \"the result. You can track progress at the task URL above. \" +\n \"Real-time completion updates arrive via webhook and are recorded in the audit log. \" +\n \"The poll_endpoint below is provided for backward compatibility.\",\n webhook_status: \"active\",\n poll_endpoint: `GET ${MANUS_API_BASE}/task.listMessages?task_id=${result.task_id}&order=desc&limit=5`,\n }, null, 2),\n },\n ],\n };\n } catch (err) {\n ctx.audit({\n tool_name: toolName,\n ocs_method: `[ui-agent:${gapId}]`,\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_dispatch\",\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error dispatching UI agent: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n };\n}\n\n// ---------------------------------------------------------------------------\n// Scope + destructive metadata for UI-agent tools\n// ---------------------------------------------------------------------------\nexport const UI_AGENT_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_create_steering_list: \"write\",\n ui_build_steering_list: \"write\",\n ui_set_account_steering_list: \"write\",\n ui_create_account: \"admin\",\n ui_create_destination_list: \"write\",\n ui_edit_destination_list: \"write\",\n ui_delete_destination_list: \"admin\",\n ui_delete_package_template: \"admin\",\n ui_edit_location_zone: \"write\",\n ui_delete_location_zone: \"admin\",\n};\n\nexport const UI_AGENT_DESTRUCTIVE_TOOLS = new Set([\n \"ui_create_steering_list\",\n \"ui_build_steering_list\",\n \"ui_set_account_steering_list\",\n \"ui_create_account\",\n \"ui_create_destination_list\",\n \"ui_edit_destination_list\",\n \"ui_delete_destination_list\",\n \"ui_delete_package_template\",\n \"ui_edit_location_zone\",\n \"ui_delete_location_zone\",\n]);\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\nexport function registerAllUiAgentTools(\n server: McpServer,\n ctx: ToolContext,\n): void {\n // =========================================================================\n // G-01: ui_create_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_create_steering_list\",\n {\n title: \"Create Steering List (UI Agent)\",\n description:\n \"Creates a new network steering list (OPLMN preference configuration) via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. A Manus browser agent will be dispatched \" +\n \"to perform the operation. Params: `name` (steering list name), `description` (optional). \" +\n \"Returns: dispatch confirmation with Manus task ID for tracking.\",\n inputSchema: {\n name: z.string().describe(\"Name for the new steering list\"),\n description: z.string().optional().describe(\"Optional description for the steering list\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_steering_list\", \"G-01\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Steering Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new steering list with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n `Click the \"Create\" or \"Add\" button to create the steering list.\\n` +\n `After creation, note the new steering list ID from the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-02: ui_build_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_build_steering_list\",\n {\n title: \"Build Steering List (UI Agent)\",\n description:\n \"Adds or removes operators (MCC-MNC) from an existing steering list via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. Params: `steering_list_id`, \" +\n \"`add_operators` (array of MCC-MNC to add), `remove_operators` (array to remove), \" +\n \"`operator_type` ('priority' or 'excluded').\",\n inputSchema: {\n steering_list_id: z.number().describe(\"ID of the steering list to modify\"),\n add_operators: z.array(z.string()).optional().describe(\"MCC-MNC codes to add (e.g. ['20801', '26201'])\"),\n remove_operators: z.array(z.string()).optional().describe(\"MCC-MNC codes to remove\"),\n operator_type: z.enum([\"priority\", \"excluded\"]).default(\"priority\").describe(\"Whether operators are priority or excluded\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_build_steering_list\", \"G-02\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Steering Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open steering list ID ${args.steering_list_id} for editing.\\n` +\n `Operator type: ${args.operator_type ?? \"priority\"}\\n` +\n (args.add_operators && (args.add_operators as string[]).length > 0\n ? `Add the following operators: ${(args.add_operators as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_operators && (args.remove_operators as string[]).length > 0\n ? `Remove the following operators: ${(args.remove_operators as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated operator list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-03: ui_set_account_steering_list\n // =========================================================================\n server.registerTool(\n \"ui_set_account_steering_list\",\n {\n title: \"Set Account Steering List (UI Agent)\",\n description:\n \"Assigns or removes a steering list at the account level via the OCS web dashboard. \" +\n \"The subscriber-level counterpart `modify_subscriber_steering_list` is available via API; \" +\n \"this account-level operation is UI-only. Params: `account_id`, `steering_list_id` (0 to remove).\",\n inputSchema: {\n account_id: z.number().describe(\"Account ID to assign the steering list to\"),\n steering_list_id: z.number().describe(\"Steering list ID to assign (0 to remove/unset)\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_set_account_steering_list\", \"G-03\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Accounts section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open account ID ${args.account_id}.\\n` +\n (args.steering_list_id === 0\n ? `Remove/unset the steering list assignment from this account.\\n`\n : `Assign steering list ID ${args.steering_list_id} to this account.\\n`) +\n `Save the changes and verify the steering list assignment is updated.\\n`,\n ),\n );\n\n // =========================================================================\n // G-05: ui_create_account\n // =========================================================================\n server.registerTool(\n \"ui_create_account\",\n {\n title: \"Create Account (UI Agent)\",\n description:\n \"Creates a new sub-account under the reseller via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. Params: `name` (account name), \" +\n \"`description` (optional), `initial_balance` (optional, default 0).\",\n inputSchema: {\n name: z.string().describe(\"Name for the new account\"),\n description: z.string().optional().describe(\"Optional description\"),\n initial_balance: z.number().optional().describe(\"Initial balance in account currency (default 0)\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_account\", \"G-05\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Accounts section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new account with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n (args.initial_balance ? ` Initial balance: ${args.initial_balance}\\n` : \"\") +\n `Click the \"Create\" or \"Add\" button.\\n` +\n `After creation, note the new account ID from the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_create_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_create_destination_list\",\n {\n title: \"Create Destination List (UI Agent)\",\n description:\n \"Creates a new destination list (named set of phone number prefixes for MOC call permissions) \" +\n \"via the OCS web dashboard. Params: `name`, `prefixes` (array of prefix strings), `description`.\",\n inputSchema: {\n name: z.string().describe(\"Name for the new destination list\"),\n prefixes: z.array(z.string()).optional().describe(\"Phone number prefixes to include (e.g. ['+31', '+49'])\"),\n description: z.string().optional().describe(\"Optional description\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_create_destination_list\", \"G-12\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Create a new destination list with the following details:\\n` +\n ` Name: ${args.name}\\n` +\n (args.description ? ` Description: ${args.description}\\n` : \"\") +\n (args.prefixes && (args.prefixes as string[]).length > 0\n ? ` Prefixes to add: ${(args.prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the new destination list and note the ID.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_edit_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_edit_destination_list\",\n {\n title: \"Edit Destination List (UI Agent)\",\n description:\n \"Edits an existing destination list via the OCS web dashboard. \" +\n \"Params: `destination_list_id`, `add_prefixes`, `remove_prefixes`, `new_name`.\",\n inputSchema: {\n destination_list_id: z.number().describe(\"ID of the destination list to edit\"),\n add_prefixes: z.array(z.string()).optional().describe(\"Prefixes to add\"),\n remove_prefixes: z.array(z.string()).optional().describe(\"Prefixes to remove\"),\n new_name: z.string().optional().describe(\"Rename the destination list\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_edit_destination_list\", \"G-12\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open destination list ID ${args.destination_list_id} for editing.\\n` +\n (args.new_name ? `Rename to: ${args.new_name}\\n` : \"\") +\n (args.add_prefixes && (args.add_prefixes as string[]).length > 0\n ? `Add prefixes: ${(args.add_prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_prefixes && (args.remove_prefixes as string[]).length > 0\n ? `Remove prefixes: ${(args.remove_prefixes as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated prefix list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-12: ui_delete_destination_list\n // =========================================================================\n server.registerTool(\n \"ui_delete_destination_list\",\n {\n title: \"Delete Destination List (UI Agent)\",\n description:\n \"Deletes a destination list via the OCS web dashboard. \" +\n \"Params: `destination_list_id`. WARNING: This is destructive and cannot be undone.\",\n inputSchema: {\n destination_list_id: z.number().describe(\"ID of the destination list to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_destination_list\", \"G-12\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Destination Lists section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find destination list ID ${args.destination_list_id}.\\n` +\n `Delete this destination list. Confirm the deletion when prompted.\\n` +\n `Verify the list no longer appears in the dashboard.\\n`,\n ),\n );\n\n // =========================================================================\n // G-18: ui_delete_package_template\n // =========================================================================\n server.registerTool(\n \"ui_delete_package_template\",\n {\n title: \"Delete Package Template (UI Agent)\",\n description:\n \"Deletes a package template from the product catalog via the OCS web dashboard. \" +\n \"This operation is not available via the OCS REST API. \" +\n \"Params: `template_id`. WARNING: This is destructive.\",\n inputSchema: {\n template_id: z.number().describe(\"ID of the package template to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_package_template\", \"G-18\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Package Templates section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find package template ID ${args.template_id}.\\n` +\n `Delete this package template. Confirm the deletion when prompted.\\n` +\n `Verify the template no longer appears in the template list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-19: ui_edit_location_zone\n // =========================================================================\n server.registerTool(\n \"ui_edit_location_zone\",\n {\n title: \"Edit Location Zone (UI Agent)\",\n description:\n \"Edits an existing location zone via the OCS web dashboard. \" +\n \"`create_location_zone` is available via API; edit is UI-only. \" +\n \"Params: `zone_id`, `new_name`, `add_countries`, `remove_countries`.\",\n inputSchema: {\n zone_id: z.number().describe(\"ID of the location zone to edit\"),\n new_name: z.string().optional().describe(\"Rename the location zone\"),\n add_countries: z.array(z.string()).optional().describe(\"ISO country codes to add (e.g. ['NL', 'DE'])\"),\n remove_countries: z.array(z.string()).optional().describe(\"ISO country codes to remove\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_edit_location_zone\", \"G-19\", \"write\", ctx, (args, dashboardUrl) =>\n `Navigate to the Location Zones section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Open location zone ID ${args.zone_id} for editing.\\n` +\n (args.new_name ? `Rename to: ${args.new_name}\\n` : \"\") +\n (args.add_countries && (args.add_countries as string[]).length > 0\n ? `Add countries: ${(args.add_countries as string[]).join(\", \")}\\n`\n : \"\") +\n (args.remove_countries && (args.remove_countries as string[]).length > 0\n ? `Remove countries: ${(args.remove_countries as string[]).join(\", \")}\\n`\n : \"\") +\n `Save the changes and verify the updated country list.\\n`,\n ),\n );\n\n // =========================================================================\n // G-19: ui_delete_location_zone\n // =========================================================================\n server.registerTool(\n \"ui_delete_location_zone\",\n {\n title: \"Delete Location Zone (UI Agent)\",\n description:\n \"Deletes a location zone via the OCS web dashboard. \" +\n \"`create_location_zone` is available via API; delete is UI-only. \" +\n \"Params: `zone_id`. WARNING: Zones in use by active templates may not be deletable.\",\n inputSchema: {\n zone_id: z.number().describe(\"ID of the location zone to delete\"),\n dry_run: z.boolean().optional().describe(\"Preview the agent prompt without dispatching\"),\n },\n },\n wrapUiAgentHandler(\"ui_delete_location_zone\", \"G-19\", \"admin\", ctx, (args, dashboardUrl) =>\n `Navigate to the Location Zones section of the OCS dashboard at ${dashboardUrl}.\\n` +\n `Find location zone ID ${args.zone_id}.\\n` +\n `Delete this location zone. Confirm the deletion when prompted.\\n` +\n `If the dashboard shows an error (e.g. zone in use by active templates), report the error.\\n` +\n `Verify the zone no longer appears in the zone list.\\n`,\n ),\n );\n}\n","/**\n * Clerk integration for the Carrier MCP Worker.\n *\n * Human identity is delegated to Clerk (sign-in, sign-up, MFA, social).\n * MCP-client tokens are still minted by @cloudflare/workers-oauth-provider —\n * the Clerk session only gates the OAuth `/authorize` consent step.\n *\n * v1.1a: org_id / org_role / org_name from the \"carrier-mcp\" JWT template\n * are read from sessionClaims. Email + publicMetadata still come from\n * users.getUser() until the template carries email.\n * v1.1c: reads Clerk Billing plan + features from session claims via auth.has()\n * so tier checks don't require a round-trip when Clerk Billing is enabled.\n * v1.1f: surfaces twoFactorVerified + factorVerificationAge for the MFA gate\n * on admin-scope OAuth grants (see mfa.ts).\n * v1.2: M2M JWT acceptance — Authorization: Bearer <clerk_m2m_jwt> issued via\n * Clerk client_credentials flow. Subject is a machine ID (mch_ prefix).\n * Custom claims (reseller_id, reseller_name, tier, scopes) are read from\n * the M2M client's privateMetadata-backed JWT claims.\n */\n\nimport { createClerkClient, type ClerkClient } from \"@clerk/backend\";\nimport type { ClerkJwtClaims, ClerkPublicMetadata, CarrierPrivateMetadata, OcsPortalCredentials, Env } from \"./types.js\";\n\n/** Prefix Clerk uses for M2M machine subject IDs. */\nconst M2M_SUBJECT_PREFIX = \"mch_\";\n\nlet cached: ClerkClient | null = null;\n\nexport function getClerkClient(env: Env): ClerkClient {\n if (!cached) {\n cached = createClerkClient({\n secretKey: env.CLERK_SECRET_KEY,\n publishableKey: env.CLERK_PUBLISHABLE_KEY,\n ...(env.CLERK_MACHINE_SECRET_KEY\n ? { machineSecretKey: env.CLERK_MACHINE_SECRET_KEY }\n : {}),\n });\n }\n return cached;\n}\n\nexport type ClerkPlan = \"free\" | \"pro\" | \"enterprise\";\n\nexport interface ClerkAuthResult {\n /** Clerk user ID (e.g. \"user_2pXkL9aB...\"). Prefix with \"clerk_\" for our `sub`. */\n userId: string;\n email: string;\n publicMetadata: ClerkPublicMetadata;\n /** v1.1a — Active Clerk organisation ID from sessionClaims (carrier-mcp JWT template). */\n orgId?: string;\n /** v1.1a — Active Clerk organisation role, e.g. \"org:admin\". */\n orgRole?: string;\n /** v1.1a — Active Clerk organisation display name (org_name claim). */\n orgName?: string;\n /**\n * v1.1c Clerk Billing — active subscription plan resolved via auth.has({ plan }).\n * `undefined` when Clerk Billing is not enabled or the user has no plan claim.\n */\n plan?: ClerkPlan;\n /**\n * v1.1c Clerk Billing — feature entitlements resolved via auth.has({ feature }).\n * Populated when CLERK_BILLING_FEATURES env lists features to probe.\n */\n features: Record<string, boolean>;\n /**\n * v1.1f MFA gate — true if the session JWT carries two-factor verification.\n * Computed from auth.sessionClaims.two_factor || factor_verification_age.\n */\n twoFactorVerified: boolean;\n /**\n * v1.1f MFA gate — seconds since the user last completed a 2FA challenge,\n * or `undefined` when the session predates the JWT template's second_factor_age claim.\n */\n factorVerificationAge?: number;\n /**\n * v1.2 — How this auth result was produced.\n * \"session\" → Clerk session cookie / session token (existing path).\n * \"m2m\" → Clerk M2M JWT (Authorization: Bearer <mch_ subject JWT>).\n * Downstream code (audit log, tools-call) uses this to tag machine vs human traffic.\n */\n auth_method: \"session\" | \"m2m\";\n}\n\n/** Clerk Billing plans we probe via auth.has({ plan }). Order matches tier hierarchy. */\nconst CLERK_PLANS: ClerkPlan[] = [\"enterprise\", \"pro\", \"free\"];\n\n/**\n * v1.2 — Validate a Clerk M2M JWT from `Authorization: Bearer <jwt>`.\n *\n * Uses `acceptsToken: 'm2m_token'` so the Clerk SDK handles JWKS fetch,\n * signature verification, and `iss` / expiry checks natively.\n *\n * Custom claims (reseller_id, reseller_name, tier, scopes) must be\n * configured in the Clerk Dashboard → M2M client → JWT template or\n * privateMetadata-backed claims.\n *\n * Returns null when:\n * - No Authorization: Bearer header present\n * - The JWT is not a valid M2M token (wrong iss, bad sig, expired)\n * - The subject does not start with the M2M prefix (mch_)\n */\nexport async function authenticateM2MRequest(\n request: Request,\n env: Env,\n): Promise<ClerkAuthResult | null> {\n const authHeader = request.headers.get(\"Authorization\");\n if (!authHeader || !/^Bearer\\s+/i.test(authHeader)) return null;\n\n const token = authHeader.replace(/^Bearer\\s+/i, \"\").trim();\n if (!token) return null;\n\n const client = getClerkClient(env);\n const origin = new URL(request.url).origin;\n\n let requestState: unknown;\n try {\n requestState = await client.authenticateRequest(request, {\n acceptsToken: \"m2m_token\" as \"session_token\",\n authorizedParties: [origin, \"https://accounts.carrier.llc\"],\n });\n } catch {\n return null;\n }\n\n if ((requestState as { status: string }).status !== \"signed-in\") return null;\n\n type M2MAuth = {\n subject?: string | null;\n claims?: Record<string, unknown> | null;\n };\n const auth = (requestState as { toAuth: () => M2MAuth | null }).toAuth();\n // M2M auth object carries `subject` (the machine ID) and `claims`.\n if (\n !auth ||\n typeof auth.subject !== \"string\" ||\n !auth.subject.startsWith(M2M_SUBJECT_PREFIX)\n ) {\n return null;\n }\n\n // Claims are set in the Clerk M2M client's JWT template / privateMetadata.\n const claims = (auth.claims ?? {}) as ClerkJwtClaims & Record<string, unknown>;\n\n const resellerId =\n typeof claims.reseller_id === \"number\" ? claims.reseller_id : undefined;\n const resellerName =\n typeof claims.reseller_name === \"string\" ? claims.reseller_name : \"\";\n const tier =\n claims.tier === \"free\" ||\n claims.tier === \"pro\" ||\n claims.tier === \"enterprise\"\n ? claims.tier\n : undefined;\n const scopes = Array.isArray(claims.scopes)\n ? (claims.scopes as Array<\"read\" | \"write\" | \"admin\">)\n : undefined;\n\n return {\n // Use the machine subject as the userId so downstream code (sub = `clerk_${userId}`)\n // produces a stable, unique identity for audit logging.\n userId: auth.subject,\n email: \"\",\n publicMetadata: {\n reseller_id: resellerId,\n reseller_name: resellerName || undefined,\n tier,\n scopes,\n role: \"user\",\n },\n orgId: typeof claims.org_id === \"string\" ? claims.org_id : undefined,\n orgRole: typeof claims.org_role === \"string\" ? claims.org_role : undefined,\n orgName: typeof claims.org_name === \"string\" ? claims.org_name : undefined,\n plan: tier,\n features: {},\n twoFactorVerified: false,\n factorVerificationAge: undefined,\n auth_method: \"m2m\",\n };\n}\n\n/**\n * Validate the incoming request against Clerk.\n * Returns null when the request is unauthenticated.\n *\n * v1.2: When `Authorization: Bearer <jwt>` is present, tries M2M acceptance\n * first. If the JWT is a valid Clerk M2M token (subject starts with mch_),\n * returns immediately without a users.getUser() round-trip.\n * Falls through to session-cookie path only when M2M validation yields null.\n *\n * Calls users.getUser() once for email and publicMetadata (reseller_id, tier,\n * scopes, role). org_id / org_role / org_name are read from sessionClaims when\n * the JWT template includes them.\n */\nexport async function authenticateClerkRequest(\n request: Request,\n env: Env,\n): Promise<ClerkAuthResult | null> {\n // v1.2 — M2M fast-path: try before session cookie so machine clients that\n // send a valid Bearer JWT never hit the session-token branch.\n const authHeader = request.headers.get(\"Authorization\");\n const hasBearer = authHeader !== null && /^Bearer\\s+/i.test(authHeader);\n if (hasBearer) {\n const m2mResult = await authenticateM2MRequest(request, env);\n if (m2mResult !== null) return m2mResult;\n // Bearer present but NOT a Clerk M2M JWT — fall through so the\n // OAuthProvider's regular bearer handler (OAUTH_KV tokens) stays intact.\n // The session-cookie branch below will also return null for a Bearer-only\n // request, which is the correct behaviour.\n }\n\n const client = getClerkClient(env);\n const origin = new URL(request.url).origin;\n\n const requestState = await client.authenticateRequest(request, {\n acceptsToken: \"session_token\",\n authorizedParties: [origin, \"https://accounts.carrier.llc\"],\n });\n if (requestState.status !== \"signed-in\") return null;\n\n const auth = requestState.toAuth();\n if (!auth || !(\"userId\" in auth) || !auth.userId) return null;\n\n const claims = (auth.sessionClaims ?? {}) as ClerkJwtClaims &\n Record<string, unknown>;\n\n const user = await client.users.getUser(auth.userId);\n const email =\n user.emailAddresses.find((e) => e.id === user.primaryEmailAddressId)\n ?.emailAddress ??\n user.emailAddresses[0]?.emailAddress ??\n \"\";\n const publicMetadata = (user.publicMetadata ?? {}) as ClerkPublicMetadata;\n\n // v1.1c Clerk Billing — probe plan + features via the session's has() helper.\n const plan = resolvePlan(auth);\n const features = resolveFeatures(auth, env);\n\n // v1.1f MFA — extract second-factor verification state from session claims.\n const twoFactorVerified = Boolean(\n claims.two_factor_verified ??\n claims.second_factor_verified ??\n (typeof claims.fva === \"object\" &&\n claims.fva !== null &&\n Array.isArray(claims.fva) &&\n (claims.fva as unknown[])[1] !== -1),\n );\n const factorVerificationAge =\n typeof claims.second_factor_age === \"number\"\n ? (claims.second_factor_age as number)\n : Array.isArray(claims.fva) &&\n typeof (claims.fva as unknown[])[1] === \"number\" &&\n ((claims.fva as number[])[1] ?? -1) >= 0\n ? // Clerk's `fva` tuple is ages in minutes; MFA compares seconds (mfa.ts).\n ((claims.fva as number[])[1] as number) * 60\n : undefined;\n\n return {\n userId: auth.userId,\n email,\n publicMetadata,\n orgId: claims.org_id ?? auth.orgId ?? undefined,\n orgRole: claims.org_role ?? auth.orgRole ?? undefined,\n orgName: claims.org_name,\n plan,\n features,\n twoFactorVerified,\n factorVerificationAge,\n auth_method: \"session\",\n };\n}\n\nfunction resolvePlan(auth: {\n has?: (p: Record<string, string>) => boolean;\n}): ClerkPlan | undefined {\n if (typeof auth.has !== \"function\") return undefined;\n for (const plan of CLERK_PLANS) {\n try {\n if (auth.has({ plan })) return plan;\n } catch {\n // has() may throw for an unconfigured plan — try the next tier\n continue;\n }\n }\n return undefined;\n}\n\nfunction resolveFeatures(\n auth: { has?: (p: Record<string, string>) => boolean },\n env: Env,\n): Record<string, boolean> {\n const list = (env.CLERK_BILLING_FEATURES ?? \"\")\n .split(\",\")\n .map((s: string) => s.trim())\n .filter(Boolean);\n const out: Record<string, boolean> = {};\n if (typeof auth.has !== \"function\") return out;\n for (const feature of list) {\n try {\n out[feature] = auth.has({ feature });\n } catch {\n out[feature] = false;\n }\n }\n return out;\n}\n\n/**\n * Build the Clerk-hosted sign-in URL with a redirect back to the current request.\n */\nexport function buildSignInRedirect(env: Env, requestUrl: string): string {\n const signInBase =\n env.CLERK_SIGN_IN_URL ?? \"https://accounts.carrier.llc/sign-in\";\n const url = new URL(signInBase);\n url.searchParams.set(\"redirect_url\", requestUrl);\n return url.toString();\n}\n\nexport function buildSignUpRedirect(env: Env, requestUrl: string): string {\n const signUpBase =\n env.CLERK_SIGN_UP_URL ?? \"https://accounts.carrier.llc/sign-up\";\n const url = new URL(signUpBase);\n url.searchParams.set(\"redirect_url\", requestUrl);\n return url.toString();\n}\n\n// ---------------------------------------------------------------------------\n// v1.1.1 — OCS portal credentials from Clerk privateMetadata.\n// Used by tools-ui-agent.ts to authenticate the Manus browser agent against\n// the OCS web dashboard for UI-only operations.\n//\n// Resolution order:\n// 1. Organization privateMetadata (org_id present)\n// 2. User privateMetadata (solo user, no org)\n//\n// Returns null when no credentials are stored — the UI agent tool surfaces\n// a clear \"link your OCS portal\" message to the user.\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch OCS portal credentials from Clerk privateMetadata.\n * Uses the Clerk REST API directly (no SDK method for privateMetadata on CF Workers).\n */\nexport async function getOcsPortalCredentials(\n env: Env,\n orgId?: string,\n userId?: string,\n): Promise<OcsPortalCredentials | null> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Try org-level first\n if (orgId) {\n try {\n const res = await fetch(`${baseUrl}/organizations/${orgId}`, { headers });\n if (res.ok) {\n const org = (await res.json()) as { private_metadata?: CarrierPrivateMetadata };\n if (org.private_metadata?.ocs_portal?.username && org.private_metadata.ocs_portal.password) {\n return org.private_metadata.ocs_portal;\n }\n }\n } catch {\n // Fall through to user-level\n }\n }\n\n // Fallback: user-level privateMetadata\n if (userId) {\n try {\n const res = await fetch(`${baseUrl}/users/${userId}`, { headers });\n if (res.ok) {\n const user = (await res.json()) as { private_metadata?: CarrierPrivateMetadata };\n if (user.private_metadata?.ocs_portal?.username && user.private_metadata.ocs_portal.password) {\n return user.private_metadata.ocs_portal;\n }\n }\n } catch {\n // No credentials available\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Stripe Projects provisioning helpers\n// ---------------------------------------------------------------------------\n\nexport interface CreateOrgOptions {\n name: string;\n slug: string;\n email: string;\n}\n\n/**\n * Provision a Clerk organisation for a Stripe Projects operator install.\n * If an org with the given slug already exists, returns the existing org ID.\n * Creates a membership for the provided email address (creates the user if absent).\n */\nexport async function createClerkOrgForOperator(\n env: Env,\n opts: CreateOrgOptions,\n): Promise<string> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n // Check if org slug already exists\n const listRes = await fetch(\n `${baseUrl}/organizations?query=${encodeURIComponent(opts.slug)}&limit=1`,\n { headers },\n );\n if (listRes.ok) {\n const list = (await listRes.json()) as {\n data?: Array<{ id: string; slug: string }>;\n };\n const existing = list.data?.find((o) => o.slug === opts.slug);\n if (existing) return existing.id;\n }\n\n // Create new org\n const createRes = await fetch(`${baseUrl}/organizations`, {\n method: \"POST\",\n headers,\n body: JSON.stringify({\n name: opts.name,\n slug: opts.slug,\n public_metadata: { source: \"stripe_projects\", email: opts.email },\n }),\n });\n if (!createRes.ok) {\n const errText = await createRes.text();\n throw new Error(`Failed to create Clerk org: ${errText}`);\n }\n const org = (await createRes.json()) as { id: string };\n return org.id;\n}\n\n// ---------------------------------------------------------------------------\n// OAuth token minting for Stripe Projects\n// ---------------------------------------------------------------------------\n\n/**\n * Mint a Carrier OAuth bearer token for a Stripe Projects operator.\n * Token is bound to the org, has read+write scope, and 30-day TTL.\n * Stored in OAUTH_KV so it's validated by OAuthProvider on subsequent requests.\n */\nexport async function mintProjectsToken(\n env: Env,\n orgId: string,\n): Promise<string> {\n // Generate a cryptographically random bearer token\n const tokenBytes = crypto.getRandomValues(new Uint8Array(32));\n const token = Array.from(tokenBytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n const ttl = 30 * 24 * 60 * 60; // 30 days in seconds\n const expiresAt = Date.now() + ttl * 1000;\n\n const record = {\n sub: `clerk_org_${orgId}`,\n org_id: orgId,\n scopes: [\"read\", \"write\"],\n issued_at: new Date().toISOString(),\n expires_at: new Date(expiresAt).toISOString(),\n source: \"stripe_projects\",\n };\n\n // Store under OAUTH_KV so the OAuthProvider validates it as a bearer token.\n // Key matches the pattern used by @cloudflare/workers-oauth-provider for bearer lookup.\n await (env as Env & { OAUTH_KV: KVNamespace }).OAUTH_KV.put(\n `token:${token}`,\n JSON.stringify(record),\n { expirationTtl: ttl },\n );\n\n return token;\n}\n\n/**\n * Store OCS portal credentials in Clerk org (or user) privateMetadata.\n * Called from the /setup endpoint or the console settings page.\n */\nexport async function setOcsPortalCredentials(\n env: Env,\n credentials: OcsPortalCredentials,\n orgId?: string,\n userId?: string,\n): Promise<boolean> {\n const baseUrl = \"https://api.clerk.com/v1\";\n const headers = {\n Authorization: `Bearer ${env.CLERK_SECRET_KEY}`,\n \"Content-Type\": \"application/json\",\n };\n\n const body = JSON.stringify({\n private_metadata: { ocs_portal: credentials },\n });\n\n // Prefer org-level storage\n const entityType = orgId ? \"organizations\" : \"users\";\n const entityId = orgId ?? userId;\n if (!entityId) return false;\n\n try {\n const res = await fetch(`${baseUrl}/${entityType}/${entityId}/metadata`, {\n method: \"PATCH\",\n headers,\n body,\n });\n return res.ok;\n } catch {\n return false;\n }\n}\n","/**\n * Carrier MCP — UI-Agent ask-reply tools.\n *\n * Provides the resumption path for Manus tasks that paused with stop_reason \"ask\".\n * When the Manus agent needs human input (e.g. 2FA code, ambiguous OCS field),\n * the webhook handler writes a pending-ask entry to KV. These tools allow\n * callers to list pending asks and reply to resume the task.\n *\n * Manus `task.reply` is invoked via `askReply` in `manus-client.ts` (primary/fallback key chain).\n *\n * TOOLS\n * -----\n * ui_agent_reply — submit a reply to a paused Manus task\n * ui_agent_list_pending — list all tasks currently waiting for input\n *\n * SAFETY\n * ------\n * - Both tools require \"write\" scope minimum.\n * - Reply content is NEVER recorded in the audit log (may contain credentials/codes).\n * - Only reply length is logged.\n * - KV pending-ask entries expire automatically at 24h TTL.\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { ToolContext } from \"./tools.js\";\nimport type { ToolScope } from \"./types.js\";\nimport { PENDING_ASK_PREFIX, PENDING_ASK_TTL_SECONDS } from \"./manus-webhook.js\";\nimport type { ManusPendingAsk } from \"./manus-webhook.js\";\nimport { askReply, getManusKeys, type ManusTaskResult } from \"./manus-client.js\";\n\n/** Doc + registry merge — ui_agent_reply enforces write|admin; list_pending allows any non-empty scope. */\nexport const UI_AGENT_ASK_TOOL_SCOPES: Record<string, ToolScope> = {\n ui_agent_reply: \"write\",\n ui_agent_list_pending: \"read\",\n};\n\n// ---------------------------------------------------------------------------\n// Shared ToolResult type (mirrors tools-ui-agent.ts)\n// ---------------------------------------------------------------------------\n\ntype ToolResult = {\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n};\n\n// ---------------------------------------------------------------------------\n// Pending-ask entry with computed expiry\n// ---------------------------------------------------------------------------\n\ninterface PendingAskEntry extends ManusPendingAsk {\n expires_at: string; // ISO 8601 — computed from asked_at + TTL\n}\n\nfunction computeExpiresAt(askedAt: string): string {\n const asked = new Date(askedAt).getTime();\n if (isNaN(asked)) return \"\";\n return new Date(asked + PENDING_ASK_TTL_SECONDS * 1000).toISOString();\n}\n\n// ---------------------------------------------------------------------------\n// Tool registrations\n// ---------------------------------------------------------------------------\n\nexport function registerUiAgentAskTools(server: McpServer, ctx: ToolContext): void {\n\n // =========================================================================\n // ui_agent_reply — resume a paused Manus task\n // =========================================================================\n server.registerTool(\n \"ui_agent_reply\",\n {\n title: \"Reply to Paused UI Agent Task\",\n description:\n \"Resumes a Manus browser automation task that paused with stop_reason 'ask'. \" +\n \"Use ui_agent_list_pending to find tasks waiting for input. \" +\n \"Provide the task_id and your reply (e.g. a 2FA code, a field value, or a yes/no answer). \" +\n \"The reply content is never recorded in audit logs — only its length is logged.\",\n inputSchema: {\n task_id: z.string().describe(\"Manus task ID to resume (from ui_agent_list_pending)\"),\n reply: z.string().describe(\"Your answer to the agent's question (e.g. a 2FA code or confirmation)\"),\n },\n },\n async (args: { task_id: string; reply: string }): Promise<ToolResult> => {\n const start = Date.now();\n const { task_id, reply } = args;\n\n // Scope enforcement — require write minimum\n if (!ctx.props.scope.includes(\"write\") && !ctx.props.scope.includes(\"admin\")) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"scope_denied\",\n dry_run: false,\n duration_ms: 0,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Scope denied: 'ui_agent_reply' requires 'write' scope. Your token has: [${ctx.props.scope.join(\", \")}].`,\n },\n ],\n };\n }\n\n const keys = getManusKeys(ctx.env);\n if (!keys) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_api_not_configured\",\n message: \"MANUS_API_KEY is not configured on this deployment.\",\n }),\n },\n ],\n };\n }\n\n // Check that a pending-ask entry exists for this task_id\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n const pendingRaw = await ctx.env.CARRIER_USERS.get(pendingKey);\n if (pendingRaw === null) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"task_not_pending\",\n message: `No pending-ask entry found for task_id=${task_id}. ` +\n \"The task may have already been resumed, completed, or expired (24h TTL). \" +\n \"Use ui_agent_list_pending to see currently waiting tasks.\",\n }),\n },\n ],\n };\n }\n\n let result: ManusTaskResult;\n try {\n const replyOutcome = await askReply(keys, task_id, reply);\n result = replyOutcome.data;\n } catch (err) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error calling Manus task.reply: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n\n if (!result.ok) {\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"error\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n error: \"manus_reply_failed\",\n message: result.error?.message ?? \"Manus task.reply returned ok=false\",\n code: result.error?.code,\n task_id,\n }),\n },\n ],\n };\n }\n\n // Audit: log reply length only — NEVER the reply content (may contain 2FA codes/credentials)\n ctx.audit({\n tool_name: \"ui_agent_reply\",\n ocs_method: \"[ui-agent:ask-reply]\",\n status: \"ui_agent_resumed\",\n dry_run: false,\n duration_ms: Date.now() - start,\n event_type: \"ui_agent_resume\",\n manus_task_id: task_id,\n });\n\n // Remove the pending-ask KV entry — task is now running again.\n // The next webhook with stop_reason=\"finish\" will also clear it, but\n // removing it here immediately prevents duplicate replies.\n await ctx.env.CARRIER_USERS.delete(pendingKey);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n status: \"resumed\",\n task_id,\n reply_length: reply.length,\n message:\n \"The Manus agent has received your reply and is continuing the task. \" +\n \"The task will emit a task_stopped webhook when complete.\",\n }, null, 2),\n },\n ],\n };\n },\n );\n\n // =========================================================================\n // ui_agent_list_pending — list tasks waiting for input\n // =========================================================================\n server.registerTool(\n \"ui_agent_list_pending\",\n {\n title: \"List Pending UI Agent Tasks (Waiting for Input)\",\n description:\n \"Returns all Manus browser automation tasks that are currently paused waiting for human input \" +\n \"(stop_reason 'ask'). Shows the agent's question, task URL, and when it was asked. \" +\n \"Entries expire after 24 hours. Use ui_agent_reply to resume a task.\",\n inputSchema: {},\n },\n async (): Promise<ToolResult> => {\n // Scope: read is sufficient (listing only, no mutations)\n if (ctx.props.scope.length === 0) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: \"Scope denied: no scopes present on token.\",\n },\n ],\n };\n }\n\n // List all manus_pending_ask:* keys from CARRIER_USERS KV\n let keys: Array<{ name: string }>;\n try {\n const listing = await ctx.env.CARRIER_USERS.list({ prefix: PENDING_ASK_PREFIX });\n keys = listing.keys;\n } catch (err) {\n return {\n isError: true,\n content: [\n {\n type: \"text\" as const,\n text: `Error listing pending tasks: ${err instanceof Error ? err.message : String(err)}`,\n },\n ],\n };\n }\n\n if (keys.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n pending_tasks: [],\n count: 0,\n message: \"No Manus tasks are currently waiting for input.\",\n }, null, 2),\n },\n ],\n };\n }\n\n // Fetch each entry in parallel\n const entries = await Promise.all(\n keys.map(async ({ name }): Promise<PendingAskEntry | null> => {\n const raw = await ctx.env.CARRIER_USERS.get(name);\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw) as ManusPendingAsk;\n return {\n ...parsed,\n expires_at: computeExpiresAt(parsed.asked_at),\n };\n } catch {\n return null;\n }\n }),\n );\n\n const validEntries = entries.filter((e): e is PendingAskEntry => e !== null);\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: JSON.stringify({\n pending_tasks: validEntries,\n count: validEntries.length,\n }, null, 2),\n },\n ],\n };\n },\n );\n}\n","/**\n * Manus webhook receiver.\n *\n * Receives push notifications from Manus for UI-agent tasks dispatched by\n * tools-ui-agent.ts. Eliminates the need for client-side polling.\n *\n * ROUTE\n * -----\n * POST /manus-webhook\n *\n * AUTHENTICATION\n * --------------\n * Header: X-Manus-Signature: <hex>\n * Payload: HMAC-SHA256(key=MANUS_WEBHOOK_SECRET, message=raw_request_body)\n * Format: raw hex string (no \"sha256=\" prefix — per Manus docs).\n *\n * IDEMPOTENCY\n * -----------\n * event_id stored in CARRIER_USERS KV under key `manus_event:{event_id}` with\n * 7-day TTL. Replayed events return 200+deduplicated without re-processing.\n *\n * EVENT TYPES\n * -----------\n * task_created — fires immediately after task.create; logged only.\n * task_stopped — fires on completion or ask; updates audit log + AE.\n * stop_reason:\n * \"finish\" — task completed; attachment URLs logged if present.\n * Clears any pending-ask KV entry for this task.\n * \"ask\" — task paused, waiting for user input.\n * Writes manus_pending_ask:{task_id} to CARRIER_USERS KV (24h TTL).\n * Emits ui_agent_needs_input AE event with truncated question.\n *\n * PENDING-ASK KV SCHEMA\n * ---------------------\n * Key: manus_pending_ask:{task_id}\n * Value: JSON { task_id, question, task_url, asked_at }\n * TTL: 24 hours (86400 seconds)\n *\n * AUDIT LOG SCHEMA (Analytics Engine blobs[]):\n * blobs[0] = \"manus_webhook\"\n * blobs[1] = event_type (\"task_created\" | \"task_stopped\")\n * blobs[2] = stop_reason (\"finish\" | \"ask\" | \"ui_agent_awaiting_input\" | \"\")\n * blobs[3] = task_id\n * blobs[4] = attachment_count (stringified number) or truncated question for ask events\n * doubles[0] = latency_ms (0 for task_created)\n * indexes[0] = task_id\n */\n\nimport type { Env } from \"./types.js\";\nimport { timingSafeEqual } from \"./timing-safe-equal.js\";\n\n// ---------------------------------------------------------------------------\n// Manus webhook payload shapes\n// ---------------------------------------------------------------------------\n\ninterface ManusTaskDetail {\n task_id: string;\n task_title?: string;\n task_url?: string;\n}\n\ninterface ManusAttachment {\n name: string;\n url: string;\n}\n\ninterface ManusWebhookPayload {\n event_id: string;\n event_type: \"task_created\" | \"task_stopped\" | string;\n task_detail: ManusTaskDetail;\n message?: string;\n attachments?: ManusAttachment[];\n stop_reason?: \"finish\" | \"ask\" | string;\n}\n\n// ---------------------------------------------------------------------------\n// R2 attachment persistence constants\n// ---------------------------------------------------------------------------\n\n/** Max bytes to fetch per attachment (25 MB). */\nconst MAX_ATTACHMENT_BYTES = 25 * 1024 * 1024;\n/** R2 key prefix for Manus attachment files. */\nconst R2_PREFIX = \"manus-attachments\";\n/**\n * Patterns that identify Cloudflare-hosted URLs.\n * Attachments already on CF infrastructure are skipped — no re-upload needed.\n */\nconst CF_ZONE_PATTERNS: RegExp[] = [\n /\\.r2\\.dev$/,\n /\\.carrier\\.llc$/,\n /\\.cloudflare\\.net$/,\n /\\.workers\\.dev$/,\n];\n\n// ---------------------------------------------------------------------------\n// Exported types for tools-ui-agent-ask.ts\n// ---------------------------------------------------------------------------\n\nexport interface ManusPendingAsk {\n task_id: string;\n question: string;\n task_url: string;\n asked_at: string; // ISO 8601\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst SIGNATURE_HEADER = \"x-manus-signature\";\n/** 7-day TTL for idempotency keys. */\nconst DEDUP_TTL_SECONDS = 7 * 24 * 3600;\n/** 24-hour TTL for pending-ask entries. */\nexport const PENDING_ASK_TTL_SECONDS = 24 * 3600;\n/** KV key prefix for pending-ask entries. */\nexport const PENDING_ASK_PREFIX = \"manus_pending_ask:\";\n/** Max chars of question to store in AE audit (credentials protection). */\nconst QUESTION_TRUNCATE_CHARS = 200;\n\n// ---------------------------------------------------------------------------\n// Handler entry point\n// ---------------------------------------------------------------------------\n\nexport async function handleManusWebhook(\n request: Request,\n env: Env,\n): Promise<Response> {\n if (!env.MANUS_WEBHOOK_SECRET) {\n console.error(\"[manus-webhook] MANUS_WEBHOOK_SECRET not configured\");\n return new Response(\"Webhook receiver not configured\", { status: 503 });\n }\n\n // 1. Read raw body (must happen before any .json() / .text() calls)\n const body = await request.text();\n\n // 2. Verify HMAC-SHA256 signature\n const sigHeader = request.headers.get(SIGNATURE_HEADER);\n const verified = await verifyHmacSignature(body, sigHeader, env.MANUS_WEBHOOK_SECRET);\n if (!verified) {\n console.warn(\"[manus-webhook] rejected — invalid or missing signature\");\n return new Response(\"Unauthorized\", { status: 401 });\n }\n\n // 3. Parse payload\n let payload: ManusWebhookPayload;\n try {\n payload = JSON.parse(body) as ManusWebhookPayload;\n } catch {\n return new Response(\"Invalid JSON body\", { status: 400 });\n }\n\n if (!payload.event_id || !payload.event_type || !payload.task_detail?.task_id) {\n return new Response(\n \"Missing required fields: event_id, event_type, task_detail.task_id\",\n { status: 400 },\n );\n }\n\n const { event_id, event_type, task_detail, attachments, stop_reason, message } = payload;\n const { task_id } = task_detail;\n\n // 4. Idempotency — CARRIER_USERS KV, 7-day TTL\n const dedupKey = `manus_event:${event_id}`;\n const alreadyProcessed = await env.CARRIER_USERS.get(dedupKey);\n if (alreadyProcessed !== null) {\n console.log(`[manus-webhook] deduplicated event_id=${event_id}`);\n return Response.json({ ok: true, deduplicated: true });\n }\n\n // 5. Mark as processed (write before handling so concurrent replays are safe)\n await env.CARRIER_USERS.put(dedupKey, \"1\", {\n expirationTtl: DEDUP_TTL_SECONDS,\n });\n\n try {\n // 6. Handle event\n if (event_type === \"task_created\") {\n handleTaskCreated(env, task_id, event_id);\n return Response.json({ ok: true });\n }\n\n if (event_type === \"task_stopped\") {\n await handleTaskStopped(env, task_id, event_id, stop_reason, attachments, message, task_detail.task_url);\n return Response.json({ ok: true });\n }\n\n // Unknown event type — log + ack\n console.log(`[manus-webhook] unknown event_type=${event_type} task_id=${task_id}`);\n return Response.json({ ok: true });\n } catch (err) {\n try {\n await env.CARRIER_USERS.delete(dedupKey);\n } catch (rollbackErr) {\n console.error(\n `[manus-webhook] dedup rollback failed: ${(rollbackErr as Error).message}`,\n );\n }\n throw err;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Event handlers\n// ---------------------------------------------------------------------------\n\nfunction handleTaskCreated(env: Env, task_id: string, event_id: string): void {\n console.log(`[manus-webhook] task_created task_id=${task_id} event_id=${event_id}`);\n\n writeManusAudit(env, {\n event_type: \"task_created\",\n task_id,\n stop_reason: \"\",\n attachment_count: 0,\n latency_ms: 0,\n });\n}\n\nasync function handleTaskStopped(\n env: Env,\n task_id: string,\n event_id: string,\n stop_reason: string | undefined,\n attachments: ManusAttachment[] | undefined,\n message: string | undefined,\n task_url: string | undefined,\n): Promise<void> {\n const reason = stop_reason ?? \"unknown\";\n const attachmentCount = attachments?.length ?? 0;\n\n if (reason === \"finish\") {\n console.log(\n `[manus-webhook] task_stopped:finish task_id=${task_id} attachments=${attachmentCount}`,\n );\n if (attachmentCount > 0) {\n const urls = (attachments ?? []).map((a) => `${a.name}: ${a.url}`).join(\", \");\n console.log(`[manus-webhook] attachments task_id=${task_id} urls=[${urls}]`);\n }\n\n // Persist attachments to R2 before clearing the pending-ask entry.\n if (attachmentCount > 0) {\n for (const attachment of attachments ?? []) {\n await persistAttachmentToR2(env, task_id, attachment);\n }\n }\n\n // Clear any pending-ask entry now that the task has finished.\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n await env.CARRIER_USERS.delete(pendingKey);\n console.log(`[manus-webhook] cleared pending-ask for task_id=${task_id}`);\n\n } else if (reason === \"ask\") {\n const question = message ?? \"\";\n const truncatedQuestion = question.slice(0, QUESTION_TRUNCATE_CHARS);\n\n console.log(\n `[manus-webhook] task_stopped:needs_user_input task_id=${task_id} question_len=${question.length}`,\n );\n\n // Write pending-ask entry to KV with 24h TTL.\n const pendingKey = `${PENDING_ASK_PREFIX}${task_id}`;\n const pendingEntry: ManusPendingAsk = {\n task_id,\n question,\n task_url: task_url ?? \"\",\n asked_at: new Date().toISOString(),\n };\n await env.CARRIER_USERS.put(pendingKey, JSON.stringify(pendingEntry), {\n expirationTtl: PENDING_ASK_TTL_SECONDS,\n });\n\n // Emit ask-specific AE event with truncated question (blobs[2]=\"ui_agent_awaiting_input\").\n // The generic writeManusAudit below also fires (blobs[2]=\"ask\") for compatibility.\n writeManusAuditAsk(env, {\n task_id,\n truncated_question: truncatedQuestion,\n event_id,\n });\n\n } else {\n console.log(\n `[manus-webhook] task_stopped:${reason} task_id=${task_id} event_id=${event_id}`,\n );\n }\n\n writeManusAudit(env, {\n event_type: \"task_stopped\",\n task_id,\n stop_reason: reason,\n attachment_count: attachmentCount,\n latency_ms: 0, // no task_created timestamp available without a lookup; 0 is accurate per current design\n });\n}\n\n// ---------------------------------------------------------------------------\n// R2 attachment persistence\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch an attachment from Manus and stream it to R2.\n * Skips CF-hosted URLs (already on Cloudflare infrastructure).\n * Enforces 25 MB cap via Content-Length header and buffer size check.\n */\nasync function persistAttachmentToR2(\n env: Env,\n task_id: string,\n attachment: ManusAttachment,\n): Promise<void> {\n // Skip CF-hosted URLs — no re-upload needed\n try {\n const hostname = new URL(attachment.url).hostname;\n if (CF_ZONE_PATTERNS.some((re) => re.test(hostname))) {\n console.log(`[manus-webhook] skipping CF-hosted attachment url=${attachment.url}`);\n return;\n }\n } catch {\n console.warn(`[manus-webhook] invalid attachment URL: ${attachment.url}`);\n return;\n }\n\n let res: Response;\n try {\n res = await fetch(attachment.url);\n } catch (err) {\n console.error(`[manus-webhook] fetch attachment failed url=${attachment.url}: ${(err as Error).message}`);\n return;\n }\n\n if (!res.ok) {\n console.warn(`[manus-webhook] attachment fetch non-ok status=${res.status} url=${attachment.url}`);\n return;\n }\n\n // Check Content-Length header before buffering\n const contentLengthHeader = res.headers.get(\"content-length\");\n if (contentLengthHeader !== null) {\n const declared = parseInt(contentLengthHeader, 10);\n if (!isNaN(declared) && declared > MAX_ATTACHMENT_BYTES) {\n console.warn(\n `[manus-webhook] attachment too large (content-length=${declared}) url=${attachment.url} — skipping`,\n );\n return;\n }\n }\n\n let buffer: ArrayBuffer;\n try {\n buffer = await res.arrayBuffer();\n } catch (err) {\n console.error(`[manus-webhook] attachment buffer failed: ${(err as Error).message}`);\n return;\n }\n\n if (buffer.byteLength > MAX_ATTACHMENT_BYTES) {\n console.warn(\n `[manus-webhook] attachment too large (actual=${buffer.byteLength}) url=${attachment.url} — skipping`,\n );\n return;\n }\n\n const filename = sanitiseFilename(attachment.name);\n const r2Key = `${R2_PREFIX}/${task_id}/${filename}`;\n const contentType = res.headers.get(\"content-type\") ?? \"application/octet-stream\";\n\n try {\n await env.DOWNLOADS.put(r2Key, buffer, {\n httpMetadata: { contentType },\n });\n console.log(`[manus-webhook] stored attachment r2=${r2Key} size=${buffer.byteLength}`);\n } catch (err) {\n console.error(`[manus-webhook] R2 put failed key=${r2Key}: ${(err as Error).message}`);\n }\n}\n\n/**\n * Sanitise an attachment filename for safe use as an R2 key component.\n * - Strips path separators\n * - Collapses whitespace to underscores\n * - Replaces unsafe characters\n * - Truncates to 200 chars\n */\nfunction sanitiseFilename(name: string): string {\n return name\n .replace(/[/\\\\]/g, \"_\")\n .replace(/\\s+/g, \"_\")\n .replace(/[^a-zA-Z0-9._\\-]/g, \"_\")\n .slice(0, 200);\n}\n\n// ---------------------------------------------------------------------------\n// Analytics Engine writes\n// ---------------------------------------------------------------------------\n\ninterface ManusAuditEntry {\n event_type: string;\n task_id: string;\n stop_reason: string;\n attachment_count: number;\n latency_ms: number;\n}\n\nfunction writeManusAudit(env: Env, entry: ManusAuditEntry): void {\n // Fire-and-forget — AE writes are best-effort\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_webhook\",\n entry.event_type,\n entry.stop_reason,\n entry.task_id,\n String(entry.attachment_count),\n ],\n doubles: [entry.latency_ms],\n indexes: [entry.task_id],\n });\n } catch (err) {\n console.error(`[manus-webhook] audit write failed: ${(err as Error).message}`);\n }\n}\n\nfunction writeManusAuditAsk(\n env: Env,\n entry: { task_id: string; truncated_question: string; event_id: string },\n): void {\n // Separate AE event for ask-path — status distinguishes from finish.\n // blobs[2] = \"ui_agent_awaiting_input\" distinguishes from \"finish\" status.\n try {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n \"manus_webhook\",\n \"task_stopped\",\n \"ui_agent_awaiting_input\",\n entry.task_id,\n entry.truncated_question,\n entry.event_id,\n ],\n doubles: [0],\n indexes: [entry.task_id],\n });\n } catch (err) {\n console.error(`[manus-webhook] ask audit write failed: ${(err as Error).message}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// HMAC-SHA256 signature verification\n// ---------------------------------------------------------------------------\n\n/**\n * Verify HMAC-SHA256 signature from Manus.\n * Header value is a raw hex string (64 chars, no \"sha256=\" prefix).\n * Falls back to also accepting \"sha256=<hex>\" for forward-compat.\n */\nasync function verifyHmacSignature(\n body: string,\n header: string | null,\n secret: string,\n): Promise<boolean> {\n if (!header) return false;\n\n // Accept raw hex or \"sha256=<hex>\"\n const hex = header.startsWith(\"sha256=\") ? header.slice(7) : header;\n if (!/^[0-9a-f]{64}$/i.test(hex)) return false;\n\n const enc = new TextEncoder();\n let keyMaterial: CryptoKey;\n try {\n keyMaterial = await crypto.subtle.importKey(\n \"raw\",\n enc.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"],\n );\n } catch {\n return false;\n }\n\n const sig = await crypto.subtle.sign(\"HMAC\", keyMaterial, enc.encode(body));\n const computed = Array.from(new Uint8Array(sig))\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\n const normalizedHex = hex.toLowerCase();\n return timingSafeEqual(computed, normalizedHex);\n}\n","/**\n * Carrier MCP — Manus API v2 client.\n *\n * Implements ALL Manus API v2 endpoints per the official OpenAPI spec.\n * Auth: `x-manus-api-key` header on every request.\n *\n * KEY CHAIN:\n * Primary key: env.MANUS_API_KEY\n * Fallback key: env.MANUS_API_KEY_FALLBACK (optional)\n * On HTTP 401/403/429, automatically retries with the fallback key.\n *\n * PROFILES (from official spec):\n * \"manus-1.6\" — standard capability (default)\n * \"manus-1.6-lite\" — lightweight, faster responses\n * \"manus-1.6-max\" — maximum capability\n *\n * @see https://open.manus.ai/docs/v2/introduction\n */\n\nimport type { Env } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** Base URL for all Manus API v2 calls. Paths are appended directly. */\nexport const MANUS_API_BASE = \"https://api.manus.ai/v2\";\n\n// ---------------------------------------------------------------------------\n// Profiles (from official OpenAPI spec)\n// ---------------------------------------------------------------------------\n\nexport const MANUS_PROFILES = [\n \"manus-1.6\",\n \"manus-1.6-lite\",\n \"manus-1.6-max\",\n] as const;\n\nexport type ManusProfile = (typeof MANUS_PROFILES)[number];\n\nexport const MANUS_DEFAULT_PROFILE: ManusProfile = \"manus-1.6\";\n\n/** One-line description per profile for the ui_agent_profiles_list tool. */\nexport const MANUS_PROFILE_DESCRIPTIONS: Record<ManusProfile, string> = {\n \"manus-1.6\":\n \"Standard capability agent — balanced speed and quality, default for all tasks.\",\n \"manus-1.6-lite\":\n \"Lightweight, fast, lowest cost — suitable for most OCS dashboard operations.\",\n \"manus-1.6-max\":\n \"Maximum capability — for operations requiring advanced reasoning and complex multi-step flows.\",\n};\n\n// ---------------------------------------------------------------------------\n// Key helpers\n// ---------------------------------------------------------------------------\n\nexport interface ManusKeys {\n primary: string;\n fallback?: string;\n}\n\nexport function getManusKeys(env: Env): ManusKeys | null {\n if (!env.MANUS_API_KEY) return null;\n return {\n primary: env.MANUS_API_KEY,\n fallback: env.MANUS_API_KEY_FALLBACK,\n };\n}\n\nexport function resolveManusProfile(env: Env): ManusProfile {\n const val = env.MANUS_DEFAULT_PROFILE;\n if (val && (MANUS_PROFILES as readonly string[]).includes(val)) {\n return val as ManusProfile;\n }\n return MANUS_DEFAULT_PROFILE;\n}\n\n/**\n * Validates a caller-supplied profile string against the whitelist.\n * Returns the profile on success or throws with a descriptive error.\n */\nexport function validateManusProfile(profile: string): ManusProfile {\n if ((MANUS_PROFILES as readonly string[]).includes(profile)) {\n return profile as ManusProfile;\n }\n throw new Error(\n `Invalid agent_profile \"${profile}\". Accepted profiles: ${MANUS_PROFILES.join(\", \")}. ` +\n `Use ui_agent_profiles_list to see available options.`,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Domain types (from OpenAPI spec components/schemas)\n// ---------------------------------------------------------------------------\n\n/** Standard API envelope — all responses use this shape. */\nexport interface ManusApiResponse {\n ok: boolean;\n request_id?: string;\n error?: { code: string; message: string };\n}\n\n/** Task object from task.detail / task.create / task.list */\nexport interface ManusTask extends ManusApiResponse {\n id?: string;\n task_id?: string;\n task_url?: string;\n status?: \"running\" | \"stopped\" | \"waiting\" | \"error\";\n title?: string;\n task_type?: \"standard\" | \"project\" | \"agent_subtask\";\n share_visibility?: \"private\" | \"team\" | \"public\";\n agent_profile?: ManusProfile;\n credit_usage?: number;\n created_at?: number;\n updated_at?: number;\n created_by_api_key?: { id: string; name: string } | null;\n}\n\n/** Alias for backward compatibility */\nexport type ManusTaskResult = ManusTask;\n\n/** Task attachment */\nexport interface ManusTaskAttachment {\n type?: \"image\" | \"file\" | \"voice\" | \"slides\";\n filename?: string;\n url?: string;\n content_type?: string;\n}\n\n/** Task event from task.listMessages */\nexport interface ManusTaskEvent {\n id?: string;\n type?:\n | \"user_message\"\n | \"assistant_message\"\n | \"error_message\"\n | \"status_update\"\n | \"tool_used\"\n | \"plan_update\"\n | \"new_plan_step\"\n | \"explanation\"\n | \"user_stop\"\n | \"structured_output_result\";\n timestamp?: number;\n user_message?: {\n content?: string;\n message_type?: \"text\" | \"voice\";\n attachments?: ManusTaskAttachment[];\n };\n assistant_message?: {\n content?: string;\n attachments?: ManusTaskAttachment[];\n };\n error_message?: {\n error_type?: string;\n content?: string;\n };\n status_update?: {\n agent_status?: \"running\" | \"stopped\" | \"waiting\" | \"error\";\n status_detail?: string;\n waiting_for_event_type?: string;\n waiting_for_event_id?: string;\n confirm_input_schema?: Record<string, unknown>;\n };\n structured_output_result?: {\n success?: boolean;\n value?: unknown;\n error?: string;\n };\n // Verbose-only fields\n tool_used?: { name?: string; input?: string; output?: string };\n plan_update?: { steps?: unknown[] };\n new_plan_step?: { step?: unknown };\n explanation?: { content?: string };\n}\n\n/** Paginated message list from task.listMessages */\nexport interface ManusMessageList extends ManusApiResponse {\n task_id?: string;\n messages: ManusTaskEvent[];\n has_more?: boolean;\n next_cursor?: string;\n}\n\n/** Backward-compatible alias for code that uses ManusMessage */\nexport interface ManusMessage {\n id?: string;\n message_id?: string;\n task_id?: string;\n role: \"user\" | \"assistant\" | string;\n content: string;\n created_at?: string;\n}\n\n/** Attachment from old interface (backward compat) */\nexport interface ManusAttachment {\n name: string;\n url: string;\n content_type?: string;\n}\n\n/** Project object */\nexport interface ManusProject {\n id?: string;\n name?: string;\n description?: string;\n instruction?: string;\n created_at?: number;\n updated_at?: number;\n}\n\n/** Connector info */\nexport interface ManusConnectorInfo {\n id?: string;\n name?: string;\n type?: \"builtin\" | \"byok\" | \"mcp\";\n description?: string;\n}\n\n/** Skill info */\nexport interface ManusSkillInfo {\n id?: string;\n name?: string;\n description?: string;\n owner_type?: \"personal\" | \"official\" | \"team\" | \"marketplace\";\n}\n\n/** File info */\nexport interface ManusFile {\n id?: string;\n filename?: string;\n status?: \"pending\" | \"uploaded\" | \"deleted\" | \"error\";\n created_at?: number;\n}\n\n/** File detail */\nexport interface ManusFileDetail extends ManusFile {\n size?: number;\n content_type?: string;\n download_url?: string;\n}\n\n/** Agent */\nexport interface ManusAgent {\n id?: string;\n task_id?: string;\n nickname?: string;\n description?: string;\n avatar_url?: string;\n created_at?: number;\n updated_at?: number;\n}\n\n/** Browser client */\nexport interface ManusBrowserClient {\n client_id?: string;\n client_name?: string;\n ua?: string;\n}\n\n/** Webhook */\nexport interface ManusWebhook {\n id?: string;\n url?: string;\n status?: \"active\" | \"inactive\";\n created_at?: number;\n}\n\n/** Usage record */\nexport interface ManusUsageRecord {\n task_id?: string;\n title?: string;\n credits?: number;\n type?: string;\n created_at?: number;\n}\n\n/** Team usage log entry */\nexport interface ManusTeamUsageLog {\n user_id?: string;\n user_name?: string;\n email?: string;\n task_count?: number;\n credits?: number;\n}\n\n/** Daily statistic */\nexport interface ManusDailyStatistic {\n date?: number;\n credits?: number;\n}\n\n/** Website checkpoint */\nexport interface ManusWebsiteCheckpoint {\n version_id?: string;\n message?: string;\n status?: \"pending\" | \"success\" | \"failed\" | \"unspecified\";\n created_at?: number;\n}\n\n/** Task list item (from task.list) */\nexport interface ManusTaskListResponse extends ManusApiResponse {\n data?: ManusTask[];\n has_more?: boolean;\n next_cursor?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Fallback wrapper\n// ---------------------------------------------------------------------------\n\n/** Status codes that trigger a fallback retry. */\nconst FALLBACK_TRIGGER_CODES = new Set([401, 403, 429]);\n\nexport interface WithFallbackResult<T> {\n data: T;\n key_used: \"primary\" | \"fallback\";\n _httpStatus: number;\n}\n\nexport class ManusApiError extends Error {\n constructor(\n message: string,\n public readonly httpStatus: number,\n public readonly manusError: string | undefined,\n public readonly keyUsed: \"primary\" | \"fallback\",\n public readonly bothFailed: boolean,\n ) {\n super(message);\n this.name = \"ManusApiError\";\n }\n}\n\n/**\n * Execute `fn` with primary key; on FALLBACK_TRIGGER_CODES retry with fallback.\n * Throws ManusApiError only when all available keys fail on a trigger code.\n */\nexport async function withFallback<T>(\n fn: (apiKey: string) => Promise<WithFallbackResult<T>>,\n keys: ManusKeys,\n): Promise<WithFallbackResult<T>> {\n const primaryResult = await fn(keys.primary);\n\n if (!FALLBACK_TRIGGER_CODES.has(primaryResult._httpStatus)) {\n return { ...primaryResult, key_used: \"primary\" };\n }\n\n // Primary returned a trigger code — try fallback if available\n if (!keys.fallback) {\n throw new ManusApiError(\n `Manus API request failed: HTTP ${primaryResult._httpStatus}`,\n primaryResult._httpStatus,\n undefined,\n \"primary\",\n false,\n );\n }\n\n const fallbackResult = await fn(keys.fallback);\n\n if (!FALLBACK_TRIGGER_CODES.has(fallbackResult._httpStatus)) {\n return { ...fallbackResult, key_used: \"fallback\" };\n }\n\n throw new ManusApiError(\n `Manus API request failed with both keys: HTTP ${fallbackResult._httpStatus}`,\n fallbackResult._httpStatus,\n undefined,\n \"fallback\",\n true,\n );\n}\n\n// ---------------------------------------------------------------------------\n// Internal fetch helpers\n// ---------------------------------------------------------------------------\n\nasync function manusPost<T>(\n path: string,\n apiKey: string,\n body: Record<string, unknown>,\n): Promise<WithFallbackResult<T>> {\n const res = await fetch(`${MANUS_API_BASE}/${path}`, {\n method: \"POST\",\n headers: {\n \"x-manus-api-key\": apiKey,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = (await res.json()) as T;\n return { _httpStatus: res.status, data, key_used: \"primary\" };\n}\n\nasync function manusGet<T>(\n path: string,\n apiKey: string,\n params?: Record<string, string | number | boolean | undefined>,\n): Promise<WithFallbackResult<T>> {\n const url = new URL(`${MANUS_API_BASE}/${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) {\n if (v !== undefined && v !== null) {\n url.searchParams.set(k, String(v));\n }\n }\n }\n const res = await fetch(url.toString(), {\n headers: { \"x-manus-api-key\": apiKey },\n });\n const data = (await res.json()) as T;\n return { _httpStatus: res.status, data, key_used: \"primary\" };\n}\n\n// ---------------------------------------------------------------------------\n// TASK ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/task.create */\nexport async function createTask(\n keys: ManusKeys,\n opts: {\n prompt: string;\n title?: string;\n profile?: ManusProfile | string;\n outputSchema?: Record<string, unknown>;\n projectId?: string;\n locale?: string;\n interactiveMode?: boolean;\n hideInTaskList?: boolean;\n shareVisibility?: \"private\" | \"team\" | \"public\";\n connectors?: string[];\n enableSkills?: string[];\n forceSkills?: string[];\n },\n): Promise<WithFallbackResult<ManusTask>> {\n const message: Record<string, unknown> = { content: opts.prompt };\n if (opts.connectors?.length) message.connectors = opts.connectors;\n if (opts.enableSkills?.length) message.enable_skills = opts.enableSkills;\n if (opts.forceSkills?.length) message.force_skills = opts.forceSkills;\n\n const body: Record<string, unknown> = {\n message,\n agent_profile: opts.profile ?? MANUS_DEFAULT_PROFILE,\n hide_in_task_list: opts.hideInTaskList ?? true,\n interactive_mode: opts.interactiveMode ?? false,\n };\n if (opts.title) body.title = opts.title;\n if (opts.projectId) body.project_id = opts.projectId;\n if (opts.locale) body.locale = opts.locale;\n if (opts.shareVisibility) body.share_visibility = opts.shareVisibility;\n if (opts.outputSchema) body.structured_output_schema = opts.outputSchema;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.create\", apiKey, body),\n keys,\n );\n}\n\n/** GET /v2/task.detail */\nexport async function getTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusTask>> {\n return withFallback(\n (apiKey) => manusGet<ManusTask>(\"task.detail\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** GET /v2/task.list */\nexport async function listTasks(\n keys: ManusKeys,\n opts?: {\n scope?: \"standard\" | \"project\" | \"agent_subtask\";\n agentId?: string;\n projectId?: string;\n limit?: number;\n cursor?: string;\n },\n): Promise<WithFallbackResult<ManusTaskListResponse>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusTaskListResponse>(\"task.list\", apiKey, {\n scope: opts?.scope,\n agent_id: opts?.agentId,\n project_id: opts?.projectId,\n limit: opts?.limit,\n cursor: opts?.cursor,\n }),\n keys,\n );\n}\n\n/** GET /v2/task.listMessages */\nexport async function listMessages(\n keys: ManusKeys,\n taskId: string,\n opts?: {\n order?: \"asc\" | \"desc\";\n limit?: number;\n cursor?: string;\n verbose?: boolean;\n slidesFormat?: string;\n },\n): Promise<WithFallbackResult<ManusMessageList>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusMessageList>(\"task.listMessages\", apiKey, {\n task_id: taskId,\n order: opts?.order ?? \"desc\",\n limit: opts?.limit ?? 20,\n cursor: opts?.cursor,\n verbose: opts?.verbose,\n slides_format: opts?.slidesFormat,\n }),\n keys,\n );\n}\n\n/** POST /v2/task.sendMessage — reply to a task (replaces the old task.reply) */\nexport async function sendMessage(\n keys: ManusKeys,\n taskId: string,\n content: string,\n opts?: {\n agentProfile?: ManusProfile | string;\n connectors?: string[];\n enableSkills?: string[];\n forceSkills?: string[];\n outputSchema?: Record<string, unknown>;\n },\n): Promise<WithFallbackResult<ManusTask>> {\n const message: Record<string, unknown> = { content };\n if (opts?.connectors?.length) message.connectors = opts.connectors;\n if (opts?.enableSkills?.length) message.enable_skills = opts.enableSkills;\n if (opts?.forceSkills?.length) message.force_skills = opts.forceSkills;\n\n const body: Record<string, unknown> = {\n task_id: taskId,\n message,\n };\n if (opts?.agentProfile) body.agent_profile = opts.agentProfile;\n if (opts?.outputSchema) body.structured_output_schema = opts.outputSchema;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.sendMessage\", apiKey, body),\n keys,\n );\n}\n\n/**\n * Backward-compatible alias for sendMessage.\n * The old code called `askReply(keys, taskId, reply)` — this maps to task.sendMessage.\n */\nexport async function askReply(\n keys: ManusKeys,\n taskId: string,\n reply: string,\n): Promise<WithFallbackResult<ManusTask>> {\n return sendMessage(keys, taskId, reply);\n}\n\n/** POST /v2/task.confirmAction — confirm a pending action (not for messageAskUser) */\nexport async function confirmAction(\n keys: ManusKeys,\n taskId: string,\n eventId: string,\n input?: Record<string, unknown>,\n): Promise<WithFallbackResult<ManusTask>> {\n const body: Record<string, unknown> = {\n task_id: taskId,\n event_id: eventId,\n };\n if (input) body.input = input;\n\n return withFallback(\n (apiKey) => manusPost<ManusTask>(\"task.confirmAction\", apiKey, body),\n keys,\n );\n}\n\n/** POST /v2/task.stop */\nexport async function stopTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"task.stop\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** POST /v2/task.delete */\nexport async function deleteTask(\n keys: ManusKeys,\n taskId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"task.delete\", apiKey, { task_id: taskId }),\n keys,\n );\n}\n\n/** POST /v2/task.update */\nexport async function updateTask(\n keys: ManusKeys,\n taskId: string,\n opts: {\n title?: string;\n shareVisibility?: \"private\" | \"team\" | \"public\";\n },\n): Promise<WithFallbackResult<ManusApiResponse>> {\n const body: Record<string, unknown> = { task_id: taskId };\n if (opts.title !== undefined) body.title = opts.title;\n if (opts.shareVisibility) body.share_visibility = opts.shareVisibility;\n\n return withFallback(\n (apiKey) => manusPost<ManusApiResponse>(\"task.update\", apiKey, body),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// PROJECT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/project.create */\nexport async function createProject(\n keys: ManusKeys,\n opts: {\n name: string;\n description?: string;\n instruction?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & { project?: ManusProject }>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { project?: ManusProject }>(\n \"project.create\",\n apiKey,\n opts,\n ),\n keys,\n );\n}\n\n/** GET /v2/project.list */\nexport async function listProjects(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusProject[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusProject[] }>(\n \"project.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// FILE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/file.upload (multipart/form-data) */\nexport async function uploadFile(\n keys: ManusKeys,\n file: Blob | ArrayBuffer,\n filename: string,\n): Promise<WithFallbackResult<ManusApiResponse & { file?: ManusFile }>> {\n return withFallback(async (apiKey) => {\n const formData = new FormData();\n const blob =\n file instanceof Blob ? file : new Blob([file]);\n formData.append(\"file\", blob, filename);\n\n const res = await fetch(`${MANUS_API_BASE}/file.upload`, {\n method: \"POST\",\n headers: { \"x-manus-api-key\": apiKey },\n body: formData,\n });\n const data = (await res.json()) as ManusApiResponse & {\n file?: ManusFile;\n };\n return { _httpStatus: res.status, data, key_used: \"primary\" as const };\n }, keys);\n}\n\n/** GET /v2/file.detail */\nexport async function getFileDetail(\n keys: ManusKeys,\n fileId: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { file?: ManusFileDetail }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { file?: ManusFileDetail }>(\n \"file.detail\",\n apiKey,\n { file_id: fileId },\n ),\n keys,\n );\n}\n\n/** POST /v2/file.delete */\nexport async function deleteFile(\n keys: ManusKeys,\n fileId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"file.delete\", apiKey, { file_id: fileId }),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// CONNECTOR & SKILL ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/connector.list */\nexport async function listConnectors(\n keys: ManusKeys,\n projectId?: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusConnectorInfo[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusConnectorInfo[] }>(\n \"connector.list\",\n apiKey,\n projectId ? { project_id: projectId } : undefined,\n ),\n keys,\n );\n}\n\n/** GET /v2/skill.list */\nexport async function listSkills(\n keys: ManusKeys,\n projectId?: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusSkillInfo[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusSkillInfo[] }>(\n \"skill.list\",\n apiKey,\n projectId ? { project_id: projectId } : undefined,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// AGENT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/agent.list */\nexport async function listAgents(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusAgent[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusAgent[] }>(\n \"agent.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n/** GET /v2/agent.detail */\nexport async function getAgentDetail(\n keys: ManusKeys,\n agentId: string,\n): Promise<WithFallbackResult<ManusApiResponse & { agent?: ManusAgent }>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { agent?: ManusAgent }>(\n \"agent.detail\",\n apiKey,\n { agent_id: agentId },\n ),\n keys,\n );\n}\n\n/** POST /v2/agent.update */\nexport async function updateAgent(\n keys: ManusKeys,\n agentId: string,\n opts: {\n nickname?: string;\n description?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & { agent?: ManusAgent }>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { agent?: ManusAgent }>(\n \"agent.update\",\n apiKey,\n { agent_id: agentId, ...opts },\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// BROWSER CLIENT ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/browser.onlineList */\nexport async function listOnlineBrowsers(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusBrowserClient[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusBrowserClient[] }>(\n \"browser.onlineList\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// WEBHOOK ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** POST /v2/webhook.create */\nexport async function createWebhook(\n keys: ManusKeys,\n url: string,\n): Promise<\n WithFallbackResult<ManusApiResponse & { webhook?: ManusWebhook }>\n> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & { webhook?: ManusWebhook }>(\n \"webhook.create\",\n apiKey,\n { url },\n ),\n keys,\n );\n}\n\n/** GET /v2/webhook.list */\nexport async function listWebhooks(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { data?: ManusWebhook[] }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { data?: ManusWebhook[] }>(\n \"webhook.list\",\n apiKey,\n ),\n keys,\n );\n}\n\n/** POST /v2/webhook.delete */\nexport async function deleteWebhook(\n keys: ManusKeys,\n webhookId: string,\n): Promise<WithFallbackResult<ManusApiResponse>> {\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse>(\"webhook.delete\", apiKey, {\n webhook_id: webhookId,\n }),\n keys,\n );\n}\n\n/** GET /v2/webhook.publicKey */\nexport async function getWebhookPublicKey(\n keys: ManusKeys,\n): Promise<\n WithFallbackResult<ManusApiResponse & { public_key?: string }>\n> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & { public_key?: string }>(\n \"webhook.publicKey\",\n apiKey,\n ),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// USAGE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/usage.list */\nexport async function listUsage(\n keys: ManusKeys,\n opts?: { limit?: number; cursor?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: ManusUsageRecord[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: ManusUsageRecord[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >(\"usage.list\", apiKey, {\n limit: opts?.limit,\n cursor: opts?.cursor,\n }),\n keys,\n );\n}\n\n/** GET /v2/usage.teamStatistic */\nexport async function getTeamStatistic(\n keys: ManusKeys,\n opts?: { startDate?: string; endDate?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: {\n daily_statistics?: ManusDailyStatistic[];\n total_credits?: number;\n };\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: {\n daily_statistics?: ManusDailyStatistic[];\n total_credits?: number;\n };\n }\n >(\"usage.teamStatistic\", apiKey, {\n start_date: opts?.startDate,\n end_date: opts?.endDate,\n }),\n keys,\n );\n}\n\n/** GET /v2/usage.teamLog */\nexport async function getTeamLog(\n keys: ManusKeys,\n opts?: {\n limit?: number;\n cursor?: string;\n startDate?: string;\n endDate?: string;\n sortBy?: string;\n isAsc?: boolean;\n },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n data?: ManusTeamUsageLog[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n data?: ManusTeamUsageLog[];\n has_more?: boolean;\n next_cursor?: string;\n }\n >(\"usage.teamLog\", apiKey, {\n limit: opts?.limit,\n cursor: opts?.cursor,\n start_date: opts?.startDate,\n end_date: opts?.endDate,\n sort_by: opts?.sortBy,\n is_asc: opts?.isAsc,\n }),\n keys,\n );\n}\n\n// ---------------------------------------------------------------------------\n// WEBSITE ENDPOINTS\n// ---------------------------------------------------------------------------\n\n/** GET /v2/website.status */\nexport async function getWebsiteStatus(\n keys: ManusKeys,\n opts: { taskId?: string; websiteId?: string },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n return withFallback(\n (apiKey) =>\n manusGet<ManusApiResponse & Record<string, unknown>>(\n \"website.status\",\n apiKey,\n {\n task_id: opts.taskId,\n website_id: opts.websiteId,\n },\n ),\n keys,\n );\n}\n\n/** GET /v2/website.listCheckpoints */\nexport async function listWebsiteCheckpoints(\n keys: ManusKeys,\n opts: { taskId?: string; websiteId?: string },\n): Promise<\n WithFallbackResult<\n ManusApiResponse & {\n website_id?: string;\n checkpoints?: ManusWebsiteCheckpoint[];\n }\n >\n> {\n return withFallback(\n (apiKey) =>\n manusGet<\n ManusApiResponse & {\n website_id?: string;\n checkpoints?: ManusWebsiteCheckpoint[];\n }\n >(\"website.listCheckpoints\", apiKey, {\n task_id: opts.taskId,\n website_id: opts.websiteId,\n }),\n keys,\n );\n}\n\n/** POST /v2/website.publish */\nexport async function publishWebsite(\n keys: ManusKeys,\n opts: {\n taskId?: string;\n websiteId?: string;\n visibility?: \"public\" | \"team\" | \"private\";\n },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n const body: Record<string, unknown> = {};\n if (opts.taskId) body.task_id = opts.taskId;\n if (opts.websiteId) body.website_id = opts.websiteId;\n if (opts.visibility) body.visibility = opts.visibility;\n\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & Record<string, unknown>>(\n \"website.publish\",\n apiKey,\n body,\n ),\n keys,\n );\n}\n\n/** POST /v2/website.update */\nexport async function updateWebsite(\n keys: ManusKeys,\n opts: {\n taskId?: string;\n websiteId?: string;\n versionId?: string;\n customDomain?: string;\n },\n): Promise<WithFallbackResult<ManusApiResponse & Record<string, unknown>>> {\n const body: Record<string, unknown> = {};\n if (opts.taskId) body.task_id = opts.taskId;\n if (opts.websiteId) body.website_id = opts.websiteId;\n if (opts.versionId) body.version_id = opts.versionId;\n if (opts.customDomain) body.custom_domain = opts.customDomain;\n\n return withFallback(\n (apiKey) =>\n manusPost<ManusApiResponse & Record<string, unknown>>(\n \"website.update\",\n apiKey,\n body,\n ),\n keys,\n );\n}\n","/**\n * Carrier MCP — Stripe Connect tools (Phase 16).\n *\n * Provides AI-agent access to the operator Stripe Connect layer.\n * All tools call the Stripe API directly using STRIPE_SECRET_KEY from env.\n * The connected account ID is looked up from CARRIER_USERS KV\n * under key `stripe_account:<operatorId>`.\n *\n * Tools registered here:\n * stripe_connect_status — read-only: account status + capabilities\n * stripe_connect_payouts — read-only: list recent payouts\n * stripe_connect_balance — read-only: available + pending balance\n * stripe_connect_refund — write (HARD_BLOCK): refund a charge\n * stripe_connect_dispute_list — read-only: list active disputes\n * radar_review_list — read-only: list pending Radar reviews\n * radar_review_approve — admin (HARD_BLOCK): approve a review\n * radar_review_decline — admin (HARD_BLOCK): decline/close a review\n * radar_value_list_add — admin (HARD_BLOCK): add to block/allow list\n * radar_rule_toggle — admin: documented stub (Stripe API limitation)\n *\n * HARD_BLOCK pattern: destructive tools require a confirm_token stored in\n * OAUTH_KV with a 5-min TTL (same pattern as pricing-tools.ts).\n */\n\nimport { z } from \"zod\";\nimport type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport * as Sentry from \"@sentry/cloudflare\";\nimport type { Env, CarrierProps, ToolScope } from \"./types.js\";\nimport { writeAudit } from \"./audit.js\";\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\nexport interface StripeConnectToolContext {\n env: Env;\n props: CarrierProps;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Hard-block confirm token stored in KV with 5-min TTL. */\nasync function verifyConfirmToken(\n env: Env,\n sub: string,\n toolName: string,\n token: string,\n): Promise<boolean> {\n const key = `confirm:${sub}:${toolName}`;\n const stored = await env.OAUTH_KV.get(key);\n if (!stored || stored !== token) return false;\n await env.OAUTH_KV.delete(key); // single-use\n return true;\n}\n\nasync function issueConfirmToken(env: Env, sub: string, toolName: string): Promise<string> {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n const token = Array.from(bytes).map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n const key = `confirm:${sub}:${toolName}`;\n await env.OAUTH_KV.put(key, token, { expirationTtl: 300 }); // 5 min TTL\n return token;\n}\n\ntype ToolResult = { content: Array<{ type: \"text\"; text: string }>; isError?: boolean };\n\nfunction ok(text: string): ToolResult {\n return { content: [{ type: \"text\", text }] };\n}\n\nfunction err(text: string): ToolResult {\n return { isError: true, content: [{ type: \"text\", text }] };\n}\n\n/** Call Stripe REST API (GET). */\nasync function stripeGet<T = unknown>(\n stripeKey: string,\n path: string,\n connectedAccountId?: string,\n): Promise<{ ok: boolean; status: number; data: T }> {\n const headers: Record<string, string> = { Authorization: `Bearer ${stripeKey}` };\n if (connectedAccountId) headers[\"Stripe-Account\"] = connectedAccountId;\n const res = await fetch(`https://api.stripe.com${path}`, { headers });\n const data = (await res.json()) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n/** Call Stripe REST API (POST, form-encoded). */\nasync function stripePost<T = unknown>(\n stripeKey: string,\n path: string,\n params: Record<string, string>,\n connectedAccountId?: string,\n): Promise<{ ok: boolean; status: number; data: T }> {\n const headers: Record<string, string> = {\n Authorization: `Bearer ${stripeKey}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n };\n if (connectedAccountId) headers[\"Stripe-Account\"] = connectedAccountId;\n const res = await fetch(`https://api.stripe.com${path}`, {\n method: \"POST\",\n headers,\n body: new URLSearchParams(params).toString(),\n });\n const data = (await res.json()) as T;\n return { ok: res.ok, status: res.status, data };\n}\n\n/** Doc + registry merge — mirrors the tool inventory in this file's header comment. */\nexport const STRIPE_CONNECT_TOOL_SCOPES: Record<string, ToolScope> = {\n stripe_connect_status: \"read\",\n stripe_connect_payouts: \"read\",\n stripe_connect_balance: \"read\",\n stripe_connect_refund: \"write\",\n stripe_connect_dispute_list: \"read\",\n radar_review_list: \"read\",\n radar_review_approve: \"admin\",\n radar_review_decline: \"admin\",\n radar_value_list_add: \"admin\",\n radar_rule_toggle: \"admin\",\n};\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerStripeConnectTools(\n server: McpServer,\n ctx: StripeConnectToolContext,\n): void {\n const { env, props } = ctx;\n const operatorId = props.org_id ?? props.sub;\n const kvKey = `stripe_account:${operatorId}`;\n\n /** Look up the operator's connected Stripe account ID from KV. */\n async function getAccountId(): Promise<string | null> {\n return env.CARRIER_USERS.get(kvKey);\n }\n\n // -------------------------------------------------------------------------\n // stripe_connect_status\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_status\",\n \"Read-only: returns the Stripe Connect account status, capabilities, and requirements for the authenticated operator.\",\n {\n operator_id: z\n .string()\n .optional()\n .describe(\"Override operator_id (admin use). Defaults to caller's org/user.\"),\n },\n async ({ operator_id }) => {\n const opId = operator_id ?? operatorId;\n const opKvKey = operator_id ? `stripe_account:${operator_id}` : kvKey;\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const accountId = await env.CARRIER_USERS.get(opKvKey);\n if (!accountId) {\n return ok(JSON.stringify({ status: \"not_connected\", operator_id: opId }));\n }\n\n const result = await stripeGet<{\n id: string;\n charges_enabled: boolean;\n payouts_enabled: boolean;\n details_submitted: boolean;\n requirements: unknown;\n capabilities: unknown;\n default_currency: string;\n settings?: { payouts?: { schedule?: { interval: string; delay_days: number } } };\n }>(stripeKey, `/v1/accounts/${accountId}`);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n const a = result.data;\n const status = a.charges_enabled && a.details_submitted ? \"active\" : \"pending\";\n\n writeAudit(env, {\n tool_name: \"stripe_connect_status\",\n ocs_method: \"stripe.account.read\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({\n status,\n operator_id: opId,\n account_id: accountId,\n charges_enabled: a.charges_enabled,\n payouts_enabled: a.payouts_enabled,\n details_submitted: a.details_submitted,\n requirements: a.requirements,\n capabilities: a.capabilities,\n default_currency: a.default_currency,\n payout_schedule: a.settings?.payouts?.schedule,\n }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_payouts\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_payouts\",\n \"Read-only: list recent payouts for the operator's connected Stripe account.\",\n {\n limit: z.number().int().min(1).max(50).default(10).describe(\"Number of payouts to return.\"),\n status: z\n .enum([\"pending\", \"paid\", \"failed\", \"canceled\", \"in_transit\"])\n .optional()\n .describe(\"Filter by payout status.\"),\n },\n async ({ limit, status }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (status) params.set(\"status\", status);\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n amount: number;\n currency: string;\n status: string;\n arrival_date: number;\n automatic: boolean;\n created: number;\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/payouts?${params.toString()}`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_payouts\",\n ocs_method: \"stripe.payouts.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ payouts: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_balance\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_balance\",\n \"Read-only: returns the current available and pending balance per currency for the operator's connected Stripe account.\",\n {},\n async () => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const result = await stripeGet<{\n available: Array<{ amount: number; currency: string }>;\n pending: Array<{ amount: number; currency: string }>;\n }>(stripeKey, `/v1/balance`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_balance\",\n ocs_method: \"stripe.balance.read\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({\n account_id: accountId,\n available: result.data.available ?? [],\n pending: result.data.pending ?? [],\n }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_refund (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_refund\",\n \"Admin: issue a refund on a charge via the operator's connected Stripe account. Requires confirm_token (call without token first to get one).\",\n {\n charge_id: z.string().min(1).describe(\"Stripe charge ID (ch_...).\"),\n amount_cents: z\n .number()\n .int()\n .min(1)\n .optional()\n .describe(\"Partial refund amount in cents. Omit for full refund.\"),\n reason: z.enum([\"duplicate\", \"fraudulent\", \"requested_by_customer\"]).optional(),\n confirm_token: z\n .string()\n .optional()\n .describe(\"Confirmation token from previous call. Required to execute.\"),\n },\n async ({ charge_id, amount_cents, reason, confirm_token }) => {\n const start = Date.now();\n const toolName = \"stripe_connect_refund\";\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Refund ${amount_cents ? `${amount_cents} cents on` : \"(full) on\"} charge ${charge_id} requires confirmation.\\n` +\n `confirm_token: ${token}\\n` +\n `Call again with confirm_token=\"${token}\" to execute. Token expires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) {\n return err(\"Invalid or expired confirm_token. Call without token to get a new one.\");\n }\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params: Record<string, string> = { charge: charge_id };\n if (amount_cents) params.amount = String(amount_cents);\n if (reason) params.reason = reason;\n\n const result = await stripePost<{\n id: string;\n amount: number;\n currency: string;\n reason: string | null;\n status: string;\n }>(stripeKey, \"/v1/refunds\", params, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.refund.create\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Refund issued: ${result.data.id} — status: ${result.data.status}`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // stripe_connect_dispute_list\n // -------------------------------------------------------------------------\n\n server.tool(\n \"stripe_connect_dispute_list\",\n \"Read-only: list active disputes for the operator's connected Stripe account.\",\n {\n limit: z.number().int().min(1).max(50).default(10),\n status: z\n .string()\n .optional()\n .describe(\"Filter by dispute status (e.g. needs_response, under_review).\"),\n },\n async ({ limit, status }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n const accountId = await getAccountId();\n if (!accountId) return err(\"No connected Stripe account found.\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (status) params.set(\"status\", status);\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n charge: string;\n amount: number;\n currency: string;\n status: string;\n reason: string;\n evidence_details: { due_by: number | null };\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/disputes?${params.toString()}`, accountId);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"stripe_connect_dispute_list\",\n ocs_method: \"stripe.disputes.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ disputes: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_list\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_list\",\n \"Read-only: list pending Radar reviews requiring manual platform decision.\",\n {\n open_only: z.boolean().default(true).describe(\"If true, only returns open (undecided) reviews.\"),\n limit: z.number().int().min(1).max(50).default(10),\n },\n async ({ open_only, limit }) => {\n const start = Date.now();\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const params = new URLSearchParams({ limit: String(limit) });\n if (open_only) params.set(\"open\", \"true\");\n\n const result = await stripeGet<{\n data: Array<{\n id: string;\n charge: string | { id: string };\n reason: string | null;\n opened_reason: string | null;\n closed_reason: string | null;\n created: number;\n closed: boolean;\n }>;\n has_more: boolean;\n }>(stripeKey, `/v1/radar/reviews?${params.toString()}`);\n\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: \"radar_review_list\",\n ocs_method: \"stripe.radar.reviews.list\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(JSON.stringify({ reviews: result.data.data, has_more: result.data.has_more }));\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_approve (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_approve\",\n \"Admin: approve a Radar review, allowing the charge to proceed. Requires confirm_token.\",\n {\n review_id: z.string().min(1).describe(\"Stripe Radar review ID (prv_...).\"),\n confirm_token: z.string().optional(),\n },\n async ({ review_id, confirm_token }) => {\n const toolName = \"radar_review_approve\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Approving review ${review_id} allows the charge to proceed.\\n` +\n `confirm_token: ${token}\\nCall again with confirm_token=\"${token}\" to execute. Expires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const result = await stripePost<{ id: string; closed: boolean }>(\n stripeKey,\n `/v1/radar/reviews/${review_id}/approve`,\n {},\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.review.approve\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Review ${review_id} approved. Charge will proceed.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_review_decline (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_review_decline\",\n \"Admin: decline a Radar review, blocking/closing the charge. Requires confirm_token.\",\n {\n review_id: z.string().min(1),\n confirm_token: z.string().optional(),\n },\n async ({ review_id, confirm_token }) => {\n const toolName = \"radar_review_decline\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Declining review ${review_id} will close/block the charge.\\n` +\n `confirm_token: ${token}\\nExpires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n // Stripe closes a review by approving it with close_reason=fraudulent\n // or by calling close on the underlying charge. The /approve endpoint\n // with a reason is the supported path for platform-level decline.\n const result = await stripePost<{ id: string; closed: boolean }>(\n stripeKey,\n `/v1/radar/reviews/${review_id}/approve`,\n { reason: \"fraudulent\" },\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.review.decline\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Review ${review_id} declined.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_value_list_add (HARD_BLOCK)\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_value_list_add\",\n \"Admin: add an item (email, IP, card fingerprint, country code) to a Stripe Radar block/allow list. Requires confirm_token.\",\n {\n value_list_id: z.string().min(1).describe(\"Stripe Radar value list ID (rsl_...).\"),\n value: z\n .string()\n .min(1)\n .describe(\"The value to add (email, IP address, country code, etc.).\"),\n confirm_token: z.string().optional(),\n },\n async ({ value_list_id, value, confirm_token }) => {\n const toolName = \"radar_value_list_add\";\n const start = Date.now();\n\n if (!confirm_token) {\n const token = await issueConfirmToken(env, props.sub, toolName);\n return ok(\n `HARD_BLOCK: Adding \"${value}\" to list ${value_list_id} will affect future charge decisions.\\n` +\n `confirm_token: ${token}\\nExpires in 5 minutes.`,\n );\n }\n\n const valid = await verifyConfirmToken(env, props.sub, toolName, confirm_token);\n if (!valid) return err(\"Invalid or expired confirm_token.\");\n\n try {\n const stripeKey = env.STRIPE_SECRET_KEY;\n if (!stripeKey) return err(\"Stripe not configured\");\n\n const result = await stripePost<{ id: string; value: string }>(\n stripeKey,\n \"/v1/radar/value_list_items\",\n { value_list: value_list_id, value },\n );\n if (!result.ok) return err(`Stripe error: ${JSON.stringify(result.data)}`);\n\n writeAudit(env, {\n tool_name: toolName,\n ocs_method: \"stripe.radar.value_list.add\",\n status: \"ok\",\n dry_run: false,\n duration_ms: Date.now() - start,\n sub: props.sub,\n reseller_id: props.reseller_id,\n });\n\n return ok(`Added \"${value}\" to Radar list ${value_list_id}.`);\n } catch (e) {\n Sentry.captureException(e);\n return err(`Error: ${e instanceof Error ? e.message : \"unknown\"}`);\n }\n },\n );\n\n // -------------------------------------------------------------------------\n // radar_rule_toggle\n // -------------------------------------------------------------------------\n\n server.tool(\n \"radar_rule_toggle\",\n \"Admin: enable or disable a Stripe Radar rule. NOTE: Stripe does not expose rule CRUD via the public API — this tool returns Dashboard instructions.\",\n {\n rule_id: z.string().min(1).describe(\"Stripe Radar rule ID.\"),\n enabled: z.boolean().describe(\"true = enable, false = disable.\"),\n },\n async ({ rule_id, enabled }) => {\n // Stripe Radar rules are not manageable via the REST API — only the Dashboard.\n return ok(\n `Stripe Radar does not expose rule enable/disable via the public API.\\n` +\n `To ${enabled ? \"enable\" : \"disable\"} rule ${rule_id}:\\n` +\n `1. Open https://dashboard.stripe.com/radar/rules\\n` +\n `2. Find rule ${rule_id} and toggle it ${enabled ? \"on\" : \"off\"}.\\n\\n` +\n `Note: If you need this automated, use the Radar for Platforms beta — contact Stripe support at https://support.stripe.com.`,\n );\n },\n );\n}\n","import type { Env, AuditRow } from \"./types.js\";\n\n/**\n * Fire-and-forget Analytics Engine write.\n * Never await — AE writes are non-blocking and best-effort.\n *\n * Schema:\n * blobs[0] = tool_name\n * blobs[1] = ocs_method\n * blobs[2] = status ('ok' | 'error' | 'scope_denied' | 'dry_run')\n * blobs[3] = dry_run ('0' | '1')\n * blobs[4] = sub (user email)\n * blobs[5] = manus_task_id (empty when not a Manus dispatch)\n * blobs[6] = manus_profile (empty when absent)\n * blobs[7] = manus_key_used: \"primary\" | \"fallback\" (empty when absent)\n * doubles[0] = duration_ms\n * doubles[1] = ocs_status_code (0 = success, -1 = network error)\n * indexes[0] = reseller_id (string; enables per-reseller filtering in SQL queries)\n *\n * Query example (Workers Analytics Engine SQL API):\n * SELECT blob1 AS tool, SUM(_sample_interval) AS calls\n * FROM carrier_mcp_audit\n * WHERE timestamp > NOW() - INTERVAL '7' DAY\n * GROUP BY tool ORDER BY calls DESC\n *\n * Note: use SUM(_sample_interval) not COUNT(*) — AE downsamples at high volume.\n */\nexport function writeAudit(\n env: Env,\n row: AuditRow & { sub: string; reseller_id: number },\n): void {\n env.AUDIT_LOG.writeDataPoint({\n blobs: [\n row.tool_name,\n row.ocs_method,\n row.status,\n row.dry_run ? \"1\" : \"0\",\n row.sub,\n row.manus_task_id ?? \"\",\n row.manus_profile ?? \"\",\n row.manus_key_used ?? \"\",\n ],\n doubles: [row.duration_ms, row.ocs_status_code ?? 0],\n indexes: [String(row.reseller_id)],\n });\n}\n"],"mappings":"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K;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA;AAAA,EAGL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA;AAAA,EAGL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAA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","names":["baseUrl","token","result","token","err","server","z","token","err","server","z","z","DRY_RUN_FIELD","z","server","token","result","client","z","token","err","server","z","z","server","result","err","z","err","server","z","token","z","registerAppTool","registerAppResource","RESOURCE_MIME_TYPE","safeCallWithToken","err","server","registerAppResource","RESOURCE_MIME_TYPE","registerAppTool","z","token","result","z","registerAppTool","registerAppResource","RESOURCE_MIME_TYPE","safeCallWithToken","err","server","registerAppResource","RESOURCE_MIME_TYPE","registerAppTool","z","token","result","newBalance","structured","server","z","server","z","currentMonth","firstDayNextMonth","currentMonth","currentMonth","firstDayNextMonth","resolveUserTier","resolveUserTier","props","props","token","server","result","err","z","z","token","err","server","z","result","err","z","baseUrl","noManusKeyError","result","err","server","z","z","MANUS_API_BASE","MANUS_API_BASE","server","z","result","err","z","Sentry","token","server","props","z","result","token"]}
|