Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, email [email protected] and we’ll put it right.

Serve a valid TLS certificate for MCP

What we checked

We opened a TLS connection to your endpoint and inspected the certificate it presented and the protocol it negotiated:

TLS certificate is expired or not yet valid: score capped
TLS check failed: the certificate doesn't match the endpoint's hostname.
TLS certificate is valid but uses a weak key
Endpoint negotiates a TLS version below the TLS 1.2 minimum
TLS check failed: the certificate chain is untrusted (self-signed or from an unknown authority).
TLS not yet verified: we couldn't open a connection to check the certificate.

Why it matters

TLS is what makes the connection to your server private and tamper-evident. A client that can’t verify your certificate has no way to know it’s really talking to you and not an attacker on the path, so a broken certificate undermines every other security property the endpoint claims. A weak key or an obsolete protocol version leaves the channel open to attacks that modern TLS closed years ago. A valid certificate is the foundation the rest of your transport security builds on: it’s what lets you safely enforce HTTPS and then advertise HSTS so clients never fall back to plaintext.

Does a broken certificate cap my score?

Yes, but only while it’s broken. Those failures hold the endpoint score to a ceiling rather than docking a few points. Reissue or reconfigure the certificate and the cap lifts on our next crawl, with no lasting penalty.

How to fix it

Serve a certificate that is CA-issued (e.g. Let’s Encrypt), matches the hostname clients connect to, and uses a strong key (RSA 2048-bit or larger, or ECDSA P-256). Serve it over TLS 1.2 or higher (prefer TLS 1.3); see Mozilla’s TLS configuration guidance. Make sure the full chain (leaf plus intermediates) is served, which is what most “untrusted” errors actually are.

# Obtain a free, auto-renewing Let's Encrypt certificate.
# Certbot generates a strong key and installs the full chain for you.
sudo certbot --nginx -d mcp.example.com

# Renewal is handled by a systemd timer / cron job; test it with:
sudo certbot renew --dry-run

How we re-check

We re-open the TLS connection on our next crawl. Once the certificate is CA-trusted, in-date, hostname-matching, backed by a strong key, and negotiates TLS 1.2+, the check passes 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.

Prompt
Context: this repository's infrastructure serves a remote MCP server
over HTTPS. VerifyMCP's TLS check failed (an expired certificate, a
hostname mismatch, a weak key, an outdated protocol, an untrusted chain,
or an unreachable endpoint), which caps the endpoint score because a
client cannot verify it is really talking to this server.

Goal: the endpoint serves a CA-issued, in-date, hostname-matching
certificate with a strong key (RSA 2048-bit+ or ECDSA P-256), negotiates
TLS 1.2 or higher, and presents the full certificate chain, so the next
crawl records a valid certificate.

Do this:
1. Identify which failure fired and match the fix: reissue an
   expired certificate, correct the SAN/hostname on the cert,
   regenerate a weak key, raise the minimum negotiated protocol, or add
   the missing intermediate certificates to the served chain.
2. Use a CA that auto-renews (e.g. Let's Encrypt via certbot, or a
   proxy like Caddy) rather than a manually tracked expiry date.
3. Configure the TLS terminator (nginx, Caddy, load balancer) to serve
   TLSv1.2 and TLSv1.3 only, and to serve the leaf certificate together
   with all intermediates.
4. Verify with `openssl s_client -connect <host>:443 -servername <host>`
   that the chain, hostname, and negotiated protocol are all correct.

Rules:
- Never self-sign a certificate or bypass validation to make the check
  pass; the certificate has to be genuinely CA-trusted.
- If raising the minimum TLS version would drop support for TLS
  1.0/1.1 clients still connecting to this endpoint, check whether that
  traffic exists and ask the human before cutting it off. TLS 1.2+ is
  still the correct end state, so treat any remaining 1.0/1.1 traffic as
  a migration to schedule, not an outcome to preserve.
- This is production infrastructure: confirm the change in staging or a
  maintenance window before touching the live certificate.

Report back: the failure you fixed, and the `openssl s_client`
output (or external TLS report) showing a trusted chain, matching
hostname, and TLS 1.2+ negotiation.

Reference: https://verifymcp.io/docs/remote/tls

Written by Stuart Blackler · Last reviewed 30 June 2026.