+ {/* Headline */}
+
+ {succeeded ? (
+
+ ) : (
+
+ )}
+
+ {succeeded ? "Handshake succeeded" : (result?.error ?? error ?? "Handshake failed")}
+
+
+
+ {/* Credential used — always shown, per security requirement */}
+ {result?.credentialSource && (
+
+ Credential:{" "}
+
+ {CREDENTIAL_SOURCE_COPY[result.credentialSource] ?? result.credentialSource}
+
+
+ )}
+
+ {result && (
+ <>
+ {/* Latency */}
+
Latency: {result.latencyMs} ms
+
+ {/* Negotiation path */}
+ {result.negotiationPath && (
+
+ Path: {result.negotiationPath}
+
+ )}
+
+ {/* Server identity */}
+ {(result.serverName ?? result.serverVersion ?? result.protocolVersion) && (
+
+ {result.serverName && (
+
+ Server: {result.serverName}
+ {result.serverVersion && (
+ v{result.serverVersion}
+ )}
+
+ )}
+ {result.protocolVersion && (
+
+ Protocol:{" "}
+ {result.protocolVersion}
+
+ )}
+
+ )}
+
+ {/* Capabilities */}
+ {result.capabilities && Object.keys(result.capabilities).length > 0 && (
+
+
Capabilities:
+
+ {Object.keys(result.capabilities).map((capability) => (
+
+ {capability}
+
+ ))}
+
+
+ )}
+
+ {/* Component counts, cross-checked against the virtual server's own aggregate */}
+ {allCountKeys.length > 0 && (
+
+
+ {allCountKeys.map((key) => (
+
+ ))}
+ {result.countsPartial && (
+ (partial)
+ )}
+
+ {mismatchKeys.length > 0 && (
+
+
+
+ Component counts don't match the virtual server's aggregate
+ {result.countsPartial
+ ? " (handshake counts are a paginated lower bound, so this may not be a real mismatch)"
+ : ""}
+ . This can mean a federated source is unreachable or filtering has diverged.
+
+
+ )}
+
+ )}
+
+ {/* Failure class + actionable copy */}
+ {!succeeded && result.failureClass && (
+
+
+ Failure class: {result.failureClass}
+
+
+ {FAILURE_CLASS_COPY[
+ result.failureClass as GatewayHandshakeResponseFailureClass & string
+ ] ?? "Check the server URL, credentials, and that it speaks MCP."}
+
+
+ )}
+
+ {/* Raw preview */}
+ {result.rawPreview && (
+
+
Raw preview:
+
+
+
+
+
+
+ )}
+ >
+ )}
+
+ );
+}
+
+export function HandshakeTestPanel({ serverUrl, aggregatedCounts }: HandshakeTestPanelProps) {
+ const [status, setStatus] = useState