mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-11 08:38:24 +00:00
feat(mcp): discover Ace media services by name
This commit is contained in:
parent
415b84232f
commit
c2971654fb
5 changed files with 117 additions and 0 deletions
|
|
@ -428,6 +428,66 @@
|
|||
{"name": "SUPABASE_URL", "description": "Supabase Project URL", "secret": false},
|
||||
{"name": "SUPABASE_SERVICE_ROLE_KEY", "description": "Supabase Service Role Key", "secret": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "suno_acedatacloud",
|
||||
"title": "Suno by Ace Data Cloud",
|
||||
"description": "Generate Suno music, lyrics and covers through Ace Data Cloud. Retrieve the same task until final audio is ready. Requires your own Ace API token and service access.",
|
||||
"icon_url": "https://raw.githubusercontent.com/AceDataCloud/MCPs/4a2abb23a6f19ea8460c4883dabb5ad378a428b7/suno/vscode/icon.png",
|
||||
"category": "Media Generation",
|
||||
"registry_url": "https://registry.modelcontextprotocol.io/servers/io.github.AceDataCloud%2Fmcp-suno",
|
||||
"transport": "http",
|
||||
"url": "https://suno.mcp.acedata.cloud/mcp",
|
||||
"auth_type": "bearer_token",
|
||||
"env_vars": []
|
||||
},
|
||||
{
|
||||
"name": "seedance_acedatacloud",
|
||||
"title": "Seedance by Ace Data Cloud",
|
||||
"description": "Generate Seedance videos from text or images through Ace Data Cloud. Query the same task for terminal video results. Requires your own Ace API token and service access.",
|
||||
"icon_url": "https://raw.githubusercontent.com/AceDataCloud/MCPs/4a2abb23a6f19ea8460c4883dabb5ad378a428b7/seedance/vscode/icon.png",
|
||||
"category": "Media Generation",
|
||||
"registry_url": "https://registry.modelcontextprotocol.io/servers/io.github.AceDataCloud%2Fmcp-seedance",
|
||||
"transport": "http",
|
||||
"url": "https://seedance.mcp.acedata.cloud/mcp",
|
||||
"auth_type": "bearer_token",
|
||||
"env_vars": []
|
||||
},
|
||||
{
|
||||
"name": "happyhorse_acedatacloud",
|
||||
"title": "HappyHorse by Ace Data Cloud",
|
||||
"description": "Generate and edit Happy Horse videos through Ace Data Cloud. Query the same task for final video results. Requires your own Ace API token and service access.",
|
||||
"icon_url": "https://cdn.acedata.cloud/e58fce2811.jpg",
|
||||
"category": "Media Generation",
|
||||
"registry_url": "https://registry.modelcontextprotocol.io/servers/io.github.AceDataCloud%2Fmcp-happyhorse",
|
||||
"transport": "http",
|
||||
"url": "https://happyhorse.mcp.acedata.cloud/mcp",
|
||||
"auth_type": "bearer_token",
|
||||
"env_vars": []
|
||||
},
|
||||
{
|
||||
"name": "gpt_image_acedatacloud",
|
||||
"title": "GPT Image by Ace Data Cloud",
|
||||
"description": "Generate and edit GPT Image images through the Ace Data Cloud OpenAI MCP server, which also exposes chat, embeddings and audio tools. Requires your own Ace API token and service access.",
|
||||
"icon_url": "https://raw.githubusercontent.com/AceDataCloud/MCPs/4a2abb23a6f19ea8460c4883dabb5ad378a428b7/openai/vscode/icon.png",
|
||||
"category": "Media Generation",
|
||||
"registry_url": "https://registry.modelcontextprotocol.io/servers/io.github.AceDataCloud%2Fmcp-openai",
|
||||
"transport": "http",
|
||||
"url": "https://openai.mcp.acedata.cloud/mcp",
|
||||
"auth_type": "bearer_token",
|
||||
"env_vars": []
|
||||
},
|
||||
{
|
||||
"name": "nano_banana_acedatacloud",
|
||||
"title": "Nano Banana by Ace Data Cloud",
|
||||
"description": "Generate and edit NanoBanana images through Ace Data Cloud. Retrieve the same task for final images. Requires your own Ace API token and service access.",
|
||||
"icon_url": "https://raw.githubusercontent.com/AceDataCloud/MCPs/4a2abb23a6f19ea8460c4883dabb5ad378a428b7/nanobanana/vscode/icon.png",
|
||||
"category": "Media Generation",
|
||||
"registry_url": "https://registry.modelcontextprotocol.io/servers/io.github.AceDataCloud%2Fmcp-nanobanana-pro",
|
||||
"transport": "http",
|
||||
"url": "https://nanobanana.mcp.acedata.cloud/mcp",
|
||||
"auth_type": "bearer_token",
|
||||
"env_vars": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1932,6 +1932,33 @@ describe("CreateMCPServer", () => {
|
|||
});
|
||||
|
||||
describe("when prefillData is provided", () => {
|
||||
it("opens the credential field for an authenticated discovery entry without supplying a token", async () => {
|
||||
render(
|
||||
<CreateMCPServer
|
||||
{...defaultProps}
|
||||
prefillData={{
|
||||
name: "suno_acedatacloud",
|
||||
title: "Suno by Ace Data Cloud",
|
||||
description: "Music generation with your own API token",
|
||||
category: "Media Generation",
|
||||
transport: "http",
|
||||
url: "https://suno.mcp.acedata.cloud/mcp",
|
||||
auth_type: "bearer_token",
|
||||
}}
|
||||
/>,
|
||||
);
|
||||
|
||||
expect(await screen.findByText("Authentication Value")).toBeInTheDocument();
|
||||
expect(screen.getByRole("combobox", { name: "Authentication", exact: true })).toHaveTextContent("Bearer Token");
|
||||
expect(screen.getByPlaceholderText("https://your-mcp-server.com")).toHaveValue(
|
||||
"https://suno.mcp.acedata.cloud/mcp",
|
||||
);
|
||||
expect(getServerNameInput()).toHaveValue("suno_acedatacloud");
|
||||
expect(screen.getByPlaceholderText("Enter token or secret")).toHaveValue("");
|
||||
expect(screen.getByPlaceholderText("Enter token or secret")).toHaveAttribute("type", "password");
|
||||
expect(networking.createMCPServer).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should populate form fields from discovery data", async () => {
|
||||
const prefillData = {
|
||||
name: "github-mcp",
|
||||
|
|
|
|||
|
|
@ -384,6 +384,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
alias: sanitizedName,
|
||||
description: prefillData.description || "",
|
||||
transport: transport,
|
||||
...(prefillData.auth_type === AUTH_TYPE.BEARER_TOKEN ? { auth_type: AUTH_TYPE.BEARER_TOKEN } : {}),
|
||||
};
|
||||
|
||||
if (transport === "stdio") {
|
||||
|
|
|
|||
|
|
@ -131,6 +131,34 @@ describe("MCPDiscovery", () => {
|
|||
expect(onSelectServer).toHaveBeenCalledWith(githubServer);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["suno", "Suno by Ace Data Cloud"],
|
||||
["seedance", "Seedance by Ace Data Cloud"],
|
||||
["happy horse", "HappyHorse by Ace Data Cloud"],
|
||||
["gpt image", "GPT Image by Ace Data Cloud"],
|
||||
["nanobanana", "Nano Banana by Ace Data Cloud"],
|
||||
])("finds %s from the bundled catalog and selects its authenticated connection", async (query, title) => {
|
||||
const testDirectory = dirname(fileURLToPath(import.meta.url));
|
||||
const registry = JSON.parse(
|
||||
readFileSync(resolve(testDirectory, "../../../../../../../litellm/proxy/mcp_registry.json"), "utf8"),
|
||||
) as { servers: DiscoverableMCPServer[] };
|
||||
vi.mocked(fetchDiscoverableMCPServers).mockResolvedValue({
|
||||
servers: registry.servers,
|
||||
categories: [...new Set(registry.servers.map((server) => server.category))],
|
||||
});
|
||||
const onSelectServer = vi.fn();
|
||||
renderWithProviders(<MCPDiscovery {...defaultProps} onSelectServer={onSelectServer} />);
|
||||
await screen.findByText(title);
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText("Search servers..."), { target: { value: query } });
|
||||
await userEvent.click(await screen.findByText(title));
|
||||
|
||||
const server = registry.servers.find((entry) => entry.title === title)!;
|
||||
expect(onSelectServer).toHaveBeenCalledWith(server);
|
||||
expect(server.auth_type).toBe("bearer_token");
|
||||
expect(screen.queryByText("GitHub")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("offers a custom-server escape hatch", async () => {
|
||||
const onCustomServer = vi.fn();
|
||||
render(<MCPDiscovery {...defaultProps} onCustomServer={onCustomServer} />);
|
||||
|
|
|
|||
|
|
@ -562,6 +562,7 @@ export interface DiscoverableMCPServer {
|
|||
category: string;
|
||||
registry_url?: string | null;
|
||||
transport: string;
|
||||
auth_type?: "bearer_token" | null;
|
||||
url?: string | null;
|
||||
command?: string | null;
|
||||
args?: string[] | null;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue