Visitar URL original
fix(ui): respect display density and default icon sizes (#1728) · modelcontextprotocol/registry@876f408 · GitHub
Skip to content

Commit 876f408

Browse files
authored
fix(ui): respect display density and default icon sizes (#1728)
Icon selection currently compares raster dimensions with a 40 CSS-pixel tile, which selects undersized images on high-density displays. Use the current device pixel ratio when scoring candidates: for example, a 2× display now chooses a 96×96 icon over a 48×48 icon for that tile. Treat omitted or empty `sizes` like `"any"`, matching the schema's default that an icon without sizes is usable at any size. This keeps an SVG without size metadata from losing to a fixed-size raster icon. Follow-up to #1586. Validation: - Focused JavaScript assertions against the actual HTML helpers passed for default/1×/1.5×/2×/3× density, omitted/empty/`any` sizes in both candidate orders, undersized fallback, theme preference, unsafe schemes, and attribute escaping. - `go test ./internal/api/handlers/v0 -run '^TestUIHTML_' -count=1` passed. - `git diff --check` passed.
1 parent c1d6a1c commit 876f408

1 file changed

Lines changed: 8 additions & 6 deletions

File tree

‎internal/api/handlers/v0/ui_index.html‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -559,23 +559,25 @@ <h4 class="font-medium text-gray-900 mb-2">Remotes</h4>
559559
}
560560
}
561561

562-
// Smallest icon at least as large as the rendered size, so it stays crisp
563-
// without pulling a needlessly large file. Scalable icons win outright.
562+
// Smallest icon at least as large as the rendered size in device pixels,
563+
// so it stays crisp without pulling a needlessly large file. Scalable
564+
// icons and icons with omitted sizes (usable at any size) win outright.
564565
// `theme: 'dark'` means "for a dark background"; this UI is light, so those
565566
// are used only when nothing else is available.
566567
const ICON_RENDER_PX = 40;
567568

568569
function iconScore(icon) {
569570
const sizes = Array.isArray(icon.sizes) ? icon.sizes : [];
570-
if (sizes.includes('any')) return 0;
571+
if (!sizes.length || sizes.includes('any')) return 0;
572+
const requiredPx = ICON_RENDER_PX * (window.devicePixelRatio || 1);
571573
const widths = sizes
572574
.map((s) => parseInt(String(s).split('x')[0], 10))
573575
.filter((n) => Number.isFinite(n) && n > 0);
574-
if (!widths.length) return ICON_RENDER_PX * 100;
575-
const atLeast = widths.filter((w) => w >= ICON_RENDER_PX);
576+
if (!widths.length) return requiredPx * 100;
577+
const atLeast = widths.filter((w) => w >= requiredPx);
576578
return atLeast.length
577579
? Math.min(...atLeast)
578-
: ICON_RENDER_PX * 100 + (ICON_RENDER_PX - Math.max(...widths));
580+
: requiredPx * 100 + (requiredPx - Math.max(...widths));
579581
}
580582

581583
function pickIcon(server) {

0 commit comments

Comments
 (0)