diff --git a/src/backend/base/langflow/components/tools/__init__.py b/src/backend/base/langflow/components/tools/__init__.py
index f2f5db6dc..53a61e1cb 100644
--- a/src/backend/base/langflow/components/tools/__init__.py
+++ b/src/backend/base/langflow/components/tools/__init__.py
@@ -11,6 +11,7 @@ from .glean_search_api import GleanSearchAPIComponent
from .google_search_api import GoogleSearchAPIComponent
from .google_search_api_core import GoogleSearchAPICore
from .google_serper_api import GoogleSerperAPIComponent
+from .google_serper_api_core import GoogleSerperAPICore
from .mcp_stdio import MCPStdio
from .python_code_structured_tool import PythonCodeStructuredTool
from .python_repl import PythonREPLToolComponent
@@ -42,6 +43,7 @@ __all__ = [
"GoogleSearchAPIComponent",
"GoogleSearchAPICore",
"GoogleSerperAPIComponent",
+ "GoogleSerperAPICore",
"MCPStdio",
"PythonCodeStructuredTool",
"PythonREPLToolComponent",
diff --git a/src/backend/base/langflow/components/tools/google_serper_api.py b/src/backend/base/langflow/components/tools/google_serper_api.py
index 038c9d2e1..e9e587c95 100644
--- a/src/backend/base/langflow/components/tools/google_serper_api.py
+++ b/src/backend/base/langflow/components/tools/google_serper_api.py
@@ -7,10 +7,11 @@ from langflow.schema import Data
class GoogleSerperAPIComponent(LCToolComponent):
- display_name = "Google Serper API"
+ display_name = "Google Serper API [DEPRECATED]"
description = "Call the Serper.dev Google Search API."
name = "GoogleSerperAPI"
icon = "Google"
+ legacy = True
inputs = [
SecretStrInput(name="serper_api_key", display_name="Serper API Key", required=True),
MultilineInput(
diff --git a/src/backend/base/langflow/components/tools/google_serper_api_core.py b/src/backend/base/langflow/components/tools/google_serper_api_core.py
new file mode 100644
index 000000000..a46e19057
--- /dev/null
+++ b/src/backend/base/langflow/components/tools/google_serper_api_core.py
@@ -0,0 +1,74 @@
+from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper
+
+from langflow.custom import Component
+from langflow.io import IntInput, MultilineInput, Output, SecretStrInput
+from langflow.schema import DataFrame
+from langflow.schema.message import Message
+
+
+class GoogleSerperAPICore(Component):
+ display_name = "Google Serper API"
+ description = "Call the Serper.dev Google Search API."
+ icon = "Serper"
+
+ inputs = [
+ SecretStrInput(
+ name="serper_api_key",
+ display_name="Serper API Key",
+ required=True,
+ ),
+ MultilineInput(
+ name="input_value",
+ display_name="Input",
+ tool_mode=True,
+ ),
+ IntInput(
+ name="k",
+ display_name="Number of results",
+ value=4,
+ required=True,
+ ),
+ ]
+
+ outputs = [
+ Output(
+ display_name="Results",
+ name="results",
+ type_=DataFrame,
+ method="search_serper",
+ ),
+ ]
+
+ def search_serper(self) -> DataFrame:
+ try:
+ wrapper = self._build_wrapper()
+ results = wrapper.results(query=self.input_value)
+ list_results = results.get("organic", [])
+
+ # Convert results to DataFrame using list comprehension
+ df_data = [
+ {
+ "title": result.get("title", ""),
+ "link": result.get("link", ""),
+ "snippet": result.get("snippet", ""),
+ }
+ for result in list_results
+ ]
+
+ return DataFrame(df_data)
+ except (ValueError, KeyError, ConnectionError) as e:
+ error_message = f"Error occurred while searching: {e!s}"
+ self.status = error_message
+ # Return DataFrame with error as a list of dictionaries
+ return DataFrame([{"error": error_message}])
+
+ def text_search_serper(self) -> Message:
+ search_results = self.search_serper()
+ text_result = search_results.to_string(index=False) if not search_results.empty else "No results found."
+ return Message(text=text_result)
+
+ def _build_wrapper(self):
+ return GoogleSerperAPIWrapper(serper_api_key=self.serper_api_key, k=self.k)
+
+ def build(self):
+ return self.search_serper
diff --git a/src/backend/tests/unit/components/tools/test_google_serper_api_core.py b/src/backend/tests/unit/components/tools/test_google_serper_api_core.py
new file mode 100644
index 000000000..1f09e369d
--- /dev/null
+++ b/src/backend/tests/unit/components/tools/test_google_serper_api_core.py
@@ -0,0 +1,114 @@
+from unittest.mock import MagicMock, patch
+
+import pytest
+from langflow.components.tools import GoogleSerperAPICore
+from langflow.schema import DataFrame
+
+
+@pytest.fixture
+def google_serper_component():
+ return GoogleSerperAPICore()
+
+
+@pytest.fixture
+def mock_search_results():
+ return {
+ "organic": [
+ {
+ "title": "Test Title 1",
+ "link": "https://test1.com",
+ "snippet": "Test snippet 1",
+ },
+ {
+ "title": "Test Title 2",
+ "link": "https://test2.com",
+ "snippet": "Test snippet 2",
+ },
+ ]
+ }
+
+
+def test_component_initialization(google_serper_component):
+ assert google_serper_component.display_name == "Google Serper API"
+ assert google_serper_component.icon == "Serper"
+
+ input_names = [input_.name for input_ in google_serper_component.inputs]
+ assert "serper_api_key" in input_names
+ assert "input_value" in input_names
+ assert "k" in input_names
+
+
+@patch("langchain_community.utilities.google_serper.requests.get")
+@patch("langchain_community.utilities.google_serper.requests.post")
+def test_search_serper_success(mock_post, mock_get, google_serper_component, mock_search_results):
+ # Configure mocks
+ mock_response = MagicMock()
+ mock_response.status_code = 200
+ mock_response.json.return_value = mock_search_results
+ mock_post.return_value = mock_response
+ mock_get.return_value = mock_response
+
+ # Configure component
+ google_serper_component.serper_api_key = "test_api_key"
+ google_serper_component.input_value = "test query"
+ google_serper_component.k = 2
+
+ # Execute search
+ result = google_serper_component.search_serper()
+
+ # Verify results
+ assert isinstance(result, DataFrame)
+ assert len(result) == 2
+ assert list(result.columns) == ["title", "link", "snippet"]
+ assert result.iloc[0]["title"] == "Test Title 1"
+ assert result.iloc[1]["link"] == "https://test2.com"
+
+
+@patch("langchain_community.utilities.google_serper.requests.get")
+@patch("langchain_community.utilities.google_serper.requests.post")
+def test_search_serper_error_handling(mock_post, mock_get, google_serper_component):
+ # Configure mocks to simulate error
+ mock_response = MagicMock()
+ mock_response.status_code = 403
+ mock_response.raise_for_status.side_effect = ConnectionError("API connection failed")
+ mock_post.return_value = mock_response
+ mock_get.return_value = mock_response
+
+ # Configure component
+ google_serper_component.serper_api_key = "test_api_key"
+ google_serper_component.input_value = "test query"
+ google_serper_component.k = 2
+
+ # Execute search
+ result = google_serper_component.search_serper()
+
+ # Verify error handling
+ assert isinstance(result, DataFrame)
+ assert "error" in result.columns
+ assert "API connection failed" in result.iloc[0]["error"]
+
+
+def test_text_search_serper(google_serper_component):
+ with patch.object(google_serper_component, "search_serper") as mock_search:
+ mock_search.return_value = DataFrame(
+ [{"title": "Test Title", "link": "https://test.com", "snippet": "Test snippet"}]
+ )
+
+ result = google_serper_component.text_search_serper()
+ assert result.text is not None
+ assert "Test Title" in result.text
+ assert "https://test.com" in result.text
+
+
+def test_build_wrapper(google_serper_component):
+ google_serper_component.serper_api_key = "test_api_key"
+ google_serper_component.k = 2
+
+ wrapper = google_serper_component._build_wrapper()
+ assert wrapper.serper_api_key == "test_api_key"
+ assert wrapper.k == 2
+
+
+def test_build_method(google_serper_component):
+ build_result = google_serper_component.build()
+ assert build_result == google_serper_component.search_serper
diff --git a/src/frontend/src/icons/Serper/Serper.jsx b/src/frontend/src/icons/Serper/Serper.jsx
index ff0bb9e04..2f6f9f9f7 100644
--- a/src/frontend/src/icons/Serper/Serper.jsx
+++ b/src/frontend/src/icons/Serper/Serper.jsx
@@ -1,17 +1,26 @@
const SvgSerper = (props) => (
);
+
export default SvgSerper;
diff --git a/src/frontend/src/icons/Serper/serper.svg b/src/frontend/src/icons/Serper/serper.svg
index a984dbfe8..0ada1892e 100644
--- a/src/frontend/src/icons/Serper/serper.svg
+++ b/src/frontend/src/icons/Serper/serper.svg
@@ -1,38 +1,5 @@
-
-
-