feat(site): add MCP server admin UI (#23301)

This adds the UI but does not add it to the Settings sidebar. Until it's
actually functional and usable (which will come in future PRs) it will
remain hidden.

Next step is wiring this up to chats and actually testing the full flow
end-to-end, but we aren't there yet.
This commit is contained in:
Kyle Carberry
2026-03-19 18:53:35 +00:00
committed by GitHub
parent a908d51097
commit 7db77bbefa
6 changed files with 1755 additions and 2 deletions
+35
View File
@@ -402,6 +402,7 @@ export type DeploymentConfig = Readonly<{
const chatProviderConfigsPath = "/api/experimental/chats/providers";
const chatModelConfigsPath = "/api/experimental/chats/model-configs";
const mcpServerConfigsPath = "/api/experimental/mcp/servers";
type ChatCostDateParams = {
start_date?: string;
@@ -3221,6 +3222,40 @@ class ApiMethods {
`${chatModelConfigsPath}/${encodeURIComponent(modelConfigId)}`,
);
};
getMCPServerConfigs = async (): Promise<TypesGen.MCPServerConfig[]> => {
const response =
await this.axios.get<TypesGen.MCPServerConfig[]>(mcpServerConfigsPath);
return response.data;
};
createMCPServerConfig = async (
req: TypesGen.CreateMCPServerConfigRequest,
): Promise<TypesGen.MCPServerConfig> => {
const response = await this.axios.post<TypesGen.MCPServerConfig>(
mcpServerConfigsPath,
req,
);
return response.data;
};
updateMCPServerConfig = async (
id: string,
req: TypesGen.UpdateMCPServerConfigRequest,
): Promise<TypesGen.MCPServerConfig> => {
const response = await this.axios.patch<TypesGen.MCPServerConfig>(
`${mcpServerConfigsPath}/${encodeURIComponent(id)}`,
req,
);
return response.data;
};
deleteMCPServerConfig = async (id: string): Promise<void> => {
await this.axios.delete(
`${mcpServerConfigsPath}/${encodeURIComponent(id)}`,
);
};
getAIBridgeModels = async (options: SearchParamOptions) => {
const url = getURLWithSearchParams("/api/v2/aibridge/models", options);
+41
View File
@@ -631,3 +631,44 @@ export const deleteChatUsageLimitGroupOverride = (
});
},
});
// ── MCP Server Configs ───────────────────────────────────────
const mcpServerConfigsKey = ["mcp-server-configs"] as const;
export const mcpServerConfigs = () => ({
queryKey: mcpServerConfigsKey,
queryFn: (): Promise<TypesGen.MCPServerConfig[]> => API.getMCPServerConfigs(),
});
const invalidateMCPServerConfigQueries = async (queryClient: QueryClient) => {
await queryClient.invalidateQueries({ queryKey: mcpServerConfigsKey });
};
export const createMCPServerConfig = (queryClient: QueryClient) => ({
mutationFn: (req: TypesGen.CreateMCPServerConfigRequest) =>
API.createMCPServerConfig(req),
onSuccess: async () => {
await invalidateMCPServerConfigQueries(queryClient);
},
});
type UpdateMCPServerConfigMutationArgs = {
id: string;
req: TypesGen.UpdateMCPServerConfigRequest;
};
export const updateMCPServerConfig = (queryClient: QueryClient) => ({
mutationFn: ({ id, req }: UpdateMCPServerConfigMutationArgs) =>
API.updateMCPServerConfig(id, req),
onSuccess: async () => {
await invalidateMCPServerConfigQueries(queryClient);
},
});
export const deleteMCPServerConfig = (queryClient: QueryClient) => ({
mutationFn: (id: string) => API.deleteMCPServerConfig(id),
onSuccess: async () => {
await invalidateMCPServerConfigQueries(queryClient);
},
});