fix(site): bundle Notion/Linear/Figma icons and unify tool icon rendering#26228
Draft
tracyjohnsonux wants to merge 6 commits into
Draft
fix(site): bundle Notion/Linear/Figma icons and unify tool icon rendering#26228tracyjohnsonux wants to merge 6 commits into
tracyjohnsonux wants to merge 6 commits into
Conversation
The tool-call icon render path stacked two CSS filter systems: a class-based `brightness-0 dark:invert` silhouette filter on the `<img>`, plus the inline `filter` style that `ExternalImage` adds via `getExternalImageStylesFromUrl` for any URL listed in `defaultParametersForBuiltinIcons`. Inline style wins over class, so bundled icons quietly used the older `monochrome` pipeline while cross-origin URLs used the silhouette one. The result was visibly random across MCP servers, and Notion's composite block logo (a white-filled rounded square layered under a black "N") collapsed into a featureless square under the silhouette filter. - Bundle the popular MCP brand SVGs we did not yet ship (Atlassian, Auth0, Cloudflare, Databricks, Datadog, Figma plus a monochrome-safe Figma variant, Firecrawl, Grafana, Linear, MongoDB, Netlify, Notion, PagerDuty, Sentry, Snowflake). All normalised to the repo's 256x256 viewBox via a fit-and-centre transform around the upstream Brandfetch symbol art, matching the existing `github.svg`, `slack.svg`, `gitlab.svg` convention, and registered for the existing `monochrome` mode in `externalImages.ts`. - Add `site/src/pages/AgentsPage/data/knownMcpServers.ts`, a small registry keyed on Server URL hostname patterns. The MCP server admin form watches the URL field and pre-fills any empty sibling fields (display name, slug, icon URL) when a known host is recognised. Existing user input is never overwritten. The Details section auto-expands so the suggested icon is visible before save. - Drop the class-based silhouette filter and the Notion regex special case it required from `ToolIcon`. External MCP icons now route through the single `ExternalImage` pipeline: bundled paths receive the theme-aware `monochrome` filter, cross-origin URLs render unfiltered to match the MCP pill, and no two filter systems ever fight on the same `<img>`. Notion's composite block logo no longer needs special handling: admins (or the URL prefill) pick `/icon/notion.svg`, a flat lowercase wordmark that filters cleanly to a muted silhouette in both themes. Existing MCP servers pointing at third-party CDN URLs continue to render unfiltered until an admin re-saves them with the bundled icon.
74f0d0d to
8376c83
Compare
Adding MCP servier potential services for better tool call experience.
Adopt the SVGs uploaded directly to the branch and drop the intermediate files I had committed. - Use `figma-black.svg` (monochrome) and `figma-color.svg` (color) in place of `figma-monochrome.svg` / `figma.svg`. - Use `grafana-labs.svg` in place of `grafana.svg`. - Update `icons.json`, `defaultParametersForBuiltinIcons`, and the knownMcpServers registry to point at the new filenames.
…lears the icon field When the admin clears the icon URL field and the current Server URL still matches a known MCP server, immediately re-suggest the bundled default. This keeps the registry suggestion one keystroke away without forcing the admin to retype the Server URL just to get the suggestion back. Add `CreateServerKnownUrlIconRestoresOnClear` story to cover the clear-then-restore flow.
Keep only the brands the original bug screenshots covered (Notion, Linear, Figma). Drop the 12 speculative additions (Atlassian, Auth0, Cloudflare, Databricks, Datadog, Firecrawl, Grafana, MongoDB, Netlify, PagerDuty, Sentry, Snowflake) along with their `icons.json`, `externalImages.ts`, and `knownMcpServers.ts` entries. Adjust the `CreateServerKnownUrlIconRestoresOnClear` storybook scenario to exercise Linear instead of Sentry. Follow-up PR will land the deferred brands as a data-only change once the platform pieces here are merged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tool-call icons rendered inconsistently across MCP servers: Linear and Notion came out as flat silhouettes, GitHub washed out near-white in dark mode, and Notion's block logo collapsed into a featureless square. Root cause was two CSS filter systems fighting on the same
<img>, with the winner decided per-URL.Diagnosis
The
ToolIconcomponent applied a class-basedbrightness-0 dark:invert opacity-*silhouette filter to every external MCP icon. Separately,ExternalImageruns everysrcthroughgetExternalImageStylesFromUrlinsite/src/theme/externalImages.ts; if the URL is same-origin and listed indefaultParametersForBuiltinIcons, it sets an inlinestyle.filter(for examplegrayscale(100%) contrast(0%) brightness(250%)for themonochromemode).Inline style wins over class for the same CSS property. So:
cdn.jsdelivr.net/.../linear-dark.webpbrightness(0) invert(1))cdn.brandfetch.io/.../symbol.svg/icon/github.svgmonochrome(class silhouette silently dropped)The sourcing inconsistency itself came from administrators manually pasting different CDN URLs into the MCP server admin form's free-text icon field. Nothing in our code chose those.
Notion's
notion-logo-block-main.svglayersfill="white"(rounded square) underfill="black"(the "N"). Any single-channel silhouette filter crushes both fills to one shade, producing a featureless block in the chat row.What this PR does
Bundles the three brand SVGs directly named in the bug:
notion.svg,linear.svg,figma-black.svg(monochrome-safe variant), andfigma-color.svg(full-colour reference variant). All normalised to the repo's 256x256 viewBox, registered inicons.jsonso they appear in the icon picker, and mapped to the existingmonochromemode indefaultParametersForBuiltinIcons.Adds
site/src/pages/AgentsPage/data/knownMcpServers.ts, a small registry keyed on Server URL hostname patterns. The MCP server admin form watches the URL field and pre-fills any empty sibling fields (display name, slug, icon URL) when a known host is recognised. User input is never overwritten. When the icon URL is pre-filled, the form auto-expands the Details section so the suggested icon is visible before save. Clearing the icon field while a known URL is present re-suggests the bundled default so admins do not have to retype the URL to recover the suggestion.Registry starts with the brands this PR bundles (Notion, Linear, Figma) plus the popular brands we already shipped (GitHub, GitLab, Bitbucket, Slack, Discord). Additional brands land in the follow-up PR below.
Drops the class-based silhouette filter and the Notion regex special case from
ToolIcon. External MCP icons now route through the singleExternalImage+getExternalImageStylesFromUrlpipeline:/icon/*.svgpaths receive the theme-awaremonochromefilter (grayscale(100%) contrast(0%) brightness(70%)in light,brightness(250%)in dark), producing a uniform muted silhouette that matches the surrounding lucide icons.<img>.Follow-up PR
A data-only follow-up will land the remaining 12 popular MCP brand bundles I had ready (Atlassian, Auth0, Cloudflare, Databricks, Datadog, Firecrawl, Grafana Labs, MongoDB, Netlify, PagerDuty, Sentry, Snowflake) plus their
icons.json/externalImages.ts/knownMcpServers.tsentries. Keeping them out of this PR holds the surface area tight while the platform pieces (filter pipeline collapse, form prefill, clear-restore) get reviewed.Migration
Existing MCP server entries whose
icon_urlwas set by an administrator to a third-party CDN URL keep working: they render unfiltered throughExternalImage, the same way the MCP server pill renders them today. They'll start using the bundled icons when an administrator re-saves the server, either by accepting the URL-prefill suggestion or by selecting the bundled icon from the picker. No backend migration is required.Testing
MCPToolNotionIconBundledstory inTool.stories.tsxexercises the bundled-icon path and asserts the inlinemonochromefilter is applied.MCPToolNotionIconstory keeps regression coverage for the cross-origin Brandfetch URL.CreateServerKnownUrlPrefill,CreateServerKnownUrlPrefillRespectsExistingValues, andCreateServerKnownUrlIconRestoresOnClearstories inMCPServerAdminPanel.stories.tsxexercise the URL-host-keyed prefill and the clear-restore behaviour on both empty and partially-filled forms.Tool.stories.tsx(115/115),MCPServerAdminPanel.stories.tsx(19/19).This PR was generated by Coder Agents.