alita-sdk 0.3.122__py3-none-any.whl → 0.3.124__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.
@@ -50,6 +50,8 @@ class AlitaClient:
50
50
  self.datasources_predict = f"{self.base_url}{self.api_path}/datasources/predict/prompt_lib/{self.project_id}"
51
51
  self.datasources_search = f"{self.base_url}{self.api_path}/datasources/search/prompt_lib/{self.project_id}"
52
52
  self.app = f"{self.base_url}{self.api_path}/applications/application/prompt_lib/{self.project_id}"
53
+ self.mcp_tools_list = f"{self.base_url}{self.api_path}/mcp_sse/tools_list/{self.project_id}"
54
+ self.mcp_tools_call = f"{self.base_url}{self.api_path}/mcp_sse/tools_call/{self.project_id}"
53
55
  self.application_versions = f"{self.base_url}{self.api_path}/applications/version/prompt_lib/{self.project_id}"
54
56
  self.list_apps_url = f"{self.base_url}{self.api_path}/applications/applications/prompt_lib/{self.project_id}"
55
57
  self.integration_details = f"{self.base_url}{self.api_path}/integrations/integration/{self.project_id}"
@@ -61,6 +63,16 @@ class AlitaClient:
61
63
  self.ai_section_url = f'{self.base_url}{self.api_path}/integrations/integrations/default/{self.project_id}?section=ai'
62
64
  self.configurations: list = configurations or []
63
65
 
66
+ def get_mcp_toolkits(self):
67
+ url = self.mcp_tools_list
68
+ data = requests.get(url, headers=self.headers, verify=False).json()
69
+ return data
70
+
71
+ def mcp_tool_call(self, params: dict[str, Any]):
72
+ url = self.mcp_tools_call
73
+ data = requests.post(url, headers=self.headers, json=params, verify=False).json()
74
+ return data
75
+
64
76
  def prompt(self, prompt_id, prompt_version_id, chat_history=None, return_tool=False):
65
77
  url = f"{self.prompt_versions}/{prompt_id}/{prompt_version_id}"
66
78
  data = requests.get(url, headers=self.headers, verify=False).json()
@@ -13,6 +13,7 @@
13
13
  # limitations under the License.
14
14
 
15
15
  import importlib
16
+ from json import dumps
16
17
  from traceback import format_exc
17
18
  from langchain.chains.llm import LLMChain
18
19
 
@@ -33,6 +34,7 @@ from ..retrievers.AlitaRetriever import AlitaRetriever
33
34
  from ..tools.log import print_log
34
35
 
35
36
 
37
+
36
38
  def get_model(model_type: str, model_params: dict):
37
39
  """ Get LLM or ChatLLM """
38
40
  if model_type is None:
@@ -181,6 +183,11 @@ def add_documents(vectorstore, documents):
181
183
  metadata = []
182
184
  for document in documents:
183
185
  texts.append(document.page_content)
186
+ for key in document.metadata:
187
+ if isinstance(document.metadata[key], list):
188
+ document.metadata[key] = "; ".join(document.metadata[key])
189
+ if isinstance(document.metadata[key], dict):
190
+ document.metadata[key] = dumps(document.metadata[key])
184
191
  metadata.append(document.metadata)
185
192
  vectorstore.add_texts(texts, metadatas=metadata)
186
193
 
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Union, Any, Optional, Annotated
2
+ from typing import Union, Any, Optional, Annotated, get_type_hints
3
3
  from uuid import uuid4
4
4
 
5
5
  import yaml
@@ -329,11 +329,17 @@ def create_graph(
329
329
  structured_output=node.get('structured_output', False)))
330
330
  break
331
331
  elif node_type == 'llm':
332
+ output_vars = node.get('output', [])
333
+ output_vars_dict = {
334
+ var: get_type_hints(state_class).get(var, str).__name__
335
+ for var in output_vars
336
+ }
332
337
  lg_builder.add_node(node_id, LLMNode(
333
338
  client=client, prompt=node.get('prompt', {}),
334
339
  name=node['id'], return_type='dict',
335
340
  response_key=node.get('response_key', 'messages'),
336
- output_variables=node.get('output', []),
341
+ structured_output_dict=output_vars_dict,
342
+ output_variables=output_vars,
337
343
  input_variables=node.get('input', ['messages']),
338
344
  structured_output=node.get('structured_output', False)))
339
345
  elif node_type == 'router':
