This commit is contained in:
2025-08-06 15:39:05 +08:00
parent 351a79d54c
commit 6798be3b42
26 changed files with 1243 additions and 469 deletions

View File

@@ -20,6 +20,7 @@ import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { api, type MCPServer } from "@/lib/api";
import { useTrackEvent } from "@/hooks";
import { useTranslation } from "@/hooks/useTranslation";
interface MCPServerListProps {
/**
@@ -50,6 +51,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
onServerRemoved,
onRefresh,
}) => {
const { t } = useTranslation();
const [removingServer, setRemovingServer] = useState<string | null>(null);
const [testingServer, setTestingServer] = useState<string | null>(null);
const [expandedServers, setExpandedServers] = useState<Set<string>>(new Set());
@@ -184,11 +186,11 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
const getScopeDisplayName = (scope: string) => {
switch (scope) {
case "local":
return "Local (Project-specific)";
return t('localProjectSpecific');
case "project":
return "Project (Shared via .mcp.json)";
return t('projectSharedMcp');
case "user":
return "User (All projects)";
return t('userAllProjects');
default:
return scope;
}
@@ -220,7 +222,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{server.status?.running && (
<Badge variant="outline" className="gap-1 flex-shrink-0 border-green-500/50 text-green-600 bg-green-500/10">
<CheckCircle className="h-3 w-3" />
Running
{t('running')}
</Badge>
)}
</div>
@@ -237,7 +239,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
className="h-6 px-2 text-xs hover:bg-primary/10"
>
<ChevronDown className="h-3 w-3 mr-1" />
Show full
{t('showFull')}
</Button>
</div>
)}
@@ -299,7 +301,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{server.command && (
<div className="space-y-1">
<div className="flex items-center justify-between">
<p className="text-xs font-medium text-muted-foreground">Command</p>
<p className="text-xs font-medium text-muted-foreground">{t('command')}</p>
<div className="flex items-center gap-1">
<Button
variant="ghost"
@@ -308,7 +310,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
className="h-6 px-2 text-xs hover:bg-primary/10"
>
<Copy className="h-3 w-3 mr-1" />
{isCopied ? "Copied!" : "Copy"}
{isCopied ? t('copied') : t('copy')}
</Button>
<Button
variant="ghost"
@@ -317,7 +319,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
className="h-6 px-2 text-xs hover:bg-primary/10"
>
<ChevronUp className="h-3 w-3 mr-1" />
Hide
{t('hide')}
</Button>
</div>
</div>
@@ -329,7 +331,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{server.args && server.args.length > 0 && (
<div className="space-y-1">
<p className="text-xs font-medium text-muted-foreground">Arguments</p>
<p className="text-xs font-medium text-muted-foreground">{t('arguments')}</p>
<div className="text-xs font-mono bg-muted/50 p-2 rounded space-y-1">
{server.args.map((arg, idx) => (
<div key={idx} className="break-all">
@@ -343,7 +345,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{server.transport === "sse" && server.url && (
<div className="space-y-1">
<p className="text-xs font-medium text-muted-foreground">URL</p>
<p className="text-xs font-medium text-muted-foreground">{t('url')}</p>
<p className="text-xs font-mono bg-muted/50 p-2 rounded break-all">
{server.url}
</p>
@@ -352,7 +354,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{Object.keys(server.env).length > 0 && (
<div className="space-y-1">
<p className="text-xs font-medium text-muted-foreground">Environment Variables</p>
<p className="text-xs font-medium text-muted-foreground">{t('environmentVariables')}</p>
<div className="text-xs font-mono bg-muted/50 p-2 rounded space-y-1">
{Object.entries(server.env).map(([key, value]) => (
<div key={key} className="break-all">
@@ -384,9 +386,9 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
{/* Header */}
<div className="flex items-center justify-between mb-6">
<div>
<h3 className="text-base font-semibold">Configured Servers</h3>
<h3 className="text-base font-semibold">{t('configuredServers')}</h3>
<p className="text-sm text-muted-foreground">
{servers.length} server{servers.length !== 1 ? "s" : ""} configured
{servers.length} {servers.length !== 1 ? t('servers') : 'server'} {t('serversConfigured')}
</p>
</div>
<Button
@@ -396,7 +398,7 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
className="gap-2 hover:bg-primary/10 hover:text-primary hover:border-primary/50"
>
<RefreshCw className="h-4 w-4" />
Refresh
{t('app.refresh')}
</Button>
</div>
@@ -406,9 +408,9 @@ export const MCPServerList: React.FC<MCPServerListProps> = ({
<div className="p-4 bg-primary/10 rounded-full mb-4">
<Network className="h-12 w-12 text-primary" />
</div>
<p className="text-muted-foreground mb-2 font-medium">No MCP servers configured</p>
<p className="text-muted-foreground mb-2 font-medium">{t('noMcpServersConfigured')}</p>
<p className="text-sm text-muted-foreground">
Add a server to get started with Model Context Protocol
{t('addServerToGetStarted')}
</p>
</div>
) : (