diff --git a/src/backend/base/langflow/api/v1/mcp_projects.py b/src/backend/base/langflow/api/v1/mcp_projects.py
index 88bfd55b7..388123a88 100644
--- a/src/backend/base/langflow/api/v1/mcp_projects.py
+++ b/src/backend/base/langflow/api/v1/mcp_projects.py
@@ -327,7 +327,7 @@ async def install_mcp_config(
request: Request,
current_user: CurrentActiveMCPUser,
):
- """Install MCP server configuration for Cursor or Claude."""
+ """Install MCP server configuration for Cursor, Windsurf, or Claude."""
# Check if the request is coming from a local IP address
client_ip = get_client_ip(request)
if not is_local_ip(client_ip):
@@ -408,6 +408,8 @@ async def install_mcp_config(
# Determine the config file path based on the client and OS
if body.client.lower() == "cursor":
config_path = Path.home() / ".cursor" / "mcp.json"
+ elif body.client.lower() == "windsurf":
+ config_path = Path.home() / ".codeium" / "windsurf" / "mcp_config.json"
elif body.client.lower() == "claude":
if os_type == "Darwin": # macOS
config_path = Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json"
@@ -502,7 +504,7 @@ async def check_installed_mcp_servers(
project_id: UUID,
current_user: CurrentActiveMCPUser,
):
- """Check if MCP server configuration is installed for this project in Cursor or Claude."""
+ """Check if MCP server configuration is installed for this project in Cursor, Windsurf, or Claude."""
try:
# Verify project exists and user has access
async with session_scope() as session:
@@ -544,6 +546,27 @@ async def check_installed_mcp_servers(
except json.JSONDecodeError:
logger.warning("Failed to parse Cursor config JSON at: %s", cursor_config_path)
+ # Check Windsurf configuration
+ windsurf_config_path = Path.home() / ".codeium" / "windsurf" / "mcp_config.json"
+ logger.debug(
+ "Checking Windsurf config at: %s (exists: %s)", windsurf_config_path, windsurf_config_path.exists()
+ )
+ if windsurf_config_path.exists():
+ try:
+ with windsurf_config_path.open("r") as f:
+ windsurf_config = json.load(f)
+ if "mcpServers" in windsurf_config and project_server_name in windsurf_config["mcpServers"]:
+ logger.debug("Found Windsurf config for project server: %s", project_server_name)
+ results.append("windsurf")
+ else:
+ logger.debug(
+ "Windsurf config exists but no entry for server: %s (available servers: %s)",
+ project_server_name,
+ list(windsurf_config.get("mcpServers", {}).keys()),
+ )
+ except json.JSONDecodeError:
+ logger.warning("Failed to parse Windsurf config JSON at: %s", windsurf_config_path)
+
# Check Claude configuration
claude_config_path = None
os_type = platform.system()
diff --git a/src/frontend/src/icons/Windsurf/Windsurf.jsx b/src/frontend/src/icons/Windsurf/Windsurf.jsx
new file mode 100644
index 000000000..1ef5e4784
--- /dev/null
+++ b/src/frontend/src/icons/Windsurf/Windsurf.jsx
@@ -0,0 +1,18 @@
+import { stringToBool } from "@/utils/utils";
+
+const SvgWindsurf = (props) => (
+
+);
+export default SvgWindsurf;
diff --git a/src/frontend/src/icons/Windsurf/index.tsx b/src/frontend/src/icons/Windsurf/index.tsx
new file mode 100644
index 000000000..9ac43757f
--- /dev/null
+++ b/src/frontend/src/icons/Windsurf/index.tsx
@@ -0,0 +1,11 @@
+import { useDarkStore } from "@/stores/darkStore";
+import React, { forwardRef } from "react";
+import SvgWindsurf from "./Windsurf";
+
+export const WindsurfIcon = forwardRef<
+ SVGSVGElement,
+ React.PropsWithChildren<{}>
+>((props, ref) => {
+ const isdark = useDarkStore((state) => state.dark).toString();
+ return ;
+});
diff --git a/src/frontend/src/icons/Windsurf/windsurf.svg b/src/frontend/src/icons/Windsurf/windsurf.svg
new file mode 100644
index 000000000..85536d8f5
--- /dev/null
+++ b/src/frontend/src/icons/Windsurf/windsurf.svg
@@ -0,0 +1,3 @@
+
\ No newline at end of file
diff --git a/src/frontend/src/icons/eagerIconImports.ts b/src/frontend/src/icons/eagerIconImports.ts
index 10736e663..3b8e61758 100644
--- a/src/frontend/src/icons/eagerIconImports.ts
+++ b/src/frontend/src/icons/eagerIconImports.ts
@@ -112,6 +112,7 @@ import { WolframIcon } from "@/icons/Wolfram";
import { XAIIcon } from "@/icons/xAI";
import { YouTubeSvgIcon as YouTubeIcon } from "@/icons/Youtube";
import { ZepMemoryIcon } from "@/icons/ZepMemory";
+import { WindsurfIcon } from "./Windsurf";
// Export the eagerly loaded icons map
export const eagerIconsMapping = {
@@ -225,6 +226,7 @@ export const eagerIconsMapping = {
WatsonxAI: WatsonxAiIcon,
Weaviate: WeaviateIcon,
Wikipedia: WikipediaIcon,
+ Windsurf: WindsurfIcon,
Wolfram: WolframIcon,
xAI: XAIIcon,
YouTube: YouTubeIcon,
diff --git a/src/frontend/src/icons/lazyIconImports.ts b/src/frontend/src/icons/lazyIconImports.ts
index b76fcdbd0..e096079f9 100644
--- a/src/frontend/src/icons/lazyIconImports.ts
+++ b/src/frontend/src/icons/lazyIconImports.ts
@@ -296,6 +296,8 @@ export const lazyIconsMapping = {
import("@/icons/Wikipedia/Wikipedia").then((mod) => ({
default: mod.default,
})),
+ Windsurf: () =>
+ import("@/icons/Windsurf").then((mod) => ({ default: mod.WindsurfIcon })),
Wolfram: () =>
import("@/icons/Wolfram/Wolfram").then((mod) => ({ default: mod.default })),
xAI: () => import("@/icons/xAI").then((mod) => ({ default: mod.XAIIcon })),
diff --git a/src/frontend/src/pages/MainPage/pages/homePage/components/McpServerTab.tsx b/src/frontend/src/pages/MainPage/pages/homePage/components/McpServerTab.tsx
index 11d127bff..50e9cf237 100644
--- a/src/frontend/src/pages/MainPage/pages/homePage/components/McpServerTab.tsx
+++ b/src/frontend/src/pages/MainPage/pages/homePage/components/McpServerTab.tsx
@@ -102,6 +102,11 @@ const autoInstallers = [
title: "Claude",
icon: "Claude",
},
+ {
+ name: "windsurf",
+ title: "Windsurf",
+ icon: "Windsurf",
+ },
];
const operatingSystemTabs = [