aixtools 0.1.9__py3-none-any.whl → 0.1.11__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 aixtools might be problematic. Click here for more details.

Files changed (48) hide show
  1. aixtools/_version.py +2 -2
  2. aixtools/compliance/__init__.py +9 -0
  3. aixtools/compliance/private_data.py +5 -3
  4. aixtools/mcp/client.py +102 -1
  5. aixtools/testing/aix_test_model.py +2 -0
  6. {aixtools-0.1.9.dist-info → aixtools-0.1.11.dist-info}/METADATA +2 -1
  7. {aixtools-0.1.9.dist-info → aixtools-0.1.11.dist-info}/RECORD +10 -46
  8. aixtools-0.1.11.dist-info/top_level.txt +1 -0
  9. aixtools-0.1.9.dist-info/top_level.txt +0 -5
  10. docker/mcp-base/Dockerfile +0 -33
  11. docker/mcp-base/zscaler.crt +0 -28
  12. notebooks/example_faulty_mcp_server.ipynb +0 -74
  13. notebooks/example_mcp_server_stdio.ipynb +0 -76
  14. notebooks/example_raw_mcp_client.ipynb +0 -84
  15. notebooks/example_tool_doctor.ipynb +0 -65
  16. scripts/config.sh +0 -28
  17. scripts/lint.sh +0 -32
  18. scripts/log_view.sh +0 -18
  19. scripts/run_example_mcp_server.sh +0 -14
  20. scripts/run_faulty_mcp_server.sh +0 -13
  21. scripts/run_server.sh +0 -29
  22. scripts/test.sh +0 -30
  23. tests/__init__.py +0 -0
  24. tests/unit/__init__.py +0 -0
  25. tests/unit/a2a/__init__.py +0 -0
  26. tests/unit/a2a/google_sdk/__init__.py +0 -0
  27. tests/unit/a2a/google_sdk/pydantic_ai_adapter/__init__.py +0 -0
  28. tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_agent_executor.py +0 -188
  29. tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_storage.py +0 -156
  30. tests/unit/a2a/google_sdk/test_card.py +0 -114
  31. tests/unit/a2a/google_sdk/test_remote_agent_connection.py +0 -413
  32. tests/unit/a2a/google_sdk/test_utils.py +0 -208
  33. tests/unit/agents/__init__.py +0 -0
  34. tests/unit/agents/test_prompt.py +0 -363
  35. tests/unit/compliance/test_private_data.py +0 -329
  36. tests/unit/google/__init__.py +0 -1
  37. tests/unit/google/test_client.py +0 -233
  38. tests/unit/mcp/__init__.py +0 -0
  39. tests/unit/mcp/test_client.py +0 -242
  40. tests/unit/server/__init__.py +0 -0
  41. tests/unit/server/test_path.py +0 -225
  42. tests/unit/server/test_utils.py +0 -362
  43. tests/unit/utils/__init__.py +0 -0
  44. tests/unit/utils/test_files.py +0 -146
  45. tests/unit/vault/__init__.py +0 -0
  46. tests/unit/vault/test_vault.py +0 -246
  47. {aixtools-0.1.9.dist-info → aixtools-0.1.11.dist-info}/WHEEL +0 -0
  48. {aixtools-0.1.9.dist-info → aixtools-0.1.11.dist-info}/entry_points.txt +0 -0
aixtools/_version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '0.1.9'
32
- __version_tuple__ = version_tuple = (0, 1, 9)
31
+ __version__ = version = '0.1.11'
32
+ __version_tuple__ = version_tuple = (0, 1, 11)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -0,0 +1,9 @@
1
+ """
2
+ Compliance module for aixtools.
3
+
4
+ This module provides utilities for managing compliance-related data and operations.
5
+ """
6
+
7
+ from .private_data import PrivateData
8
+
9
+ __all__ = ["PrivateData"]
@@ -1,3 +1,5 @@
1
+ """Private data management module for aixtools compliance."""
2
+
1
3
  import json
2
4
  from pathlib import Path
3
5
 
@@ -90,7 +92,7 @@ class PrivateData:
90
92
 
91
93
  def _has_private_data_file(self) -> bool:
92
94
  """Check if the private data file exists in the workspace."""
93
- private_data_path = self.get_private_data_path() # type: ignore
95
+ private_data_path = self._get_private_data_path()
94
96
  return private_data_path.exists()
95
97
 
96
98
  def save(self) -> None:
@@ -102,7 +104,7 @@ class PrivateData:
102
104
  return
103
105
  # If there is private data, serialize this object as JSON
104
106
  private_data_path.parent.mkdir(parents=True, exist_ok=True)
105
- with open(private_data_path, "w") as f:
107
+ with open(private_data_path, "w", encoding="utf-8") as f:
106
108
  # Dump class as JSON, excluding the context
107
109
  data_dict = self.__dict__.copy()
108
110
  data_dict["ctx"] = None
