starlink-enterprise-mcp
This server exposes the Starlink Enterprise API as MCP tools, letting AI agents manage Starlink service accounts, devices, and billing through natural-language tool calls.
Account & products: view account info, products, and query data usage.
Service lines: list, create, update, nickname, change product/public IP, add/remove terminals, manage priority-data opt-in/out, recurring data blocks, one-time top-ups, consume-from-pool, billing partial periods, and deactivate service lines.
User terminals: list/add/remove terminals, reboot them, assign configs, and configure L2VPN VLANs.
Routers: view/get/update/reboot router configs, TLS configs, default configs, sandbox clients, local content, and sandbox heartbeat.
Addresses & contacts: create, read, update, and delete account addresses and contacts.
Data pools: list pools, query usage, and enable/disable automatic top-up.
Aviation/managed accounts: post flight events and create managed customer accounts.
Deployment/operator controls: run locally via stdio or hosted via HTTP, stateless multi-instance, Firestore persistence, OAuth proxy with service-account client credentials, transparent bearer re-minting, and tunable tool exposure (disable destructive tools, etc.).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@starlink-enterprise-mcp list my Starlink terminals and their status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Starlink Enterprise MCP Server
π°οΈ Hosted, multi-account MCP for the Starlink Enterprise API Any AI agent β Claude, ChatGPT, anything that speaks MCP β connects with a real Starlink V2 Service Account, drives the full Enterprise API, and stays connected indefinitely. The Client Secret never touches the model.
β‘ Features
π Hosted OAuth proxy with API-key login β The server is the OAuth 2.1 authorization server. But Starlink has no interactive OAuth and no MFA, so the browser login page doesn't ask for a username and password β it asks for a Service Account Client ID + Client Secret. The server validates them with a
client_credentialsgrant; credentials never enter the model's context.π Transparent token re-minting β Starlink bearer tokens are short-lived (~15 min) and have no refresh token. The server stores the service-account credentials alongside the issued MCP token and silently re-mints a fresh bearer before expiry, and again on any
401. AI sessions stay alive across long conversations.πͺ Stateless login state β OAuth pending state rides in HMAC-signed
HttpOnlycookies, so logins survive container restarts and Cloud Run instance switches.ποΈ Firestore persistence β Issued tokens and DCR client registrations survive deploys and scaling events when
MCP_PERSISTENCE=firestore.π€ Claude and ChatGPT support β Public-client dynamic registration (
token_endpoint_auth_method=none, PKCE only) means ChatGPT connects out of the box alongside confidential clients like Claude.𧬠55 auto-generated tools from the spec β The Starlink Enterprise v2 OpenAPI spec, regenerated on every build. Drop in a new spec and rebuild to pick up new endpoints.
π― No curated layer needed β At 55 operations the full tool surface fits comfortably in a model's working memory, so every tool is exposed directly with read/write/destructive annotations.
βΎοΈ Stateless by default β No
Mcp-Session-Id, no in-memory session map, no session affinity. Any instance can serve any request, so autoscaling and cold starts stop breaking mid-conversation.π§Ύ Typed results β Every tool declares an
outputSchemaderived from the OpenAPI response, and returns matchingstructuredContent. The model gets a typed object, not an opaque JSON blob.πͺ Operator-tunable β Disable globs (
MCP_DISABLED_TOOLS=delete_*,*reboot*), a semantic destructive toggle (MCP_DISABLE_DESTRUCTIVE=true), branded login page (MCP_LOGIN_HEADER,MCP_ICON_URL). No code change for per-deployment policy.π§ͺ A real test suite β 108 tests, including a draft-2020-12 JSON Schema guard that compiles every tool's input and output schema on every run, and end-to-end JSON-RPC over the actual transport.
Related MCP server: agentforge
π How auth differs from a username/password MCP
Username/password OAuth proxy | This server (Starlink) | |
Login page collects | username + password | Service Account Client ID + Client Secret |
Upstream grant |
|
|
MFA | yes | none (service accounts skip MFA) |
Refresh | upstream refresh token | re-run |
Token TTL | hours | ~15 min, re-minted on expiry / 401 |
The DCR + browser-redirect OAuth shell is identical β what changed is the login form and the upstream grant.
ποΈ Architecture
AI client (Claude/ChatGPT)
β OAuth 2.1 DCR + browser login (PKCE)
βΌ
[ Starlink MCP HTTP server (this repo) ] β OAuth proxy, login page (Client ID + Secret), cookies, Firestore
β per-account Starlink bearer (client_credentials)
βΌ
[ Starlink Enterprise API https://www.starlink.com/api ]Each issued MCP bearer maps to a stored upstream Starlink token plus the service-account credentials used to mint it, so the server can re-mint silently.
π» Running locally (stdio)
npm install
npm run build
export STARLINK_CLIENT_ID=<your-service-account-client-id>
export STARLINK_CLIENT_SECRET=<your-service-account-secret>
npm start # MCP_TRANSPORT defaults to stdioCreate a V2 service account at Account Settings β API V2 Service Accounts (requires the Admin or Service Account Management role).
Add this entry to your local MCP client config (Claude Desktop, etc.):
{
"mcpServers": {
"starlink": {
"command": "node",
"args": ["/path/to/starlink-enterprise-mcp/build/index.js"],
"env": {
"STARLINK_CLIENT_ID": "...",
"STARLINK_CLIENT_SECRET": "..."
}
}
}
}You can also set STARLINK_ACCESS_TOKEN directly to skip the grant if you
already hold a bearer.
π Running as a hosted server (HTTP)
export MCP_TRANSPORT=http
export MCP_PORT=3000
export MCP_BASE_URL=https://mcp.example.com
export MCP_SESSION_SECRET=<32+ random hex> # signs login-state cookies
npm startConnect from Claude / ChatGPT by giving it the URL https://mcp.example.com/mcp.
The client DCR-registers, redirects the user to /authorize, the user pastes
their Service Account Client ID + Secret, and the bearer flows back to the AI
automatically. No upstream operator credentials are needed in HTTP mode β
each user brings their own service account.
Pass-through mode (credentials configured in the MCP client)
Set MCP_AUTH_MODE=passthrough and the connector supplies the Starlink Service
Account as its OAuth client_id + client_secret (configured in Claude/ChatGPT,
not on a login page). The server treats any presented client_id as a dynamic
client, then at the /token exchange validates the client_secret against
Starlink's client_credentials grant β a successful grant is the
authentication. The credentials are then bound to that session and re-minted as
usual. No login page, no server-side credentials, fully multi-tenant.
export MCP_AUTH_MODE=passthroughIn the client's connector setup, point it at https://β¦/mcp and enter your
Starlink Service Account Client ID and Client Secret as the OAuth client
credentials. Requirements: the client must use the authorization-code flow with
PKCE and send the client_secret at the token endpoint (client_secret_post).
Single-account mode (skip the login page)
If you set STARLINK_CLIENT_ID + STARLINK_CLIENT_SECRET on the server, the
/authorize step auto-logs-in with those and the credential-entry page is never
shown β every user who connects shares that one Starlink account. Leave them
unset for the multi-tenant login-page behavior above.
export STARLINK_CLIENT_ID=<service-account-id>
export STARLINK_CLIENT_SECRET=<service-account-secret>Trade-off: in single-account mode the endpoint is only as private as its URL β DCR registration is open, so anyone who can reach
/mcpand complete the (credential-free) OAuth flow uses that shared account. Put it behind access control, or accept that the URL is the secret.
βοΈ Cloud Run deployment
Ships with a Cloud Run-friendly Dockerfile.
Component | Purpose |
Cloud Run service | Runs the HTTP server. No session affinity or |
Firestore (native mode) | Persistent token store and DCR client registry |
Cloud Run SA β | Firestore access |
Pushes to main deploy through .github/workflows/deploy.yml, which runs the
suite, builds the image in the runner, pushes it to Artifact Registry, and
deploys it by digest. It then asserts the live revision is that digest, that an
unauthenticated /mcp answers 401, and that pass-through advertises no
registration_endpoint.
It does not use gcloud builds submit. That path stages a source tarball in the
legacy gs://<project>_cloudbuild bucket and is refused under the external
account credentials GitHub Actions federates with, whatever storage role the
deploy identity holds.
To deploy by hand from a checkout instead:
image=<region>-docker.pkg.dev/<project>/cloud-run-source-deploy/starlink-enterprise-mcp
docker build -t "$image:$(git rev-parse HEAD)" .
docker push "$image:$(git rev-parse HEAD)"
gcloud run deploy starlink-enterprise-mcp --image "$image:$(git rev-parse HEAD)" \
--region=<region> --project=<project> --port=3000Required env vars on Cloud Run:
Var | Notes |
| enable the HTTP transport |
| public URL, e.g. |
| 32+ chars; signs login-state cookies & must be stable across instances |
| enable Firestore-backed tokens and clients |
| Firestore project ID (auto-set on Cloud Run) |
Transport and protocol options:
Var | Default | Notes |
|
|
|
|
| Return plain JSON instead of SSE, for intermediaries that break event streams |
| unset | Comma-separated allowlist; a non-matching |
|
|
|
|
| Page size for |
|
| Enable task augmentation (see above) |
|
| Firestore collection for task state |
| Starlink API docs |
|
Also optional: STARLINK_API_URL, STARLINK_TOKEN_URL (defaults are correct
for production), MCP_LOGIN_HEADER, MCP_ICON_URL, MCP_LOGIN_LOGO_URL,
MCP_DISABLED_TOOLS, MCP_DISABLED_ACTIONS, MCP_DISABLE_DESTRUCTIVE,
MCP_CORS_ORIGIN.
MCP_ICON_URLnow does double duty: it still serves the favicon and login-page logo, and it is also advertised as the server's MCPiconsentry so clients can render it in a connector list.
Other targets: fly.toml (Fly.io), render.yaml (Render), railway.toml
(Railway), docker-compose.yml, and k8s/ manifests (apply with
kubectl apply -k k8s/).
Security note on persistence. In HTTP mode the issued-token records hold each user's Starlink service-account Client ID + Secret so the server can re-mint bearers. Protect the token store accordingly β restrict the Firestore collection / file volume, and rotate
MCP_SESSION_SECRETand service-account secrets per Starlink's guidance if exposure is suspected.
π OAuth flow (detailed)
AI client hits
GET /.well-known/oauth-protected-resource/mcpand/.well-known/oauth-authorization-serverfor discovery.AI client POSTs
/register(RFC 7591 DCR). Public clients passtoken_endpoint_auth_method=noneand get back aclient_idonly; confidential clients also get aclient_secret. Registrations persist in Firestore.AI redirects the user's browser to
/authorize?...with PKCE parameters. The server stores the pending request in a signed cookie (mcp_pending_auth, 15 min TTL) and renders the login page.User submits their Service Account Client ID + Client Secret β server runs
POST {STARLINK_TOKEN_URL}withgrant_type=client_credentials. On success it stores the Starlink token + credentials and issues an authorization code.The server redirects back to the AI client; cookies are cleared.
AI exchanges the code at
/tokenfor the MCP-issued bearer + refresh token.On every
/mcprequest, the server verifies the bearer and transparently re-mints the upstream Starlink token if it's near expiry. On a401from the API, the client re-mints and retries once.
π MCP spec conformance
Targets MCP 2025-11-25 and negotiates down to any revision the client asks for (2025-06-18, 2025-03-26, 2024-11-05).
Feature | Revision | Status |
Streamable HTTP, stateless | 2025-03-26 | Default. |
| 2025-06-18 | Unsupported version β 400 |
Structured output ( | 2025-06-18 | 52 of 55 tools; |
Tool | 2025-06-18 | All tools |
OAuth Resource Server + protected-resource metadata | 2025-06-18 | RFC 9728 discovery, |
No JSON-RPC batching | 2025-06-18 | Not accepted |
Icons on server and tools | 2025-11-25 (SEP-973) | From |
| 2025-11-25 | Sent at initialize |
Invalid | 2025-11-25 | Via |
Validation errors as tool errors, not protocol errors | 2025-11-25 (SEP-1303) | Arguments validated, types coerced |
Tool-name format guidance | 2025-11-25 (SEP-986) | Validated at startup |
JSON Schema 2020-12 as default dialect | 2025-11-25 (SEP-1613) | Input and output schemas |
Tasks (durable requests, polling, deferred results) | 2025-11-25 (SEP-1686) | Opt-in via |
| 2024-11-05 | Opt-in via |
| 2024-11-05 | Supported |
Not implemented, and why: resources and prompts (this server exposes an API surface, not documents or templates), completions (nothing to complete without prompts or resource templates), sampling, elicitation, and roots (client-side features this server has no use for β every tool call is fully specified by its arguments).
Stateless vs. session mode
Stateless is the default. Each request gets a fresh Server and transport, and
no Mcp-Session-Id is issued.
This matters on any autoscaled host. With sessions, initialize builds
in-memory state on one instance, and the next tools/call gets load-balanced to
an instance that has never heard of that session ID β the client sees
Invalid or missing session ID and the conversation dies. Stateless has no
affinity requirement, so min-instances=1 and session affinity stop being
load-bearing.
Nothing is given up here: this server sends no server-initiated messages. The
tool list is fixed at build time from the OpenAPI spec, and there are no
resources or prompts to subscribe to, so the standalone GET /mcp SSE stream
that sessions exist to support has nothing to carry. In stateless mode it
answers 405 rather than opening a stream that can never produce anything.
Set MCP_STATELESS=false on a single-instance deployment to restore sessions.
Tasks
Off by default. A task-augmented tools/call returns a handle immediately and
the client collects the result later via tasks/result, decoupling the tool's
runtime from the HTTP request's lifetime.
Enabling it on Cloud Run needs two things that are not the default:
--no-cpu-throttling, or the container is frozen once the response is sent and the detached work never finishes.MCP_PERSISTENCE=firestore, or the poll lands on an instance that has never heard of the task. With Firestore the store is shared and any instance can answer. Without it you get an in-memory store and a startup warning.
export MCP_TASKS=true
export MCP_PERSISTENCE=firestore # required for more than one instanceTask documents live in mcp_tasks (override with MCP_TASKS_COLLECTION) and
carry an expiresAt field β set a Firestore TTL policy on it to have Firestore
reclaim them. Client-requested TTLs are clamped to 24 hours.
π§° Tools
55 tools generated from spec/starlink-enterprise-v2.json, grouped by tag:
Group | Examples |
Account |
|
Service Lines |
|
User Terminals |
|
Routers |
|
Addresses |
|
Contacts |
|
Data Pools |
|
Flights |
|
Managed |
|
Each tool carries a human-readable title, an inputSchema, an outputSchema,
and the full annotation set: readOnlyHint, destructiveHint, idempotentHint
(GET/PUT/DELETE), and openWorldHint. Reboots and deletes are flagged
destructive β hide them all with MCP_DISABLE_DESTRUCTIVE=true, or selectively
with e.g. MCP_DISABLED_TOOLS=delete_*,*reboot*.
Tool names map 1:1 to operations ({method}_{path}, with the /public/v2
prefix stripped). Two deep service-line paths are abbreviated to fit the MCP
64-character name limit.
Result shape
Results carry structuredContent matching the tool's outputSchema, shaped
like the Starlink response envelope β payload under content, plus isValid:
{
"content": [{ "type": "text", "text": "{ \"content\": { \"accountNumber\": \"ACC-β¦\" } }" }],
"structuredContent": { "content": { "accountNumber": "ACC-β¦", "regionCode": "US" }, "isValid": true }
}The schemas are deliberately permissive: no required, no
additionalProperties: false, and nullable fields widened to a type union. A
Starlink response that has drifted from the published spec still validates
rather than being rejected by a strict client. If a client is still unhappy,
MCP_STRUCTURED_OUTPUT=false drops both the schemas and the structured results
in one move.
Errors come back in the result, not as protocol errors. A permission
failure, a bad argument, or an operator-disabled tool returns
isError: true with an explanatory message, so the model can read what went
wrong and retry. Only an unknown tool name is a JSON-RPC error. Arguments are
validated against the input schema before any call is made, and obvious type
mismatches ("50" for a number) are coerced rather than rejected.
π Regenerating tools
The spec lives at spec/starlink-enterprise-v2.json (sourced from
https://web-api.starlink.com/enterprise/swagger/v2/swagger.json). That host
now serves Starlink's consumer web app and no longer carries this path, and
the new spec location is not known. Do not guess a replacement URL. To refresh
once a real source turns up:
# drop a new spec into spec/starlink-enterprise-v2.json, then:
npm run generate # rewrites src/generated/
npm run build
npm testnpm run build runs generate automatically via the prebuild hook.
π§ͺ Tests
npm testThe Firestore-backed tests are emulator-gated and skip cleanly without one.
π What this server is
Two MCP transports.
stdiofor local CLI integrations andhttp(Streamable HTTP, stateless by default) for hosted deployments. Production useshttp.MCP 2025-11-25, negotiating down to older revisions on request.
Auto-generated tools from the Starlink Enterprise v2 OpenAPI spec, regenerated on every build, with typed
structuredContentresults.Hosted OAuth login where the login page collects Starlink Service Account credentials (Client ID + Secret), not a username/password. MFA does not apply to service accounts.
Transparent token re-minting via
client_credentials(no refresh token).Firestore persistence for tokens and DCR clients when
MCP_PERSISTENCE=firestore.
License
MIT
Available Tools
55 toolsdelete_contacts_by_subject_idADestructive
Delete contact β Required permission: Admin Only - API User Management, Edit.Deletes contact based on specified subject Id on the authenticated account. β [DELETE /public/v2/contacts/{subjectId}]
Inputs: subjectId (required).
delete_routers_configs_tlsADestructive
Delete TLS config β Required permission: Device command and configuration, Edit.Deletes a TLS certificate and key pair from the set of TLS configs that can be reused when saving router configs and only specifying the certificate. Does not affect any router configs that were already saved, just removes it from list of certificates that the matching key will be inserted on save for. β [DELETE /public/v2/routers/configs/tls]
Inputs: certificateBase64Pem (required).
delete_service_lines_by_service_line_numberBDestructive
Deactivate a service line β Required permission: Service plan, Edit. β [DELETE /public/v2/service-lines/{serviceLineNumber}]
Inputs: serviceLineNumber (required), reasonForCancellation, endNow.
delete_service_line_user_terminalADestructive
Remove user terminal from service line β Required permission: Service plan, Edit.This removes the user terminal from the service line, but it remains on the account and can be added to another service line. This clears any L2VPN circuits configured for the terminal. β [DELETE /public/v2/service-lines/{serviceLineNumber}/user-terminals/{deviceId}]
Inputs: serviceLineNumber (required), deviceId (required).
delete_user_terminals_by_device_idADestructive
Remove user terminal from account β Required permission: Device management, Edit.User terminal must already be removed from service lines before it can be removed from the account. See /v2/service-lines/{serviceLineNumber}/user-terminals/{deviceId} β [DELETE /public/v2/user-terminals/{deviceId}]
Inputs: deviceId (required).
get_accountARead-only
Get account information β Required permission: Account information, View. β [GET /public/v2/account]
Inputs: no named parameters.
get_addressesARead-only
Get all addresses β Required permission: Account information, View.Returns all addresses on the account in paginated form. β [GET /public/v2/addresses]
Inputs: addressIds, metadata, page.
get_addresses_by_address_reference_idARead-only
Get address β Required permission: Account information, View. β [GET /public/v2/addresses/{addressReferenceId}]
Inputs: addressReferenceId (required).
get_contactsARead-only
Get contacts β Required permission: User management, Edit.Get list of contacts on the authenticated user's account. β [GET /public/v2/contacts]
Inputs: page.
get_data_poolsARead-only
Pre-Release: Get all multi-service line enabled data pools. β Required permission: Service plan, View.This endpoint is available for select audiences only. β [GET /public/v2/data-pools]
Inputs: productReferenceId, dataPoolIds, page.
get_data_pools_usageARead-only
Pre-Release: Query data pool usage with service line and monthly breakdowns. β Required permission: Service plan, View.This endpoint is available for select audiences only. β [GET /public/v2/data-pools/usage]
Inputs: dataPoolIds, asOfTimestamp, page, limit.
get_productsARead-only
Get products β Required permission: Service plan, View.Gets all products available to this account that could be assigned to service lines. Each product includes data block product info if compatible. β [GET /public/v2/products]
Inputs: page.
get_routers_by_router_idARead-only
Get router β Required permission: Device management, View. β [GET /public/v2/routers/{routerId}]
Inputs: routerId (required).
get_routers_configsARead-only
Get all router configs β Required permission: Device command and configuration, View.Return all router configs on this account in paginated form β [GET /public/v2/routers/configs]
Inputs: page.
get_routers_configs_by_config_idBRead-only
Get router config β Required permission: Device command and configuration, View. β [GET /public/v2/routers/configs/{configId}]
Inputs: configId (required).
get_routers_configs_defaultARead-only
Get default router config β Required permission: Device command and configuration, View.Gets the router config id that will be assigned to any routers when they are first added to this account. β [GET /public/v2/routers/configs/default]
Inputs: no named parameters.
get_routers_configs_tlsARead-only
Get TLS configs β Required permission: Device command and configuration, View.Gets a paginated list of TLS configs on this account. β [GET /public/v2/routers/configs/tls]
Inputs: page.
get_routers_local_contentARead-only
Get list of router local content files β Required permission: Device command and configuration, View. β [GET /public/v2/routers/local-content]
Inputs: no named parameters.
get_routers_sandbox_clientsARead-only
Get sandbox clients β Required permission: Device command and configuration, View.Returns clients that were unsandboxed through the management API and have access that has not yet expired, paginated 1000 at a time. Clients that are allowed internet access due to sandbox disablement are not returned. β [GET /public/v2/routers/sandbox/clients]
Inputs: sandboxId, expiryAfter, page.
get_service_line_billing_cycles_partial_periodsARead-only
Get billing partial periods β Required permission: Service plan, View.Get the previous billing partial periods for this service line. For more information about this endpoint, see https://starlink.readme.io/docs/understanding-proration. β [GET /public/v2/service-lines/{serviceLineNumber}/billing-cycles/partial-periods]
Inputs: serviceLineNumber (required).
get_service_linesARead-only
Get all service lines β Required permission: Service plan, View. β [GET /public/v2/service-lines]
Inputs: addressReferenceId, searchString, dataPoolId, page, +1 more.
get_service_lines_by_service_line_numberARead-only
Get service line β Required permission: Service plan, View. β [GET /public/v2/service-lines/{serviceLineNumber}]
Inputs: serviceLineNumber (required).
get_user_terminalsARead-only
Get all user terminals β Required permission: Device management, View.Gets all user terminals on the account, filtered by the optional filter parameters, in paginated form β [GET /public/v2/user-terminals]
Inputs: serviceLineNumbers, userTerminalIds, hasServiceLine, searchString, +1 more.
get_user_terminals_l2vpnARead-only
Get L2VPN circuits available for this account β Required permission: Device command and configuration, View. β [GET /public/v2/user-terminals/l2vpn]
Inputs: no named parameters.
patch_service_lines_by_service_line_number_consume_from_poolA
Pre-Release: Set whether a service line should consume from a data pool. β Required permission: Service plan, Edit.This endpoint is available for select audiences only. β [PATCH /public/v2/service-lines/{serviceLineNumber}/consume-from-pool]
Inputs: serviceLineNumber (required), consumeFromPool.
post_addressesC
Create address β Required permission: Account information, Edit. β [POST /public/v2/addresses]
Inputs: addressLines (required), administrativeAreaCode (required), regionCode (required), formattedAddress (required), +7 more.
post_contactsB
Create contact β Required permission: Admin Only - API User Management, Edit.Creates the contact if it is new, and adds the contact to the authenticated account. β [POST /public/v2/contacts]
Inputs: firstName (required), lastName (required), roles (required), email (required), +2 more.
post_data_pools_by_data_pool_id_set_automatic_top_upB
Pre-Release: Enable or disable automatic top-up for a data pool. β Required permission: Service plan, Edit.This endpoint is available for select audiences only. β [POST /public/v2/data-pools/{dataPoolId}/set-automatic-top-up]
Inputs: dataPoolId (required), enabled.
post_data_usage_queryC
Query data usage β Required permission: Service plan, View.Retrieve the real-time data tracking info for this account's data usage. For detailed instructions, please refer to the API documentation: https://starlink.readme.io/docs/data-usage-api β [POST /public/v2/data-usage/query]
Inputs: page, limit, serviceLineNumbers, previousBillingCycles, +2 more.
post_flights_statusB
Post a flight event β Required permission: Aviation flight status management, Edit.Post a real-time flight event on a Starlink-enabled plane. This endpoint is only accessible from an aviation account. β [POST /public/v2/flights/status]
Inputs: tailNumber (required), flightNumber (required), eventType (required), eventTimeUtc, +5 more.
post_managed_customersA
Create a managed customer account β This endpoint is only callable with an authorized provider account. β [POST /public/v2/managed/customers]
Inputs: firstName (required), lastName (required), email (required), phone (required), +2 more.
post_routers_by_router_id_rebootADestructive
Reboot router β Required permission: Device command and configuration, Edit. β [POST /public/v2/routers/{routerId}/reboot]
Inputs: routerId (required).
post_routers_configsB
Create router config β Required permission: Device command and configuration, Edit. β [POST /public/v2/routers/configs]
Inputs: routerConfigJson (required), nickname.
post_routers_configs_tlsA
Create TLS config β Required permission: Device command and configuration, Edit.Creates a TLS config that allows this certificate and key to be used in router configs when a certificate and key are required by only specifying the certificate (matching key will be added). TLS configs are identified by their certificate string base64 encoded which must be unique on the account. β [POST /public/v2/routers/configs/tls]
Inputs: certificateBase64Pem (required), keyBase64Pem (required).
post_routers_local_contentA
Upload router local content file β Required permission: Device command and configuration, Edit.Upload html file to allow it to be configured as the HTTPS server local content file for router configs. File must be HTML, under 4MB, and file name under 100 characters. Files are stored in a public bucket for configured routers to download. File should be attached as multipart/form-data. See https://starlink.readme.io/docs/local-content for example upload script. β [POST /public/v2/routers/local-content]
Inputs: File (required).
post_routers_sandbox_clientsA
Batch update sandbox clients β Required permission: Device command and configuration, Edit.Update the sandbox state for multiple clients. If sandboxing is enabled, sandboxed clients will only have access to domains in the sandbox domain allow list. If a client is duplicated, records the client with the latest expiry. β [POST /public/v2/routers/sandbox/clients]
Inputs: no named parameters.
post_service_linesA
Create service line β Required permission: Service plan, Edit.Service line must be linked to an address and a subscription/product-ID, and can optionally be immediately configured with data blocks. β [POST /public/v2/service-lines]
Inputs: addressReferenceId (required), productReferenceId (required), dataBlockProducts.
post_service_lines_by_service_line_number_data_opt_inA
Opt in priority data β Required permission: Service plan, Edit.Opt in the service line to continue using priority data after reaching the plan capacity. Only applies to some products. β [POST /public/v2/service-lines/{serviceLineNumber}/data/opt-in]
Inputs: serviceLineNumber (required).
post_service_lines_by_service_line_number_data_opt_outA
Opt out priority data β Required permission: Service plan, Edit.Opt out the service line from continuing to use priority data even when plan capacity is exceeded. If the service line reaches the plan capacity, it will switch to using standard data. Only applies to some products. β [POST /public/v2/service-lines/{serviceLineNumber}/data/opt-out]
Inputs: serviceLineNumber (required).
post_service_lines_by_service_line_number_data_top_upA
Adds one-time top up data block to service line β Required permission: Service plan, Edit.Service line must be on a top up plan β [POST /public/v2/service-lines/{serviceLineNumber}/data/top-up]
Inputs: serviceLineNumber (required), productId (required), count (required).
post_service_lines_by_service_line_number_user_terminalsA
Add user terminal to service line β Required permission: Service plan, Edit.User terminal must already be on the account. See POST /v2/user-terminals to add user terminal to account. β [POST /public/v2/service-lines/{serviceLineNumber}/user-terminals]
Inputs: serviceLineNumber (required), deviceId (required).
post_user_terminalsA
Add user terminal to account β Required permission: Device management, Edit.This will add the user terminal to the account, but won't start service. User terminals must be present on the account before adding to a service line. β [POST /public/v2/user-terminals]
Inputs: deviceId (required).
post_user_terminals_by_device_id_rebootCDestructive
Reboot user terminal β Required permission: Device command and configuration, Edit. β [POST /public/v2/user-terminals/{deviceId}/reboot]
Inputs: deviceId (required).
put_addresses_by_address_reference_idB
Update address β Required permission: Account information, Edit. β [PUT /public/v2/addresses/{addressReferenceId}]
Inputs: addressReferenceId (required), addressLines (required), administrativeAreaCode (required), regionCode (required), +8 more.
put_contacts_by_subject_idB
Update contact β Required permission: Admin Only - API User Management, Edit.Update contact on the authenticated account. β [PUT /public/v2/contacts/{subjectId}]
Inputs: subjectId (required), roles, phoneNumber.
put_routers_configs_assignA
Router config assignment β Required permission: Device configuration assignment, Edit.Assign the config (or none) to the routers. For each router if it is currently online, the config will immediately be sent to the router. Else, the config will be sent to the router when it comes online. Configs are sent to the router within 1-2 minutes. On error no assignment occurs. β [PUT /public/v2/routers/configs/assign]
Inputs: routerIds (required), configId.
put_routers_configs_by_config_idA
Update router config β Required permission: Device command and configuration, Edit.Update a given router config. Any router assigned to this config will immediately receive the update if it is online. Otherwise, the router will receive the update when it comes online. β [PUT /public/v2/routers/configs/{configId}]
Inputs: configId (required), routerConfigJson (required), nickname.
put_routers_configs_defaultA
Set default router config β Required permission: Device configuration assignment, Edit.Set the default router config on the account. Use an empty string to remove the default config from the account. Any NEW routers on this account will be assigned this config. β [PUT /public/v2/routers/configs/default]
Inputs: configId (required).
put_routers_sandbox_heartbeatA
Update sandbox heartbeat β Required permission: Device command and configuration, Edit.Heartbeats verify the health of enterprise systems that manage router sandboxing. If heartbeats are not received for an account, Starlink API will instruct routers under the account disable sandboxes until reboot. β [PUT /public/v2/routers/sandbox/heartbeat]
Inputs: healthy (required).
put_service_lines_by_service_line_number_data_recurringA
Set recurring data blocks on service line β Required permission: Service plan, Edit.Service line must be on a top up plan β [PUT /public/v2/service-lines/{serviceLineNumber}/data/recurring]
Inputs: serviceLineNumber (required), recurringDataBlocks, dataPoolId, applyToCurrentMonth.
put_service_lines_by_service_line_number_nicknameB
Set service line nickname β Required permission: Service plan, Edit. β [PUT /public/v2/service-lines/{serviceLineNumber}/nickname]
Inputs: serviceLineNumber (required), nickname (required).
put_service_lines_by_service_line_number_productC
Update service line product β Required permission: Service plan, Edit. β [PUT /public/v2/service-lines/{serviceLineNumber}/product]
Inputs: serviceLineNumber (required), productReferenceId (required), recurringDataBlocks, dataPoolId, +1 more.
put_service_lines_by_service_line_number_public_ipA
Set service line public IP setting β Required permission: Device command and configuration, Edit.Enable or disable public ip setting on a service line β [PUT /public/v2/service-lines/{serviceLineNumber}/public-ip]
Inputs: serviceLineNumber (required), publicIp (required).
put_user_terminals_by_device_id_l2vpnB
Set L2VPN VLANs for user terminal β Required permission: Device configuration assignment, Edit.Terminal must be on subscription that allows L2VPN. Maximum 2 circuits per Starlink PoP. Use null or empty circuit list to clear all L2VPN circuits for terminal. See /user-terminals/available-circuits for all configurable circuits and associated Starlink PoP. β [PUT /public/v2/user-terminals/{deviceId}/l2vpn]
Inputs: deviceId (required).
put_user_terminals_configs_assignA
User terminal config assignment β Required permission: Device configuration assignment, Edit.Assign the config (or none) to the user terminals. For each terminal if it is currently online, the config will immediately be sent. Else, the config will be sent when it comes online. On error no assignment occurs. Currently terminal configIds are only visible on starlink website. β [PUT /public/v2/user-terminals/configs/assign]
Inputs: userTerminalIds (required), configId.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelogβ¦
TDQS
Scored across 55 tools
Most tools have distinct resource and action combinations, making them easily distinguishable. Overlaps are minimal, e.g., between list and single-resource getters, but descriptions clarify.
The naming generally follows a verb_resource_by_identifier pattern, but there are a few outliers like 'post_data_usage_query' and 'put_routers_sandbox_heartbeat' that break the pattern. Overall, it is mostly consistent.
With 55 tools, the server is comprehensive but could be considered heavy for typical use. The count is justified by the broad scope of enterprise management, but it borders on too many.
The tool set covers CRUD and additional operations for most core entities (account, service lines, user terminals, routers, data). Minor gaps exist, such as a single flight endpoint, but the primary domain is well-covered.
Maintenance
Related MCP Connectors
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.
Hosted MCP server connecting AI assistants to 9,000+ apps and 40,000+ actions via Zapier.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA production-ready MCP server that provides secure, delegated access to Microsoft 365 services including Email, SharePoint, OneDrive, and Calendar. It enables AI models to search messages, browse files, manage calendar events, and parse document contents using OAuth 2.1 authentication.MIT
- AlicenseAqualityDmaintenanceMCP server that exposes 300+ AI agents as tools via a single API key. Supports listing agents, invoking any agent with chat-completion style messages, checking agent health, and retrieving platform statistics.54MIT
- AlicenseNot gradedqualityDmaintenanceA production-grade MCP server designed for multi-tenant, authenticated, and observable AI agent systems, enabling secure tool execution across heterogeneous data sources.67MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to discover and execute tools via a secure MCP server with JWT authentication, RBAC, rate limiting, and audit logging.1MIT