mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-06-18 13:46:02 +00:00
GET /api/mcp/config returns 403 for non-admin users, but the previous
client returned the error body as MCPConfig, causing MCPServerList to
crash with 'Cannot convert undefined or null to object' on
Object.entries(config.mcp_servers).
- api.ts: introduce MCPConfigRequestError; loadMCPConfig and
updateMCPConfig now throw it (carrying status + isAdminRequired)
instead of letting non-2xx bodies leak through as parsed config
- tool-settings-page.tsx: render a friendly 'admin privileges required'
empty state when the React Query error is an admin-required
MCPConfigRequestError; keep MCPServerList resilient with
Object.entries(servers ?? {}) and an empty-state for no servers
- i18n: add settings.tools.adminRequired and settings.tools.empty in
en-US, zh-CN and the Translations type
- tests: cover 403 / 5xx / instanceof / detail-fallback for both
loadMCPConfig and updateMCPConfig in tests/unit/core/mcp/api.test.ts
Refs: #3527
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
} from "@/components/ui/item";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useI18n } from "@/core/i18n/hooks";
|
||||
import { MCPConfigRequestError } from "@/core/mcp/api";
|
||||
import { useMCPConfig, useEnableMCPServer } from "@/core/mcp/hooks";
|
||||
import type { MCPServerConfig } from "@/core/mcp/types";
|
||||
import { env } from "@/env";
|
||||
@@ -18,6 +19,8 @@ import { SettingsSection } from "./settings-section";
|
||||
export function ToolSettingsPage() {
|
||||
const { t } = useI18n();
|
||||
const { config, isLoading, error } = useMCPConfig();
|
||||
const adminRequired =
|
||||
error instanceof MCPConfigRequestError && error.isAdminRequired;
|
||||
return (
|
||||
<SettingsSection
|
||||
title={t.settings.tools.title}
|
||||
@@ -25,6 +28,10 @@ export function ToolSettingsPage() {
|
||||
>
|
||||
{isLoading ? (
|
||||
<div className="text-muted-foreground text-sm">{t.common.loading}</div>
|
||||
) : adminRequired ? (
|
||||
<div className="text-muted-foreground text-sm">
|
||||
{t.settings.tools.adminRequired}
|
||||
</div>
|
||||
) : error ? (
|
||||
<div>Error: {error.message}</div>
|
||||
) : (
|
||||
@@ -37,12 +44,21 @@ export function ToolSettingsPage() {
|
||||
function MCPServerList({
|
||||
servers,
|
||||
}: {
|
||||
servers: Record<string, MCPServerConfig>;
|
||||
servers?: Record<string, MCPServerConfig>;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const { mutate: enableMCPServer } = useEnableMCPServer();
|
||||
const entries = Object.entries(servers ?? {});
|
||||
if (entries.length === 0) {
|
||||
return (
|
||||
<div className="text-muted-foreground text-sm">
|
||||
{t.settings.tools.empty}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
{Object.entries(servers).map(([name, config]) => (
|
||||
{entries.map(([name, config]) => (
|
||||
<Item className="w-full" variant="outline" key={name}>
|
||||
<ItemContent>
|
||||
<ItemTitle>
|
||||
|
||||
Reference in New Issue
Block a user