Skip to content

Commit 9298117

Browse files
authored
Merge pull request #43 from Kode-Rex/feat/add-max-results-parameter
feat: Add max_results parameter to search tool
2 parents 634ab91 + 2fbb167 commit 9298117

File tree

4 files changed

+16
-10
lines changed

4 files changed

+16
-10
lines changed

docker/clients/serper_client.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,22 @@ def _convert_organic_results(organic_results: list) -> List[APISearchResult]:
3535
]
3636

3737

38-
def fetch_search_results(query: str, api_key: str) -> List[APISearchResult]:
38+
def fetch_search_results(
39+
query: str, api_key: str, max_results: int = 5
40+
) -> List[APISearchResult]:
3941
"""
4042
Fetches search results from the Serper API.
4143
4244
Args:
4345
query: The search query
4446
api_key: The Serper API key
47+
max_results: Maximum number of results to return (default: 5)
4548
4649
Returns:
4750
A list of APISearchResult objects from Serper API
4851
"""
4952
url = "https://google.serper.dev/search"
50-
payload = json.dumps({"q": query})
53+
payload = json.dumps({"q": query, "num": max_results})
5154
headers = {"X-API-KEY": api_key, "Content-Type": "application/json"}
5255

5356
try:
@@ -57,7 +60,8 @@ def fetch_search_results(query: str, api_key: str) -> List[APISearchResult]:
5760

5861
# Process and return the search results
5962
if "organic" in data:
60-
return _convert_organic_results(data["organic"])
63+
results = _convert_organic_results(data["organic"])
64+
return results[:max_results] # Ensure we don't exceed max_results
6165
return []
6266
except Exception as e:
6367
logger.error(f"Error fetching search results: {str(e)}")

docker/services/search_service.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616

1717

1818
def fetch_with_fallback(
19-
query: str, serper_api_key: str = ""
19+
query: str, serper_api_key: str = "", max_results: int = 5
2020
) -> Tuple[List[APISearchResult], str]:
2121
"""
2222
Fetch search results with automatic fallback from Serper to DuckDuckGo.
2323
2424
Args:
2525
query: Search query string
2626
serper_api_key: Optional Serper API key
27+
max_results: Maximum number of results to return (default: 5)
2728
2829
Returns:
2930
Tuple of (results list, source name)
@@ -35,13 +36,13 @@ def fetch_with_fallback(
3536
if serper_api_key:
3637
logger.info("Using Serper API for search")
3738
search_source = "Serper API"
38-
api_results = fetch_search_results(query, serper_api_key)
39+
api_results = fetch_search_results(query, serper_api_key, max_results)
3940

4041
# Fall back to DuckDuckGo if no API key or no results from Serper
4142
if not api_results:
4243
_log_fallback_reason(serper_api_key)
4344
search_source = "DuckDuckGo (free fallback)"
44-
api_results = fetch_duckduckgo_search_results(query)
45+
api_results = fetch_duckduckgo_search_results(query, max_results)
4546

4647
return api_results, search_source
4748

docker/tests/unit/services/test_search_service_with_serper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def test_uses_serper_when_key_provided(self, mock_serper):
2929
assert source == "Serper API"
3030
assert len(results) == 1
3131
assert results[0].title == "Serper Result"
32-
mock_serper.assert_called_once_with("test query", "fake_key")
32+
mock_serper.assert_called_once_with("test query", "fake_key", 5)
3333

3434
@patch("services.search_service.fetch_duckduckgo_search_results")
3535
@patch("services.search_service.fetch_search_results")

docker/tools/search_tool.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
SERPER_API_KEY = os.environ.get("SERPER_API_KEY", "")
2222

2323

24-
async def search_tool(query: str, ctx=None) -> dict:
24+
async def search_tool(query: str, ctx=None, max_results: int = 5) -> dict:
2525
"""Search the web for information on a given query.
2626
2727
This MCP tool searches the web using Serper API (premium) or DuckDuckGo
@@ -30,11 +30,12 @@ async def search_tool(query: str, ctx=None) -> dict:
3030
Args:
3131
query: The search query string
3232
ctx: Optional MCP context (may contain authentication headers)
33+
max_results: Maximum number of results to return (default: 5)
3334
3435
Returns:
3536
Dict representation of SearchResponse model (for MCP JSON serialization)
3637
"""
37-
logger.info(f"Processing search request: {query}")
38+
logger.info(f"Processing search request: {query} (max {max_results} results)")
3839

3940
# Validate authentication if WEBCAT_API_KEY is set
4041
is_valid, error_msg = validate_bearer_token(ctx)
@@ -49,7 +50,7 @@ async def search_tool(query: str, ctx=None) -> dict:
4950
return response.model_dump()
5051

5152
# Fetch results with automatic fallback
52-
api_results, search_source = fetch_with_fallback(query, SERPER_API_KEY)
53+
api_results, search_source = fetch_with_fallback(query, SERPER_API_KEY, max_results)
5354

5455
# Check if we got any results
5556
if not api_results:

0 commit comments

Comments
 (0)