Controller requirements
SZ-MCP calls your controller from a Cloudflare Worker, over the public internet. That imposes three requirements, and the first one is the one that stops most setups. A controller that cannot meet the first two — on a private network, or with a self-signed certificate — can be reached through the controller tunnel instead.
1. A publicly trusted TLS certificate
Section titled “1. A publicly trusted TLS certificate”Your controller must present a certificate issued by a public CA on the port you expose. SmartZone ships with a self-signed certificate, which will not work.
Cloudflare Workers validate certificates on every outbound fetch and provide
no skip-verify option — there is no setting in SZ-MCP that relaxes this for
a direct connection, because there is no setting in the platform to expose. A
controller reached directly with a self-signed certificate is unreachable, not
degraded. The controller tunnel is the exception: see below.
How to fix it
Section titled “How to fix it”Install a certificate from a public CA through the SmartZone admin UI. Let’s Encrypt with a DNS-01 challenge is usually the simplest path: it validates your control of the DNS name rather than requiring inbound HTTP, so the controller does not need port 80 open to the internet.
The certificate must be valid for the exact hostname you enter on the dashboard.
A certificate for sz.example.com will not satisfy a connection made to an IP
address.
Save & detect fails even though the credentials are right
Section titled “Save & detect fails even though the credentials are right”This is almost always the certificate. The TLS handshake fails before
SmartZone ever sees your username, so Save & detect reports invalid_host,
a connection-layer error, rather than “wrong password”. It is easy to misread
as a credentials problem. If you are confident the username and password are
right, suspect the certificate first, then the address and port below.
2. A publicly routable address
Section titled “2. A publicly routable address”SZ-MCP refuses to call hosts that are not publicly routable. This is checked when you save credentials and again on every call, and it applies to both hostnames and IP literals.
Refused outright:
| Category | Examples |
|---|---|
| Loopback | 127.0.0.0/8, ::1, localhost |
| Private (RFC 1918) | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
| Link-local | 169.254.0.0/16 (including cloud metadata endpoints), fe80::/10 |
| Carrier-grade NAT | 100.64.0.0/10 |
| Unique local IPv6 | fc00::/7 |
| Multicast and reserved | 224.0.0.0/4 and above, ff00::/8, 0.0.0.0/8 |
| Internal-looking names | any host ending .local, .internal, .localhost; broadcasthost |
Other reserved IPv4 ranges (192.0.0.0/24, 192.88.99.0/24, 198.18.0.0/15)
are refused too, as is every IPv6 address outside global unicast (2000::/3),
and IPv6 forms that carry a private IPv4 address.
Non-canonical IP literals are refused as a class — integer (2130706433), octal
(0177.0.0.1), hexadecimal (0x7f.0.0.1) and short (127.1) forms all expand
to real addresses at resolve time, so anything whose labels are entirely numeric
is rejected rather than normalised. A trailing dot does not help: 127.0.0.1.
is treated as 127.0.0.1.
Attempting to save one of these returns forbidden_host with a message naming
the reason, for example IPv4 10.1.2.3 is in a reserved/private range.
3. A reachable API port
Section titled “3. A reachable API port”The port is 8443 (the default, SmartZone’s API port) or 443 (for a
controller behind NAT, a reverse proxy or the controller tunnel). No other port
is accepted: saving one returns forbidden_port with port <n> is not allowed; use 8443 or 443. Whichever you choose must be open to Cloudflare’s egress and
serving the certificate from requirement 1.
SZ-MCP always speaks HTTPS to the controller. There is no plaintext option.
What is checked, and when
Section titled “What is checked, and when”| Moment | What is verified |
|---|---|
| Save & detect | Port is 8443 or 443; host is publicly routable and its name resolves only to public addresses; TLS handshake succeeds; the host answers apiInfo as a SmartZone; credentials are accepted; API version detected |
| Test connection | The same checks, re-run against the saved credentials |
Every call from Claude | Port and host checks, including the name’s resolved addresses; TLS is validated by the platform on each request |
The host check runs on every call, not only at save time, so a stored credential cannot become a route into a private range later.
A hostname is resolved (over DNS-over-HTTPS) and refused with forbidden_host
if any of its addresses is private, for example "sz.example.com" resolves to 10.1.2.3, a reserved/private address. On save and test, a name that does not
resolve is refused too; on a call, a resolver outage lets the request through.
What if my controller is private or self-signed?
Section titled “What if my controller is private or self-signed?”Use the controller tunnel. SZ-MCP creates a Cloudflare Tunnel for your
organisation with its own hostname; you run cloudflared (or its Docker image)
on a machine on the controller’s network, which needs only outbound HTTPS. Only
the SmartZone WSG and SwitchM API paths pass the tunnel, and only SZ-MCP can use
it. The controller’s own certificate is not checked on that last hop, so a
self-signed controller works.
| Step | Where |
|---|---|
| Create the tunnel | Configure › Controller › Private controller (tunnel): enter the controller’s address on your network and its port, then Create tunnel |
| Run the connector | Copy the cloudflared or Docker command the card shows. The token in it is the tunnel’s credential: keep it like a password |
| Point the login at it | Use for the login fills in the tunnel hostname and port 443; enter the username and password, then Save & detect |
Controller tunnels are in limited rollout and must be enabled per account: contact support to have them enabled. Until then the card reads “Controller tunnels are in limited rollout; ask an sz-mcp admin to enable them for your account.” Only organisation admins can set one up.
Once the login uses the tunnel, SZ-MCP can also issue a Let’s Encrypt certificate for the controller itself and renew it: the Controller certificate (Let’s Encrypt) card on the same page, Get a certificate.
Full setup: Reach a private or self-signed controller.