Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/assets/mcp-brands/figma.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/assets/mcp-brands/line.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/assets/mcp-brands/slack.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/assets/mcp-brands/supabase.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/desktop/src/renderer/assets/mcp-brands/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions apps/desktop/src/renderer/maka-tokens.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,12 @@
--brand-deep-hover: oklch(from var(--accent) calc(l - 0.06) c h);
/* Fixed external channel identity; unlike palette-derived Maka accents. */
--brand-wechat: #07c160;
/* Fixed service identities used only by the MCP market marks. */
/* Fixed service identities for MCP market tiles that fall back to a text
mark (no official brand asset). Brands with a recovered logo — Slack,
LINE, Google Calendar, Figma, Vercel, Supabase — render the real mark on
a neutral plate (mcp-brand-marks.tsx), so their tint tokens were dropped. */
--brand-dingtalk: #1677ff;
--brand-feishu: #3370ff;
--brand-slack: #4a154b;
--brand-line: #06c755;
--brand-google-calendar: #4285f4;
--brand-figma: #f24e1e;
--brand-supabase: #3ecf8e;
--bot-brand-default: var(--accent);
/* PALETTE-LEAK-0: semantic alias for informational system banners (the
plan-reminders 系统提醒 banner) — component CSS derives its tint family
Expand Down
66 changes: 66 additions & 0 deletions apps/desktop/src/renderer/mcp-brand-marks.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Official MCP catalog brand marks.
//
// Mirrors settings/provider-brand-marks.tsx exactly: each mark is a vendored
// official brand logo imported as an `.svg` asset URL (NOT an inline SVG
// literal in this TSX — the icon-governance contract bans hand-drawn inline
// SVG, and these assets sidestep it because `.svg` files are not `.tsx`
// literals). Each logo remains the trademark of its owner and is used here
// only to identify the connected MCP service.
//
// Color marks (Slack, Figma, Google Calendar, Supabase) carry their own
// brand fills and render through `<img>`. Monochrome marks (Vercel ▲, LINE)
// ship with `fill="currentColor"` and render through a mask so they inherit
// the plate's foreground color and stay legible in both light and dark —
// the same split provider-brand-marks.tsx draws between `<img>` and
// `ProviderAssetMask`.
//
// Brands WITHOUT a faithful official asset (钉钉/飞书/Notion/macOS/filesystem/
// …) fall back to the catalog text mark. We never hand-draw or approximate a
// logo we do not have — that is the banned anti-pattern.

import type { ReactElement } from 'react';
import type { McpCatalogEntry } from './mcp-catalog';
import figmaBrandMark from './assets/mcp-brands/figma.svg';
import googleCalendarBrandMark from './assets/mcp-brands/google-calendar.svg';
import lineBrandMark from './assets/mcp-brands/line.svg';
import slackBrandMark from './assets/mcp-brands/slack.svg';
import supabaseBrandMark from './assets/mcp-brands/supabase.svg';
import vercelBrandMark from './assets/mcp-brands/vercel.svg';

// Slack, LINE, Google Calendar, Figma, Vercel and Supabase logos were
// recovered byte-for-byte from the inline markup that lived in mcp-page.tsx
// before #1205 (commit e48be522); see assets/mcp-brands/*.svg for the
// extracted geometry.
type BrandRenderer = { src: string; tone: 'color' | 'mono' };

const MCP_BRAND_MARKS: Record<string, BrandRenderer> = {
slack: { src: slackBrandMark, tone: 'color' },
line: { src: lineBrandMark, tone: 'mono' },
'google-calendar': { src: googleCalendarBrandMark, tone: 'color' },
figma: { src: figmaBrandMark, tone: 'color' },
vercel: { src: vercelBrandMark, tone: 'mono' },
supabase: { src: supabaseBrandMark, tone: 'color' },
};

/** True when the catalog entry has a vendored official brand asset. */
export function hasMcpBrandMark(id: string): boolean {
return id in MCP_BRAND_MARKS;
}

// Monochrome assets ride a mask because `<img>` documents do not inherit
// `currentColor`; identical technique to provider-brand-marks' ProviderAssetMask.
function McpAssetMask({ src }: { src: string }): ReactElement {
const mask = `url("${src}")`;
return <span className="maka-mcp-brand-mask" style={{ maskImage: mask, WebkitMaskImage: mask }} aria-hidden="true" />;
}

