alita-sdk 0.3.435__py3-none-any.whl → 0.3.437__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.

Potentially problematic release.


This version of alita-sdk might be problematic. Click here for more details.

@@ -5,6 +5,7 @@ Following MCP specification: https://modelcontextprotocol.io/specification/2025-
5
5
  """
6
6
 
7
7
  import logging
8
+ import re
8
9
  import requests
9
10
  from typing import List, Optional, Any, Dict, Literal, ClassVar
10
11
 
@@ -12,6 +13,7 @@ from langchain_core.tools import BaseToolkit, BaseTool
12
13
  from pydantic import BaseModel, ConfigDict, Field
13
14
 
14
15
  from ..tools.mcp_server_tool import McpServerTool
16
+ from ..tools.mcp_remote_tool import McpRemoteTool
15
17
  from ..tools.mcp_inspect_tool import McpInspectTool
16
18
  from ...tools.utils import TOOLKIT_SPLITTER, clean_string
17
19
  from ..models.mcp_models import McpConnectionConfig
@@ -20,6 +22,119 @@ logger = logging.getLogger(__name__)
20
22
 
21
23
  name = "mcp"
22
24
 
25
+ def safe_int(value, default):
26
+ """Convert value to int, handling string inputs."""
27
+ if value is None:
28
+ return default
29
+ try:
30
+ return int(value)
31
+ except (ValueError, TypeError):
32
+ logger.warning(f"Invalid integer value '{value}', using default {default}")
33
+ return default
34
+
35
+ def optimize_tool_name(prefix: str, tool_name: str, max_total_length: int = 64) -> str:
36
+ """
37
+ Optimize tool name to fit within max_total_length while preserving meaning.
38
+
39
+ Args:
40
+ prefix: The toolkit prefix (already cleaned)
41
+ tool_name: The original tool name
42
+ max_total_length: Maximum total length for the full tool name (default: 64)
43
+
44
+ Returns:
45
+ Optimized full tool name in format: prefix___tool_name
46
+ """
47
+ splitter = TOOLKIT_SPLITTER
48
+ splitter_len = len(splitter)
49
+ prefix_len = len(prefix)
50
+
51
+ # Calculate available space for tool name
52
+ available_space = max_total_length - prefix_len - splitter_len
53
+
54
+ if available_space <= 0:
55
+ logger.error(f"Prefix '{prefix}' is too long ({prefix_len} chars), cannot create valid tool name")
56
+ # Fallback: truncate prefix itself
57
+ prefix = prefix[:max_total_length - splitter_len - 10] # Leave 10 chars for tool name
58
+ available_space = max_total_length - len(prefix) - splitter_len
59
+
60
+ # If tool name fits, use it as-is
61
+ if len(tool_name) <= available_space:
62
+ return f'{prefix}{splitter}{tool_name}'
63
+
64
+ # Tool name is too long, need to optimize
65
+ logger.debug(f"Tool name '{tool_name}' is too long ({len(tool_name)} chars), optimizing to fit {available_space} chars")
66
+
67
+ # Split tool name into parts (handle camelCase, snake_case, and mixed)
68
+ # First, split by underscores and hyphens
69
+ parts = re.split(r'[_-]', tool_name)
70
+
71
+ # Further split camelCase within each part
72
+ all_parts = []
73
+ for part in parts:
74
+ # Insert underscore before uppercase letters (camelCase to snake_case)
75
+ snake_case_part = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', part)
76
+ all_parts.extend(snake_case_part.split('_'))
77
+
78
+ # Filter out empty parts
79
+ all_parts = [p for p in all_parts if p]
80
+
81
+ # Remove redundant prefix words (case-insensitive comparison)
82
+ # Only remove if prefix is meaningful (>= 3 chars) to avoid over-filtering
83
+ prefix_lower = prefix.lower()
84
+ filtered_parts = []
85
+ for part in all_parts:
86
+ part_lower = part.lower()
87
+ # Skip if this part contains the prefix or the prefix contains this part
88
+ # But only if both are meaningful (>= 3 chars)
89
+ should_remove = False
90
+ if len(prefix_lower) >= 3 and len(part_lower) >= 3:
91
+ if part_lower in prefix_lower or prefix_lower in part_lower:
92
+ should_remove = True
93
+ logger.debug(f"Removing redundant part '{part}' (matches prefix '{prefix}')")
94
+
95
+ if not should_remove:
96
+ filtered_parts.append(part)
97
+
98
+ # If we removed all parts, keep the original parts
99
+ if not filtered_parts:
100
+ filtered_parts = all_parts
101
+
102
+ # Reconstruct tool name with filtered parts
103
+ optimized_name = '_'.join(filtered_parts)
104
+
105
+ # If still too long, truncate intelligently
106
+ if len(optimized_name) > available_space:
107
+ # Strategy: Keep beginning and end, as they often contain the most important info
108
+ # For example: "projectalita_github_io_list_branches" -> "projectalita_list_branches"
109
+
110
+ # Try removing middle parts first
111
+ if len(filtered_parts) > 2:
112
+ # Keep first and last parts, remove middle
113
+ kept_parts = [filtered_parts[0], filtered_parts[-1]]
114
+ optimized_name = '_'.join(kept_parts)
115
+
116
+ # If still too long, add parts from the end until we run out of space
117
+ if len(optimized_name) <= available_space and len(filtered_parts) > 2:
118
+ for i in range(len(filtered_parts) - 2, 0, -1):
119
+ candidate = '_'.join([filtered_parts[0]] + filtered_parts[i:])
120
+ if len(candidate) <= available_space:
121
+ optimized_name = candidate
122
+ break
123
+
124
+ # If still too long, just truncate
125
+ if len(optimized_name) > available_space:
126
+ # Try to truncate at word boundary
127
+ truncated = optimized_name[:available_space]
128
+ last_underscore = truncated.rfind('_')
129
+ if last_underscore > available_space * 0.7: # Keep if we're not losing too much
130
+ optimized_name = truncated[:last_underscore]
131
+ else:
132
+ optimized_name = truncated
133
+
134
+ full_name = f'{prefix}{splitter}{optimized_name}'
135
+ logger.info(f"Optimized tool name: '{tool_name}' ({len(tool_name)} chars) -> '{optimized_name}' ({len(optimized_name)} chars), full: '{full_name}' ({len(full_name)} chars)")
136
+
137
+ return full_name
23
138
 
24
139
  class McpToolkit(BaseToolkit):
25
140
  """
