|
|
@@ -76,9 +76,10 @@ interface McpServerCardProps {
|
|
|
mcpType: string;
|
|
|
config: McpServerConfig;
|
|
|
onConnectionStatusChange?: (mcpType: string, status: { healthy: boolean; loggedIn: boolean }) => void;
|
|
|
+ onEnabledChange?: (mcpType: string, enabled: boolean) => void;
|
|
|
}
|
|
|
|
|
|
-export function McpServerCard({ mcpType, config, onConnectionStatusChange }: McpServerCardProps) {
|
|
|
+export function McpServerCard({ mcpType, config, onConnectionStatusChange, onEnabledChange }: McpServerCardProps) {
|
|
|
const [showLoginForm, setShowLoginForm] = useState(false);
|
|
|
const [showTokenForm, setShowTokenForm] = useState(false);
|
|
|
const [email, setEmail] = useState('');
|
|
|
@@ -92,6 +93,8 @@ export function McpServerCard({ mcpType, config, onConnectionStatusChange }: Mcp
|
|
|
const [isHealthy, setIsHealthy] = useState<boolean | null>(null); // null=未检查, true=健康, false=不健康
|
|
|
const [isCheckingHealth, setIsCheckingHealth] = useState(false);
|
|
|
const [latency, setLatency] = useState<number | null>(null);
|
|
|
+ // 新增:启用/禁用状态
|
|
|
+ const [isEnabled, setIsEnabled] = useState(() => mcpTokenManager.isEnabled(mcpType));
|
|
|
|
|
|
// 监听 localStorage 变化和组件挂载
|
|
|
useEffect(() => {
|
|
|
@@ -133,6 +136,12 @@ export function McpServerCard({ mcpType, config, onConnectionStatusChange }: Mcp
|
|
|
console.log(`[McpServerCard ${mcpType}] Storage changed:`, e.key);
|
|
|
setUpdateTrigger(prev => prev + 1);
|
|
|
}
|
|
|
+ // 监听启用/禁用状态变化
|
|
|
+ if (e.key === `mcp_enabled_${mcpType}`) {
|
|
|
+ const newState = e.newValue === 'true';
|
|
|
+ setIsEnabled(newState);
|
|
|
+ onEnabledChange?.(mcpType, newState);
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
window.addEventListener('storage', handleStorageChange);
|
|
|
@@ -231,16 +240,38 @@ export function McpServerCard({ mcpType, config, onConnectionStatusChange }: Mcp
|
|
|
setUpdateTrigger(prev => prev + 1);
|
|
|
};
|
|
|
|
|
|
+ const handleToggleEnabled = () => {
|
|
|
+ const newState = mcpTokenManager.toggleEnabled(mcpType);
|
|
|
+ setIsEnabled(newState);
|
|
|
+ onEnabledChange?.(mcpType, newState);
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
- <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 border dark:border-gray-700">
|
|
|
+ <div className={`bg-white dark:bg-gray-800 rounded-lg shadow-md p-6 border dark:border-gray-700 transition-all ${!isEnabled ? 'opacity-50 grayscale' : ''}`}>
|
|
|
<div className="flex items-start justify-between mb-4">
|
|
|
<div className="flex-1">
|
|
|
- <h3 className="text-lg font-semibold text-gray-800 dark:text-white">
|
|
|
- {config.name}
|
|
|
- </h3>
|
|
|
+ <div className="flex items-center gap-3">
|
|
|
+ <h3 className="text-lg font-semibold text-gray-800 dark:text-white">
|
|
|
+ {config.name}
|
|
|
+ </h3>
|
|
|
+ {/* 启用/禁用开关 */}
|
|
|
+ <button
|
|
|
+ type="button"
|
|
|
+ onClick={handleToggleEnabled}
|
|
|
+ className={`flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium transition-all ${
|
|
|
+ isEnabled
|
|
|
+ ? 'bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300 hover:bg-green-200 dark:hover:bg-green-800'
|
|
|
+ : 'bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600'
|
|
|
+ }`}
|
|
|
+ title={isEnabled ? '点击禁用此 MCP 服务器' : '点击启用此 MCP 服务器'}
|
|
|
+ >
|
|
|
+ <span className={`w-1.5 h-1.5 rounded-full ${isEnabled ? 'bg-green-500' : 'bg-gray-400'}`} />
|
|
|
+ {isEnabled ? '启用' : '禁用'}
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
<p className="text-sm text-gray-500 dark:text-gray-400 mt-1">
|
|
|
{config.authType === 'none' ? '无需认证' : '需要登录'}
|
|
|
- {latency !== null && isHealthy && (
|
|
|
+ {latency !== null && isHealthy && isEnabled && (
|
|
|
<span className="ml-2 text-xs text-gray-400">
|
|
|
({latency}ms)
|
|
|
</span>
|
|
|
@@ -264,7 +295,15 @@ export function McpServerCard({ mcpType, config, onConnectionStatusChange }: Mcp
|
|
|
</div>
|
|
|
)}
|
|
|
|
|
|
- {showLoginForm && !isLoggedIn && (
|
|
|
+ {!isEnabled && (
|
|
|
+ <div className="mb-4 p-3 bg-gray-100 dark:bg-gray-700/50 rounded-lg border border-gray-200 dark:border-gray-600">
|
|
|
+ <p className="text-sm text-gray-600 dark:text-gray-400">
|
|
|
+ 此 MCP 服务器已禁用。点击右上角的"启用"按钮来启用它。
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
+
|
|
|
+ {showLoginForm && !isLoggedIn && isEnabled && (
|
|
|
<form onSubmit={handleLogin} className="mb-4 space-y-3">
|
|
|
<div>
|
|
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
|
|
|
@@ -379,7 +418,7 @@ export function McpServerCard({ mcpType, config, onConnectionStatusChange }: Mcp
|
|
|
<p className="text-xs text-gray-500 dark:text-gray-400">
|
|
|
{config.url}
|
|
|
</p>
|
|
|
- {config.authType === 'jwt' && (
|
|
|
+ {config.authType === 'jwt' && isEnabled && (
|
|
|
<div className="flex gap-2">
|
|
|
{!isLoggedIn ? (
|
|
|
!showLoginForm && !showTokenForm && (
|