/**
* Official brand mark for a catalog entry. Renders the vendored logo when one
* exists; otherwise falls back to the entry's text mark.
*/
export function McpBrandMark({ entry }: { entry: McpCatalogEntry }): ReactElement {
const brand = MCP_BRAND_MARKS[entry.id];
if (!brand) return <span>{entry.mark}</span>;
if (brand.tone === 'mono') return <McpAssetMask src={brand.src} />;
return <img src={brand.src} alt="" />;
}
10 changes: 8 additions & 2 deletions apps/desktop/src/renderer/mcp-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
X,
} from '@maka/ui/icons';
import { MCP_CATALOG, catalogEntryMatches, type McpCatalogEntry } from './mcp-catalog';
import { McpBrandMark, hasMcpBrandMark } from './mcp-brand-marks';
import { parseMcpImport } from './mcp-import';
import { settingsActionErrorMessage } from './settings/settings-error-copy';

Expand Down Expand Up @@ -396,8 +397,13 @@ function McpCatalogCard(props: {
const cancelling = props.phase === 'cancelling';
return (
<article className="maka-mcp-market-card">
<div className="maka-mcp-market-icon" data-brand={props.entry.id} aria-hidden="true">
<span>{props.entry.mark}</span>
<div
className="maka-mcp-market-icon"
data-brand={props.entry.id}
data-logo={hasMcpBrandMark(props.entry.id) ? 'true' : undefined}
aria-hidden="true"
>
<McpBrandMark entry={props.entry} />
</div>
<div className="maka-mcp-market-copy">
<strong>{props.entry.name}</strong>
Expand Down
53 changes: 26 additions & 27 deletions apps/desktop/src/renderer/styles/module-pages/mcp.css
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,34 @@
letter-spacing: var(--tracking-normal);
}

.maka-mcp-market-icon[data-brand="line"] span {
font-size: var(--font-size-caption);
/* Tiles that carry an official brand logo (mcp-brand-marks.tsx) drop the
per-brand tint and ride a quiet neutral plate — a colourful logo already
supplies the brand identity, so tinting the plate too would double up and
fight the mark. Mirrors provider-brand-marks' neutral `.providerLogo`. */
.maka-mcp-market-icon[data-logo="true"] {
background: var(--foreground-5);
color: var(--foreground);
box-shadow: inset 0 0 0 1px oklch(from var(--foreground) l c h / 0.06);
}

/* Color marks (Slack/Figma/Google Calendar/Supabase) keep their own fills via
<img>; monochrome marks (Vercel/LINE) inherit the plate foreground through a
currentColor mask. Both sit at the same 64% ratio as the provider plates. */
.maka-mcp-market-icon img,
.maka-mcp-market-icon .maka-mcp-brand-mask {
width: 64%;
height: 64%;
display: block;
}

.maka-mcp-brand-mask {
background: currentColor;
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
}

/* Text-mark brands with no official asset keep their tinted plate. */
.maka-mcp-market-icon[data-brand="dingtalk"] {
background: color-mix(in oklab, var(--brand-dingtalk) 12%, var(--background));
color: color-mix(in oklab, var(--brand-dingtalk) 72%, var(--foreground));
Expand All @@ -198,31 +222,6 @@
color: color-mix(in oklab, var(--brand-feishu) 72%, var(--foreground));
}

.maka-mcp-market-icon[data-brand="slack"] {
background: color-mix(in oklab, var(--brand-slack) 10%, var(--background));
color: color-mix(in oklab, var(--brand-slack) 72%, var(--foreground));
}

.maka-mcp-market-icon[data-brand="line"] {
background: color-mix(in oklab, var(--brand-line) 15%, var(--background));
color: color-mix(in oklab, var(--brand-line) 62%, var(--foreground));
}

.maka-mcp-market-icon[data-brand="google-calendar"] {
background: color-mix(in oklab, var(--brand-google-calendar) 12%, var(--background));
color: color-mix(in oklab, var(--brand-google-calendar) 72%, var(--foreground));
}

.maka-mcp-market-icon[data-brand="figma"] {
background: color-mix(in oklab, var(--brand-figma) 12%, var(--background));
color: color-mix(in oklab, var(--brand-figma) 70%, var(--foreground));
}

.maka-mcp-market-icon[data-brand="supabase"] {
background: color-mix(in oklab, var(--brand-supabase) 14%, var(--background));
color: color-mix(in oklab, var(--brand-supabase) 62%, var(--foreground));
}

.maka-mcp-market-copy {
min-width: 0;
display: grid;
Expand Down
Loading