@@ -277,6 +392,7 @@ class McpToolkit(BaseToolkit):
277
392
  server_tool = cls._create_tool_from_dict(
278
393
  tool_dict=tool_metadata,
279
394
  toolkit_name=toolkit_name,
395
+ connection_config=connection_config,
280
396
  timeout=timeout,
281
397
  client=client
282
398
  )
@@ -480,6 +596,7 @@ class McpToolkit(BaseToolkit):
480
596
  cls,
481
597
  tool_dict: Dict[str, Any],
482
598
  toolkit_name: str,
599
+ connection_config: McpConnectionConfig,
483
600
  timeout: int,
484
601
  client
485
602
  ) -> Optional[BaseTool]:
@@ -491,23 +608,34 @@ class McpToolkit(BaseToolkit):
491
608
  # Clean toolkit name for prefixing
492
609
  clean_prefix = clean_string(toolkit_name, max_length_value)
493
610
 
494
- full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}{tool_dict.get("name", "unknown")}'
611
+ # Optimize tool name to fit within 64 character limit
612
+ full_tool_name = optimize_tool_name(clean_prefix, tool_dict.get("name", "unknown"))
495
613
 
496
614
  # Check if this is a prompt (converted to tool)
497
615
  is_prompt = tool_dict.get("_mcp_type") == "prompt"
498
616
  item_type = "prompt" if is_prompt else "tool"
499
617
 
