@carrierllc/mcp

中文文档
0.13.75发布于 2026/11/06MITTypeScriptES Module近 30 天下载 6112

Carrier MCP — natural-language control of MVNO/eSIM fleets via the network OCS. Stdio mode for direct integration with Claude Desktop, Cursor, Windsurf, and MCP-compatible clients. Ships the carrier CLI (plugin install + white-label eSIM storefront scaf

原始使用文档
文档目录26 节
  1. Durable inventory issuance
  2. Quick start
  3. Interactive CLI (non-developers)
  4. Natural-language answers
  5. OAuth and terminal handoff
  6. Existing bash/zsh terminal (explicit setup)
  7. Supported read-only MCP owners
  8. Domain commands
  9. Stdio server (token env)
  10. Install in Claude Desktop
  11. Install in Cursor
  12. Install in Windsurf
  13. Remote HTTP (OAuth 2.1)
  14. Environment variables
  15. The browser agent costs real money
  16. Opting in to the OCS portal password
  17. Tools (52 total)
  18. Reseller (6)
  19. Subscriber (13)
  20. Packages (9)
  21. Templates & Zones (7)
  22. Statistics & Misc (8)
  23. Intelligence (9)
  24. Prompts (5)
  25. Destructive tools and dry_run
  26. Links

@carrierllc/mcp

Natural language control of your MVNO/eSIM fleet. 43 OCS tools + 9 intelligence composites + 5 prompts. Direct stdio mode — no OAuth required.

npm License: MIT


Durable inventory issuance

assign_package with account_for_subs (or no ICCID) calls the authenticated Carrier API's /v1/subscribers/issue-from-inventory route. Supply a stable request_key: 1–200 characters, first character alphanumeric, remaining characters alphanumeric, _, ., :, or -. No key is generated. Optional business_reference identifies an existing storefront order; the API must authorize it, it is not proof of ownership.

Set CARRIER_API_TOKEN to your own Carrier credential. Hosted MCP and carrier packages assign --account-id … --template-id … --request-key … --commit forward the current authenticated session credential. Explicit ICCID assignment remains the scoped OCS subscriber path, mutually exclusive with inventory/business reference.

Unknown response/transport outcomes preserve request_key and never trigger an automatic second dispatch. Reconcile using the same key; do not mint a replacement. Dry-run validates without allocating or resolving credentials.

Quick start

Interactive CLI (non-developers)

npx -y -p @carrierllc/mcp carrier-mcp
# opens the Carrier TUI: status, sign-up/sign-in, install MCP, fleet NL examples
carrier status          # plugin + MCP + next steps
carrier plugin install  # zero-cred MCP URL; OAuth on first use in Claude
carrier open signup     # create account
carrier examples        # paste-ready “talk to fleet” prompts
carrier login               # browser once; native OAuth refreshes silently
carrier ask "fleet health"   # uses CLI OAuth / compatible Claude Code OAuth / explicit key
carrier exec -- bash        # real child terminal with CARRIER_API_KEY in its environment

Entry A: register https://mcp.carrier.llc/mcp with no token. The first tool call in Claude/Cursor opens Clerk OAuth (Google / GitHub / email).

Natural-language answers

carrier ask "how many subscribers are there?" and the interactive home's Ask the fleet action present executed tool results as readable answers. Known OCS list summaries use the server's authoritative summary.total, not a recount of the displayed rows. That number describes the result/page, not necessarily the entire fleet; paging, missing rows and shortened display are reported explicitly. Nested subscriber status and SIM inventory status remain separate. A server facet that could not read nested status is not a claim that subscriber status is missing.

This is deterministic presentation, not another AI/model call. The original question distinguishes counts from requested lists/status/details. Unsupported predictions and judgements receive an explicit limitation rather than unrelated records. Current subscriber status uses the shared OCS open-period normalizer, with its maintained closed-history fallback; SIM inventory remains separate.

Default JSON presentation uses typed scalar allowlists and explicit shallow account/result wrappers. Unknown fields, nested shapes, and wrong field types are omitted with a safe limitation; they are never recursively dumped. Safe ordinary scalar facts remain readable. Empty or unsupported summary facets are omitted. Plain-text tool answers are passed through, shortened only at whole sentence/row boundaries; this is not a general redaction guarantee for arbitrary prose. Oversized indivisible rows are omitted entirely with the raw-output hint.

carrier ask "how many subscribers are there?" --json

--json is explicit raw access: complete JSON stdout, no banner/spinner; plain text is encoded as a JSON string. Raw output may contain sensitive data. Failures remain nonzero with errors on stderr. The MCP machine contract and domain commands are unchanged. Ambiguous intents and confirmation-required mutations still do not execute a resolved tool.

OAuth and terminal handoff

Carrier commands, status and Ask the Fleet share credential resolution. Explicit CARRIER_API_KEY / CARRIER_ORG_API_KEY always win. Native carrier login stores a private refreshable session with one cross-process owner lock and atomic writes. Login, refresh and logout serialize; a completed logout cannot be resurrected by an earlier refresh. A crashed CLI owner leaves a fail-closed credentials.lock directory: verify that no CLI login/refresh is running before manually removing that directory. Changing the callback port triggers fresh client registration. Native login and refresh request the exact production MCP resource. A present wrong/malformed token-response resource is rejected before credential storage; legacy absence is distinct and refresh retains a previously known binding.

Existing bash/zsh terminal (explicit setup)

source "$(carrier shell-path bash)" # use zsh instead of bash in zsh
carrier_auth_export
# CARRIER_API_KEY is now exported in THIS shell and its subsequent children.
# Before an arbitrary headless job, refresh this snapshot again:
carrier_auth_export && your-headless-job
carrier logout
carrier_auth_clear                 # erase this shell's snapshot too

Only a shipped static file is sourced. No secret is printed, evaluated as code, put in command arguments/history, or written to a startup file. The function reads an anonymous private pipe via an inherited descriptor. It refuses shell traps and turns off xtrace/verbose without restoring them, because the next caller command could expand the newly exported environment. Bash opt-in loading enables errtrace so caller ERR traps are visible for refusal. Trusted commands, same-UID process environment readers and crash dumps can still expose a bearer; this is not protection from a compromised shell/OS. Do not re-enable tracing around credentials.

Shell acceptance requires both bash and zsh: pnpm test:oauth-shell. CARRIER_TEST_ZSH may point to an isolated zsh binary and CARRIER_TEST_ZSH_MODULE_PATH to its matching modules. The general repair suite reports a missing zsh interpreter as an explicit SKIP, never a zsh pass; the acceptance command fails when either interpreter is unavailable.

OAuth exports carry CARRIER_OAUTH_ORIGIN, CARRIER_OAUTH_EXPIRES_AT (epoch ms) and a CARRIER_OAUTH_HANDOFF fingerprint plus non-secret CARRIER_OAUTH_BINDING. Carrier invocations reread only the selected owner, source directory/file, server, registration and opaque subject/grant. Same-owner token rotation is allowed; expiry, logout, owner/config/account/org changes fail closed, never switch to another valid client session. Old exports without binding must be exported again. These metadata equality checks are not cryptographic account/org proof. Arbitrary programs retain it until expiry: re-run carrier_auth_export before consumption. Replacing CARRIER_API_KEY intentionally overrides the fingerprint and remains authoritative. carrier_auth_clear removes this shell's exported key and metadata, not the other client's login.

carrier exec -- <command> [args...] remains available for a trusted child only; no setup required, no parent-shell mutation, and child exit/signal is preserved. OAuth is a short-lived bearer, not an ak_ key.

Supported read-only MCP owners

Without a native session, a current compatible MCP access token may be reused; no refresh grant is copied, rotated or written by Carrier. If the owner expires, refresh it in that client or use native carrier login. No owner reauth command is invoked. Multiple current owners require CARRIER_MCP_OAUTH_OWNER=hermes or claude; the CLI never guesses which account to use.

  • Claude Code 2.1.277 and 2.1.296: exact inspected config and storage adapters. The owner's .claude.json lives under CLAUDE_CONFIG_DIR || ~; an existing legacy .config.json takes precedence. For the consuming CLI's cwd, local projects[real git root || real cwd].mcpServers wins over approved ancestor .mcp.json project config, which wins over user config. Other projects are not candidates. Project import supports explicit trusted user settings approval only; pending/rejected or ambiguous policy/settings fail closed. Hashes the actual {type,url,headers:headers||{}} in original insertion order: HTTP, SSE and absent type remain distinct. No hardcoded empty-header hash. Managed selection remains unsupported and fails closed; no inferred plugin/proxy/CLI override resolution. Authorization/API-key/cookie headers and unresolved environment substitutions are not imported as OAuth. CLAUDE_SECURESTORAGE_CONFIG_DIR takes precedence by presence for credential storage; present-empty selects ~/.claude, while nonempty and CLAUDE_CONFIG_DIR retain the exact NFC strings (no trim or resolve before the Keychain hash). USER || os.userInfo().username selects the exact account, with Claude's invalid-account fallback. An approved custom OAuth environment selects only its own suffix; unrelated suffixes/accounts are never enumerated. Linux reads the private .credentials.json. CARRIER_MCP_OAUTH_FILE explicitly selects that file backend on either platform, without consulting Keychain. CamelCase expiry is epoch milliseconds.
  • Hermes: selected HERMES_HOME (default ~/.hermes), exact configured mcp_servers.carrier.url, with private mcp-tokens/carrier.json, .client.json and .meta.json. Real snake_case access-token fields, hermes_issuer, Bearer type and absolute expires_at in seconds are required. Issuer/discovery endpoints, client registration and resource configuration are checked. Legacy relative-only expiry is refused. Config JSON and simple scalar block YAML are supported; nested/alias/flow constructs fail closed.

CARRIER_MCP_OAUTH_SERVER selects an alternative explicit name. Private mode and current-user file ownership, exact issuer/resource, read scope and finite future expiry are required. CARRIER_OAUTH_ACCOUNT optionally selects the Carrier opaque token's user prefix; it is not cryptographic account/org proof. Only the server validates actual token audience, organization and grant permissions. Invalid native state never falls through to another owner.

On macOS the packaged native/claude-keychain.js uses the built-in JXA Objective-C bridge and Apple Security Framework: one generic-password query, exact service and account, kSecMatchLimitOne, kSecReturnData, kSecUseAuthenticationUIFail, plus process-local legacy UI inhibition. There is no compiler/download/install-at-login dependency, no security -w, no broad dump, and no owner lock/refresh/login. Only non-secret selectors reach stdin. Only the selected access-token fields reach an inherited private FD; stdout/stderr are discarded. Owner refresh grants, client secrets and unrelated credentials never leave the helper. Apple may report an ACL prompt requirement or locked store identically (errSecInteractionNotAllowed): locked denotes that noninteractive refusal, not a diagnosis of the physical Keychain state. errSecAuthFailed/user-cancel are denied, parse errors are malformed, and other failures are unavailable. None falls back to plaintext or Hermes. Only errSecItemNotFound for the exact item permits Claude's documented private file fallback. An existing item without the exact MCP entry does not fall back. Keychain reuse requires claude --version to be exactly 2.1.277 or 2.1.296; other versions fail closed. Compatibility is an explicit inspected allowlist, not a version range. The source contracts are tested on Linux; a real Darwin absent-item probe also executes the packaged helper byte-for-byte without stdout/stderr. Successful existing-item access and installed end-to-end Mac OAuth remain unproved. The inspected Mac 2.1.296 query returned denied (OSStatus -25293), not absence; this adapter never broadens Keychain access or falls back after that refusal. Claude Desktop, Cursor, Windsurf and mcp-remote remain unsupported owners. Issuer-less entries are intentionally rejected. carrier logout disables MCP reuse until a successful native login and never edits the owner's store or another shell's explicit keys.

Native API references: Apple SecItemCopyMatching, Apple SecItem.h, Apple JXA release notes, Claude authentication storage.

Domain commands

With a headless key in the environment, each capability has its own command, grouped by the same domains the console uses: subscribers, packages, templates, zones, steering, intelligence.

carrier subscribers list --account-id 1170
carrier subscribers usage --iccid 8944… --json     # last 7 days by default
carrier packages list --iccid 8944…
carrier intelligence fleet-health
carrier steering assign --iccid 8944… --list-id 12 --commit

carrier <domain> --help lists the verbs, carrier <domain> <verb> --help the flags. Two rules apply everywhere:

  • --json prints the raw tool response on stdout and nothing else, so it pipes into jq.
  • Commands that change something preview as a dry run. Add --commit to apply.

Stdio server (token env)

CARRIER_OCS_API_TOKEN=your_key npx -y -p @carrierllc/mcp carrier-mcp

Get a key at mcp.carrier.llc or an org API key from the console.


Install in Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "carrier": {
      "command": "npx",
      "args": ["-y", "-p", "@carrierllc/mcp", "carrier-mcp"],
      "env": {
        "CARRIER_OCS_API_TOKEN": "YOUR_KEY"
      }
    }
  }
}

