fix(web): render the connected header when a modern server omits serverInfo (#1773)

A modern-era server/discover makes serverInfo optional (SHOULD, not MUST); a conforming modern server that omits it left initializeResult undefined, collapsing the entire connected header + tab bar so the server was uninspectable. Gate initializeResult on connectionStatus alone with a catalog-name fallback, and thread a serverInfoReported flag so the Connection Info modal reports the omission truthfully instead of presenting the inferred name as server-sent. Closes #1772.
This commit is contained in:
Cliff Hall 2026-07-25 11:40:31 -04:00 • committed by GitHub
commit 820d38c438
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -8,6 +8,7 @@ import { renderWithMantine, screen } from "../../../test/renderWithMantine";
import {
CLEAR_OAUTH_STATE_AND_DISCONNECT_LABEL,
ConnectionInfoContent,
SERVER_INFO_NOT_REPORTED_LABEL,
} from "./ConnectionInfoContent";
const fullResult: InitializeResult = {
@ -62,6 +63,72 @@ describe("ConnectionInfoContent", () => {
expect(screen.getAllByText("—")).toHaveLength(3);
});
it("renders an em-dash when the reported version is an empty string", () => {
renderWithMantine(
<ConnectionInfoContent
initializeResult={{
...fullResult,
serverInfo: { name: "Empty Version Server", version: "" },
}}
clientCapabilities={fullClientCaps}
transport="stdio"
/>,
);
// An empty version reads as unknown ("—"), not a blank row (#1772).
expect(screen.getByText("Empty Version Server")).toBeInTheDocument();
expect(screen.getAllByText("—")).toHaveLength(3);
});
it("renders an em-dash when the reported name is an empty string", () => {
renderWithMantine(
<ConnectionInfoContent
initializeResult={{
...fullResult,
serverInfo: { name: "", version: "1.0.0" },
}}
clientCapabilities={fullClientCaps}
transport="stdio"
/>,
);
// `initialize` mandates the name field, not a non-empty value, so an empty
// reported name also reads as unknown ("—") — symmetric with version.
expect(screen.getByText("1.0.0")).toBeInTheDocument();
expect(screen.getAllByText("—")).toHaveLength(3);
});
it("shows 'not reported' for name and version when serverInfo was not reported", () => {
renderWithMantine(
<ConnectionInfoContent
initializeResult={{
...fullResult,
// App synthesizes a catalog-name fallback here when a modern server
// omits serverInfo; the modal must not present it as server-reported.
serverInfo: { name: "my-catalog-name", version: "" },
}}
serverInfoReported={false}
clientCapabilities={fullClientCaps}
transport="streamable-http"
/>,
);
// The inferred catalog name is NOT shown as the server's reported name...
expect(screen.queryByText("my-catalog-name")).not.toBeInTheDocument();
// ...both Name and Version read as not reported instead.
expect(screen.getAllByText(SERVER_INFO_NOT_REPORTED_LABEL)).toHaveLength(2);
});
it("renders an em-dash when the protocol version is empty", () => {
renderWithMantine(
<ConnectionInfoContent
initializeResult={{ ...fullResult, protocolVersion: "" }}
clientCapabilities={fullClientCaps}
transport="stdio"
/>,
);
// App supplies `protocolVersion ?? ""`; an empty one reads as unknown ("—"),
// symmetric with Name/Version (#1772).
expect(screen.getAllByText("—")).toHaveLength(3);
});
it("renders server and client capability sections", () => {
renderWithMantine(
<ConnectionInfoContent