500
- return McpServerTool(
618
+ # Build description and ensure it doesn't exceed 1000 characters
619
+ description = f"MCP {item_type} '{tool_dict.get('name')}' from toolkit '{toolkit_name}': {tool_dict.get('description', '')}"
620
+ if len(description) > 1000:
621
+ description = description[:997] + "..."
622
+ logger.debug(f"Trimmed description for tool '{tool_dict.get('name')}' from {len(description)} to 1000 chars")
623
+
624
+ # Use McpRemoteTool for remote MCP servers (HTTP/SSE)
625
+ return McpRemoteTool(
501
626
  name=full_tool_name,
502
- description=f"MCP {item_type} '{tool_dict.get('name')}' from toolkit '{toolkit_name}': {tool_dict.get('description', '')}",
627
+ description=description,
503
628
  args_schema=McpServerTool.create_pydantic_model_from_schema(
504
629
  tool_dict.get("inputSchema", {})
505
630
  ),
506
631
  client=client,
507
632
  server=toolkit_name,
633
+ server_url=connection_config.url,
634
+ server_headers=connection_config.headers,
508
635
  tool_timeout_sec=timeout,
509
636
  is_prompt=is_prompt,
510
- prompt_name=tool_dict.get("_mcp_prompt_name") if is_prompt else None
637
+ prompt_name=tool_dict.get("_mcp_prompt_name") if is_prompt else None,
638
+ original_tool_name=tool_dict.get('name') # Store original name for MCP server invocation
511
639
  )
512
640
  except Exception as e:
513
641
  logger.error(f"Failed to create MCP tool '{tool_dict.get('name')}' from toolkit '{toolkit_name}': {e}")
@@ -596,11 +724,18 @@ class McpToolkit(BaseToolkit):
596
724
 
597
725
  # Clean server name for prefixing (use tool_metadata.server instead of toolkit_name)
598
726
  clean_prefix = clean_string(tool_metadata.server, max_length_value)
599
- full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}{tool_metadata.name}'
727
+ # Optimize tool name to fit within 64 character limit
728
+ full_tool_name = optimize_tool_name(clean_prefix, tool_metadata.name)
729
+
730
+ # Build description and ensure it doesn't exceed 1000 characters
731
+ description = f"MCP tool '{tool_metadata.name}' from server '{tool_metadata.server}': {tool_metadata.description}"
732
+ if len(description) > 1000:
733
+ description = description[:997] + "..."
734
+ logger.debug(f"Trimmed description for tool '{tool_metadata.name}' from {len(description)} to 1000 chars")
600
735
 
601
736
  return McpServerTool(
602
737
  name=full_tool_name,
603
- description=f"MCP tool '{tool_metadata.name}' from server '{tool_metadata.server}': {tool_metadata.description}",
738
+ description=description,
604
739
  args_schema=McpServerTool.create_pydantic_model_from_schema(tool_metadata.input_schema),
605
740
  client=client,
606
741
  server=tool_metadata.server,
@@ -626,11 +761,18 @@ class McpToolkit(BaseToolkit):
626
761
  # Clean toolkit name for prefixing
627
762
  clean_prefix = clean_string(toolkit_name, max_length_value)
628
763
 
629
- full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}{available_tool["name"]}'
764
+ # Optimize tool name to fit within 64 character limit
765
+ full_tool_name = optimize_tool_name(clean_prefix, available_tool["name"])
766
+
767
+ # Build description and ensure it doesn't exceed 1000 characters
768
+ description = f"MCP tool '{available_tool['name']}' from toolkit '{toolkit_name}': {available_tool.get('description', '')}"
769
+ if len(description) > 1000:
770
+ description = description[:997] + "..."
771
+ logger.debug(f"Trimmed description for tool '{available_tool['name']}' from {len(description)} to 1000 chars")
630
772
 