Install in Cursor

Add to ~/.cursor/mcp.json:

{
  "mcpServers": {
    "carrier": {
      "command": "npx",
      "args": ["-y", "-p", "@carrierllc/mcp", "carrier-mcp"],
      "env": {
        "CARRIER_OCS_API_TOKEN": "YOUR_KEY"
      }
    }
  }
}

Install in Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "carrier": {
      "command": "npx",
      "args": ["-y", "-p", "@carrierllc/mcp", "carrier-mcp"],
      "env": {
        "CARRIER_OCS_API_TOKEN": "YOUR_KEY"
      }
    }
  }
}

Remote HTTP (OAuth 2.1)

For multi-user deployments with OAuth 2.1 + PKCE, use the remote endpoint:

{
  "mcpServers": {
    "carrier": {
      "type": "http",
      "url": "https://mcp.carrier.llc/mcp"
    }
  }
}

Environment variables

VariableRequiredDefaultDescription
CARRIER_API_TOKENInventory issuance—Your own authenticated Carrier API credential. Required for durable assign_package inventory; never falls back to an OCS token.
CARRIER_API_BASE_URLNohttps://api.carrier.llcCarrier REST API origin for durable inventory. Do not use the OCS provider URL.
CARRIER_OCS_API_TOKENExplicit OCS tools—Your OCS API token; not a Carrier API credential. Older releases used a different variable name; it is still read
CARRIER_OCS_BASE_URLNohttps://ocs.esimvault.cloudOCS base URL (no trailing slash)
BROWSER_USE_API_KEYNo—Browser Use Cloud key. Enables the browsing agent (ui_agent_ask). Runs are billed to this key at roughly $0.20–1.00 each
CARRIER_BROWSER_USE_MAX_RUNSNo10Browser-agent runs allowed per CLI process. 0 disables the agent. See the caveats below
CARRIER_ALLOW_PORTAL_PASSWORDNounsetSet to 1 to allow the ten OCS-dashboard tools to use a portal login from this machine. See below
CARRIER_OCS_PORTAL_USERNAMENo—OCS portal username. Only used when the flag above is set
CARRIER_OCS_PORTAL_PASSWORDNo—OCS portal password. Only used when the flag above is set
CARRIER_OCS_DASHBOARD_URLNohttps://ocs.esimvault.cloudDashboard the portal agent logs into
GREENZONE_PORTAL_URLNo—Portal host for the greenzone_whitelist_* tools. Wins over the two below
CARRIER_OCS_PORTAL_URLNo—Reseller portal host. Used by Greenzone when GREENZONE_PORTAL_URL is unset
OCS_DASHBOARD_URLNohttps://portal-esimvault.cloudPortal host Greenzone falls back to. CARRIER_OCS_BASE_URL is never used for the portal

