academia-mcp 1.10.5__py3-none-any.whl → 1.10.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Optional
2
+ from typing import Optional, List
3
3
 
4
4
  from academia_mcp.utils import post_with_retries, get_with_retries
5
5
  from academia_mcp.settings import settings
@@ -16,6 +16,7 @@ def web_search(
16
16
  query: str,
17
17
  limit: Optional[int] = 20,
18
18
  provider: Optional[str] = "tavily",
19
+ include_domains: Optional[List[str]] = None,
19
20
  ) -> str:
20
21
  """
21
22
  Search the web using Exa Search, Brave Search or Tavily and return normalized results.
@@ -29,9 +30,15 @@ def web_search(
29
30
  query: The search query, required.
30
31
  limit: The maximum number of items to return. 20 by default, maximum 25.
31
32
  provider: The provider to use. "exa", "tavily" or "brave". "tavily" by default.
33
+ include_domains: Optional list of domains to include in the search. None by default.
32
34
  """
33
35
  providers = ("tavily", "brave", "exa")
34
36
  assert provider in providers, "Error: provider must be either 'exa', 'tavily' or 'brave'"
37
+ if include_domains:
38
+ assert len(include_domains) > 0, "Error: include_domains should be a non-empty list"
39
+ assert all(
40
+ isinstance(domain, str) for domain in include_domains
41
+ ), "Error: include_domains should be a list of strings"
35
42
 
36
43
  is_tavily_available = bool(settings.TAVILY_API_KEY)
37
44
  is_exa_available = bool(settings.EXA_API_KEY)
@@ -51,16 +58,18 @@ def web_search(
51
58
 
52
59
  result = {}
53
60
  if provider == "exa":
54
- result = json.loads(exa_web_search(query, limit))
61
+ result = json.loads(exa_web_search(query, limit, include_domains=include_domains))
55
62
  elif provider == "brave":
56
63
  result = json.loads(brave_web_search(query, limit))
57
64
  elif provider == "tavily":
58
- result = json.loads(tavily_web_search(query, limit))
65
+ result = json.loads(tavily_web_search(query, limit, include_domains=include_domains))
59
66
  result["search_provider"] = provider
60
67
  return sanitize_output(json.dumps(result, ensure_ascii=False))
61
68
 
62
69
 
63
- def tavily_web_search(query: str, limit: Optional[int] = 20) -> str:
70
+ def tavily_web_search(
71
+ query: str, limit: Optional[int] = 20, include_domains: Optional[List[str]] = None
72
+ ) -> str:
64
73
  """
65
74
  Search the web using Tavily and return results.
66
75
 
@@ -71,11 +80,17 @@ def tavily_web_search(query: str, limit: Optional[int] = 20) -> str:
71
80
  Args:
72
81
  query: The search query, required.
73
82
  limit: The maximum number of items to return. 20 by default, maximum 25.
83
+ include_domains: Optional list of domains to include in the search. None by default.
74
84
  """
75
85
  assert isinstance(query, str), "Error: Your search query must be a string"
76
86
  assert query.strip(), "Error: Your query should not be empty"
77
87
  assert isinstance(limit, int), "Error: limit should be an integer"
78
88
  assert 0 < limit <= 25, "Error: limit should be between 1 and 25"
89
+ if include_domains:
90
+ assert len(include_domains) > 0, "Error: include_domains should be a non-empty list"
91
+ assert all(
92
+ isinstance(domain, str) for domain in include_domains
93
+ ), "Error: include_domains should be a list of strings"
79
94
 
80
95
  key = settings.TAVILY_API_KEY or ""
81
96
  assert key, "Error: TAVILY_API_KEY is not set and no api_key was provided"
@@ -85,6 +100,8 @@ def tavily_web_search(query: str, limit: Optional[int] = 20) -> str:
85
100
  "auto_parameters": True,
86
101
  "exclude_domains": EXCLUDE_DOMAINS,
87
102
  }
103
+ if include_domains:
104
+ payload["include_domains"] = include_domains
88
105
  response = post_with_retries(TAVILY_SEARCH_URL, payload, key)
89
106
  results = response.json()["results"]
90
107
  for result in results:
@@ -96,7 +113,9 @@ def tavily_web_search(query: str, limit: Optional[int] = 20) -> str:
96
113
  return sanitize_output(json.dumps({"results": results}, ensure_ascii=False))
97
114
 
98
115
 