@@ -118,7 +120,7 @@ class PrivateData:
118
120
  self._private_datasets = []
119
121
  self._idap_datasets = []
120
122
  return
121
- with open(private_data_path, "r") as f:
123
+ with open(private_data_path, "r", encoding="utf-8") as f:
122
124
  data = json.load(f)
123
125
  self.has_private_data = data.get("_has_private_data", False)
124
126
  self._private_datasets = data.get("_private_datasets", [])
aixtools/mcp/client.py CHANGED
@@ -1,12 +1,18 @@
1
1
  """MCP server utilities with caching and robust error handling."""
2
2
 
3
3
  import asyncio
4
- from typing import Any
4
+ from contextlib import asynccontextmanager
5
+ from datetime import timedelta
6
+ from typing import Any, AsyncGenerator
5
7
 
6
8
  import anyio
9
+ import httpx
10
+ from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
7
11
  from cachebox import TTLCache
8
12
  from mcp import types as mcp_types
13
+ from mcp.client import streamable_http
9
14
  from mcp.shared.exceptions import McpError
15
+ from mcp.shared.message import SessionMessage
10
16
  from pydantic_ai import RunContext, exceptions
11
17
  from pydantic_ai.mcp import MCPServerStreamableHTTP, ToolResult
12
18
  from pydantic_ai.toolsets.abstract import ToolsetTool
@@ -16,6 +22,7 @@ from aixtools.logging.logging_config import get_logger
16
22
 
17
23
  MCP_TOOL_CACHE_TTL = 300 # 5 minutes
18
24
  DEFAULT_MCP_CONNECTION_TIMEOUT = 30
25
+ DEFAULT_MCP_READ_TIMEOUT = float(60 * 5) # 5 minutes
19
26
  CACHE_KEY = "TOOL_LIST"
20
27
 
21
28
  logger = get_logger(__name__)
@@ -145,6 +152,23 @@ class CachedMCPServerStreamableHTTP(MCPServerStreamableHTTP):
145
152
  logger.warning("MCP %s: %s exception %s: %s", self.url, func.__name__, type(exc), exc)
146
153
  return fallback(exc)
147
154
 
155
+ @property
156
+ def _transport_client(self):
157
+ """Override base transport client with wrapper logging and suppressing exceptions"""
158
+ return patched_streamablehttp_client
159
+
160
+ @asynccontextmanager
161
+ async def client_streams(self):
162
+ """Override base client_streams with wrapper logging and suppressing exceptions"""
163
+ try:
164
+ async with super().client_streams() as streams: # pylint: disable=contextmanager-generator-missing-cleanup
165
+ try:
166
+ yield streams
167
+ except Exception as exc: # pylint: disable=broad-except
168
+ logger.error("MCP %s: client_streams; %s: %s", self.url, type(exc).__name__, exc)
169
+ except Exception as exc: # pylint: disable=broad-except
170
+ logger.error("MCP %s: client_streams: %s: %s", self.url, type(exc).__name__, exc)
171
+
148
172
  async def __aenter__(self):
149
173
  """Enter the context of the cached MCP server with complete cancellation isolation."""
150
174
  async with self._isolation_lock:
@@ -272,3 +296,80 @@ class CachedMCPServerStreamableHTTP(MCPServerStreamableHTTP):
272
296
  raise exceptions.ModelRetry(text)
273
297
 
274
298
  return content[0] if len(content) == 1 else content