The browser agent costs real money

ui_agent_ask and the OCS-dashboard tools dispatch a hosted browser agent. Each run costs roughly $0.20–1.00, billed to your own BROWSER_USE_API_KEY.

CARRIER_BROWSER_USE_MAX_RUNS caps how many runs one CLI process may start. Read what it does not do:

  • It caps runs, not dollars. The vendor prices a run after it finishes.
  • It does not survive a restart. Each new CLI process starts a fresh count, so a caller that respawns the CLI between runs is not bounded by it.

The only hard financial ceiling is a spend limit set in your Browser Use account. Set one.

Opting in to the OCS portal password

Ten ui_* tools — steering lists, sub-account creation, destination lists, package-template deletion, location-zone edits — have no OCS REST equivalent. They work by driving the OCS web dashboard, which means logging into it. By default the CLI has no portal login and these tools refuse.

You can supply one. Understand what you are supplying first:

  • This is a portal password, not a scoped API token. It grants full dashboard access to anyone who holds it. CARRIER_OCS_API_TOKEN is a different kind of secret and is not a precedent for this.
  • An environment variable is a poor place for one. It is readable from shell history, from ps output by any process on the machine, and from CI logs.
  • It is sent to Browser Use Cloud, which types it into the OCS login form.

Carrier never logs it, never returns it in tool output, and never writes it to an audit row — but the exposure above is yours to accept.

