This guide explains how to use Codanna's HTTPS MCP server with self-signed certificates, particularly for secure local development and production deployments.
The HTTPS MCP server provides:
- TLS/SSL encryption for secure communication
- SSE (Server-Sent Events) transport compatible with Claude Code
- OAuth2 authentication flow for secure access control
- Self-signed certificate generation with proper X.509 attributes
- Bearer token validation for API security
Claude Code uses Node.js internally, which maintains its own certificate store separate from your system's certificate store. This means that even if you trust a certificate in your operating system (macOS Keychain, Windows Certificate Store, etc.), Node.js won't recognize it.
When connecting to an HTTPS server with a self-signed certificate, you'll encounter:
fetch failederrors in Claude Codeunable to verify the first certificateerrors- Connection failures despite the certificate being trusted in your browser
The solution is to explicitly tell Node.js about your certificate using the NODE_EXTRA_CA_CERTS environment variable.
cargo run --all-features -- serve --https --watchOr if installed:
codanna serve --https --watchOn first run, this will:
- Generate a self-signed certificate
- Save it to
~/Library/Application Support/codanna/certs/server.pem(macOS) - Display certificate details and fingerprint
Create a directory for your certificates and copy the generated certificate:
# Create SSL directory if it doesn't exist
mkdir -p ~/.ssl
# Copy the certificate
cp ~/Library/Application\ Support/codanna/certs/server.pem ~/.ssl/codanna-ca.pemAdd to .mcp.json in your project root:
{
"mcpServers": {
"codanna-https": {
"type": "sse",
"url": "https://127.0.0.1:8443/mcp/sse"
}
}
}NODE_EXTRA_CA_CERTS=~/.ssl/codanna-ca.pem claudeIn Claude Code, use the /mcp command to check the connection status. You should see:
codanna-https ✔ connected
Add to your ~/.bashrc or ~/.zshrc:
alias claude-secure='NODE_EXTRA_CA_CERTS=~/.ssl/codanna-ca.pem claude'Then use:
claude-secureFor system-wide trust (though Node.js still requires NODE_EXTRA_CA_CERTS):
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain \
~/Library/Application\ Support/codanna/certs/server.pemThe HTTPS server includes a complete OAuth2 implementation:
- Discovery:
/.well-known/oauth-authorization-server - Registration:
/oauth/register - Authorization:
/oauth/authorize - Token Exchange:
/oauth/token
This flow is handled automatically by Claude Code when connecting to the server.
Problem: Claude Code shows "fetch failed" when trying to connect.
Solution: Ensure you're running Claude Code with NODE_EXTRA_CA_CERTS:
NODE_EXTRA_CA_CERTS=~/.ssl/codanna-ca.pem claudeProblem: Server says certificate already exists but you want to regenerate.
Solution: Delete the existing certificates:
rm -rf ~/Library/Application\ Support/codanna/certs/Then restart the server to generate new ones.
Problem: Server returns 401 errors.
Solution: The OAuth flow should handle authentication automatically. If you see 401 errors:
- Check server logs for Bearer token validation messages
- Ensure you're using the SSE transport type in
.mcp.json - Try reconnecting with
/mcpcommand in Claude Code
Problem: You can access https://127.0.0.1:8443/health in browser but Claude Code fails.
Solution: Browsers use the system certificate store, but Node.js doesn't. You must use NODE_EXTRA_CA_CERTS.
Self-signed certificates are acceptable for local development. The NODE_EXTRA_CA_CERTS approach is secure as it only trusts your specific certificate.
Consider these alternatives for production:
- Let's Encrypt: Use certbot to get free, valid certificates
- Reverse Proxy: Place nginx/caddy with valid certs in front of your server
- Cloud Provider: Use managed certificates from AWS, GCP, Azure
- Corporate CA: Use your organization's internal certificate authority
DO NOT use NODE_TLS_REJECT_UNAUTHORIZED=0 in production. This disables ALL certificate validation and is a serious security risk.
The HTTPS server (src/mcp/https_server.rs) provides:
- Certificate Generation: Using
rcgencrate with proper X.509 attributes - TLS Configuration: Via
rustlsandaxum-server - Local IP Detection: Automatically includes local network IP in certificate SANs
- Certificate Persistence: Reuses certificates across server restarts
- Bearer Token Validation: Middleware for secure API access
- OAuth2 Endpoints: Complete authorization code flow implementation
Certificates stored in: ~/Library/Application Support/codanna/certs/
Certificates stored in: ~/.config/codanna/certs/
Certificates stored in: %APPDATA%\codanna\certs\
Note: On Windows, use forward slashes in paths for NODE_EXTRA_CA_CERTS:
set NODE_EXTRA_CA_CERTS=C:/Users/username/.ssl/codanna-ca.pem
claudeWe're investigating ways to make certificate trust easier:
- Automatic Trust Setup: A
codanna trust-certcommand that handles all setup - Certificate Bundle: Including the CA cert in a format Claude Code can auto-detect
- Platform Integration: Better integration with system certificate stores
- Documentation: In-app guidance when certificate issues are detected
- Node.js TLS Documentation
- Claude Code MCP Documentation
- Model Context Protocol Specification
- GitHub Issue #2899 - Self-signed certificate support
While self-signed certificates require an extra setup step with NODE_EXTRA_CA_CERTS, they provide a secure way to run HTTPS MCP servers locally or in controlled environments. The key is understanding that Node.js needs explicit trust configuration separate from your operating system's certificate store.
For the best developer experience, we recommend creating a shell alias or wrapper script that automatically sets the NODE_EXTRA_CA_CERTS environment variable when launching Claude Code.