299
+
300
+
301
+ class PatchedStreamableHTTPTransport(streamable_http.StreamableHTTPTransport):
302
+ """Patched StreamableHTTPTransport with exception suppression for _handle_post_request."""
303
+
304
+ async def _handle_post_request(self, ctx: streamable_http.RequestContext) -> None:
305
+ """Patched _handle_post_request with proper error handling."""
306
+ try:
307
+ await super()._handle_post_request(ctx)
308
+ except Exception as exc: # pylint: disable=broad-except
309
+ logger.error("MCP %s: _handle_post_request %s: %s", self.url, type(exc).__name__, exc)
310
+
311
+
312
+ @asynccontextmanager
313
+ async def patched_streamablehttp_client( # noqa: PLR0913, pylint: disable=too-many-arguments,too-many-positional-arguments,too-many-locals
314
+ url: str,
315
+ headers: dict[str, str] | None = None,
316
+ timeout: float | timedelta = 30,
317
+ sse_read_timeout: float | timedelta = DEFAULT_MCP_READ_TIMEOUT,
318
+ terminate_on_close: bool = True,
319
+ httpx_client_factory: streamable_http.McpHttpClientFactory = streamable_http.create_mcp_http_client,
320
+ auth: httpx.Auth | None = None,
321
+ ) -> AsyncGenerator[
322
+ tuple[
323
+ MemoryObjectReceiveStream[SessionMessage | Exception],
324
+ MemoryObjectSendStream[SessionMessage],
325
+ streamable_http.GetSessionIdCallback,
326
+ ],
327
+ None,
328
+ ]:
329
+ """Patched version of `streamablehttp_client` with exception suppression."""
330
+ try:
331
+ transport = PatchedStreamableHTTPTransport(url, headers, timeout, sse_read_timeout, auth)
332
+
333
+ read_stream_writer, read_stream = anyio.create_memory_object_stream[SessionMessage | Exception](0)
334
+ write_stream, write_stream_reader = anyio.create_memory_object_stream[SessionMessage](0)
335
+ async with anyio.create_task_group() as tg:
336
+ try:
337
+ async with httpx_client_factory(
338
+ headers=transport.request_headers,
339
+ timeout=httpx.Timeout(transport.timeout, read=transport.sse_read_timeout),
340
+ auth=transport.auth,
341
+ ) as client:
342
+ # Define callbacks that need access to tg
343
+ def start_get_stream() -> None:
344
+ tg.start_soon(transport.handle_get_stream, client, read_stream_writer)
345
+
346
+ tg.start_soon(
347
+ transport.post_writer,
348
+ client,
349
+ write_stream_reader,
350
+ read_stream_writer,
351
+ write_stream,
352
+ start_get_stream,
353
+ tg,
354
+ )
355
+
356
+ try:
357
+ yield (
358
+ read_stream,
359
+ write_stream,
360
+ transport.get_session_id,
361
+ )
362
+ except GeneratorExit:
363
+ logger.warning("patched_streamablehttp_client: GeneratorExit caught, closing streams.")
364
+ finally:
365
+ if transport.session_id and terminate_on_close:
366
+ await transport.terminate_session(client)
367
+ tg.cancel_scope.cancel()
368
+ finally:
369
+ await read_stream_writer.aclose()
370
+ await write_stream.aclose()
371
+ except Exception as exc: # pylint: disable=broad-except
372
+ if str(exc) == "Attempted to exit cancel scope in a different task than it was entered in":
373
+ logger.warning("MCP %s: patched_streamablehttp_client: enter/exit cancel scope task mismatch.", url)
374
+ else:
375
+ logger.error("MCP %s: patched_streamablehttp_client: %s: %s", url, type(exc).__name__, exc)
@@ -108,6 +108,8 @@ class AixTestModel(Model):
108
108
  messages: list[ModelMessage],
109
109
  model_settings: ModelSettings | None,
110
110
  model_request_parameters: ModelRequestParameters,
111
+ *args, # pylint: disable=unused-argument # Accept additional arguments for compatibility with pydantic-ai 1.0.9
112
+ **kwargs, # pylint: disable=unused-argument
111
113
  ) -> AsyncIterator[StreamedResponse]:
112
114
  model_response = await self._request(messages, model_settings, model_request_parameters)
113
115
  yield TestStreamedResponse(_model_name=self.model_name, _structured_response=model_response, _messages=messages)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aixtools
3
- Version: 0.1.9
3
+ Version: 0.1.11
4
4
  Summary: Tools for AI exploration and debugging
5
5
  Requires-Python: >=3.11.2
6
6
  Description-Content-Type: text/markdown
@@ -16,6 +16,7 @@ Requires-Dist: langchain-chroma>=0.2.3
16
16
  Requires-Dist: langchain-ollama>=0.3.2
17
17
  Requires-Dist: langchain-openai>=0.3.14
18
18
  Requires-Dist: mcp>=1.11.0
19
+ Requires-Dist: mypy>=1.18.2
19
20
  Requires-Dist: pandas>=2.2.3
20
21
  Requires-Dist: pydantic-ai>=0.4.10
21
22
  Requires-Dist: pylint>=3.3.7
@@ -1,5 +1,5 @@
1
1
  aixtools/__init__.py,sha256=9NGHm7LjsQmsvjTZvw6QFJexSvAU4bCoN_KBk9SCa00,260
2
- aixtools/_version.py,sha256=ib8ckvf-NNDfacXd8unW0p5cf-gl57XyQvjoEMc_pvc,704
2
+ aixtools/_version.py,sha256=0-Ruc52ECccw_8Ef0d7jMkzrb8fkobUkZLqGGvcm1ik,706
3
3
  aixtools/app.py,sha256=JzQ0nrv_bjDQokllIlGHOV0HEb-V8N6k_nGQH-TEsVU,5227
4
4
  aixtools/chainlit.md,sha256=yC37Ly57vjKyiIvK4oUvf4DYxZCwH7iocTlx7bLeGLU,761
5
5
  aixtools/context.py,sha256=I_MD40ZnvRm5WPKAKqBUAdXIf8YaurkYUUHSVVy-QvU,598
@@ -29,7 +29,8 @@ aixtools/agents/__init__.py,sha256=MAW196S2_G7uGqv-VNjvlOETRfuV44WlU1leO7SiR0A,2
29
29
  aixtools/agents/agent.py,sha256=E1zu70t53RqIbcLI_R09wUtsiYZR1bTnElCQ5PrsrKw,6127