Two independent things must both be true, and neither alone does anything:

export CARRIER_ALLOW_PORTAL_PASSWORD=1
export CARRIER_OCS_PORTAL_USERNAME='...'
export CARRIER_OCS_PORTAL_PASSWORD='...'

With the flag set, the CLI prints the warning to stderr at startup. Without both halves, the ten tools return the same "requires the remote Worker" refusal they returned before this option existed.

Every one of the ten accepts dry_run: true, which returns the agent prompt with the credentials redacted and dispatches nothing. Use it first.

ui_request_reseller_relay_change is not one of the ten and is never gated: it drafts text and touches no portal.


Tools (52 total)

Reseller (6)

ToolScopeDescription
list_reseller_accountsreadList all accounts across all resellers
get_reseller_inforeadRetrieve reseller details
esim_status_per_accountreadeSIM status breakdown per account
list_sponsorsreadList all sponsor networks
list_steering_listsreadList all network steering lists
modify_account_balancewriteAdjust or set reseller account balance

Subscriber (13)

ToolScopeDescription
get_subscriberreadGet full subscriber details by ICCID or MSISDN
list_subscribersreadList subscribers with optional filters
get_sim_provider_statusreadCheck SIM provider-level status
get_subscriber_locationreadGet last known subscriber location
hlr_get_bitratereadGet HLR bitrate for a subscriber
modify_subscriber_balancewriteAdjust or set subscriber balance
modify_subscriber_statuswriteChange subscriber OCS status
change_sim_statuswriteChange SIM status at provider level
modify_subscriber_contact_infowriteUpdate subscriber contact info
set_subscriber_traffic_restrictionswriteConfigure traffic restrictions
modify_subscriber_steering_listwriteChange network steering list for a subscriber
hlr_set_bitratewriteSet HLR bitrate for a subscriber
move_subscriber_range_to_accountwriteMove subscriber range to another account