99
- def exa_web_search(query: str, limit: Optional[int] = 20) -> str:
116
+ def exa_web_search(
117
+ query: str, limit: Optional[int] = 20, include_domains: Optional[List[str]] = None
118
+ ) -> str:
100
119
  """
101
120
  Search the web using Exa and return results.
102
121
 
@@ -107,11 +126,17 @@ def exa_web_search(query: str, limit: Optional[int] = 20) -> str:
107
126
  Args:
108
127
  query: The search query, required.
109
128
  limit: The maximum number of items to return. 20 by default, maximum 25.
129
+ include_domains: Optional list of domains to include in the search. None by default.
110
130
  """
111
131
  assert isinstance(query, str), "Error: Your search query must be a string"
112
132
  assert query.strip(), "Error: Your query should not be empty"
113
133
  assert isinstance(limit, int), "Error: limit should be an integer"
114
134
  assert 0 < limit <= 25, "Error: limit should be between 1 and 25"
135
+ if include_domains:
136
+ assert len(include_domains) > 0, "Error: include_domains should be a non-empty list"
137
+ assert all(
138
+ isinstance(domain, str) for domain in include_domains
139
+ ), "Error: include_domains should be a list of strings"
115
140
 
116
141
  key = settings.EXA_API_KEY or ""
117
142
  assert key, "Error: EXA_API_KEY is not set and no api_key was provided"
@@ -129,6 +154,8 @@ def exa_web_search(query: str, limit: Optional[int] = 20) -> str:
129
154
  "context": False,
130
155
  },
131
156
  }
157
+ if include_domains:
158
+ payload["includeDomains"] = include_domains
132
159
 
133
160
  response = post_with_retries(EXA_SEARCH_URL, payload, key)
134
161
  results = response.json()["results"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: academia-mcp
3
- Version: 1.10.5
3
+ Version: 1.10.6
4
4
  Summary: MCP server that provides different tools to search for scientific publications
5
5
  Author-email: Ilya Gusev <phoenixilya@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/IlyaGusev/academia_mcp
@@ -23,10 +23,10 @@ academia_mcp/tools/s2.py,sha256=QX7-pbetab3Xt_1tvVPU6o5D_NAe9y6jcTGRBK1vwtY,6200
23
23
  academia_mcp/tools/show_image.py,sha256=jiJlQ53dbZ0T61OBhCT3IKVvBl9NHc6jHgWLfg5BxiE,3856
24
24
  academia_mcp/tools/speech_to_text.py,sha256=YZzMqdvunzXkpcadP_mYhm6cs4qH1Y_42SfY-7eX4O4,1601
25
25
  academia_mcp/tools/visit_webpage.py,sha256=swlFwWRzWc7-AHP2ouRZJScSTA4dHZ32fuJnA2V0lUc,3311
26
- academia_mcp/tools/web_search.py,sha256=0gKE3gtLBhdQ6G1eSgYLs1LIuo__PHwsYx5I5mTn254,6408
27
- academia_mcp-1.10.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
28
- academia_mcp-1.10.5.dist-info/METADATA,sha256=UeUZu8wGM23bbwue80r60CSinNd2lcCWoIPHXdmr0Sc,6311
29
- academia_mcp-1.10.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
- academia_mcp-1.10.5.dist-info/entry_points.txt,sha256=gxkiKJ74w2FwJpSECpjA3XtCfI5ZfrM6N8cqnwsq4yY,51
31
- academia_mcp-1.10.5.dist-info/top_level.txt,sha256=CzGpRFsRRJRqWEb1e3SUlcfGqRzOxevZGaJWrtGF8W0,13
32
- academia_mcp-1.10.5.dist-info/RECORD,,
26
+ academia_mcp/tools/web_search.py,sha256=2haTqnWkoISWS7VZSI0h7mW-jjWFItA8SL1FkkUxzI8,7864
27
+ academia_mcp-1.10.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
28
+ academia_mcp-1.10.6.dist-info/METADATA,sha256=pwPpp2xupjkVubi5Yt6JQqknFserzyRn-0xc2MGsIYI,6311
29
+ academia_mcp-1.10.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ academia_mcp-1.10.6.dist-info/entry_points.txt,sha256=gxkiKJ74w2FwJpSECpjA3XtCfI5ZfrM6N8cqnwsq4yY,51
31
+ academia_mcp-1.10.6.dist-info/top_level.txt,sha256=CzGpRFsRRJRqWEb1e3SUlcfGqRzOxevZGaJWrtGF8W0,13
32
+ academia_mcp-1.10.6.dist-info/RECORD,,