30
30
  aixtools/agents/agent_batch.py,sha256=0Zu9yNCRPAQZPjXQ-dIUAmP1uGTVbxVt7xvnMpoJMjU,2251
31
31
  aixtools/agents/prompt.py,sha256=VCOVSnhNKsPIT347ouzwM1PH4I9UTm2cSnTh3ZpjRwk,3391
32
- aixtools/compliance/private_data.py,sha256=aYEd13eHUajs72nQxCXsa7tklXnqyurUaYuNzm8belQ,5258
32
+ aixtools/compliance/__init__.py,sha256=vnw0zEdySIJWvDAJ8DCRRaWmY_agEOz1qlpAdhmtiuo,191
33
+ aixtools/compliance/private_data.py,sha256=56VzAZ76lCq_fpfllkdm9ok8AQeEeIqrC-pqcfMjGpY,5342
33
34
  aixtools/db/__init__.py,sha256=b8vRhme3egV-aUZbAntnOaDkSXB8UT0Xy5oqQhU_z0Q,399
34
35
  aixtools/db/database.py,sha256=caWe95GlxZYlxn2ubDmR-_cQUW0ulkpR3BHunKIaOsw,3369
35
36
  aixtools/db/vector_db.py,sha256=be4JGyXj3o8VEfy9L6SO1aAoDET_zazMJkYfjlYHTYQ,4133
@@ -51,7 +52,7 @@ aixtools/logging/mcp_logger.py,sha256=d2I5l4t0d6rQH17w23FpE1IUD8Ax-mSaKfByCH86q4
51
52
  aixtools/logging/model_patch_logging.py,sha256=MY2EvR7ZSctC4hJxNMe8iACeVayUJ2V5In2GAnKdgOo,2880
52
53
  aixtools/logging/open_telemetry.py,sha256=fJjF1ou_8GyfNfbyWDQPGK6JAUrUaPwURYPHhXEtDBE,1121
53
54
  aixtools/mcp/__init__.py,sha256=tLo2KZ1Ojo-rgEEJBGtZfUw-iOoopWoHDnYQTq3IzfE,163
54
- aixtools/mcp/client.py,sha256=yUcurbNQ8bRaPc8-gK_ESpcPb26d5ckDOEDQrG_YW0c,11823
55
+ aixtools/mcp/client.py,sha256=zN5Na3Vgub2-BoJeldtFrpciBW-TrLjZUpjcQm-biqU,16661
55
56
  aixtools/mcp/example_client.py,sha256=QCFGP3NCNJMOKWjUOnFwjnbJhUSb879IA1ZYmwjRnmc,889
56
57
  aixtools/mcp/example_server.py,sha256=1SWCyrLWsAnOa81HC4QbPJo_lBVu0b3SZBWI-qDh1vQ,458
57
58
  aixtools/mcp/fast_mcp_log.py,sha256=XYOS406dVjn5YTHyGRsRvVNQ0SKlRObfrKj6EeLFjHg,1057
@@ -63,7 +64,7 @@ aixtools/server/path.py,sha256=SaIJxvmhJy3kzx5zJ6d4cKP6kKu2wFFciQkOLGTA4gg,3056
63
64
  aixtools/server/utils.py,sha256=tZWITIx6M-luV9yve4j3rPtYGSSA6zWS0JWEAySne_M,2276
64
65
  aixtools/server/workspace_privacy.py,sha256=grcj82eHSd7gFbb5f_w9nv4TWp50QyU952l0iIPoChM,2375
65
66
  aixtools/testing/__init__.py,sha256=mlmaAR2gmS4SbsYNCxnIprmFpFp-syjgVUkpUszo3mE,166
66
- aixtools/testing/aix_test_model.py,sha256=dlI3sdyvmu4fUs_K4-oazs_a7cE6V-gnI6RQ0_fPVxg,5925
67
+ aixtools/testing/aix_test_model.py,sha256=KDSPwvOOzBVFym14hkXw7BWSLqkFH9nu5OVdfNZoUeQ,6099
67
68
  aixtools/testing/mock_tool.py,sha256=4I0LxxSkLhGIKM2YxCP3cnYI8IYJjdKhfwGZ3dioXsM,2465
68
69
  aixtools/testing/model_patch_cache.py,sha256=238gKC_gSpR3BkeejhetObOkpOR1l2Iz3A6B_eUTRNc,10158
69
70
  aixtools/tools/doctor/__init__.py,sha256=FPwYzC1eJyw8IH0-BP0wgxSprLy6Y_4yXCek7496f2k,64
@@ -80,45 +81,8 @@ aixtools/utils/chainlit/cl_agent_show.py,sha256=vaRuowp4BRvhxEr5hw0zHEJ7iaSF_5bo
80
81
  aixtools/utils/chainlit/cl_utils.py,sha256=fxaxdkcZg6uHdM8uztxdPowg3a2f7VR7B26VPY4t-3c,5738