Packages (9)

ToolScopeDescription
list_subscriber_packagesreadList all prepaid packages for a subscriber
list_package_templatesreadList all prepaid package templates
assign_packagewriteAssign package template to subscriber
assign_recurring_packagewriteAssign recurring package to subscriber
modify_package_limitswriteChange data/voice/SMS limits on active package
modify_package_expirywriteChange expiration date of active package
modify_package_statuswriteActivate or deactivate a subscriber package
stop_resume_recurring_packagewriteStop or resume recurring package auto-renewal
delete_subscriber_packagewriteRemove a package from a subscriber

Templates & Zones (7)

ToolScopeDescription
clean_all_packageswriteRemove ALL packages from a subscriber
create_package_templatewriteCreate a new prepaid package template
modify_template_corewriteModify core settings of a package template
modify_template_recurringwriteModify recurring settings of a package template
modify_template_throttlingwriteModify throttling settings of a package template
list_location_zonesreadList countries/networks in a location zone
list_detailed_location_zonesreadGet detailed location zone definitions

Statistics & Misc (8)

ToolScopeDescription
subscriber_usagereadGet daily usage for a subscriber (max 7 days)
subscriber_network_eventsreadGet network events for a subscriber (max 7 days)
subscriber_active_periodreadGet subscriber active period
get_tariffreadRetrieve customer tariff/pricing table
list_destination_prefixesreadList phone number prefixes in destination lists
list_network_profilesreadList all available network profiles
create_location_zonewriteCreate a new location zone
send_smswriteSend MT SMS to a subscriber