631
773
  return McpServerTool(
632
774
  name=full_tool_name,
633
- description=f"MCP tool '{available_tool['name']}' from toolkit '{toolkit_name}': {available_tool.get('description', '')}",
775
+ description=description,
634
776
  args_schema=McpServerTool.create_pydantic_model_from_schema(
635
777
  available_tool.get("inputSchema", {})
636
778
  ),
@@ -736,16 +878,6 @@ def get_tools(tool_config: dict, alita_client, llm=None, memory_store=None) -> L
736
878
  return []
737
879
 
738
880
  # Type conversion for numeric settings that may come as strings from config
739
- def safe_int(value, default):
740
- """Convert value to int, handling string inputs."""
741
- if value is None:
742
- return default
743
- try:
744
- return int(value)
745
- except (ValueError, TypeError):
746
- logger.warning(f"Invalid integer value '{value}', using default {default}")
747
- return default
748
-
749
881
  return McpToolkit.get_toolkit(
750
882
  url=url,
751
883
  headers=headers,
@@ -0,0 +1,177 @@
1
+ """
2
+ MCP Remote Tool for direct HTTP/SSE invocation.
3
+ This tool is used for remote MCP servers accessed via HTTP/SSE.
4
+ """
5
+
6
+ import asyncio
7
+ import json
8
+ import logging
9
+ import time
10
+ import uuid
11
+ from concurrent.futures import ThreadPoolExecutor
12
+ from typing import Any, Dict, Optional
13
+
14
+ from .mcp_server_tool import McpServerTool
15
+ from pydantic import Field
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class McpRemoteTool(McpServerTool):
21
+ """
22
+ Tool for invoking remote MCP server tools via HTTP/SSE.
23
+ Extends McpServerTool and overrides _run to use direct HTTP calls instead of client.mcp_tool_call.
24
+ """
25
+
26
+ # Remote MCP connection details
27
+ server_url: str = Field(..., description="URL of the remote MCP server")
28
+ server_headers: Optional[Dict[str, str]] = Field(default=None, description="HTTP headers for authentication")
29
+ original_tool_name: Optional[str] = Field(default=None, description="Original tool name from MCP server (before optimization)")
30
+ is_prompt: bool = False # Flag to indicate if this is a prompt tool
31
+ prompt_name: Optional[str] = None # Original prompt name if this is a prompt
32
+
33
+ def __getstate__(self):
34
+ """Custom serialization for pickle compatibility."""
35
+ state = super().__getstate__()
36
+ # Ensure headers are serializable
37
+ if 'server_headers' in state and state['server_headers'] is not None:
38
+ state['server_headers'] = dict(state['server_headers'])
39
+ return state
40
+
41
+ def _run(self, *args, **kwargs):
42
+ """
43
+ Execute the MCP tool via direct HTTP/SSE call to the remote server.
44
+ Overrides the parent method to avoid using client.mcp_tool_call.
45
+ """
46
+ try:
47
+ # Always create a new event loop for sync context
48
+ with ThreadPoolExecutor() as executor:
49
+ future = executor.submit(self._run_in_new_loop, kwargs)
50
+ return future.result(timeout=self.tool_timeout_sec)
51
+ except Exception as e:
52
+ logger.error(f"Error executing remote MCP tool '{self.name}': {e}")
53
+ return f"Error executing tool: {e}"
54
+
55
+ def _run_in_new_loop(self, kwargs: Dict[str, Any]) -> str:
56
+ """Run the async tool invocation in a new event loop."""
57
+ return asyncio.run(self._execute_remote_tool(kwargs))
58
+
59
+ async def _execute_remote_tool(self, kwargs: Dict[str, Any]) -> str:
60
+ """Execute the actual remote MCP tool call."""
61
+ import aiohttp
62
+ from ...tools.utils import TOOLKIT_SPLITTER
63
+
64
+ # Use the original tool name from discovery for MCP server invocation
65
+ # The MCP server doesn't know about our optimized names
66
+ tool_name_for_server = self.original_tool_name
67
+
68
+ # Fallback: extract from optimized name if original not stored (backwards compatibility)
69
+ if not tool_name_for_server:
70
+ tool_name_for_server = self.name.rsplit(TOOLKIT_SPLITTER, 1)[-1] if TOOLKIT_SPLITTER in self.name else self.name
71
+ logger.warning(f"original_tool_name not set for '{self.name}', using extracted name: {tool_name_for_server}")
72
+
73
+ # Build the MCP request based on whether this is a prompt or tool
74
+ if self.is_prompt:
75
+ # For prompts, use prompts/get endpoint
76
+ mcp_request = {
77
+ "jsonrpc": "2.0",
78
+ "id": f"prompt_get_{int(time.time())}_{uuid.uuid4().hex[:8]}",
79
+ "method": "prompts/get",
80
+ "params": {
81
+ "name": self.prompt_name or tool_name_for_server.replace("prompt_", ""),
82
+ "arguments": kwargs.get("arguments", kwargs)
83
+ }
84
+ }
85
+ else:
86
+ # For regular tools, use tools/call endpoint
87
+ mcp_request = {
88
+ "jsonrpc": "2.0",
89
+ "id": f"tool_call_{int(time.time())}_{uuid.uuid4().hex[:8]}",
90
+ "method": "tools/call",
91
+ "params": {
92
+ "name": tool_name_for_server,
93
+ "arguments": kwargs
94
+ }
95
+ }
96
+
97
+ # Set up headers
98
+ headers = {
99
+ "Content-Type": "application/json",
100
+ "Accept": "application/json, text/event-stream"
101
+ }
102
+ if self.server_headers:
103
+ headers.update(self.server_headers)
104
+
105
+ # Execute the HTTP request
106
+ timeout = aiohttp.ClientTimeout(total=self.tool_timeout_sec)
107
+ async with aiohttp.ClientSession(timeout=timeout) as session:
108
+ try:
109
+ logger.debug(f"Calling remote MCP tool '{tool_name_for_server}' (optimized name: '{self.name}') at {self.server_url}")
110
+ logger.debug(f"Request: {json.dumps(mcp_request, indent=2)}")
111
+
112
+ async with session.post(self.server_url, json=mcp_request, headers=headers) as response:
113
+ if response.status != 200:
114
+ error_text = await response.text()
115
+ raise Exception(f"HTTP {response.status}: {error_text}")
116
+
117
+ # Handle both JSON and SSE responses
118
+ content_type = response.headers.get('Content-Type', '')
119
+ if 'text/event-stream' in content_type:
120
+ # Parse SSE format
121
+ text = await response.text()
122
+ data = self._parse_sse(text)
123
+ else:
124
+ # Parse regular JSON
125
+ data = await response.json()
126
+
127
+ logger.debug(f"Response: {json.dumps(data, indent=2)}")
128
+
129
+ # Check for MCP error
130
+ if "error" in data:
131
+ error = data["error"]
132
+ error_msg = error.get("message", str(error))
133
+ raise Exception(f"MCP Error: {error_msg}")
134
+
135
+ # Extract result
136
+ result = data.get("result", {})
137
+
138
+ # Format the result based on content type
139
+ if isinstance(result, dict):
140
+ # Check for content array (common in MCP responses)
141
+ if "content" in result:
142
+ content_items = result["content"]
143
+ if isinstance(content_items, list):
144
+ # Extract text from content items
145
+ text_parts = []
146
+ for item in content_items:
147
+ if isinstance(item, dict):
148
+ if item.get("type") == "text" and "text" in item:
149
+ text_parts.append(item["text"])
150
+ elif "text" in item:
151
+ text_parts.append(item["text"])
152
+ else:
153
+ text_parts.append(json.dumps(item))
154
+ else:
155
+ text_parts.append(str(item))
156
+ return "\n".join(text_parts)
157
+
158
+ # Return formatted JSON if no content field
159
+ return json.dumps(result, indent=2)
160
+
161
+ # Return as string for other types
162
+ return str(result)
163
+
164
+ except asyncio.TimeoutError:
165
+ raise Exception(f"Tool execution timed out after {self.tool_timeout_sec}s")
166
+ except Exception as e:
167
+ logger.error(f"Error calling remote MCP tool '{tool_name_for_server}': {e}", exc_info=True)
168
+ raise
169
+
170
+ def _parse_sse(self, text: str) -> Dict[str, Any]:
171
+ """Parse Server-Sent Events (SSE) format response."""
172
+ for line in text.split('\n'):
173
+ line = line.strip()
174
+ if line.startswith('data:'):
175
+ json_str = line[5:].strip()
176
+ return json.loads(json_str)
177
+ raise ValueError("No data found in SSE response")
@@ -15,63 +15,12 @@ class McpServerTool(BaseTool):
15
15
  description: str
16
16
  args_schema: Optional[Type[BaseModel]] = None
17
17
  return_type: str = "str"
18
- client: Any = Field(default=None, exclude=True) # Exclude from serialization
18
+ client: Any
19
19
  server: str
20
20
  tool_timeout_sec: int = 60
21
- is_prompt: bool = False # Flag to indicate if this is a prompt tool
22
- prompt_name: Optional[str] = None # Original prompt name if this is a prompt
23
21
 
24
22
  model_config = ConfigDict(arbitrary_types_allowed=True)
25
23
 
26
- def __getstate__(self):
27
- """Custom serialization to exclude non-serializable objects."""
28
- state = self.__dict__.copy()
29
- # Remove the client since it contains threading objects that can't be pickled
30
- state['client'] = None
31
- # Store args_schema as a schema dict instead of the dynamic class
32
- if hasattr(self, 'args_schema') and self.args_schema is not None:
33
- # Convert the Pydantic model back to schema dict for pickling
34
- try:
35
- state['_args_schema_dict'] = self.args_schema.model_json_schema()
36
- state['args_schema'] = None
37
- except Exception as e:
38
- logger.warning(f"Failed to serialize args_schema: {e}")
39
- # If conversion fails, just remove it
40
- state['args_schema'] = None
41
- state['_args_schema_dict'] = {}
42
- return state
43
-
44
- def __setstate__(self, state):
45
- """Custom deserialization to handle missing objects."""
46
- # Restore the args_schema from the stored schema dict
47
- args_schema_dict = state.pop('_args_schema_dict', {})
48
-
49
- # Initialize required Pydantic internal attributes
50
- if '__pydantic_fields_set__' not in state:
51
- state['__pydantic_fields_set__'] = set(state.keys())
52
- if '__pydantic_extra__' not in state:
53
- state['__pydantic_extra__'] = None
54
- if '__pydantic_private__' not in state:
55
- state['__pydantic_private__'] = None
56
-
57
- # Directly update the object's __dict__ to bypass Pydantic validation
58
- self.__dict__.update(state)
59
-
60
- # Recreate the args_schema from the stored dict if available
61
- if args_schema_dict:
62
- try:
63
- recreated_schema = self.create_pydantic_model_from_schema(args_schema_dict)
64
- self.__dict__['args_schema'] = recreated_schema
65
- except Exception as e:
66
- logger.warning(f"Failed to recreate args_schema: {e}")
67
- self.__dict__['args_schema'] = None
68
- else:
69
- self.__dict__['args_schema'] = None
70
-
71
- # Note: client will be None after unpickling
72
- # The toolkit should reinitialize the client when needed
73
-
74
-
75
24
  @staticmethod
76
25
  def create_pydantic_model_from_schema(schema: dict, model_name: str = "ArgsSchema"):
77
26
  def parse_type(field: dict, name: str = "Field") -> Any:
@@ -143,30 +92,14 @@ class McpServerTool(BaseTool):
143
92
 
144
93
  def _run(self, *args, **kwargs):
145
94
  # Extract the actual tool/prompt name (remove toolkit prefix)
146
- actual_name = self.name.rsplit(TOOLKIT_SPLITTER)[1] if TOOLKIT_SPLITTER in self.name else self.name
147
-
148
- if self.is_prompt:
149
- # For prompts, use prompts/get endpoint
150
- call_data = {
151
- "server": self.server,
152
- "tool_timeout_sec": self.tool_timeout_sec,
153
- "tool_call_id": str(uuid.uuid4()),
154
- "method": "prompts/get",
155
- "params": {
156
- "name": self.prompt_name or actual_name.replace("prompt_", ""),
157
- "arguments": kwargs.get("arguments", kwargs)
158
- }
159
- }
160
- else:
161
- # For regular tools, use tools/call endpoint
162
- call_data = {
163
- "server": self.server,
164
- "tool_timeout_sec": self.tool_timeout_sec,
165
- "tool_call_id": str(uuid.uuid4()),
166
- "params": {
167
- "name": actual_name,
168
- "arguments": kwargs
169
- }
95
+ call_data = {
96
+ "server": self.server,
97
+ "tool_timeout_sec": self.tool_timeout_sec,
98
+ "tool_call_id": str(uuid.uuid4()),
99
+ "params": {
100
+ "name": self.name.rsplit(TOOLKIT_SPLITTER)[1] if TOOLKIT_SPLITTER in self.name else self.name,
101
+ "arguments": kwargs
170
102
  }
103
+ }
171
104
 
172
105
  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.435
3
+ Version: 0.3.437
4
4
  Summary: SDK for building langchain agents using resources 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 <lifedj27@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -103,7 +103,7 @@ alita_sdk/runtime/toolkits/application.py,sha256=HHAKgwKOckxc7EQG-AV7rz4POOzQJKF
103
103
  alita_sdk/runtime/toolkits/artifact.py,sha256=YChNCX4QhVpaQG7Jk4TS-Wl0Aruc4slQ2K21zh9nNO0,3176
104
104
  alita_sdk/runtime/toolkits/configurations.py,sha256=kIDAlnryPQfbZyFxV-9SzN2-Vefzx06TX1BBdIIpN90,141
105
105
  alita_sdk/runtime/toolkits/datasource.py,sha256=qk78OdPoReYPCWwahfkKLbKc4pfsu-061oXRryFLP6I,2498
106
- alita_sdk/runtime/toolkits/mcp.py,sha256=MnsvXHRbEIE_8O_qPtsGaW3ZiwSOeWUGYVCZGbHLH1E,31402
106
+ alita_sdk/runtime/toolkits/mcp.py,sha256=reAzEnhQe_G5-lQa3P-nV4MCn_YAIx8lllCBFL5uxTk,37624
107
107
  alita_sdk/runtime/toolkits/prompt.py,sha256=WIpTkkVYWqIqOWR_LlSWz3ug8uO9tm5jJ7aZYdiGRn0,1192
108
108
  alita_sdk/runtime/toolkits/subgraph.py,sha256=wwUK8JjPXkGzyVZ3tAukmvST6eGbqx_U11rpnmbrvtg,2105
109
109
  alita_sdk/runtime/toolkits/tools.py,sha256=YCTjrTJuwj2V2C8ZQqXhFvUbVr7NQcUHZlCQLLvoeGA,10946
@@ -122,7 +122,8 @@ alita_sdk/runtime/tools/llm.py,sha256=iRG_wU4T01LRsjEMPZe5Uah7LiMqDc-vspwkMuQtlt
122
122
  alita_sdk/runtime/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
123
123
  alita_sdk/runtime/tools/loop_output.py,sha256=U4hO9PCQgWlXwOq6jdmCGbegtAxGAPXObSxZQ3z38uk,8069
124
124
  alita_sdk/runtime/tools/mcp_inspect_tool.py,sha256=38X8euaxDbEGjcfp6ElvExZalpZun6QEr6ZEW4nU5pQ,11496
125
- alita_sdk/runtime/tools/mcp_server_tool.py,sha256=HPlEppCbNafee41wSxZL1wnVyYCiOwdMD_dy0eE9IUs,7505
125
+ alita_sdk/runtime/tools/mcp_remote_tool.py,sha256=SfqU-GW7C0ujSLyqRMIYf2AzLxMbYIV2brY6q9yYFCY,8071
126
+ alita_sdk/runtime/tools/mcp_server_tool.py,sha256=-xO3H6BM63KaIV1CdcQKPVE0WPigiqOgFZDX7m2_yGs,4419
126
127
  alita_sdk/runtime/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8QwB0UwpsWCYruXU,11692
127
128
  alita_sdk/runtime/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
128
129
  alita_sdk/runtime/tools/router.py,sha256=p7e0tX6YAWw2M2Nq0A_xqw1E2P-Xz1DaJvhUstfoZn4,1584
@@ -358,8 +359,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
358
359
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
359
360
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
360
361
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
361
- alita_sdk-0.3.435.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
362
- alita_sdk-0.3.435.dist-info/METADATA,sha256=kuNOhhnRzdqSLgYrM41t-qLOE62bgF6VE-0r9no-3Z0,19071
363
- alita_sdk-0.3.435.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
364
- alita_sdk-0.3.435.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
365
- alita_sdk-0.3.435.dist-info/RECORD,,
362
+ alita_sdk-0.3.437.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
363
+ alita_sdk-0.3.437.dist-info/METADATA,sha256=fCP3C5QT6Qn1COsbs7uehjpBAicDl_G_rsIfCFl3tDE,19071
364
+ alita_sdk-0.3.437.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
365
+ alita_sdk-0.3.437.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
366
+ alita_sdk-0.3.437.dist-info/RECORD,,