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:
@@ -495,6 +495,8 @@ export const enUS: Translations = {
|
||||
tools: {
|
||||
title: "Tools",
|
||||
description: "Manage the configuration and enabled status of MCP tools.",
|
||||
adminRequired: "Admin privileges are required to manage MCP tools.",
|
||||
empty: "No MCP tools configured.",
|
||||
},
|
||||
channels: {
|
||||
title: "Channels",
|
||||
|
||||
@@ -406,6 +406,8 @@ export interface Translations {
|
||||
tools: {
|
||||
title: string;
|
||||
description: string;
|
||||
adminRequired: string;
|
||||
empty: string;
|
||||
};
|
||||
channels: {
|
||||
title: string;
|
||||
|
||||
@@ -476,6 +476,8 @@ export const zhCN: Translations = {
|
||||
tools: {
|
||||
title: "工具",
|
||||
description: "管理 MCP 工具的配置和启用状态。",
|
||||
adminRequired: "需要管理员权限才能管理 MCP 工具。",
|
||||
empty: "暂无 MCP 工具。",
|
||||
},
|
||||
channels: {
|
||||
title: "渠道",
|
||||
|
||||
@@ -3,8 +3,36 @@ import { getBackendBaseURL } from "@/core/config";
|
||||
|
||||
import type { MCPConfig } from "./types";
|
||||
|
||||
export class MCPConfigRequestError extends Error {
|
||||
readonly status: number;
|
||||
constructor(status: number, message: string) {
|
||||
super(message);
|
||||
this.name = "MCPConfigRequestError";
|
||||
this.status = status;
|
||||
}
|
||||
get isAdminRequired(): boolean {
|
||||
return this.status === 403;
|
||||
}
|
||||
}
|
||||
|
||||
async function readErrorDetail(
|
||||
response: Response,
|
||||
fallback: string,
|
||||
): Promise<string> {
|
||||
const error = (await response.json().catch(() => ({}))) as {
|
||||
detail?: unknown;
|
||||
};
|
||||
return typeof error.detail === "string" ? error.detail : fallback;
|
||||
}
|
||||
|
||||
export async function loadMCPConfig() {
|
||||
const response = await fetch(`${getBackendBaseURL()}/api/mcp/config`);
|
||||
if (!response.ok) {
|
||||
throw new MCPConfigRequestError(
|
||||
response.status,
|
||||
await readErrorDetail(response, "Failed to load MCP configuration"),
|
||||
);
|
||||
}
|
||||
return response.json() as Promise<MCPConfig>;
|
||||
}
|
||||
|
||||
@@ -16,5 +44,11 @@ export async function updateMCPConfig(config: MCPConfig) {
|
||||
},
|
||||
body: JSON.stringify(config),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new MCPConfigRequestError(
|
||||
response.status,
|
||||
await readErrorDetail(response, "Failed to update MCP configuration"),
|
||||
);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { loadMCPConfig, updateMCPConfig } from "./api";
|
||||
import { loadMCPConfig, MCPConfigRequestError, updateMCPConfig } from "./api";
|
||||
|
||||
export function useMCPConfig() {
|
||||
const { data, isLoading, error } = useQuery({
|
||||
queryKey: ["mcpConfig"],
|
||||
queryFn: () => loadMCPConfig(),
|
||||
retry: (count, error) =>
|
||||
!(error instanceof MCPConfigRequestError) && count < 3,
|
||||
});
|
||||
return { config: data, isLoading, error };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user