From effc40132a4c286dc0bc8312000de009a912f48f Mon Sep 17 00:00:00 2001 From: Tin Chi Lo Date: Mon, 15 Jun 2026 16:44:20 -0700 Subject: [PATCH] fix(mcp): default Slack registry entry to streamable HTTP with OAuth Slack offers a hosted MCP server at https://mcp.slack.com/mcp over streamable HTTP with OAuth, so the curated discovery preset should point there instead of spawning the npx stdio bot-token server. Carry an auth_type through the discovery entry into the create-server form so the preset lands on OAuth by default. --- litellm/proxy/mcp_registry.json | 11 ++++----- .../mcp_server/test_mcp_discovery.py | 11 +++++++++ .../mcp_tools/create_mcp_server.test.tsx | 24 +++++++++++++++++++ .../mcp_tools/create_mcp_server.tsx | 4 ++++ .../src/components/mcp_tools/types.tsx | 1 + 5 files changed, 44 insertions(+), 7 deletions(-) diff --git a/litellm/proxy/mcp_registry.json b/litellm/proxy/mcp_registry.json index 84431634e24..3de402775bc 100644 --- a/litellm/proxy/mcp_registry.json +++ b/litellm/proxy/mcp_registry.json @@ -69,13 +69,10 @@ "icon_url": "https://cdn.simpleicons.org/slack", "category": "Communication", "registry_url": null, - "transport": "stdio", - "command": "npx", - "args": ["-y", "@modelcontextprotocol/server-slack"], - "env_vars": [ - {"name": "SLACK_BOT_TOKEN", "description": "Slack Bot User OAuth Token", "secret": true}, - {"name": "SLACK_TEAM_ID", "description": "Slack Team/Workspace ID", "secret": false} - ] + "transport": "http", + "url": "https://mcp.slack.com/mcp", + "auth_type": "oauth2", + "env_vars": [] }, { "name": "discord", diff --git a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py index 9a741a3f861..6e190ef0e0f 100644 --- a/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py +++ b/tests/test_litellm/proxy/_experimental/mcp_server/test_mcp_discovery.py @@ -94,6 +94,17 @@ class TestMCPRegistryFile: assert linear["url"] == "https://mcp.linear.app/mcp" assert "/sse" not in linear["url"] + def test_slack_defaults_to_streamable_http_oauth(self, registry_path): + """Slack's MCP server should default to streamable HTTP with the hosted /mcp endpoint and OAuth.""" + with open(registry_path, "r") as f: + data = json.load(f) + slack = next(s for s in data["servers"] if s["name"] == "slack") + assert slack["transport"] == "http" + assert slack["url"] == "https://mcp.slack.com/mcp" + assert slack["auth_type"] == "oauth2" + assert "command" not in slack + assert "args" not in slack + def test_well_known_servers_present(self, registry_path): """Ensure key well-known MCPs are in the registry.""" with open(registry_path, "r") as f: diff --git a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx index e70548d6a96..72f9b1a6b2a 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.test.tsx @@ -754,6 +754,30 @@ describe("CreateMCPServer", () => { expect(nameInput).toHaveValue("github_mcp"); }); }); + + it("prefills streamable HTTP, URL, and OAuth from a discovery preset like Slack", async () => { + const prefillData = { + name: "slack", + title: "Slack", + description: "Channel management, messaging, and Slack workspace integration", + category: "Communication", + transport: "http", + url: "https://mcp.slack.com/mcp", + auth_type: "oauth2", + }; + + render(); + + await waitFor(() => { + const urlInput = screen.getByPlaceholderText("https://your-mcp-server.com"); + expect(urlInput).toHaveValue("https://mcp.slack.com/mcp"); + }); + + // Setting auth_type to oauth2 should render the OAuth form fields + await waitFor(() => { + expect(screen.getByText("OAuth Flow Type")).toBeInTheDocument(); + }); + }); }); describe("with back to discovery button", () => { diff --git a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx index ddcc9f65d38..fb56ceda998 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/create_mcp_server.tsx @@ -273,6 +273,10 @@ const CreateMCPServer: React.FC = ({ transport: transport, }; + if (prefillData.auth_type) { + prefillValues.auth_type = prefillData.auth_type; + } + if (transport === "stdio") { const stdioObj: Record = {}; if (prefillData.command) stdioObj.command = prefillData.command; diff --git a/ui/litellm-dashboard/src/components/mcp_tools/types.tsx b/ui/litellm-dashboard/src/components/mcp_tools/types.tsx index cd3ffcab5ec..63074770567 100644 --- a/ui/litellm-dashboard/src/components/mcp_tools/types.tsx +++ b/ui/litellm-dashboard/src/components/mcp_tools/types.tsx @@ -332,6 +332,7 @@ export interface DiscoverableMCPServer { url?: string | null; command?: string | null; args?: string[] | null; + auth_type?: string | null; env_vars?: Array<{ name: string; description?: string; secret?: boolean }> | null; }