alita-sdk 0.3.430__py3-none-any.whl → 0.3.432__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.
- alita_sdk/runtime/toolkits/mcp.py +82 -89
- alita_sdk/runtime/toolkits/tools.py +11 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +22 -14
- {alita_sdk-0.3.430.dist-info → alita_sdk-0.3.432.dist-info}/METADATA +1 -1
- {alita_sdk-0.3.430.dist-info → alita_sdk-0.3.432.dist-info}/RECORD +8 -8
- {alita_sdk-0.3.430.dist-info → alita_sdk-0.3.432.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.430.dist-info → alita_sdk-0.3.432.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.430.dist-info → alita_sdk-0.3.432.dist-info}/top_level.txt +0 -0
|
@@ -28,7 +28,7 @@ class McpToolkit(BaseToolkit):
|
|
|
28
28
|
"""
|
|
29
29
|
|
|
30
30
|
tools: List[BaseTool] = []
|
|
31
|
-
|
|
31
|
+
toolkit_name: Optional[str] = None
|
|
32
32
|
|
|
33
33
|
# Class variable (not Pydantic field) for tool name length limit
|
|
34
34
|
toolkit_max_length: ClassVar[int] = 0 # No limit for MCP tool names
|
|
@@ -63,15 +63,6 @@ class McpToolkit(BaseToolkit):
|
|
|
63
63
|
|
|
64
64
|
return create_model(
|
|
65
65
|
'mcp',
|
|
66
|
-
server_name=(
|
|
67
|
-
str,
|
|
68
|
-
Field(
|
|
69
|
-
description="MCP server name/identifier",
|
|
70
|
-
json_schema_extra={
|
|
71
|
-
'tooltip': 'Unique identifier for this MCP server'
|
|
72
|
-
}
|
|
73
|
-
)
|
|
74
|
-
),
|
|
75
66
|
url=(
|
|
76
67
|
str,
|
|
77
68
|
Field(
|
|
@@ -160,7 +151,6 @@ class McpToolkit(BaseToolkit):
|
|
|
160
151
|
@classmethod
|
|
161
152
|
def get_toolkit(
|
|
162
153
|
cls,
|
|
163
|
-
server_name: str,
|
|
164
154
|
url: str,
|
|
165
155
|
headers: Optional[Dict[str, str]] = None,
|
|
166
156
|
timeout: int = 60,
|
|
@@ -169,7 +159,7 @@ class McpToolkit(BaseToolkit):
|
|
|
169
159
|
selected_tools: List[str] = None,
|
|
170
160
|
enable_caching: bool = True,
|
|
171
161
|
cache_ttl: int = 300,
|
|
172
|
-
toolkit_name:
|
|
162
|
+
toolkit_name: str = None,
|
|
173
163
|
client = None,
|
|
174
164
|
**kwargs
|
|
175
165
|
) -> 'McpToolkit':
|
|
@@ -183,7 +173,6 @@ class McpToolkit(BaseToolkit):
|
|
|
183
173
|
4. Return all tools via get_tools() method
|
|
184
174
|
|
|
185
175
|
Args:
|
|
186
|
-
server_name: MCP server name/identifier
|
|
187
176
|
url: MCP server HTTP URL
|
|
188
177
|
headers: HTTP headers for authentication
|
|
189
178
|
timeout: Request timeout in seconds
|
|
@@ -192,7 +181,7 @@ class McpToolkit(BaseToolkit):
|
|
|
192
181
|
selected_tools: List of specific tools to enable (empty = all tools)
|
|
193
182
|
enable_caching: Whether to enable caching
|
|
194
183
|
cache_ttl: Cache TTL in seconds
|
|
195
|
-
toolkit_name:
|
|
184
|
+
toolkit_name: Toolkit name/identifier and prefix for tools
|
|
196
185
|
client: Alita client for MCP communication
|
|
197
186
|
**kwargs: Additional configuration options
|
|
198
187
|
|
|
@@ -201,8 +190,11 @@ class McpToolkit(BaseToolkit):
|
|
|
201
190
|
"""
|
|
202
191
|
if selected_tools is None:
|
|
203
192
|
selected_tools = []
|
|
193
|
+
|
|
194
|
+
if not toolkit_name:
|
|
195
|
+
raise ValueError("toolkit_name is required")
|
|
204
196
|
|
|
205
|
-
logger.info(f"Creating MCP toolkit
|
|
197
|
+
logger.info(f"Creating MCP toolkit: {toolkit_name}")
|
|
206
198
|
|
|
207
199
|
# Parse headers if they're provided as a JSON string
|
|
208
200
|
parsed_headers = headers
|
|
@@ -232,15 +224,14 @@ class McpToolkit(BaseToolkit):
|
|
|
232
224
|
raise ValueError(f"Invalid MCP connection configuration: {e}")
|
|
233
225
|
|
|
234
226
|
# Create toolkit instance
|
|
235
|
-
toolkit = cls(
|
|
227
|
+
toolkit = cls(toolkit_name=toolkit_name)
|
|
236
228
|
|
|
237
229
|
# Generate tools from the MCP server
|
|
238
230
|
toolkit.tools = cls._create_tools_from_server(
|
|
239
|
-
|
|
231
|
+
toolkit_name=toolkit_name,
|
|
240
232
|
connection_config=connection_config,
|
|
241
233
|
timeout=timeout,
|
|
242
234
|
selected_tools=selected_tools,
|
|
243
|
-
toolkit_name=toolkit_name,
|
|
244
235
|
client=client,
|
|
245
236
|
discovery_mode=discovery_mode
|
|
246
237
|
)
|
|
@@ -250,11 +241,10 @@ class McpToolkit(BaseToolkit):
|
|
|
250
241
|
@classmethod
|
|
251
242
|
def _create_tools_from_server(
|
|
252
243
|
cls,
|
|
253
|
-
|
|
244
|
+
toolkit_name: str,
|
|
254
245
|
connection_config: McpConnectionConfig,
|
|
255
246
|
timeout: int,
|
|
256
247
|
selected_tools: List[str],
|
|
257
|
-
toolkit_name: Optional[str],
|
|
258
248
|
client,
|
|
259
249
|
discovery_mode: str = "dynamic"
|
|
260
250
|
) -> List[BaseTool]:
|
|
@@ -265,11 +255,11 @@ class McpToolkit(BaseToolkit):
|
|
|
265
255
|
|
|
266
256
|
# First, try direct HTTP discovery since we have valid connection config
|
|
267
257
|
try:
|
|
268
|
-
logger.info(f"Discovering tools from MCP
|
|
258
|
+
logger.info(f"Discovering tools from MCP toolkit '{toolkit_name}' at {connection_config.url}")
|
|
269
259
|
|
|
270
260
|
# Use synchronous HTTP discovery for toolkit initialization
|
|
271
261
|
tool_metadata_list = cls._discover_tools_sync(
|
|
272
|
-
|
|
262
|
+
toolkit_name=toolkit_name,
|
|
273
263
|
connection_config=connection_config,
|
|
274
264
|
timeout=timeout
|
|
275
265
|
)
|
|
@@ -286,8 +276,7 @@ class McpToolkit(BaseToolkit):
|
|
|
286
276
|
for tool_metadata in tool_metadata_list:
|
|
287
277
|
server_tool = cls._create_tool_from_dict(
|
|
288
278
|
tool_dict=tool_metadata,
|
|
289
|
-
|
|
290
|
-
toolkit_name=toolkit_name or server_name,
|
|
279
|
+
toolkit_name=toolkit_name,
|
|
291
280
|
timeout=timeout,
|
|
292
281
|
client=client
|
|
293
282
|
)
|
|
@@ -295,34 +284,33 @@ class McpToolkit(BaseToolkit):
|
|
|
295
284
|
if server_tool:
|
|
296
285
|
tools.append(server_tool)
|
|
297
286
|
|
|
298
|
-
logger.info(f"Successfully created {len(tools)} MCP tools from
|
|
287
|
+
logger.info(f"Successfully created {len(tools)} MCP tools from toolkit '{toolkit_name}' via direct discovery")
|
|
299
288
|
|
|
300
289
|
except Exception as e:
|
|
301
|
-
logger.error(f"Direct discovery failed for MCP
|
|
290
|
+
logger.error(f"Direct discovery failed for MCP toolkit '{toolkit_name}': {e}")
|
|
302
291
|
|
|
303
292
|
# Fallback to static mode if available and not already static
|
|
304
293
|
if client and discovery_mode != "static":
|
|
305
|
-
logger.info(f"Falling back to static discovery for
|
|
306
|
-
tools = cls._create_tools_static(
|
|
294
|
+
logger.info(f"Falling back to static discovery for toolkit '{toolkit_name}'")
|
|
295
|
+
tools = cls._create_tools_static(toolkit_name, selected_tools, timeout, client)
|
|
307
296
|
else:
|
|
308
|
-
logger.warning(f"No fallback available for
|
|
297
|
+
logger.warning(f"No fallback available for toolkit '{toolkit_name}' - returning empty tools list")
|
|
309
298
|
|
|
310
299
|
# Always add the inspection tool (not subject to selected_tools filtering)
|
|
311
300
|
inspection_tool = cls._create_inspection_tool(
|
|
312
|
-
|
|
313
|
-
connection_config=connection_config
|
|
314
|
-
toolkit_name=toolkit_name or server_name
|
|
301
|
+
toolkit_name=toolkit_name,
|
|
302
|
+
connection_config=connection_config
|
|
315
303
|
)
|
|
316
304
|
if inspection_tool:
|
|
317
305
|
tools.append(inspection_tool)
|
|
318
|
-
logger.info(f"Added MCP inspection tool for
|
|
306
|
+
logger.info(f"Added MCP inspection tool for toolkit '{toolkit_name}'")
|
|
319
307
|
|
|
320
308
|
return tools
|
|
321
309
|
|
|
322
310
|
@classmethod
|
|
323
311
|
def _discover_tools_sync(
|
|
324
312
|
cls,
|
|
325
|
-
|
|
313
|
+
toolkit_name: str,
|
|
326
314
|
connection_config: McpConnectionConfig,
|
|
327
315
|
timeout: int
|
|
328
316
|
) -> List[Dict[str, Any]]:
|
|
@@ -340,7 +328,10 @@ class McpToolkit(BaseToolkit):
|
|
|
340
328
|
"params": {}
|
|
341
329
|
}
|
|
342
330
|
|
|
343
|
-
headers = {
|
|
331
|
+
headers = {
|
|
332
|
+
"Content-Type": "application/json",
|
|
333
|
+
"Accept": "application/json, text/event-stream"
|
|
334
|
+
}
|
|
344
335
|
if connection_config.headers:
|
|
345
336
|
headers.update(connection_config.headers)
|
|
346
337
|
|
|
@@ -355,26 +346,33 @@ class McpToolkit(BaseToolkit):
|
|
|
355
346
|
if response.status_code != 200:
|
|
356
347
|
raise Exception(f"HTTP {response.status_code}: {response.text}")
|
|
357
348
|
|
|
358
|
-
|
|
349
|
+
# Check if response is actually JSON
|
|
350
|
+
content_type = response.headers.get('Content-Type', '')
|
|
351
|
+
if 'application/json' not in content_type:
|
|
352
|
+
raise Exception(f"Expected JSON response but got Content-Type: {content_type}. Response: {response.text[:200]}")
|
|
353
|
+
|
|
354
|
+
try:
|
|
355
|
+
data = response.json()
|
|
356
|
+
except ValueError as json_err:
|
|
357
|
+
raise Exception(f"Invalid JSON response: {json_err}. Response text: {response.text[:200]}")
|
|
359
358
|
|
|
360
359
|
if "error" in data:
|
|
361
360
|
raise Exception(f"MCP Error: {data['error']}")
|
|
362
361
|
|
|
363
362
|
# Parse MCP response and extract tools
|
|
364
363
|
tools_data = data.get("result", {}).get("tools", [])
|
|
365
|
-
logger.info(f"Discovered {len(tools_data)} tools from MCP
|
|
364
|
+
logger.info(f"Discovered {len(tools_data)} tools from MCP toolkit '{toolkit_name}'")
|
|
366
365
|
|
|
367
366
|
return tools_data
|
|
368
367
|
|
|
369
368
|
except Exception as e:
|
|
370
|
-
logger.error(f"Failed to discover tools from MCP
|
|
369
|
+
logger.error(f"Failed to discover tools from MCP toolkit '{toolkit_name}': {e}")
|
|
371
370
|
raise
|
|
372
371
|
|
|
373
372
|
@classmethod
|
|
374
373
|
def _create_tool_from_dict(
|
|
375
374
|
cls,
|
|
376
375
|
tool_dict: Dict[str, Any],
|
|
377
|
-
server_name: str,
|
|
378
376
|
toolkit_name: str,
|
|
379
377
|
timeout: int,
|
|
380
378
|
client
|
|
@@ -384,31 +382,30 @@ class McpToolkit(BaseToolkit):
|
|
|
384
382
|
# Store toolkit_max_length in local variable to avoid contextual access issues
|
|
385
383
|
max_length_value = cls.toolkit_max_length
|
|
386
384
|
|
|
387
|
-
# Clean
|
|
388
|
-
clean_prefix = clean_string(
|
|
385
|
+
# Clean toolkit name for prefixing
|
|
386
|
+
clean_prefix = clean_string(toolkit_name, max_length_value)
|
|
389
387
|
|
|
390
388
|
full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}{tool_dict.get("name", "unknown")}'
|
|
391
389
|
|
|
392
390
|
return McpServerTool(
|
|
393
391
|
name=full_tool_name,
|
|
394
|
-
description=f"MCP tool '{tool_dict.get('name')}' from
|
|
392
|
+
description=f"MCP tool '{tool_dict.get('name')}' from toolkit '{toolkit_name}': {tool_dict.get('description', '')}",
|
|
395
393
|
args_schema=McpServerTool.create_pydantic_model_from_schema(
|
|
396
394
|
tool_dict.get("inputSchema", {})
|
|
397
395
|
),
|
|
398
396
|
client=client,
|
|
399
|
-
server=
|
|
397
|
+
server=toolkit_name,
|
|
400
398
|
tool_timeout_sec=timeout
|
|
401
399
|
)
|
|
402
400
|
except Exception as e:
|
|
403
|
-
logger.error(f"Failed to create MCP tool '{tool_dict.get('name')}' from
|
|
401
|
+
logger.error(f"Failed to create MCP tool '{tool_dict.get('name')}' from toolkit '{toolkit_name}': {e}")
|
|
404
402
|
return None
|
|
405
403
|
|
|
406
404
|
@classmethod
|
|
407
405
|
def _create_tools_static(
|
|
408
406
|
cls,
|
|
409
|
-
|
|
407
|
+
toolkit_name: str,
|
|
410
408
|
selected_tools: List[str],
|
|
411
|
-
toolkit_name: Optional[str],
|
|
412
409
|
timeout: int,
|
|
413
410
|
client
|
|
414
411
|
) -> List[BaseTool]:
|
|
@@ -421,10 +418,10 @@ class McpToolkit(BaseToolkit):
|
|
|
421
418
|
|
|
422
419
|
try:
|
|
423
420
|
all_toolkits = client.get_mcp_toolkits()
|
|
424
|
-
server_toolkit = next((tk for tk in all_toolkits if tk.get('name') ==
|
|
421
|
+
server_toolkit = next((tk for tk in all_toolkits if tk.get('name') == toolkit_name), None)
|
|
425
422
|
|
|
426
423
|
if not server_toolkit:
|
|
427
|
-
logger.warning(f"MCP
|
|
424
|
+
logger.warning(f"MCP toolkit '{toolkit_name}' not found in available toolkits")
|
|
428
425
|
return tools
|
|
429
426
|
|
|
430
427
|
# Extract tools from the toolkit
|
|
@@ -440,8 +437,7 @@ class McpToolkit(BaseToolkit):
|
|
|
440
437
|
|
|
441
438
|
# Create the tool
|
|
442
439
|
server_tool = cls._create_single_tool(
|
|
443
|
-
|
|
444
|
-
toolkit_name=toolkit_name or server_name,
|
|
440
|
+
toolkit_name=toolkit_name,
|
|
445
441
|
available_tool=available_tool,
|
|
446
442
|
timeout=timeout,
|
|
447
443
|
client=client
|
|
@@ -450,7 +446,7 @@ class McpToolkit(BaseToolkit):
|
|
|
450
446
|
if server_tool:
|
|
451
447
|
tools.append(server_tool)
|
|
452
448
|
|
|
453
|
-
logger.info(f"Successfully created {len(tools)} MCP tools from
|
|
449
|
+
logger.info(f"Successfully created {len(tools)} MCP tools from toolkit '{toolkit_name}' using static mode")
|
|
454
450
|
|
|
455
451
|
except Exception as e:
|
|
456
452
|
logger.error(f"Error in static tool creation: {e}")
|
|
@@ -461,15 +457,15 @@ class McpToolkit(BaseToolkit):
|
|
|
461
457
|
# We don't have full connection config in static mode, so create a basic one
|
|
462
458
|
# The inspection tool will work as long as the server is accessible
|
|
463
459
|
inspection_tool = McpInspectTool(
|
|
464
|
-
name=f"{clean_string(
|
|
465
|
-
server_name=
|
|
460
|
+
name=f"{clean_string(toolkit_name, 50)}{TOOLKIT_SPLITTER}mcp_inspect",
|
|
461
|
+
server_name=toolkit_name,
|
|
466
462
|
server_url="", # Will be populated by the client if available
|
|
467
|
-
description=f"Inspect available tools, prompts, and resources from MCP
|
|
463
|
+
description=f"Inspect available tools, prompts, and resources from MCP toolkit '{toolkit_name}'"
|
|
468
464
|
)
|
|
469
465
|
tools.append(inspection_tool)
|
|
470
|
-
logger.info(f"Added MCP inspection tool for
|
|
466
|
+
logger.info(f"Added MCP inspection tool for toolkit '{toolkit_name}' (static mode)")
|
|
471
467
|
except Exception as e:
|
|
472
|
-
logger.warning(f"Failed to create inspection tool for {
|
|
468
|
+
logger.warning(f"Failed to create inspection tool for {toolkit_name}: {e}")
|
|
473
469
|
|
|
474
470
|
return tools
|
|
475
471
|
|
|
@@ -505,7 +501,6 @@ class McpToolkit(BaseToolkit):
|
|
|
505
501
|
@classmethod
|
|
506
502
|
def _create_single_tool(
|
|
507
503
|
cls,
|
|
508
|
-
server_name: str,
|
|
509
504
|
toolkit_name: str,
|
|
510
505
|
available_tool: Dict[str, Any],
|
|
511
506
|
timeout: int,
|
|
@@ -516,51 +511,50 @@ class McpToolkit(BaseToolkit):
|
|
|
516
511
|
# Store toolkit_max_length in local variable to avoid contextual access issues
|
|
517
512
|
max_length_value = cls.toolkit_max_length
|
|
518
513
|
|
|
519
|
-
# Clean
|
|
520
|
-
clean_prefix = clean_string(
|
|
514
|
+
# Clean toolkit name for prefixing
|
|
515
|
+
clean_prefix = clean_string(toolkit_name, max_length_value)
|
|
521
516
|
|
|
522
517
|
full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}{available_tool["name"]}'
|
|
523
518
|
|
|
524
519
|
return McpServerTool(
|
|
525
520
|
name=full_tool_name,
|
|
526
|
-
description=f"MCP tool '{available_tool['name']}' from
|
|
521
|
+
description=f"MCP tool '{available_tool['name']}' from toolkit '{toolkit_name}': {available_tool.get('description', '')}",
|
|
527
522
|
args_schema=McpServerTool.create_pydantic_model_from_schema(
|
|
528
523
|
available_tool.get("inputSchema", {})
|
|
529
524
|
),
|
|
530
525
|
client=client,
|
|
531
|
-
server=
|
|
526
|
+
server=toolkit_name,
|
|
532
527
|
tool_timeout_sec=timeout
|
|
533
528
|
)
|
|
534
529
|
except Exception as e:
|
|
535
|
-
logger.error(f"Failed to create MCP tool '{available_tool.get('name')}' from
|
|
530
|
+
logger.error(f"Failed to create MCP tool '{available_tool.get('name')}' from toolkit '{toolkit_name}': {e}")
|
|
536
531
|
return None
|
|
537
532
|
|
|
538
533
|
@classmethod
|
|
539
534
|
def _create_inspection_tool(
|
|
540
535
|
cls,
|
|
541
|
-
|
|
542
|
-
connection_config: McpConnectionConfig
|
|
543
|
-
toolkit_name: str
|
|
536
|
+
toolkit_name: str,
|
|
537
|
+
connection_config: McpConnectionConfig
|
|
544
538
|
) -> Optional[BaseTool]:
|
|
545
|
-
"""Create the inspection tool for the MCP
|
|
539
|
+
"""Create the inspection tool for the MCP toolkit."""
|
|
546
540
|
try:
|
|
547
541
|
# Store toolkit_max_length in local variable to avoid contextual access issues
|
|
548
542
|
max_length_value = cls.toolkit_max_length
|
|
549
543
|
|
|
550
|
-
# Clean
|
|
551
|
-
clean_prefix = clean_string(
|
|
544
|
+
# Clean toolkit name for prefixing
|
|
545
|
+
clean_prefix = clean_string(toolkit_name, max_length_value)
|
|
552
546
|
|
|
553
547
|
full_tool_name = f'{clean_prefix}{TOOLKIT_SPLITTER}mcp_inspect'
|
|
554
548
|
|
|
555
549
|
return McpInspectTool(
|
|
556
550
|
name=full_tool_name,
|
|
557
|
-
server_name=
|
|
551
|
+
server_name=toolkit_name,
|
|
558
552
|
server_url=connection_config.url,
|
|
559
553
|
server_headers=connection_config.headers,
|
|
560
|
-
description=f"Inspect available tools, prompts, and resources from MCP
|
|
554
|
+
description=f"Inspect available tools, prompts, and resources from MCP toolkit '{toolkit_name}'"
|
|
561
555
|
)
|
|
562
556
|
except Exception as e:
|
|
563
|
-
logger.error(f"Failed to create MCP inspection tool for
|
|
557
|
+
logger.error(f"Failed to create MCP inspection tool for toolkit '{toolkit_name}': {e}")
|
|
564
558
|
return None
|
|
565
559
|
|
|
566
560
|
def get_tools(self) -> List[BaseTool]:
|
|
@@ -568,31 +562,31 @@ class McpToolkit(BaseToolkit):
|
|
|
568
562
|
return self.tools
|
|
569
563
|
|
|
570
564
|
async def refresh_tools(self):
|
|
571
|
-
"""Manually refresh tools from the MCP
|
|
572
|
-
if not self.
|
|
573
|
-
logger.warning("Cannot refresh tools:
|
|
565
|
+
"""Manually refresh tools from the MCP toolkit."""
|
|
566
|
+
if not self.toolkit_name:
|
|
567
|
+
logger.warning("Cannot refresh tools: toolkit_name not set")
|
|
574
568
|
return
|
|
575
569
|
|
|
576
570
|
try:
|
|
577
571
|
from ..clients.mcp_manager import get_mcp_manager
|
|
578
572
|
manager = get_mcp_manager()
|
|
579
|
-
await manager.refresh_server(self.
|
|
580
|
-
logger.info(f"Successfully refreshed tools for
|
|
573
|
+
await manager.refresh_server(self.toolkit_name)
|
|
574
|
+
logger.info(f"Successfully refreshed tools for toolkit {self.toolkit_name}")
|
|
581
575
|
except Exception as e:
|
|
582
|
-
logger.error(f"Failed to refresh tools for
|
|
576
|
+
logger.error(f"Failed to refresh tools for toolkit {self.toolkit_name}: {e}")
|
|
583
577
|
|
|
584
578
|
async def get_server_health(self) -> Dict[str, Any]:
|
|
585
|
-
"""Get health status of the configured MCP
|
|
586
|
-
if not self.
|
|
579
|
+
"""Get health status of the configured MCP toolkit."""
|
|
580
|
+
if not self.toolkit_name:
|
|
587
581
|
return {"status": "not_configured"}
|
|
588
582
|
|
|
589
583
|
try:
|
|
590
584
|
from ..clients.mcp_manager import get_mcp_manager
|
|
591
585
|
manager = get_mcp_manager()
|
|
592
|
-
health_info = await manager.get_server_health(self.
|
|
586
|
+
health_info = await manager.get_server_health(self.toolkit_name)
|
|
593
587
|
return health_info
|
|
594
588
|
except Exception as e:
|
|
595
|
-
logger.error(f"Failed to get server health for {self.
|
|
589
|
+
logger.error(f"Failed to get server health for {self.toolkit_name}: {e}")
|
|
596
590
|
return {"status": "error", "error": str(e)}
|
|
597
591
|
|
|
598
592
|
|
|
@@ -611,14 +605,14 @@ def get_tools(tool_config: dict, alita_client, llm=None, memory_store=None) -> L
|
|
|
611
605
|
List of configured MCP tools
|
|
612
606
|
"""
|
|
613
607
|
settings = tool_config.get('settings', {})
|
|
608
|
+
toolkit_name = tool_config.get('toolkit_name')
|
|
614
609
|
|
|
615
610
|
# Extract required fields
|
|
616
|
-
server_name = settings.get('server_name')
|
|
617
611
|
url = settings.get('url')
|
|
618
612
|
headers = settings.get('headers')
|
|
619
613
|
|
|
620
|
-
if not
|
|
621
|
-
logger.error("MCP toolkit configuration missing required '
|
|
614
|
+
if not toolkit_name:
|
|
615
|
+
logger.error("MCP toolkit configuration missing required 'toolkit_name'")
|
|
622
616
|
return []
|
|
623
617
|
|
|
624
618
|
if not url:
|
|
@@ -626,16 +620,15 @@ def get_tools(tool_config: dict, alita_client, llm=None, memory_store=None) -> L
|
|
|
626
620
|
return []
|
|
627
621
|
|
|
628
622
|
return McpToolkit.get_toolkit(
|
|
629
|
-
server_name=server_name,
|
|
630
623
|
url=url,
|
|
631
624
|
headers=headers,
|
|
632
625
|
timeout=settings.get('timeout', 60),
|
|
633
|
-
discovery_mode=settings.get('discovery_mode', '
|
|
626
|
+
discovery_mode=settings.get('discovery_mode', 'dynamic'),
|
|
634
627
|
discovery_interval=settings.get('discovery_interval', 300),
|
|
635
628
|
selected_tools=settings.get('selected_tools', []),
|
|
636
629
|
enable_caching=settings.get('enable_caching', True),
|
|
637
630
|
cache_ttl=settings.get('cache_ttl', 300),
|
|
638
|
-
toolkit_name=
|
|
631
|
+
toolkit_name=toolkit_name,
|
|
639
632
|
client=alita_client
|
|
640
633
|
).get_tools()
|
|
641
634
|
|
|
@@ -653,11 +646,11 @@ async def stop_global_discovery():
|
|
|
653
646
|
await shutdown_discovery_service()
|
|
654
647
|
|
|
655
648
|
|
|
656
|
-
async def register_mcp_server_for_discovery(
|
|
649
|
+
async def register_mcp_server_for_discovery(toolkit_name: str, connection_config):
|
|
657
650
|
"""Register an MCP server for global discovery."""
|
|
658
651
|
from ..clients.mcp_discovery import get_discovery_service
|
|
659
652
|
service = get_discovery_service()
|
|
660
|
-
await service.register_server(
|
|
653
|
+
await service.register_server(toolkit_name, connection_config)
|
|
661
654
|
|
|
662
655
|
|
|
663
656
|
def get_all_discovered_servers():
|
|
@@ -128,7 +128,8 @@ def get_tools(tools_list: list, alita_client, llm, memory_store: BaseStore = Non
|
|
|
128
128
|
tools += community_tools(tools_list, alita_client, llm)
|
|
129
129
|
# Add alita tools
|
|
130
130
|
tools += alita_tools(tools_list, alita_client, llm, memory_store)
|
|
131
|
-
# Add MCP tools
|
|
131
|
+
# Add MCP tools registered via alita-mcp CLI (static registry)
|
|
132
|
+
# Note: Tools with type='mcp' are already handled in main loop above
|
|
132
133
|
tools += _mcp_tools(tools_list, alita_client)
|
|
133
134
|
|
|
134
135
|
# Sanitize tool names to meet OpenAI's function naming requirements
|
|
@@ -183,6 +184,10 @@ def _sanitize_tool_names(tools: list) -> list:
|
|
|
183
184
|
|
|
184
185
|
|
|
185
186
|
def _mcp_tools(tools_list, alita):
|
|
187
|
+
"""
|
|
188
|
+
Handle MCP tools registered via alita-mcp CLI (static registry).
|
|
189
|
+
Skips tools with type='mcp' as those are handled by dynamic discovery.
|
|
190
|
+
"""
|
|
186
191
|
try:
|
|
187
192
|
all_available_toolkits = alita.get_mcp_toolkits()
|
|
188
193
|
toolkit_lookup = {tk["name"]: tk for tk in all_available_toolkits}
|
|
@@ -190,6 +195,11 @@ def _mcp_tools(tools_list, alita):
|
|
|
190
195
|
#
|
|
191
196
|
for selected_toolkit in tools_list:
|
|
192
197
|
server_toolkit_name = selected_toolkit['type']
|
|
198
|
+
|
|
199
|
+
# Skip tools with type='mcp' - they're handled by dynamic discovery
|
|
200
|
+
if server_toolkit_name == 'mcp':
|
|
201
|
+
continue
|
|
202
|
+
|
|
193
203
|
toolkit_conf = toolkit_lookup.get(server_toolkit_name)
|
|
194
204
|
#
|
|
195
205
|
if not toolkit_conf:
|
|
@@ -65,21 +65,17 @@ class McpInspectTool(BaseTool):
|
|
|
65
65
|
def _run(self, resource_type: str = "all") -> str:
|
|
66
66
|
"""Inspect the MCP server for available resources."""
|
|
67
67
|
try:
|
|
68
|
-
#
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
future = executor.submit(self._run_async_inspection, resource_type)
|
|
75
|
-
return future.result(timeout=self.timeout)
|
|
76
|
-
else:
|
|
77
|
-
return loop.run_until_complete(self._run_async_inspection(resource_type))
|
|
68
|
+
# Always create a new event loop for sync context
|
|
69
|
+
# This avoids issues with existing event loops in threads
|
|
70
|
+
import concurrent.futures
|
|
71
|
+
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
72
|
+
future = executor.submit(self._run_in_new_loop, resource_type)
|
|
73
|
+
return future.result(timeout=self.timeout)
|
|
78
74
|
except Exception as e:
|
|
79
75
|
logger.error(f"Error inspecting MCP server '{self.server_name}': {e}")
|
|
80
76
|
return f"Error inspecting MCP server: {e}"
|
|
81
77
|
|
|
82
|
-
def
|
|
78
|
+
def _run_in_new_loop(self, resource_type: str) -> str:
|
|
83
79
|
"""Run the async inspection in a new event loop."""
|
|
84
80
|
return asyncio.run(self._inspect_server(resource_type))
|
|
85
81
|
|
|
@@ -132,7 +128,11 @@ class McpInspectTool(BaseTool):
|
|
|
132
128
|
"params": {}
|
|
133
129
|
}
|
|
134
130
|
|
|
135
|
-
headers = {
|
|
131
|
+
headers = {
|
|
132
|
+
"Content-Type": "application/json",
|
|
133
|
+
"Accept": "application/json, text/event-stream",
|
|
134
|
+
**self.server_headers
|
|
135
|
+
}
|
|
136
136
|
|
|
137
137
|
async with session.post(self.server_url, json=request, headers=headers) as response:
|
|
138
138
|
if response.status != 200:
|
|
@@ -154,7 +154,11 @@ class McpInspectTool(BaseTool):
|
|
|
154
154
|
"params": {}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
headers = {
|
|
157
|
+
headers = {
|
|
158
|
+
"Content-Type": "application/json",
|
|
159
|
+
"Accept": "application/json, text/event-stream",
|
|
160
|
+
**self.server_headers
|
|
161
|
+
}
|
|
158
162
|
|
|
159
163
|
async with session.post(self.server_url, json=request, headers=headers) as response:
|
|
160
164
|
if response.status != 200:
|
|
@@ -176,7 +180,11 @@ class McpInspectTool(BaseTool):
|
|
|
176
180
|
"params": {}
|
|
177
181
|
}
|
|
178
182
|
|
|
179
|
-
headers = {
|
|
183
|
+
headers = {
|
|
184
|
+
"Content-Type": "application/json",
|
|
185
|
+
"Accept": "application/json, text/event-stream",
|
|
186
|
+
**self.server_headers
|
|
187
|
+
}
|
|
180
188
|
|
|
181
189
|
async with session.post(self.server_url, json=request, headers=headers) as response:
|
|
182
190
|
if response.status != 200:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: alita_sdk
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.432
|
|
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,10 +103,10 @@ 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=
|
|
106
|
+
alita_sdk/runtime/toolkits/mcp.py,sha256=lh1REOY680Q3yP4DfmzFLllmJIZy1IM90NZd1CwLrDY,25730
|
|
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
|
-
alita_sdk/runtime/toolkits/tools.py,sha256=
|
|
109
|
+
alita_sdk/runtime/toolkits/tools.py,sha256=YCTjrTJuwj2V2C8ZQqXhFvUbVr7NQcUHZlCQLLvoeGA,10946
|
|
110
110
|
alita_sdk/runtime/toolkits/vectorstore.py,sha256=BGppQADa1ZiLO17fC0uCACTTEvPHlodEDYEzUcBRbAA,2901
|
|
111
111
|
alita_sdk/runtime/tools/__init__.py,sha256=Fx7iHqkzA90-KfjdcUUzMUI_7kDarjuTsSpSzOW2pN0,568
|
|
112
112
|
alita_sdk/runtime/tools/agent.py,sha256=m98QxOHwnCRTT9j18Olbb5UPS8-ZGeQaGiUyZJSyFck,3162
|
|
@@ -121,7 +121,7 @@ alita_sdk/runtime/tools/indexer_tool.py,sha256=whSLPevB4WD6dhh2JDXEivDmTvbjiMV1M
|
|
|
121
121
|
alita_sdk/runtime/tools/llm.py,sha256=iRG_wU4T01LRsjEMPZe5Uah7LiMqDc-vspwkMuQtltk,16136
|
|
122
122
|
alita_sdk/runtime/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
|
|
123
123
|
alita_sdk/runtime/tools/loop_output.py,sha256=U4hO9PCQgWlXwOq6jdmCGbegtAxGAPXObSxZQ3z38uk,8069
|
|
124
|
-
alita_sdk/runtime/tools/mcp_inspect_tool.py,sha256=
|
|
124
|
+
alita_sdk/runtime/tools/mcp_inspect_tool.py,sha256=wgnv0z9MvB-PWriGKHHpY2IMxjBkd7Cbz4kvwGp9aq8,10243
|
|
125
125
|
alita_sdk/runtime/tools/mcp_server_tool.py,sha256=y6y0j3JeUajNatpsLVJfP0JEknhlRcDRJ0PlJ3Ch8fA,6626
|
|
126
126
|
alita_sdk/runtime/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8QwB0UwpsWCYruXU,11692
|
|
127
127
|
alita_sdk/runtime/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
|
|
@@ -358,8 +358,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
|
|
|
358
358
|
alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
|
|
359
359
|
alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
|
|
360
360
|
alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
|
|
361
|
-
alita_sdk-0.3.
|
|
362
|
-
alita_sdk-0.3.
|
|
363
|
-
alita_sdk-0.3.
|
|
364
|
-
alita_sdk-0.3.
|
|
365
|
-
alita_sdk-0.3.
|
|
361
|
+
alita_sdk-0.3.432.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
362
|
+
alita_sdk-0.3.432.dist-info/METADATA,sha256=5ta9EQvl3qdFIGaqQCAQLW9VWo7PYJRHdNmffxCbdK8,19071
|
|
363
|
+
alita_sdk-0.3.432.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
364
|
+
alita_sdk-0.3.432.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
|
|
365
|
+
alita_sdk-0.3.432.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|