Skip to content

Latest commit

 

History

History
226 lines (151 loc) · 7.13 KB

File metadata and controls

226 lines (151 loc) · 7.13 KB

MCP HTTPS Server with Self-Signed Certificates

This guide explains how to use Codanna's HTTPS MCP server with self-signed certificates, particularly for secure local development and production deployments.

Overview

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

The Certificate Trust Challenge

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 failed errors in Claude Code
  • unable to verify the first certificate errors
  • Connection failures despite the certificate being trusted in your browser

Solution: NODE_EXTRA_CA_CERTS

The solution is to explicitly tell Node.js about your certificate using the NODE_EXTRA_CA_CERTS environment variable.

Step-by-Step Setup

1. Start the HTTPS Server

cargo run --all-features -- serve --https --watch

Or if installed:

codanna serve --https --watch

On 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

2. Copy Certificate to a Standard Location

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.pem

3. Configure MCP in Your Project

Add to .mcp.json in your project root:

{
  "mcpServers": {
    "codanna-https": {
      "type": "sse",
      "url": "https://127.0.0.1:8443/mcp/sse"
    }
  }
}

4. Launch Claude Code with Certificate Trust

NODE_EXTRA_CA_CERTS=~/.ssl/codanna-ca.pem claude

5. Verify Connection

In Claude Code, use the /mcp command to check the connection status. You should see:

codanna-https  ✔ connected

Alternative Setup Methods

Method 1: Shell Alias

Add to your ~/.bashrc or ~/.zshrc:

alias claude-secure='NODE_EXTRA_CA_CERTS=~/.ssl/codanna-ca.pem claude'

Then use:

claude-secure

Method 2: System-wide Trust (macOS)

For 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.pem

OAuth Authentication Flow

The HTTPS server includes a complete OAuth2 implementation:

  1. Discovery: /.well-known/oauth-authorization-server
  2. Registration: /oauth/register
  3. Authorization: /oauth/authorize
  4. Token Exchange: /oauth/token

This flow is handled automatically by Claude Code when connecting to the server.

Troubleshooting

"fetch failed" Error

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 claude

Certificate Already Exists

Problem: 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.

401 Unauthorized

Problem: Server returns 401 errors.

Solution: The OAuth flow should handle authentication automatically. If you see 401 errors:

  1. Check server logs for Bearer token validation messages
  2. Ensure you're using the SSE transport type in .mcp.json
  3. Try reconnecting with /mcp command in Claude Code

Browser Works But Claude Code Doesn't

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.

Security Considerations

For Development

Self-signed certificates are acceptable for local development. The NODE_EXTRA_CA_CERTS approach is secure as it only trusts your specific certificate.

For Production

Consider these alternatives for production:

  1. Let's Encrypt: Use certbot to get free, valid certificates
  2. Reverse Proxy: Place nginx/caddy with valid certs in front of your server
  3. Cloud Provider: Use managed certificates from AWS, GCP, Azure
  4. Corporate CA: Use your organization's internal certificate authority

Never Do This

DO NOT use NODE_TLS_REJECT_UNAUTHORIZED=0 in production. This disables ALL certificate validation and is a serious security risk.

Implementation Details

The HTTPS server (src/mcp/https_server.rs) provides:

  • Certificate Generation: Using rcgen crate with proper X.509 attributes
  • TLS Configuration: Via rustls and axum-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

Platform-Specific Notes

macOS

Certificates stored in: ~/Library/Application Support/codanna/certs/

Linux

Certificates stored in: ~/.config/codanna/certs/

Windows

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
claude

Future Improvements

We're investigating ways to make certificate trust easier:

  1. Automatic Trust Setup: A codanna trust-cert command that handles all setup
  2. Certificate Bundle: Including the CA cert in a format Claude Code can auto-detect
  3. Platform Integration: Better integration with system certificate stores
  4. Documentation: In-app guidance when certificate issues are detected

References

Summary

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.