Intelligence (9)

AI composites that chain multiple OCS calls to produce structured insights:

ToolDescription
diagnose_subscriberChains 5+ OCS calls to diagnose connectivity issues
fleet_healthSingle-call fleet overview: accounts, eSIM counts, low-balance alerts
detect_usage_anomaliesDetect abnormal usage patterns and burn-rate risks
optimize_packageMatch subscriber usage to the best available package
churn_riskScore churn risk (0-100) with retention recommendations
audit_network_coverageAudit network coverage and steering effectiveness
marketing_intelligenceMarket segmentation and upsell opportunities
high_cost_subscribersIdentify highest-cost subscribers for margin optimization
detect_country_entryResolve the current country from the last MCC and compare it to an expected country

Prompts (5)

PromptArgsDescription
fleet_health_report—Full fleet health overview
subscriber_deep_diveiccidDeep diagnostic for a single subscriber
revenue_optimization—Revenue analysis and upsell opportunities
coverage_analysis—Network coverage audit and steering recommendations
bulk_operations_planneroperationPlan and dry-run a bulk fleet operation

Destructive tools and dry_run

All write/admin tools accept an optional dry_run: true argument. When set, the tool returns the would-be request without calling OCS — safe for previewing operations.

"Suspend ICCID 8988... but check what it would do first (dry_run)"


MIT License. Copyright 2025 Lifecycle Innovations Limited.

版本与发布记录

@carrierllc/mcp 共发布 120 个版本,首次发布于 2026/05/11;过去 12 个月发布了 120 个版本。

版本发布日期距今
0.13.75latest2026/11/063 天前
0.13.742026/11/063 天前
0.13.732026/11/053 天前
0.13.722026/11/053 天前
0.13.712026/11/054 天前
0.13.702026/11/054 天前

关于 @carrierllc/mcp 的常见问题

@carrierllc/mcp 是什么?

Carrier MCP — natural-language control of MVNO/eSIM fleets via the network OCS. Stdio mode for direct integration with Claude Desktop, Cursor, Windsurf, and MCP-compatible clients. Ships the carrier CLI (plugin install + white-label eSIM storefront scaf

如何安装 @carrierllc/mcp?

在项目目录运行 npm install @carrierllc/mcp,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 carrier、carrier-mcp,可以用 npx carrier 直接运行。

@carrierllc/mcp 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@carrierllc/mcp 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@carrierllc/mcp 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@carrierllc/mcp 可以商用吗?

@carrierllc/mcp 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@carrierllc/mcp 的下载量有多少?

根据 npm 官方下载统计,@carrierllc/mcp 在 2026/10/09 – 2026/11/07 这 30 天内被下载 6,112 次,日均约 204 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@carrierllc/mcp 还在维护吗?

最新版本 0.13.75 发布于 2026/11/06(3 天前);至今共发布 120 个版本,其中过去 12 个月发布了 120 个;首次发布于 2026/05/11。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。