81
82
  aixtools/vault/__init__.py,sha256=fsr_NuX3GZ9WZ7dGfe0gp_5-z3URxAfwVRXw7Xyc0dU,141
82
83
  aixtools/vault/vault.py,sha256=9dZLWdZQk9qN_Q9Djkofw9LUKnJqnrX5H0fGusVLBhA,6037
83
- docker/mcp-base/Dockerfile,sha256=uislVoTEgRF--AAiyX24sBxlDdfA1ZU5rDM94XYFqvI,1388
84
- docker/mcp-base/zscaler.crt,sha256=fCUNiOfJlWTA7R4zV1Xyb-XC1_nMHPoYTFGvBj1oz6s,1732
85
- notebooks/example_faulty_mcp_server.ipynb,sha256=b2Cy3GXfj-gOBZ7SoUzj25F1rxp5u-32EWPHWQ-sxn8,1729
86
- notebooks/example_mcp_server_stdio.ipynb,sha256=ya4dRKNFU2vQxob-uIhKHGAzINXGQ6MehgKVmSCpHLk,1634
87
- notebooks/example_raw_mcp_client.ipynb,sha256=uchaG-LuuwEpE2oIkmhZ2s1EDb19AgT1fUv2Jxtjgu8,1795
88
- notebooks/example_tool_doctor.ipynb,sha256=bWTlPNI1ZQStwMfr-KSkTGYckJuJmRG_e112Gr4KZ0I,1339
89
- scripts/config.sh,sha256=xnA_S4p2w8fuIEPB4MiTWZdyIlCh5m4XuHY_fhE68kg,820
90
- scripts/lint.sh,sha256=YmPcjfFVe2s-xSaddgSxOsSm9dmHnsmbiLZnuaPgXmY,744
91
- scripts/log_view.sh,sha256=bp8oXFRRbbHpyvHAN85wfDHTVK7vMJOYsBx_-bgECQc,511
92
- scripts/run_example_mcp_server.sh,sha256=f7m7h7O_wo6-nAsYlOXVWIASCOh3Qbuu0XWizlxMhl8,355
93
- scripts/run_faulty_mcp_server.sh,sha256=u_-8NbPDnJQt6IinNSjh8tc2ed-_MjGyipJXrUXaGR8,291
94
- scripts/run_server.sh,sha256=5iiB9bB5M2MuOgxVQqu7Oa_tBVtJpt0uB4z9uLu2J50,720
95
- scripts/test.sh,sha256=KxXWkVqctFRNP8hItJr8K27nDHEkfwNWb1UFhpBQDOk,865
96
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
97
- tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
- tests/unit/a2a/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
99
- tests/unit/a2a/google_sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
100
- tests/unit/a2a/google_sdk/test_card.py,sha256=g8OUIX9BCtApM9y8l_nL1Q7sm3yezxu5yBxrpy76mo4,4359
101
- tests/unit/a2a/google_sdk/test_remote_agent_connection.py,sha256=nIY8eg32w96BAddaQ25mT-lr0ozPb6UrG-_Vpqx5RMY,17492
102
- tests/unit/a2a/google_sdk/test_utils.py,sha256=-eHmIk2GJH57W2bAdTzfRrUUb5jnd9Pf-QSXJogN3g8,8312
103
- tests/unit/a2a/google_sdk/pydantic_ai_adapter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
- tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_agent_executor.py,sha256=PcyCw0N3y-txu2KJzufzbCjs7ZfoBBCVjpZuRBqTmOw,7722
105
- tests/unit/a2a/google_sdk/pydantic_ai_adapter/test_storage.py,sha256=tb67pFfvyWSaDfKaiPDNBQfl6-o17WtCMZh3lQHrYxY,5468
106
- tests/unit/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
107
- tests/unit/agents/test_prompt.py,sha256=YWFZdH_F774hxw79gsWoTWBPVs8UjOAtJOgNXJ8N9gs,15384
108
- tests/unit/compliance/test_private_data.py,sha256=GjH7NCp54Bz1S-CmH_mUe53lb53kllOOJEm448OniRI,13693
109
- tests/unit/google/__init__.py,sha256=eRYHldBi5cFWL7oo2_t5TErI8ESmIjNvBZIcp-w8hSA,45
110
- tests/unit/google/test_client.py,sha256=fXR4Cozea7bdL2prM-1s9IqUQ9AheklQnHpN-4YM3gg,11005
111
- tests/unit/mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
- tests/unit/mcp/test_client.py,sha256=n9sZvmzNzJfozvxoHweAg4M5ZLNhEizq16IjcZHGdj0,8838
113
- tests/unit/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
- tests/unit/server/test_path.py,sha256=1QKiKLLRga9GNxmaUEt_wEZ9U14yzB-7PIhAOgB4wwo,9523
115
- tests/unit/server/test_utils.py,sha256=kvhzdgNfsJl5tqcRBWg2yTR5GPpyrFCOmEIOuHb3904,14848
116
- tests/unit/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
117
- tests/unit/utils/test_files.py,sha256=AKFmXQqXstyKd2PreE4EmQyhQYeqOmu1Sp80MwHrf_Q,5782
118
- tests/unit/vault/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
- tests/unit/vault/test_vault.py,sha256=T9V2Opxl3N5sJPftw0Q4lnVOs6urGpAmffe0cz6PUfw,10445
120
- aixtools-0.1.9.dist-info/METADATA,sha256=NyTMeH1c44cDNbXW7VKy2feT-xConc_uGIx0gSa68KM,18569
121
- aixtools-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
122
- aixtools-0.1.9.dist-info/entry_points.txt,sha256=dHoutULEZx7xXSqJrZdViSVjfInJibfLibi2nRXL3SE,56
123
- aixtools-0.1.9.dist-info/top_level.txt,sha256=ee4eF-0pqu45zCUVml0mWIhnXQgqMQper2-49BBVHLY,40
124
- aixtools-0.1.9.dist-info/RECORD,,
84
+ aixtools-0.1.11.dist-info/METADATA,sha256=4mR141qz8BCJbuQy5iTwN0yikrPEKeUb8XPInS5CC6k,18598
85
+ aixtools-0.1.11.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
86
+ aixtools-0.1.11.dist-info/entry_points.txt,sha256=dHoutULEZx7xXSqJrZdViSVjfInJibfLibi2nRXL3SE,56
87
+ aixtools-0.1.11.dist-info/top_level.txt,sha256=wBn-rw9bCtxrR4AYEYgjilNCUVmKY0LWby9Zan2PRJM,9
88
+ aixtools-0.1.11.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ aixtools
@@ -1,5 +0,0 @@
1
- aixtools
2
- docker
3
- notebooks
4
- scripts
5
- tests
@@ -1,33 +0,0 @@
1
- FROM ubuntu:22.04
2
-
3
- RUN apt-get -y update && \
4
- apt-get -y install ca-certificates curl gcc git libcap2-bin sudo
5
- RUN mv /usr/bin/sudo /usr/sbin
6
-
7
- # Add Zscaler CA certificate
8
- COPY ./zscaler.crt /usr/local/share/ca-certificates/
9
- RUN update-ca-certificates
10
- ENV SSL_CERT_FILE=/etc/ssl/certs/ca-certificates.crt
11
- ENV CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
12
-
13
- # Install `uv` Python package manager
14
- RUN bash -o pipefail -c "curl -LsSf https://astral.sh/uv/install.sh | env UV_INSTALL_DIR=/usr/local/bin sh"
15
-
16
- # Add a user matching the sandbox user so that the files and folders created by the MCP server
17
- # are writable by the user in the sandbox containers (UID=1000 must match!)
18
- ENV USER=mcp_user
19
- RUN useradd -m -s /bin/bash -u 1000 ${USER} && \
20
- echo "${USER} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USER} && chmod 0440 /etc/sudoers.d/${USER}
21
- USER ${USER}
22
-
23
- # Build argument: GITHUB_PAT (optional)
24
- # If provided, this GitHub Personal Access Token will be used to authenticate git
25
- # operations against github.com during the build. This is useful for accessing private repositories such as `aixtools`.
26
- # If not set, git will use unauthenticated access (public repositories only).
27
- ARG GITHUB_PAT
28
- RUN if [ -n "$GITHUB_PAT" ]; then \
29
- git config --global url."https://x-access-token:${GITHUB_PAT}@github.com/".insteadOf "https://github.com/"; \
30
- fi
31
-
32
- WORKDIR /app
33
- RUN mkdir data
@@ -1,28 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIE0zCCA7ugAwIBAgIJANu+mC2Jt3uTMA0GCSqGSIb3DQEBCwUAMIGhMQswCQYD
3
- VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8GA1UEBxMIU2FuIEpvc2Ux
4
- FTATBgNVBAoTDFpzY2FsZXIgSW5jLjEVMBMGA1UECxMMWnNjYWxlciBJbmMuMRgw
5
- FgYDVQQDEw9ac2NhbGVyIFJvb3QgQ0ExIjAgBgkqhkiG9w0BCQEWE3N1cHBvcnRA
6
- enNjYWxlci5jb20wHhcNMTQxMjE5MDAyNzU1WhcNNDIwNTA2MDAyNzU1WjCBoTEL
7
- MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBK
8
- b3NlMRUwEwYDVQQKEwxac2NhbGVyIEluYy4xFTATBgNVBAsTDFpzY2FsZXIgSW5j
9
- LjEYMBYGA1UEAxMPWnNjYWxlciBSb290IENBMSIwIAYJKoZIhvcNAQkBFhNzdXBw
10
- b3J0QHpzY2FsZXIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
11
- qT7STSxZRTgEFFf6doHajSc1vk5jmzmM6BWuOo044EsaTc9eVEV/HjH/1DWzZtcr
12
- fTj+ni205apMTlKBW3UYR+lyLHQ9FoZiDXYXK8poKSV5+Tm0Vls/5Kb8mkhVVqv7
13
- LgYEmvEY7HPY+i1nEGZCa46ZXCOohJ0mBEtB9JVlpDIO+nN0hUMAYYdZ1KZWCMNf
14
- 5J/aTZiShsorN2A38iSOhdd+mcRM4iNL3gsLu99XhKnRqKoHeH83lVdfu1XBeoQz
15
- z5V6gA3kbRvhDwoIlTBeMa5l4yRdJAfdpkbFzqiwSgNdhbxTHnYYorDzKfr2rEFM
16
- dsMU0DHdeAZf711+1CunuQIDAQABo4IBCjCCAQYwHQYDVR0OBBYEFLm33UrNww4M
17
- hp1d3+wcBGnFTpjfMIHWBgNVHSMEgc4wgcuAFLm33UrNww4Mhp1d3+wcBGnFTpjf
18
- oYGnpIGkMIGhMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTERMA8G
19
- A1UEBxMIU2FuIEpvc2UxFTATBgNVBAoTDFpzY2FsZXIgSW5jLjEVMBMGA1UECxMM
20
- WnNjYWxlciBJbmMuMRgwFgYDVQQDEw9ac2NhbGVyIFJvb3QgQ0ExIjAgBgkqhkiG
21
- 9w0BCQEWE3N1cHBvcnRAenNjYWxlci5jb22CCQDbvpgtibd7kzAMBgNVHRMEBTAD
22
- AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAw0NdJh8w3NsJu4KHuVZUrmZgIohnTm0j+
23
- RTmYQ9IKA/pvxAcA6K1i/LO+Bt+tCX+C0yxqB8qzuo+4vAzoY5JEBhyhBhf1uK+P
24
- /WVWFZN/+hTgpSbZgzUEnWQG2gOVd24msex+0Sr7hyr9vn6OueH+jj+vCMiAm5+u
25
- kd7lLvJsBu3AO3jGWVLyPkS3i6Gf+rwAp1OsRrv3WnbkYcFf9xjuaf4z0hRCrLN2
26
- xFNjavxrHmsH8jPHVvgc1VD0Opja0l/BRVauTrUaoW6tE+wFG5rEcPGS80jjHK4S
27
- pB5iDj2mUZH1T8lzYtuZy0ZPirxmtsk3135+CKNa2OCAhhFjE0xd
28
- -----END CERTIFICATE-----
@@ -1,74 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "id": "57d36f62",
6
- "metadata": {},
7
- "source": [
8
- "# Example \"Faulty MCP Server\"\n",
9
- "\n",
10
- "Run the server using the script:\n",
11
- "\n",
12
- "```bash\n",
13
- "./scripts/run_faulty_mcp_server.sh\n",
14
- "``` "
15
- ]
16
- },
17
- {
18
- "cell_type": "code",
19
- "execution_count": null,
20
- "id": "ebf6d915",
21
- "metadata": {},
22
- "outputs": [],
23
- "source": [
24
- "from aixtools.agents.agent import get_agent, run_agent\n",
25
- "from pydantic_ai.mcp import MCPServerStreamableHTTP"
26
- ]
27
- },
28
- {
29
- "cell_type": "code",
30
- "execution_count": null,
31
- "id": "97d1e607",
32
- "metadata": {},
33
- "outputs": [],
34
- "source": [
35
- "server = MCPServerStreamableHTTP(\"http://localhost:9999/mcp/\")\n",
36
- "agent = get_agent(mcp_servers=[server])"
37
- ]
38
- },
39
- {
40
- "cell_type": "code",
41
- "execution_count": null,
42
- "id": "fc560d25",
43
- "metadata": {},
44
- "outputs": [],
45
- "source": [
46
- "async with agent:\n",
47
- " # ret = await run_agent(agent, \"What is the add of 40123456789 and 2123456789?\", verbose=True, debug=True)\n",
48
- " # ret = await run_agent(agent, \"Invoke the always_error tool\", verbose=True, debug=True)\n",
49
- " ret = await run_agent(agent, \"Invoke the throw_404_exception tool\", verbose=True, debug=True)"
50
- ]
51
- }
52
- ],
53
- "metadata": {
54
- "kernelspec": {
55
- "display_name": ".venv",
56
- "language": "python",
57
- "name": "python3"
58
- },
59
- "language_info": {
60
- "codemirror_mode": {
61
- "name": "ipython",
62
- "version": 3
63
- },
64
- "file_extension": ".py",
65
- "mimetype": "text/x-python",
66
- "name": "python",
67
- "nbconvert_exporter": "python",
68
- "pygments_lexer": "ipython3",
69
- "version": "3.12.2"
70
- }
71
- },
72
- "nbformat": 4,
73
- "nbformat_minor": 5
74
- }
@@ -1,76 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "id": "57d36f62",
6
- "metadata": {},
7
- "source": [
8
- "# Example MCP Server STDIO"
9
- ]
10
- },
11
- {
12
- "cell_type": "code",
13
- "execution_count": null,
14
- "id": "ebf6d915",
15
- "metadata": {},
16
- "outputs": [],
17
- "source": [
18
- "from aixtools.agents.agent import get_agent, run_agent\n",
19
- "from aixtools.utils.config import PROJECT_DIR\n",
20
- "from pydantic_ai.mcp import MCPServerStdio"
21
- ]
22
- },
23
- {
24
- "cell_type": "code",
25
- "execution_count": null,
26
- "id": "97d1e607",
27
- "metadata": {},
28
- "outputs": [],
29
- "source": [
30
- "mcp_path = PROJECT_DIR /'aixtools' / 'mcp' / 'example_server.py'\n",
31
- "server = MCPServerStdio(command='fastmcp', args=['run', str(mcp_path)])\n",
32
- "agent = get_agent(mcp_servers=[server])"
33
- ]
34
- },
35
- {
36
- "cell_type": "code",
37
- "execution_count": null,
38
- "id": "fc560d25",
39
- "metadata": {},
40
- "outputs": [],
41
- "source": [
42
- "async with agent:\n",
43
- " ret = await run_agent(agent, \"What is the add of 40123456789 and 2123456789?\", verbose=True, debug=True)"
44
- ]
45
- },
46
- {
47
- "cell_type": "code",
48
- "execution_count": null,
49
- "id": "cad32e85",
50
- "metadata": {},
51
- "outputs": [],
52
- "source": []
53
- }
54
- ],
55
- "metadata": {
56
- "kernelspec": {
57
- "display_name": ".venv",
58
- "language": "python",
59
- "name": "python3"
60
- },
61
- "language_info": {
62
- "codemirror_mode": {
63
- "name": "ipython",
64
- "version": 3
65
- },
66
- "file_extension": ".py",
67
- "mimetype": "text/x-python",
68
- "name": "python",
69
- "nbconvert_exporter": "python",
70
- "pygments_lexer": "ipython3",
71
- "version": "3.12.2"
72
- }
73
- },
74
- "nbformat": 4,
75
- "nbformat_minor": 5
76
- }
@@ -1,84 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "id": "57d36f62",
6
- "metadata": {},
7
- "source": [
8
- "# Example \"Raw MCP Client\"\n",
9
- "\n",
10
- "Run the server using the script:\n",
11
- "\n",
12
- "```bash\n",
13
- "./scripts/run_faulty_mcp_server.sh\n",
14
- "``` "
15
- ]
16
- },
17
- {
18
- "cell_type": "code",
19
- "execution_count": null,
20
- "id": "cad32e85",
21
- "metadata": {},
22
- "outputs": [],
23
- "source": [
24
- "from fastmcp import Client\n",
25
- "import rich\n",
26
- "\n",
27
- "client = Client(\"http://localhost:9999/mcp/\")"
28
- ]
29
- },
30
- {
31
- "cell_type": "code",
32
- "execution_count": null,
33
- "id": "e372fc6a",
34
- "metadata": {},
35
- "outputs": [],
36
- "source": [
37
- "async with client:\n",
38
- " # Basic server interaction\n",
39
- " await client.ping()\n",
40
- " \n",
41
- " # # List available operations\n",
42
- " # tools = await client.list_tools()\n",
43
- " # rich.print(tools)\n",
44
- " # \n",
45
- " # # Execute 'add' tool\n",
46
- " # result = await client.call_tool(\"add\", {\"a\": 7, \"b\": 3})\n",
47
- " # rich.print(result)\n",
48
- "\n",
49
- " # Execute 'add' tool\n",
50
- " result = await client.call_tool(\"throw_404_exception\", {})\n",
51
- " rich.print(result)\n"
52
- ]
53
- },
54
- {
55
- "cell_type": "code",
56
- "execution_count": null,
57
- "id": "a8a743e2",
58
- "metadata": {},
59
- "outputs": [],
60
- "source": []
61
- }
62
- ],
63
- "metadata": {
64
- "kernelspec": {
65
- "display_name": ".venv",
66
- "language": "python",
67
- "name": "python3"
68
- },
69
- "language_info": {
70
- "codemirror_mode": {
71
- "name": "ipython",
72
- "version": 3
73
- },
74
- "file_extension": ".py",
75
- "mimetype": "text/x-python",
76
- "name": "python",
77
- "nbconvert_exporter": "python",
78
- "pygments_lexer": "ipython3",
79
- "version": "3.12.2"
80
- }
81
- },
82
- "nbformat": 4,
83
- "nbformat_minor": 5
84
- }