How to configure the CloudBees CI MCP Router to trust a custom internal CA certificate

Last Reviewed:2026-08-14()
3 minute readKnowledge base

Issue

The CloudBees CI MCP Router returns "Unable to list controllers from Operations Center." when calling the getControllers tool, even though the same API token authenticates successfully when used directly against operations center.

The CloudBees CI MCP Router debug logs show the following error:

Full OC URI to query for controllers: https://operations-center.example.com/api/json?tree=jobs[...] Error while getting controllers from OC: javax.net.ssl.SSLHandshakeException: (certificate_unknown) PKIX path building failed: unable to find valid certification path to requested target Unable to list controllers from OC: java.lang.IllegalStateException: Unable to get list of controllers from OC...

This occurs when operations center is served over HTTPS using a certificate signed by an internal or private CA that is not included in the CloudBees CI MCP Router container’s default JVM truststore. The curl command run directly from a workstation succeeds because the OS truststore includes the internal CA, but the JVM inside the container does not.

Prerequisites:

  • CA certificate(s) required to build the trust chain for operations center (PEM format), obtainable from your IT team

  • keytool available locally (included with any JDK installation)

  • Docker access to run and configure the CloudBees CI MCP Router container

Resolution

Step 1: Obtain the required CA certificates

The JVM truststore inside the CloudBees CI MCP Router container must trust every CA in the chain used to sign operations center’s TLS certificate. Which certificates you need to import depends on your environment:

  • If operations center uses a certificate signed by a publicly trusted CA already bundled with the JDK, no additional certificates are required.

  • If operations center uses a certificate signed by a private or internal CA, you must import that root CA — and any intermediate CAs in the chain — that are not already present in the default JVM cacerts.

To inspect the full certificate chain presented by operations center, run:

openssl s_client -showcerts -connect operations-center.example.com:443 \ </dev/null 2>/dev/null

The output contains one BEGIN CERTIFICATE / END CERTIFICATE block per certificate in the chain. The first block is the server (leaf) certificate; subsequent blocks are intermediate and root CA certificates. Save the CA certificates you need to import as individual PEM files (for example, root-ca.pem, intermediate-ca.pem).

If the full chain is not visible in the output, or if you are unsure which certificates are missing from the JVM truststore, obtain the CA certificate files directly from your IT team.

Step 2: Extract the default JVM cacerts from the container

Copy the default cacerts truststore from the CloudBees CI MCP Router container image to your local machine:

docker create --name mcp-router-temp cloudbees/ci-mcp-router:latest docker cp mcp-router-temp:/usr/lib/jvm/java-21/lib/security/cacerts ./cacerts-combined docker rm mcp-router-temp
The JVM path inside the container may vary by image version. If the above path does not exist, run docker run --rm --entrypoint find cloudbees/ci-mcp-router:latest /usr/lib/jvm -name cacerts to locate it.

Step 3: Import the required CA certificates into the combined truststore

Run the following command once for each CA certificate obtained in Step 1, using a unique -alias value per certificate:

keytool -import \ -alias root-ca \ -keystore ./cacerts-combined \ -file root-ca.pem \ -storepass changeit \ -noprompt

If you have intermediate CA certificates to import, repeat the command with a different alias and file for each one (for example, -alias intermediate-ca -file intermediate-ca.pem).

Step 4: Start the CloudBees CI MCP Router with the custom truststore

Mount the combined truststore into the container and pass the JVM truststore flags via JAVA_TOOL_OPTIONS:

docker run -p 7701:9000 \ -v $(pwd)/cacerts-combined:/deployments/cacerts-combined:ro \ -e OC_URL=https://operations-center.example.com/ \ -e JAVA_TOOL_OPTIONS="-Djavax.net.ssl.trustStore=/deployments/cacerts-combined -Djavax.net.ssl.trustStorePassword=changeit -Dquarkus.mcp.server.http.streamable.dummy-init=true" \ -e QUARKUS_HTTP_CORS_ENABLED=true \ cloudbees/ci-mcp-router:latest
JAVA_TOOL_OPTIONS applies to all JVM processes started in the container environment. If other JVM processes share the same environment, they will also use the custom truststore. Ensure the truststore volume remains accessible at all container restarts; if the volume becomes unavailable, the JVM will fail to start.

Step 5: Verify connectivity

After starting the container, call the getControllers tool and confirm a successful response:

curl -sN -X POST http://localhost:7701/mcp \ -H "Authorization: Basic <base64-encoded-oc-token>" \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"getControllers","arguments":{}}}' | jq

A successful response lists the available controllers:

{"jsonrpc":"2.0","id":1,"result":{"isError":false,"content":[{"text":"[{\"name\":\"cc2\",\"displayName\":\"cc2\",\"endpoint\":\"http://cc2.example.com:8080\",\"status\":\"online\"}]","type":"text"}]}}

The CloudBees CI MCP Router debug logs should show:

DEBUG Fetching controllers from OC: https://operations-center.example.com/ DEBUG Full OC URI to query: https://operations-center.example.com/api/json?tree=jobs[...] DEBUG Request ... with Authorization header available: true returned status 200 INFO Fetched from OC: https://operations-center.example.com/, controllers: [http://cc2.example.com:8080]
This article is part of our Knowledge Base and is provided for guidance-based purposes only. The solutions or workarounds described here are not officially supported by CloudBees and may not be applicable in all environments. Use at your own discretion, and test changes in a safe environment before applying them to production systems.