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
4 changes: 2 additions & 2 deletions mlflow/server/js/src/common/components/MlflowSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
InfoBookIcon,
Tooltip,
NewWindowIcon,
WrenchIcon,
McpIcon,
} from '@databricks/design-system';
import { useQueryClient } from '@mlflow/mlflow/src/common/utils/reactQueryHooks';
import type { Location } from '../utils/RoutingUtils';
Expand Down Expand Up @@ -243,7 +243,7 @@ export function MlflowSidebar({
? [
{
key: 'mcp-registry',
icon: <WrenchIcon />,
icon: <McpIcon />,
linkProps: {
to: MCPRegistryRoutes.mcpRegistryPageRoute,
isActive: isMCPRegistryActive,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import { FormattedMessage, useIntl } from 'react-intl';

import type { MCPServer } from '../types';
import MCPRegistryRoutes from '../routes';
import { resolveDisplayName } from '../utils';
import { resolveDisplayName, resolveIconSrc } from '../utils';
import { useLatestMCPServerVersionQuery } from '../hooks/useMCPServerDetailQuery';
import { CardIconWrapper } from './CardIconWrapper';
import { MCPServerIcon } from './MCPServerIcon';
import Utils from '../../common/utils/Utils';

export const MCPServerCard = ({ server }: { server: MCPServer }) => {
Expand All @@ -28,7 +29,7 @@ export const MCPServerCard = ({ server }: { server: MCPServer }) => {
>
<div css={{ display: 'flex', alignItems: 'flex-start', gap: theme.spacing.sm }}>
<CardIconWrapper>
<McpIcon />
<MCPServerIcon iconSrc={resolveIconSrc(server.icons) || resolveIconSrc(latestVersion?.server_json?.icons)} />
</CardIconWrapper>
<div css={{ display: 'flex', flexDirection: 'column', gap: theme.spacing.xs, overflow: 'hidden', flex: 1 }}>
<div css={{ display: 'flex', alignItems: 'flex-start', gap: theme.spacing.sm }}>
Expand Down
27 changes: 27 additions & 0 deletions mlflow/server/js/src/mcp-registry/components/MCPServerIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useState } from 'react';
import { McpIcon, useDesignSystemTheme } from '@databricks/design-system';

export const MCPServerIcon = ({ iconSrc, className }: { iconSrc?: string; className?: string }) => {
const { theme } = useDesignSystemTheme();
const [iconError, setIconError] = useState(false);

if (iconSrc && !iconError) {
return (
<img
src={iconSrc}
alt=""
referrerPolicy="no-referrer"
onError={() => setIconError(true)}
className={className}
css={{
flexShrink: 0,
width: theme.general.iconFontSize,
height: theme.general.iconFontSize,
objectFit: 'contain',
}}
/>
);
}

return <McpIcon className={className} css={{ flexShrink: 0, color: theme.colors.textSecondary }} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { CursorPaginationProps } from '@databricks/design-system';
import {
CursorPagination,
Empty,
McpIcon,
NoIcon,
Overflow,
PencilIcon,
Expand All @@ -24,10 +23,11 @@ import { FormattedMessage, useIntl } from 'react-intl';

import type { MCPServer } from '../types';
import MCPRegistryRoutes from '../routes';
import { emptyCenterStyles, resolveDisplayName, tagsRecordToArray } from '../utils';
import { emptyCenterStyles, resolveDisplayName, tagsRecordToArray, resolveIconSrc } from '../utils';
import { useLatestMCPServerVersionQuery } from '../hooks/useMCPServerDetailQuery';
import { Link } from '../../common/utils/RoutingUtils';
import { KeyValueTag } from '../../common/components/KeyValueTag';
import { MCPServerIcon } from './MCPServerIcon';
import Utils from '../../common/utils/Utils';

interface MCPServerTableMeta {
Expand All @@ -36,10 +36,13 @@ interface MCPServerTableMeta {

const MCPServerNameCell = ({ getValue, row }: CellContext<MCPServer, unknown>) => {
const { theme } = useDesignSystemTheme();
const { data: latestVersion } = useLatestMCPServerVersionQuery(row.original.name);
const value = getValue() as string;
return (
<span css={{ display: 'flex', alignItems: 'center', gap: theme.spacing.xs }}>
<McpIcon css={{ flexShrink: 0, color: theme.colors.textSecondary }} />
<MCPServerIcon
iconSrc={resolveIconSrc(row.original.icons) || resolveIconSrc(latestVersion?.server_json?.icons)}
/>
<Link
componentId="mlflow.mcp_registry.table.name_link"
to={MCPRegistryRoutes.getMCPServerDetailRoute(row.original.name)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import {
import type { TagColors } from '@databricks/design-system';
import { FormattedMessage, useIntl } from 'react-intl';

import type { MCPAccessBinding, MCPServer, MCPServerVersion } from '../types';
import { STATUS_TAG_COLOR, STATUS_TRANSITIONS, resolveDisplayName } from '../utils';
import type { MCPStatus } from '../types';
import type { MCPAccessBinding, MCPServer, MCPServerVersion, MCPStatus } from '../types';
import { STATUS_TAG_COLOR, STATUS_TRANSITIONS, resolveIconSrc, resolveDisplayName } from '../utils';
import { MCPServerIcon } from './MCPServerIcon';
import { MCPServerAccessBindings } from './MCPServerAccessBindings';
import { ServerJSONSection, ToolsSection } from './ServerJSONSection';
import { ConfirmationModal } from '../../admin/ConfirmationModal';
Expand Down Expand Up @@ -152,7 +152,7 @@ export const MCPServerVersionDetail = ({

<Spacer shrinks={false} />
<div css={{ display: 'flex', alignItems: 'center', gap: theme.spacing.sm }}>
<McpIcon css={{ flexShrink: 0, color: theme.colors.textSecondary }} />
<MCPServerIcon iconSrc={resolveIconSrc(version?.server_json?.icons) || resolveIconSrc(server.icons)} />
<div css={{ display: 'flex', flexDirection: 'column' }}>
<Typography.Text bold>{displayName}</Typography.Text>
<Typography.Text color="secondary" size="sm">
Expand Down
5 changes: 2 additions & 3 deletions mlflow/server/js/src/mcp-registry/pages/MCPRegistryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
PlusIcon,
SegmentedControlButton,
SegmentedControlGroup,
WrenchIcon,
McpIcon,
Spacer,
TableFilterInput,
TableFilterLayout,
Expand All @@ -36,7 +36,6 @@ import type { MCPAccessBinding } from '../types';
import { MCPAccessBindingCardGrid } from '../components/MCPAccessBindingCardGrid';
import { MCPAccessBindingListTable } from '../components/MCPAccessBindingListTable';
import { AccessBindingModal } from '../components/AccessBindingModal';
import type { MCPServer } from '../types';
import { useDebounce } from 'use-debounce';

type ViewMode = 'list' | 'grid';
Expand Down Expand Up @@ -168,7 +167,7 @@ const MCPRegistryPage = () => {
padding: theme.spacing.sm,
}}
>
<WrenchIcon />
<McpIcon />
</span>
<FormattedMessage defaultMessage="MCP Registry" description="MCP Registry page title" />
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -528,5 +528,5 @@ describe('MCPServerDetailPage', () => {
},
{ timeout: 10000 },
);
});
}, 15000);
});
3 changes: 2 additions & 1 deletion mlflow/server/js/src/mcp-registry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export interface MCPTool {
name: string;
title?: string;
description?: string;
icons?: MCPIcon[];
inputSchema?: Record<string, unknown>;
outputSchema?: Record<string, unknown>;
annotations?: Record<string, unknown>;
icons?: MCPIcon[];
execution?: Record<string, unknown>;
}

Expand Down Expand Up @@ -124,6 +124,7 @@ export interface ServerJSONPayload {
version: string;
title?: string;
description?: string;
icons?: MCPIcon[];
packages?: ServerJSONPackage[];
remotes?: ServerJSONTransport[];
repository?: ServerJSONRepository;
Expand Down
6 changes: 5 additions & 1 deletion mlflow/server/js/src/mcp-registry/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TagProps } from '@databricks/design-system';
import type { MCPRemoteTransportType, MCPStatus, MCPTool, ServerJSONPayload } from './types';
import type { MCPIcon, MCPRemoteTransportType, MCPStatus, MCPTool, ServerJSONPayload } from './types';

export const STATUS_TAG_COLOR: Record<MCPStatus, TagProps['color']> = {
draft: 'charcoal',
Expand Down Expand Up @@ -85,6 +85,10 @@ export const buildSearchFilterClause = (searchFilter: string | undefined, field:
return `${field} LIKE '%${searchFilter.replace(/'/g, "''")}%'`;
};

export const resolveIconSrc = (icons: MCPIcon[] | undefined): string | undefined => {
return icons?.[0]?.src;
};

export const isValidEndpointUrl = (url: string): boolean => {
const trimmed = url.trim();
if (!/^https?:\/\//.test(trimmed)) return false;
Expand Down
Loading