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
3 changes: 3 additions & 0 deletions apps/code/src/renderer/components/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CommandMenu } from "@features/command/components/CommandMenu";
import { CommandCenterView } from "@features/command-center/components/CommandCenterView";
import { InboxView } from "@features/inbox/components/InboxView";
import { useInboxDeepLink } from "@features/inbox/hooks/useInboxDeepLink";
import { McpServersView } from "@features/mcp-servers/components/McpServersView";
import { FolderSettingsView } from "@features/settings/components/FolderSettingsView";
import { SettingsDialog } from "@features/settings/components/SettingsDialog";
import { useSettingsDialogStore } from "@features/settings/stores/settingsDialogStore";
Expand Down Expand Up @@ -129,6 +130,8 @@ export function MainLayout() {
{view.type === "command-center" && <CommandCenterView />}

{view.type === "skills" && <SkillsView />}

{view.type === "mcp-servers" && <McpServersView />}
</Box>
</Flex>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useMcpServers } from "@features/settings/hooks/useMcpServers";
import { useMcpServers } from "@features/mcp-servers/hooks/useMcpServers";
import { useSetHeaderContent } from "@hooks/useSetHeaderContent";
import { Plugs } from "@phosphor-icons/react";
import {
AlertDialog,
Box,
Expand All @@ -14,18 +16,18 @@ import type {
} from "@renderer/api/posthogClient";
import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useEffect, useMemo, useState } from "react";
import { AddCustomServerForm } from "./mcp/AddCustomServerForm";
import { MarketplaceView } from "./mcp/MarketplaceView";
import { McpInstalledRail } from "./mcp/McpInstalledRail";
import { ServerDetailView } from "./mcp/ServerDetailView";
import { AddCustomServerForm } from "./parts/AddCustomServerForm";
import { MarketplaceView } from "./parts/MarketplaceView";
import { McpInstalledRail } from "./parts/McpInstalledRail";
import { ServerDetailView } from "./parts/ServerDetailView";

type SceneView =
| { kind: "marketplace" }
| { kind: "detail-installation"; installationId: string }
| { kind: "detail-template"; templateId: string }
| { kind: "add-custom" };

