Enforce HTTPS on your MCP server endpoint
What we checked
We tested whether your endpoint can be reached over plaintext HTTP as well as HTTPS:
Why it matters
If your MCP endpoint answers over plaintext HTTP, anyone on the network path can
read or modify the traffic, including the tool calls an agent makes and the
data your server returns. The http and https URI schemes are distinct in the
HTTP standard (RFC 7230, section 2.7),
so an https:// origin earns none of its guarantees while the http:// one
still answers. Even when you also offer HTTPS, leaving a plaintext path open
invites downgrade attacks and accidental insecure connections. The fix is to
make HTTPS the only way in: redirect every HTTP request to HTTPS and never
serve MCP over the plaintext listener. Once HTTPS is the only way in, an
HSTS header stops clients from ever attempting the plaintext
path again, and DNSSEC protects the name resolution that
happens before the connection is even made.
How to fix it
Listen on port 80 only to issue a permanent redirect to https://, and serve
MCP exclusively from the TLS listener. You need a valid certificate first: see
TLS.
# Plaintext listener: redirect everything to HTTPS.
server {
listen 80;
server_name mcp.example.com;
return 301 https://$host$request_uri;
}
# TLS listener: the only place MCP is actually served.
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/letsencrypt/live/mcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mcp.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
location /mcp {
proxy_pass http://localhost:3000;
}
} # Caddy redirects HTTP to HTTPS automatically - there is no
# plaintext path to MCP. Just name the host and it provisions TLS.
mcp.example.com {
reverse_proxy localhost:3000
} In the Cloudflare dashboard, for the zone serving your endpoint:
SSL/TLS -> Edge Certificates -> Always Use HTTPS = On
This makes Cloudflare answer any http:// request with a 301 to the
https:// equivalent, so no plaintext path reaches your origin.
Also set the SSL/TLS encryption mode to "Full (strict)" so the hop
from Cloudflare to your origin is encrypted and certificate-verified. Does redirecting HTTP to HTTPS pass the check?
Yes. In the remote scoring rubric we look for the
plaintext listener to stop serving a usable response, and a permanent redirect
from http:// to https:// is exactly that. Either a
301 or a
308 works,
though 308 is the stricter choice because it forbids clients from switching the
method to GET on the way. What fails is a plaintext listener that answers the
MCP request directly, or one that offers both schemes with no redirect at all.
How we re-check
We re-test both schemes on our next crawl. Once plaintext requests no longer return a usable response (they redirect to HTTPS or are refused), the check records HTTPS as enforced on the following score refresh.
Give this to your AI
Paste this into Claude Code (or any coding agent) from inside your server's repository. It states the failing signal, the outcome we re-check for, and the format the fix has to take.
Context: this repository (or its infrastructure) runs a remote MCP server at an HTTPS endpoint. VerifyMCP's HTTPS enforcement check failed, which means the plaintext `http://` listener still answers the MCP request directly, or offers both schemes with no redirect, so traffic on that path, including tool calls and the data returned, can be read or altered by anyone on the network. Goal: the plaintext listener no longer serves a usable response, either redirecting every request to `https://` or refusing to serve MCP over it, so the next crawl records HTTPS as enforced. Do this: 1. Confirm a valid TLS certificate is already in place; enforcement only makes sense once HTTPS actually works. 2. On the port 80 listener, issue a permanent redirect to the `https://` equivalent, a `301` or preferably a `308` (it forbids clients from switching method to `GET`), instead of serving MCP directly. 3. If a proxy such as Cloudflare terminates TLS in front of an origin, also lock the origin down (firewall rules, "Full (strict)" mode, or origin certificates) so it can't be reached over plaintext directly, bypassing the proxy's redirect. 4. Remove any application route that would still answer an MCP request on the plaintext listener. Rules: - Don't fake this with a `200` plus a meta-refresh or client-side redirect; it must be a real `301`/`308` HTTP redirect or a refusal, since the check reads the scheme and status code directly. - Don't leave the origin reachable over plaintext behind a proxy-level redirect, that still exposes exactly the traffic this check protects. - If anything depends on plaintext staying open (for example an internal health check hitting port 80 directly), confirm with the human before removing it. Report back: the files or config changed, and `curl -I http://<host>/...` showing a `301`/`308` to `https://` (or a refused connection), alongside `curl -I https://<host>/...` still succeeding. Reference: https://verifymcp.io/docs/remote/https