MCP Server
This document is intended for external users and explains how to configure CX's MCP Server with agents such as Claude Code and Codex.
What You Can Do
The current MCP Server provides the following tools:
get_context: View the currently connected source, user, tenant, and customer information.list_devices: List devices visible to the current user.list_programs: List programs visible to the current user.get_device_status: Query the online status and version attributes of a single visible device.get_device_detail: Query the details and latest attributes of a single visible device.get_program_detail: Query the detailed content of a single visible program.list_assets: List assets and groups visible to the current user.get_entity_attributes: Query device, program, or asset attributes by explicitly specified keys.list_program_targets: Query which visible devices or groups a program is currently deployed to.list_device_programs: Query the programs currently associated with a visible device.bind_device_by_ddc: Bind or create a device using a device dynamic code, optionally with a selected available device activation code ID.describe_device_binding_semantics: Explain the activation code usage rules for binding devices via dynamic code in Cloud/LAN modes.describe_activation_semantics: Explain activation code types, device activation codes, and cloud account token requirements.list_activation_codes: Query visible activation codes for the cloud account. Usestatus: "usable"to filter for available device activation codes.list_usable_device_auth_codes: Query currently available device activation codes that can be used for device binding.get_activation_code: Query details of a single activation code.activate_code: Activate a standard activation code.
The MCP Server accesses data using your login token, so different users will only see content they have permission to access.
Choosing a Connection Method
CX provides three MCP entry points:
- In-App HTTP MCP: Suitable for directly connecting to an already running management/player app. The address is
http://<device-LAN-IP>:9394/mcp. - Standalone HTTP MCP: Suitable for connecting to a persistently running
cxmcp_http. The default address ishttp://127.0.0.1:9394/mcp. - stdio MCP: Suitable for local agents such as Claude Code and Codex to launch the
cxmcp_stdioexecutable directly.
If the agent and the CX app are on the same LAN, prefer the in-app HTTP MCP. If you need a persistent server-side setup, use the standalone HTTP MCP. If you only want the agent to launch MCP on demand, use stdio MCP.
Starting cxserver
Start the local HTTP server:
./run.shcxserver is only responsible for the local HTTP server and will not start MCP.
Starting HTTP MCP in the App
In the management or player app, go to the "Local Services" screen and turn on the MCP service switch. Once enabled, the interface will display something like:
http://192.168.1.10:9394/mcpAgents on the same LAN should use this address to connect. Do not configure the in-app MCP as 127.0.0.1 unless the agent and the app are running on the same device.
Starting HTTP MCP
cxmcp_httpCustom HTTP MCP address:
cxmcp_http --host=127.0.0.1 --port=9394 --path=/mcpToken and Source
Each MCP connection requires a valid login JWT.
HTTP MCP uses request headers:
Authorization: Bearer <jwt>
X-Mht-Source-Key: cloudLAN local service uses:
Authorization: Bearer <lan-jwt>
X-Mht-Source-Key: lan
X-Mht-Lan-Host: http://127.0.0.1:9393Some cloud account features (such as activation code / MHActivation tools) require a cloud account. When using LAN source, you need to provide an additional cloud account JWT for these features:
X-Mht-Cloud-Authorization: Bearer <cloud-jwt>stdio MCP uses environment variables and command-line arguments. The examples use CX_MCP_* variable names, so you need to explicitly pass --token-env and --cloud-token-env:
CX_MCP_TOKEN='<jwt>' /path/to/cxmcp_stdio \
--source cloud \
--token-env CX_MCP_TOKENLAN local service:
CX_MCP_TOKEN_LAN='<lan-jwt>' /path/to/cxmcp_stdio \
--source lan \
--token-env CX_MCP_TOKEN_LAN \
--lan-host http://127.0.0.1:9393When using LAN source and needing activation code / MHActivation tools, provide an additional cloud account token and pass it explicitly to the CLI:
CX_MCP_TOKEN_LAN='<lan-jwt>' CX_MCP_CLOUD_TOKEN='<cloud-jwt>' /path/to/cxmcp_stdio \
--source lan \
--token-env CX_MCP_TOKEN_LAN \
--cloud-token-env CX_MCP_CLOUD_TOKEN \
--lan-host http://127.0.0.1:9393It is recommended to pass tokens via environment variables and never commit JWTs to repositories or shared configurations.
Docker stdio MCP
The Docker version of cxmcp_stdio can replace native executable installation. It is still a stdio MCP and must be run with docker run -i — do not use -d, and no port mapping is required. Replace <cxmcp-stdio-image> with the actual image name provided by your OEM or deployment environment.
Cloud:
docker run -i --rm \
-e CX_MCP_TOKEN='<jwt>' \
<cxmcp-stdio-image> \
--source cloud \
--token-env CX_MCP_TOKENLAN:
export CX_MCP_LAN_HOST='http://host.docker.internal:9393'
docker run -i --rm \
-e CX_MCP_TOKEN_LAN='<lan-jwt>' \
-e CX_MCP_CLOUD_TOKEN='<cloud-jwt>' \
<cxmcp-stdio-image> \
--source lan \
--token-env CX_MCP_TOKEN_LAN \
--cloud-token-env CX_MCP_CLOUD_TOKEN \
--lan-host "$CX_MCP_LAN_HOST"On Docker Desktop (macOS/Windows), containers accessing the host's cxserver should use host.docker.internal instead of 127.0.0.1. On Linux Docker without host.docker.internal, add the following when running:
--add-host=host.docker.internal:host-gatewayClaude Code Configuration
If the token, source, or LAN host changes, it is recommended to remove the old configuration first, then re-add it to avoid stale headers or environment variables:
claude mcp remove cx-cloud -s local
claude mcp remove cx-lan -s local
claude mcp remove cx-cloud-stdio -s local
claude mcp remove cx-lan-stdio -s localHTTP Cloud
export CX_MCP_TOKEN='<jwt>'
claude mcp add --transport http \
cx-cloud http://127.0.0.1:9394/mcp \
--header "Authorization: Bearer $CX_MCP_TOKEN" \
--header "X-Mht-Source-Key: cloud"HTTP LAN
export CX_MCP_TOKEN_LAN='<lan-jwt>'
export CX_MCP_CLOUD_TOKEN='<cloud-jwt>'
export CX_MCP_LAN_HOST='http://127.0.0.1:9393'
claude mcp add --transport http \
cx-lan http://127.0.0.1:9394/mcp \
--header "Authorization: Bearer $CX_MCP_TOKEN_LAN" \
--header "X-Mht-Source-Key: lan" \
--header "X-Mht-Lan-Host: $CX_MCP_LAN_HOST" \
--header "X-Mht-Cloud-Authorization: Bearer $CX_MCP_CLOUD_TOKEN"X-Mht-Cloud-Authorization is only needed when the LAN source requires access to cloud account features. It can be omitted for regular LAN device/program queries.
stdio Cloud
claude mcp add cx-cloud-stdio \
-e CX_MCP_TOKEN='<jwt>' \
-- /path/to/cxmcp_stdio --source cloud --token-env CX_MCP_TOKENstdio LAN
claude mcp add cx-lan-stdio \
-e CX_MCP_TOKEN_LAN='<lan-jwt>' \
-e CX_MCP_CLOUD_TOKEN='<cloud-jwt>' \
-- /path/to/cxmcp_stdio \
--source lan \
--token-env CX_MCP_TOKEN_LAN \
--cloud-token-env CX_MCP_CLOUD_TOKEN \
--lan-host http://127.0.0.1:9393You can also put the LAN host in an environment variable:
export CX_MCP_LAN_HOST='http://127.0.0.1:9393'
claude mcp add cx-lan-stdio \
-e CX_MCP_TOKEN_LAN='<lan-jwt>' \
-e CX_MCP_CLOUD_TOKEN='<cloud-jwt>' \
-- /path/to/cxmcp_stdio \
--source lan \
--token-env CX_MCP_TOKEN_LAN \
--cloud-token-env CX_MCP_CLOUD_TOKEN \
--lan-host "$CX_MCP_LAN_HOST"Verify:
claude mcp list
claude mcp get cx-lanOnce inside Claude Code, run:
/mcpConfirm that cx-lan or cx-cloud is connected and you can see the tools.
Codex Configuration
Codex uses ~/.codex/config.toml to configure MCP servers. HTTP MCP can use url, and stdio MCP can use command/args/env.
If the source or LAN host changes, it is recommended to delete the corresponding [mcp_servers.<name>] block from ~/.codex/config.toml, then rewrite it.
HTTP Cloud
[mcp_servers.cx_cloud]
url = "http://127.0.0.1:9394/mcp"
bearer_token_env_var = "CX_MCP_TOKEN"
http_headers = { "X-Mht-Source-Key" = "cloud" }Set the environment variable before launching Codex:
export CX_MCP_TOKEN='<jwt>'
codexHTTP LAN
[mcp_servers.cx_lan]
url = "http://127.0.0.1:9394/mcp"
bearer_token_env_var = "CX_MCP_TOKEN_LAN"
http_headers = { "X-Mht-Source-Key" = "lan", "X-Mht-Lan-Host" = "http://127.0.0.1:9393", "X-Mht-Cloud-Authorization" = "Bearer <cloud-jwt>" }If you prefer not to write the cloud account JWT into config.toml, you can omit X-Mht-Cloud-Authorization for now, or use stdio MCP to pass CX_MCP_CLOUD_TOKEN via env.
stdio Cloud
[mcp_servers.cx_cloud_stdio]
command = "/path/to/cxmcp_stdio"
args = ["--source", "cloud", "--token-env", "CX_MCP_TOKEN"]
env = { "CX_MCP_TOKEN" = "<jwt>" }stdio LAN
[mcp_servers.cx_lan_stdio]
command = "/path/to/cxmcp_stdio"
args = ["--source", "lan", "--token-env", "CX_MCP_TOKEN_LAN", "--cloud-token-env", "CX_MCP_CLOUD_TOKEN", "--lan-host", "http://127.0.0.1:9393"]
env = { "CX_MCP_TOKEN_LAN" = "<lan-jwt>", "CX_MCP_CLOUD_TOKEN" = "<cloud-jwt>" }To switch the LAN host, simply change the value of --lan-host. Codex args do not perform shell variable expansion, so do not write $CX_MCP_LAN_HOST here:
[mcp_servers.cx_lan_stdio]
command = "/path/to/cxmcp_stdio"
args = ["--source", "lan", "--token-env", "CX_MCP_TOKEN_LAN", "--cloud-token-env", "CX_MCP_CLOUD_TOKEN", "--lan-host", "http://127.0.0.1:9393"]
env = { "CX_MCP_TOKEN_LAN" = "<lan-jwt>", "CX_MCP_CLOUD_TOKEN" = "<cloud-jwt>" }Docker stdio Cloud
[mcp_servers.cx_cloud_stdio_docker]
command = "docker"
args = [
"run", "-i", "--rm",
"-e", "CX_MCP_TOKEN",
"<cxmcp-stdio-image>",
"--source", "cloud",
"--token-env", "CX_MCP_TOKEN"
]
env = { "CX_MCP_TOKEN" = "<jwt>" }Docker stdio LAN
[mcp_servers.cx_lan_stdio_docker]
command = "docker"
args = [
"run", "-i", "--rm",
"--add-host=host.docker.internal:host-gateway",
"-e", "CX_MCP_TOKEN_LAN",
"-e", "CX_MCP_CLOUD_TOKEN",
"<cxmcp-stdio-image>",
"--source", "lan",
"--token-env", "CX_MCP_TOKEN_LAN",
"--cloud-token-env", "CX_MCP_CLOUD_TOKEN",
"--lan-host", "http://host.docker.internal:9393"
]
env = { "CX_MCP_TOKEN_LAN" = "<lan-jwt>", "CX_MCP_CLOUD_TOKEN" = "<cloud-jwt>" }Verify:
codex mcp list
codex mcp get cx_lanRemove:
codex mcp remove cx_cloud
codex mcp remove cx_lan
codex mcp remove cx_cloud_stdio
codex mcp remove cx_lan_stdioIf your current Codex version does not have the mcp remove command, you can directly edit ~/.codex/config.toml and delete the corresponding configuration block.
Other Agents
If the agent supports Streamable HTTP MCP:
- URL:
http://127.0.0.1:9394/mcp - Header:
Authorization: Bearer <jwt> - Cloud Header:
X-Mht-Source-Key: cloud - LAN Header:
X-Mht-Source-Key: lan - LAN Header:
X-Mht-Lan-Host: http://127.0.0.1:9393 - LAN Optional Cloud Header:
X-Mht-Cloud-Authorization: Bearer <cloud-jwt>
If the agent supports stdio MCP:
- Command:
/path/to/cxmcp_stdio - Cloud args:
--source cloud --token-env CX_MCP_TOKEN - LAN args:
--source lan --token-env CX_MCP_TOKEN_LAN --cloud-token-env CX_MCP_CLOUD_TOKEN --lan-host http://127.0.0.1:9393 - Cloud Env:
CX_MCP_TOKEN=<jwt> - LAN Env:
CX_MCP_TOKEN_LAN=<lan-jwt> - LAN Optional Env:
CX_MCP_CLOUD_TOKEN=<cloud-jwt> - The LAN host can be placed in your own environment variable, but the startup argument must still be passed explicitly:
--lan-host "$CX_MCP_LAN_HOST" - Docker Command:
docker - Docker args:
run -i --rm -e CX_MCP_TOKEN <cxmcp-stdio-image> --source cloud --token-env CX_MCP_TOKEN
Frequently Asked Questions
Connection failures or tool call errors
Check:
- Whether the token has expired.
- Whether the HTTP mode is using the
Authorization: Bearer <jwt>format. - Whether the token belongs to the current source.
- Whether LAN mode has
X-Mht-Source-Key: lanandX-Mht-Lan-Hostconfigured. - Whether stdio LAN has
--lan-hostconfigured, or whether it is explicitly passed via--lan-host "$CX_MCP_LAN_HOST"in shell examples. - Whether, when using LAN source to call activation code / MHActivation tools, an additional cloud account token has been configured: HTTP via
X-Mht-Cloud-Authorization, stdio viaCX_MCP_CLOUD_TOKEN.
Configuration changes not taking effect
Remove the old MCP server first, then reconfigure. This is especially important when the source, LAN host, or command path changes — overwriting is not recommended.
Using LAN and Cloud simultaneously
It is recommended to configure them as two separate MCP servers, for example:
cx_cloudcx_lan
They can use the same HTTP MCP URL but require different tokens and source configurations.
Security Notes
- Do not commit JWTs to repositories.
- For local testing, prefer environment variables or local private configuration files.
- HTTP MCP binds to
127.0.0.1by default — do not casually expose it to the public internet. - For stdio mode, it is recommended to use the
CX_MCP_TOKENenvironment variable to pass the token;--tokenis only recommended for temporary debugging. - The LAN source's
CX_MCP_CLOUD_TOKENis a cloud account JWT and must also not be committed to repositories or shared configurations. - The current version does not support refresh tokens; you will need to provide a new JWT after the token expires.