export function McpServersSettings() {
export function McpServersView() {
const queryClient = useQueryClient();
const [view, setView] = useState<SceneView>({ kind: "marketplace" });
const [query, setQuery] = useState("");
Expand All @@ -43,6 +45,22 @@ export function McpServersSettings() {
null,
);

const headerContent = useMemo(
() => (
<Flex align="center" gap="2" className="w-full min-w-0">
<Plugs size={12} className="shrink-0 text-gray-10" />
<Text
className="truncate whitespace-nowrap font-medium text-[13px]"
title="MCP servers"
>
MCP servers
</Text>
</Flex>
),
[],
);
useSetHeaderContent(headerContent);

const {
installations,
installationsLoading,
Expand Down Expand Up @@ -254,7 +272,7 @@ export function McpServersSettings() {
})();

return (
<Flex className="min-h-0 w-full flex-1 overflow-hidden">
<Flex height="100%" className="min-h-0 overflow-hidden">
<McpInstalledRail
installations={installationList}
templates={serverList}
Expand All @@ -266,12 +284,7 @@ export function McpServersSettings() {
/>
<Box className="min-h-0 min-w-0 flex-1">
<ScrollArea className="h-full w-full">
<Box
p="6"
mx="auto"
style={{ zIndex: 1 }}
className="relative max-w-[960px]"
>
<Box p="6" mx="auto" className="relative z-[1] max-w-[960px]">
{mainContent}
</Box>
</ScrollArea>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
filterServersByCategory,
filterServersByQuery,
} from "@features/settings/hooks/mcpFilters";
} from "@features/mcp-servers/hooks/mcpFilters";
import { MagnifyingGlass, Plus, X } from "@phosphor-icons/react";
import {
Button,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { filterInstallationsByQuery } from "@features/settings/hooks/mcpFilters";
import { filterInstallationsByQuery } from "@features/mcp-servers/hooks/mcpFilters";
import { MagnifyingGlass, Plus, X } from "@phosphor-icons/react";
import {
Flex,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useMcpInstallationTools } from "@features/settings/hooks/useMcpInstallationTools";
import { useMcpInstallationTools } from "@features/mcp-servers/hooks/useMcpInstallationTools";
import {
ArrowClockwise,
ArrowLeft,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {
HardDrives,
Keyboard,
Palette,
Plugs,
SignOut,
TrafficSignal,
TreeStructure,
Expand All @@ -37,7 +36,6 @@ import { ClaudeCodeSettings } from "./sections/ClaudeCodeSettings";
import { CloudEnvironmentsSettings } from "./sections/CloudEnvironmentsSettings";
import { EnvironmentsSettings } from "./sections/environments/EnvironmentsSettings";
import { GeneralSettings } from "./sections/GeneralSettings";
import { McpServersSettings } from "./sections/McpServersSettings";
import { PersonalizationSettings } from "./sections/PersonalizationSettings";
import { PlanUsageSettings } from "./sections/PlanUsageSettings";
import { ShortcutsSettings } from "./sections/ShortcutsSettings";
Expand All @@ -51,7 +49,6 @@ interface SidebarItem {
label: string;
icon: ReactNode;
hasChevron?: boolean;
fullwidth?: boolean;
}

const SIDEBAR_ITEMS: SidebarItem[] = [
Expand All @@ -75,12 +72,6 @@ const SIDEBAR_ITEMS: SidebarItem[] = [
icon: <Palette size={16} />,
},
{ id: "claude-code", label: "Claude Code", icon: <Code size={16} /> },
{
id: "mcp-servers",
label: "MCP servers",
icon: <Plugs size={16} />,
fullwidth: true,
},
{ id: "shortcuts", label: "Shortcuts", icon: <Keyboard size={16} /> },

{
Expand All @@ -101,7 +92,6 @@ const CATEGORY_TITLES: Record<SettingsCategory, string> = {
"cloud-environments": "Cloud environments",
personalization: "Personalization",
"claude-code": "Claude Code",
"mcp-servers": "MCP Servers",
shortcuts: "Shortcuts",

signals: "Signals",
Expand All @@ -118,7 +108,6 @@ const CATEGORY_COMPONENTS: Record<SettingsCategory, React.ComponentType> = {
"cloud-environments": CloudEnvironmentsSettings,
personalization: PersonalizationSettings,
"claude-code": ClaudeCodeSettings,
"mcp-servers": McpServersSettings,
shortcuts: ShortcutsSettings,

signals: SignalSourcesSettings,
Expand Down Expand Up @@ -169,8 +158,6 @@ export function SettingsDialog() {
}

const ActiveComponent = CATEGORY_COMPONENTS[activeCategory];
const activeItem = sidebarItems.find((i) => i.id === activeCategory);
const isFullwidth = !!activeItem?.fullwidth;

const initials = user
? user.first_name && user.last_name
Expand Down Expand Up @@ -278,22 +265,16 @@ export function SettingsDialog() {
fill="url(#settings-dot-pattern)"
/>
</svg>
{isFullwidth ? (
<div className="relative z-[1] flex h-full min-h-0 w-full">
<ActiveComponent />
</div>
) : (
<ScrollArea className="h-full w-full">
<Box p="6" mx="auto" className="relative z-[1] max-w-[800px]">
<Flex direction="column" gap="4">
<Text className="font-medium text-lg leading-6.5">
{CATEGORY_TITLES[activeCategory]}
</Text>
<ActiveComponent />
</Flex>
</Box>
</ScrollArea>
)}
<ScrollArea className="h-full w-full">
<Box p="6" mx="auto" className="relative z-[1] max-w-[800px]">
<Flex direction="column" gap="4">
<Text className="font-medium text-lg leading-6.5">
{CATEGORY_TITLES[activeCategory]}
</Text>
<ActiveComponent />
</Flex>
</Box>
</ScrollArea>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ export type SettingsCategory =
| "personalization"
| "claude-code"
| "shortcuts"
| "mcp-servers"
| "signals"
| "updates"
| "advanced";
Expand Down
13 changes: 13 additions & 0 deletions apps/code/src/renderer/features/sidebar/components/SidebarMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { useSidebarData } from "../hooks/useSidebarData";
import { useTaskViewed } from "../hooks/useTaskViewed";
import { CommandCenterItem } from "./items/CommandCenterItem";
import { InboxItem, NewTaskItem } from "./items/HomeItem";
import { McpServersItem } from "./items/McpServersItem";
import { SkillsItem } from "./items/SkillsItem";
import { SidebarItem } from "./SidebarItem";
import { TaskListView } from "./TaskListView";
Expand All @@ -40,6 +41,7 @@ function SidebarMenuComponent() {
navigateToInbox,
navigateToCommandCenter,
navigateToSkills,
navigateToMcpServers,
} = useNavigationStore();

const { data: allTasks = [] } = useTasks();
Expand Down Expand Up @@ -114,6 +116,10 @@ function SidebarMenuComponent() {
navigateToSkills();
};

const handleMcpServersClick = () => {
navigateToMcpServers();
};

const handleTaskClick = (taskId: string) => {
const task = taskMap.get(taskId);
if (task) {
Expand Down Expand Up @@ -292,6 +298,13 @@ function SidebarMenuComponent() {
/>
</Box>

<Box>
<McpServersItem
isActive={sidebarData.isMcpServersActive}
onClick={handleMcpServersClick}
/>
</Box>

<Box mb="2">
<CommandCenterItem
isActive={sidebarData.isCommandCenterActive}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Plugs } from "@phosphor-icons/react";
import { SidebarItem } from "../SidebarItem";

interface McpServersItemProps {
isActive: boolean;
onClick: () => void;
}

export function McpServersItem({ isActive, onClick }: McpServersItemProps) {
return (
<SidebarItem
depth={0}
icon={<Plugs size={16} weight={isActive ? "fill" : "regular"} />}
label="MCP servers"
isActive={isActive}
onClick={onClick}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface SidebarData {
isInboxActive: boolean;
isCommandCenterActive: boolean;
isSkillsActive: boolean;
isMcpServersActive: boolean;
isLoading: boolean;
activeTaskId: string | null;
pinnedTasks: TaskData[];
Expand All @@ -58,7 +59,8 @@ interface ViewState {
| "inbox"
| "archived"
| "command-center"
| "skills";
| "skills"
| "mcp-servers";
data?: Task;
}

Expand Down Expand Up @@ -123,6 +125,7 @@ export function useSidebarData({
const isInboxActive = activeView.type === "inbox";
const isCommandCenterActive = activeView.type === "command-center";
const isSkillsActive = activeView.type === "skills";
const isMcpServersActive = activeView.type === "mcp-servers";

const activeTaskId =
activeView.type === "task-detail" && activeView.data
Expand Down Expand Up @@ -232,6 +235,7 @@ export function useSidebarData({
isInboxActive,
isCommandCenterActive,
isSkillsActive,
isMcpServersActive,
isLoading,
activeTaskId,
pinnedTasks,
Expand Down
11 changes: 10 additions & 1 deletion apps/code/src/renderer/stores/navigationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type ViewType =
| "inbox"
| "archived"
| "command-center"
| "skills";
| "skills"
| "mcp-servers";

export interface TaskInputReportAssociation {
reportId: string;
Expand Down Expand Up @@ -60,6 +61,7 @@ interface NavigationStore {
navigateToArchived: () => void;
navigateToCommandCenter: () => void;
navigateToSkills: () => void;
navigateToMcpServers: () => void;
goBack: () => void;
goForward: () => void;
canGoBack: () => boolean;
Expand Down Expand Up @@ -93,6 +95,9 @@ const isSameView = (view1: ViewState, view2: ViewState): boolean => {
if (view1.type === "skills" && view2.type === "skills") {
return true;
}
if (view1.type === "mcp-servers" && view2.type === "mcp-servers") {
return true;
}
return false;
};

Expand Down Expand Up @@ -271,6 +276,10 @@ export const useNavigationStore = create<NavigationStore>()(
navigate({ type: "skills" });
},

navigateToMcpServers: () => {
navigate({ type: "mcp-servers" });
},

goBack: () => {
const { history, historyIndex } = get();
if (historyIndex > 0) {
Expand Down
Loading