@@ -13,6 +13,8 @@ from .vectorstore import VectorStoreToolkit
13
13
  from ..community.analysis.jira_analyse import AnalyseJira
14
14
  from ..community.browseruse import BrowserUseToolkit
15
15
 
16
+ from ..tools.mcp_server_tool import McpServerTool
17
+
16
18
  logger = logging.getLogger(__name__)
17
19
 
18
20
 
@@ -36,6 +38,7 @@ def get_toolkits():
36
38
  def get_tools(tools_list: list, alita: 'AlitaClient', llm: 'LLMLikeObject') -> list:
37
39
  prompts = []
38
40
  tools = []
41
+
39
42
  for tool in tools_list:
40
43
  if tool['type'] == 'prompt':
41
44
  prompts.append([
@@ -82,4 +85,46 @@ def get_tools(tools_list: list, alita: 'AlitaClient', llm: 'LLMLikeObject') -> l
82
85
  if len(prompts) > 0:
83
86
  tools += PromptToolkit.get_toolkit(alita, prompts).get_tools()
84
87
  tools += alita_tools(tools_list, alita, llm)
88
+ tools += _mcp_tools(tools_list, alita)
89
+ return tools
90
+
91
+
92
+ def _mcp_tools(tools_list, alita):
93
+ all_available_toolkits = alita.get_mcp_toolkits()
94
+ toolkit_lookup = {tk["name"].lower(): tk for tk in all_available_toolkits}
95
+ tools = []
96
+ #
97
+ for selected_toolkit in tools_list:
98
+ toolkit_name = selected_toolkit['type'].lower()
99
+ toolkit_conf = toolkit_lookup.get(toolkit_name)
100
+ #
101
+ if not toolkit_conf:
102
+ logger.warning(f"Toolkit '{toolkit_name}' not found in available toolkits.")
103
+ continue
104
+ #
105
+ available_tools = toolkit_conf.get("tools", [])
106
+ selected_tools = [name.lower() for name in selected_toolkit['settings'].get('selected_tools', [])]
107
+ for available_tool in available_tools:
108
+ tool_name = available_tool.get("name", "").lower()
109
+ if not selected_tools or tool_name in selected_tools:
110
+ if server_tool := _init_single_mcp_tool(toolkit_name, available_tool, alita, selected_toolkit['settings']):
111
+ tools.append(server_tool)
85
112
  return tools
113
+
114
+
115
+ def _init_single_mcp_tool(toolkit_name, available_tool, alita, toolkit_settings):
116
+ try:
117
+ tool_name = available_tool["name"]
118
+ return McpServerTool(
119
+ name=tool_name,
120
+ description=available_tool.get("description", ""),
121
+ args_schema=McpServerTool.create_pydantic_model_from_schema(
122
+ available_tool.get("inputSchema", {})
123
+ ),
124
+ client=alita,
125
+ server=toolkit_name,
126
+ tool_timeout_sec=toolkit_settings["timeout"]
127
+ )
128
+ except Exception as e:
129
+ logger.error(f"Failed to create McpServerTool for '{toolkit_name}.{tool_name}': {e}")
130
+ return None
@@ -47,11 +47,10 @@ class FunctionTool(BaseTool):
47
47
  )
48
48
  logger.info(f"ToolNode response: {tool_result}")
49
49
  if not self.output_variables:
50
- return {"messages": [{"role": "assistant", "content": tool_result}]}
50
+ return {"messages": [{"role": "assistant", "content": dumps(tool_result)}]}
51
51
  else:
52
52
  return {
53
- self.output_variables[0]: tool_result,
54
- "messages": [{"role": "assistant", "content": tool_result}]
53
+ self.output_variables[0]: tool_result
55
54
  }
56
55
  except ValidationError:
57
56
  return {"messages": [
alita_sdk/tools/llm.py CHANGED
@@ -25,6 +25,7 @@ class LLMNode(BaseTool):
25
25
  client: Any = None
26
26
  return_type: str = "str"
27
27
  response_key: str = "messages"
28
+ structured_output_dict: Optional[dict[str, str]] = None
28
29
  output_variables: Optional[List[str]] = None
29
30
  input_variables: Optional[List[str]] = None
30
31
  structured_output: Optional[bool] = False
@@ -35,11 +36,19 @@ class LLMNode(BaseTool):
35
36
  llm_input = create_llm_input(self.prompt, params, kwargs)
36
37
  try:
37
38
  if self.structured_output and len(self.output_variables) > 0:
38
- struct_params = {var: {"type": "str", "description": ""} for var in self.output_variables}
39
+ struct_params = {
40
+ key: {
41
+ "type": 'list[str]' if 'list' in value else value,
42
+ "description": ""
43
+ }
44
+ for key, value in (self.structured_output_dict or {}).items()
45
+ }
39
46
  stuct_model = create_pydantic_model(f"LLMOutput", struct_params)
40
47
  llm = self.client.with_structured_output(stuct_model)
41
48
  completion = llm.invoke(llm_input)
42
49
  result = completion.model_dump()
50
+ if result.get('messages') and isinstance(result['messages'], list):
51
+ result['messages'] = [{'role': 'assistant', 'content': '\n'.join(result['messages'])}]
43
52
  return result
44
53
  else:
45
54
  completion = self.client.invoke(llm_input)
@@ -0,0 +1,58 @@
1
+ import uuid
2
+ from logging import getLogger
3
+ from typing import Any, Type, Literal, Optional
4
+
5
+ from langchain_core.tools import BaseTool
6
+ from pydantic import BaseModel, Field, create_model
7
+
8
+ logger = getLogger(__name__)
9
+
10
+
11
+ class McpServerTool(BaseTool):
12
+ name: str
13
+ description: str
14
+ args_schema: Optional[Type[BaseModel]] = None
15
+ return_type: str = "str"
16
+ client: Any
17
+ server: str
18
+ tool_timeout_sec: int = 60
19
+
20
+
21
+ @staticmethod
22
+ def create_pydantic_model_from_schema(schema: dict):
23
+ fields = {}
24
+ for field_name, field_info in schema['properties'].items():
25
+ field_type = field_info['type']
26
+ field_description = field_info.get('description', '')
27
+ if field_type == 'string':
28
+ if 'enum' in field_info:
29
+ field_type = Literal[tuple(field_info['enum'])]
30
+ else:
31
+ field_type = str
32
+ elif field_type == 'integer':
33
+ field_type = int
34
+ elif field_type == 'number':
35
+ field_type = float
36
+ elif field_type == 'boolean':
37
+ field_type = bool
38
+ else:
39
+ raise ValueError(f"Unsupported field type: {field_type}")
40
+
41
+ if field_name in schema.get('required', []):
42
+ fields[field_name] = (field_type, Field(..., description=field_description))
43
+ else:
44
+ fields[field_name] = (Optional[field_type], Field(None, description=field_description))
45
+ return create_model('DynamicModel', **fields)
46
+
47
+ def _run(self, *args, **kwargs):
48
+ call_data = {
49
+ "server": self.server,
50
+ "tool_timeout_sec": self.tool_timeout_sec,
51
+ "tool_call_id": str(uuid.uuid4()),
52
+ "params": {
53
+ "name": self.name,
54
+ "arguments": kwargs
55
+ }
56
+ }
57
+
58
+ return self.client.mcp_tool_call(call_data)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.122
3
+ Version: 0.3.124
4
4
  Summary: SDK for building langchain agents using resouces from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedjik@gmail.com>
6
6
  Project-URL: Homepage, https://projectalita.ai
@@ -4,7 +4,7 @@ alita_sdk/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
4
4
  alita_sdk/agents/llamaAgentParser.py,sha256=N_Nw6WJ8xrNX3fr_JFwjUIg_Urai9lLU3poMgZz0Cyk,1701
5
5
  alita_sdk/clients/__init__.py,sha256=5O_7WsZmvg5z5uZf_Jkx-f8j5C6yKIuSwQR6AQ-TM84,31
6
6
  alita_sdk/clients/artifact.py,sha256=W6oLlthtsUHfUWjhihaDdhLZdRVqj1D2j7oHHELxJfs,2639
7
- alita_sdk/clients/client.py,sha256=j97yBXpmy5nCIfkZ6hbzCHnVDbgqrEiTOTQdBDpKQiQ,17912
7
+ alita_sdk/clients/client.py,sha256=aBVoT9rX5D9vF2iGPywmjAi2CPM0m43NnHiKmKlTmPA,18475
8
8
  alita_sdk/clients/datasource.py,sha256=HAZovoQN9jBg0_-lIlGBQzb4FJdczPhkHehAiVG3Wx0,1020
9
9
  alita_sdk/clients/prompt.py,sha256=li1RG9eBwgNK_Qf0qUaZ8QNTmsncFrAL2pv3kbxZRZg,1447
10
10
  alita_sdk/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -19,7 +19,7 @@ alita_sdk/langchain/assistant.py,sha256=V0MpZG9IQRlKMr1SfAabVbUsIp-gNPO9A1SWxuFi
19
19
  alita_sdk/langchain/chat_message_template.py,sha256=kPz8W2BG6IMyITFDA5oeb5BxVRkHEVZhuiGl4MBZKdc,2176
20
20
  alita_sdk/langchain/constants.py,sha256=eHVJ_beJNTf1WJo4yq7KMK64fxsRvs3lKc34QCXSbpk,3319
21
21
  alita_sdk/langchain/indexer.py,sha256=0ENHy5EOhThnAiYFc7QAsaTNp9rr8hDV_hTK8ahbatk,37592
22
- alita_sdk/langchain/langraph_agent.py,sha256=vxsbjOE0UWZIuyXNGEMR1QJ8t5yHS7Kzjt8a8nLb-jw,20626
22
+ alita_sdk/langchain/langraph_agent.py,sha256=f9rGk6QGQbfbGudwpM5ax9yS-xDlElFqGAOsZbGvrtI,20919
23
23
  alita_sdk/langchain/mixedAgentParser.py,sha256=M256lvtsL3YtYflBCEp-rWKrKtcY1dJIyRGVv7KW9ME,2611
24
24
  alita_sdk/langchain/mixedAgentRenderes.py,sha256=asBtKqm88QhZRILditjYICwFVKF5KfO38hu2O-WrSWE,5964
25
25
  alita_sdk/langchain/utils.py,sha256=Npferkn10dvdksnKzLJLBI5bNGQyVWTBwqp3vQtUqmY,6631
@@ -41,7 +41,7 @@ alita_sdk/langchain/document_loaders/constants.py,sha256=QpgMiKo-riIBuU67DGhXi7Z
41
41
  alita_sdk/langchain/document_loaders/utils.py,sha256=ifh0UJiweIb2iEb2_THJy2pbAnTupOffGtTdRA7vjeE,874
42
42
  alita_sdk/langchain/interfaces/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  alita_sdk/langchain/interfaces/kwextractor.py,sha256=kSJA9L8g8UArmHu7Bd9dIO0Rrq86JPUb8RYNlnN68FQ,3072
44
- alita_sdk/langchain/interfaces/llm_processor.py,sha256=oX5feXsQ5D-8q3Mf40Txltv3kkHKb2xBeNPwecy5yDQ,8442
44
+ alita_sdk/langchain/interfaces/llm_processor.py,sha256=AbuWlZ54Cu5zy6AExRN0ou3r15i4pY3WSIVPJx8ltkA,8764
45
45
  alita_sdk/langchain/interfaces/loaders.py,sha256=li-O2dubiDNYn-qfVcDsuD4LqP_IZ61cV2vHUZAqeXc,3337
46
46
  alita_sdk/langchain/interfaces/splitters.py,sha256=tW65-Ejj9VYyxXFZNgPts_CKILQ18bWp_1bZ-24FKGc,3630
47
47
  alita_sdk/langchain/retrievers/AlitaRetriever.py,sha256=osChtJxUlfpsFESpJSE5mnJAkxTXnzgFZnC6l5mUlbo,6148
@@ -68,18 +68,19 @@ alita_sdk/toolkits/application.py,sha256=LrxbBV05lkRP3_WtKGBKtMdoQHXVY-_AtFr1cUu
68
68
  alita_sdk/toolkits/artifact.py,sha256=7zb17vhJ3CigeTqvzQ4VNBsU5UOCJqAwz7fOJGMYqXw,2348
69
69
  alita_sdk/toolkits/datasource.py,sha256=v3FQu8Gmvq7gAGAnFEbA8qofyUhh98rxgIjY6GHBfyI,2494
70
70
  alita_sdk/toolkits/prompt.py,sha256=WIpTkkVYWqIqOWR_LlSWz3ug8uO9tm5jJ7aZYdiGRn0,1192
71
- alita_sdk/toolkits/tools.py,sha256=7qECx6O6IHIE5GjpJet4XhF_9in2-EYYy5BEKIGxr0o,3285
71
+ alita_sdk/toolkits/tools.py,sha256=ZYi-oZwezaqcZe6Ft6w2hlpbuCKYyDNjl3WRWViVT08,5074
72
72
  alita_sdk/toolkits/vectorstore.py,sha256=di08-CRl0KJ9xSZ8_24VVnPZy58iLqHtXW8vuF29P64,2893
73
73
  alita_sdk/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
74
  alita_sdk/tools/application.py,sha256=UJlYd3Sub10LpAoKkKEpvd4miWyrS-yYE5NKyqx-H4Q,2194
75
75
  alita_sdk/tools/artifact.py,sha256=uTa6K5d-NCDRnuLJVd6vA5TNIPH39onyPIyW5Thz4C0,6160
76
76
  alita_sdk/tools/datasource.py,sha256=pvbaSfI-ThQQnjHG-QhYNSTYRnZB0rYtZFpjCfpzxYI,2443
77
77
  alita_sdk/tools/echo.py,sha256=spw9eCweXzixJqHnZofHE1yWiSUa04L4VKycf3KCEaM,486
78
- alita_sdk/tools/function.py,sha256=g5VaLtgYHoEMgid1s1zU2NzavqT2IErjhSIWqqPw3Yk,2617
78
+ alita_sdk/tools/function.py,sha256=wzPS5Y8ScmsXspmn73MQnkCcAghsllAg7BLh61ZNuVw,2543
79
79
  alita_sdk/tools/indexer_tool.py,sha256=P9S_omk5TZkizb6UXyxMO87Pzj4UCaye0CuXBgCnhTU,4258
80
- alita_sdk/tools/llm.py,sha256=oiaecQNvFLqokmImyfbBKQ_bNMD8hrD8lhTFpiUytdA,2779
80
+ alita_sdk/tools/llm.py,sha256=JA0OnSU13CLdkS5NFv6iRk8P7k-B47L-oPjk8xrzk48,3223
81
81
  alita_sdk/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
82
82
  alita_sdk/tools/loop_output.py,sha256=NoGIGYc42wY3NNcWRijYzRnUVXcCn5cRVd8QmuIpoHU,8068
83
+ alita_sdk/tools/mcp_server_tool.py,sha256=xcH9AiqfR2TYrwJ3Ixw-_A7XDodtJCnwmq1SsikXpYk,1930
83
84
  alita_sdk/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8QwB0UwpsWCYruXU,11692
84
85
  alita_sdk/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
85
86
  alita_sdk/tools/router.py,sha256=wCvZjVkdXK9dMMeEerrgKf5M790RudH68pDortnHSz0,1517
@@ -91,10 +92,10 @@ alita_sdk/utils/evaluate.py,sha256=iM1P8gzBLHTuSCe85_Ng_h30m52hFuGuhNXJ7kB1tgI,1
91
92
  alita_sdk/utils/logging.py,sha256=hBE3qAzmcLMdamMp2YRXwOOK9P4lmNaNhM76kntVljs,3124
92
93
  alita_sdk/utils/streamlit.py,sha256=zp8owZwHI3HZplhcExJf6R3-APtWx-z6s5jznT2hY_k,29124
93
94
  alita_sdk/utils/utils.py,sha256=dM8whOJAuFJFe19qJ69-FLzrUp6d2G-G6L7d4ss2XqM,346
94
- alita_sdk-0.3.122.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
95
+ alita_sdk-0.3.124.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
95
96
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
96
97
  tests/test_jira_analysis.py,sha256=I0cErH5R_dHVyutpXrM1QEo7jfBuKWTmDQvJBPjx18I,3281
97
- alita_sdk-0.3.122.dist-info/METADATA,sha256=_tp0Oa-uXYLh9RmhhlYGM4dazECkrNy0vtUUFMce_Cg,7075
98
- alita_sdk-0.3.122.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
99
- alita_sdk-0.3.122.dist-info/top_level.txt,sha256=SWRhxB7Et3cOy3RkE5hR7OIRnHoo3K8EXzoiNlkfOmc,25
100
- alita_sdk-0.3.122.dist-info/RECORD,,
98
+ alita_sdk-0.3.124.dist-info/METADATA,sha256=SLr3I6hYo-6OFuiJYygEXnREyu4nt2GlWBoqh4jHw6M,7075
99
+ alita_sdk-0.3.124.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
100
+ alita_sdk-0.3.124.dist-info/top_level.txt,sha256=SWRhxB7Et3cOy3RkE5hR7OIRnHoo3K8EXzoiNlkfOmc,25
101
+ alita_sdk-0.3.124.dist-info/RECORD,,