maton-agent-toolkit 0.1.0__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.
@@ -0,0 +1,7 @@
1
+ """Maton Agent Toolkit - MCP-based toolkit for AI agent frameworks."""
2
+
3
+ from .configuration import Configuration, Context
4
+ from .shared.constants import VERSION
5
+
6
+ __all__ = ["Configuration", "Context", "VERSION"]
7
+ __version__ = VERSION
@@ -0,0 +1,14 @@
1
+ """Configuration types for Maton Agent Toolkit."""
2
+
3
+ from typing_extensions import TypedDict
4
+
5
+
6
+ class Context(TypedDict, total=False):
7
+ """Context for MCP connection."""
8
+ connection: str | None
9
+ mode: str | None
10
+
11
+
12
+ class Configuration(TypedDict, total=False):
13
+ """Configuration for Maton Agent Toolkit."""
14
+ context: Context | None
@@ -0,0 +1,5 @@
1
+ """Maton Agent Toolkit for CrewAI."""
2
+
3
+ from .toolkit import MatonAgentToolkit, create_maton_agent_toolkit
4
+
5
+ __all__ = ["MatonAgentToolkit", "create_maton_agent_toolkit"]
@@ -0,0 +1,134 @@
1
+ """Maton Agent Toolkit for CrewAI."""
2
+
3
+ import asyncio
4
+ from typing import List, Any, Type, Callable, Awaitable
5
+
6
+ from pydantic import BaseModel
7
+ from crewai.tools import BaseTool
8
+
9
+ from ..shared.toolkit_core import ToolkitCore
10
+ from ..shared.mcp_client import McpTool
11
+ from ..shared.schema_utils import json_schema_to_pydantic_model
12
+ from ..configuration import Configuration
13
+
14
+
15
+ class MatonTool(BaseTool):
16
+ """Tool for interacting with Maton via MCP."""
17
+
18
+ run_tool: Callable[..., Awaitable[str]]
19
+ method: str
20
+ name: str = ""
21
+ description: str = ""
22
+ args_schema: Type[BaseModel] | None = None
23
+
24
+ def _run(self, **kwargs: Any) -> str:
25
+ """Synchronous execution - wraps async call."""
26
+ loop = asyncio.get_event_loop()
27
+ if loop.is_running():
28
+ # If we're already in an async context, create a new loop
29
+ import concurrent.futures
30
+ with concurrent.futures.ThreadPoolExecutor() as pool:
31
+ future = pool.submit(
32
+ asyncio.run,
33
+ self.run_tool(self.method, kwargs)
34
+ )
35
+ return future.result()
36
+ else:
37
+ return loop.run_until_complete(
38
+ self.run_tool(self.method, kwargs)
39
+ )
40
+
41
+ async def _arun(self, **kwargs: Any) -> str:
42
+ """Async execution via MCP."""
43
+ return await self.run_tool(self.method, kwargs)
44
+
45
+
46
+ class MatonAgentToolkit(ToolkitCore[List[MatonTool]]):
47
+ """
48
+ Maton Agent Toolkit for CrewAI.
49
+
50
+ Example:
51
+ toolkit = await create_maton_agent_toolkit(
52
+ api_key='YOUR_MATON_API_KEY',
53
+ )
54
+ tools = toolkit.get_tools()
55
+ agent = Agent(role="...", tools=tools)
56
+ await toolkit.close()
57
+ """
58
+
59
+ def __init__(
60
+ self,
61
+ api_key: str | None = None,
62
+ configuration: Configuration | None = None
63
+ ):
64
+ super().__init__(api_key, configuration)
65
+
66
+ def _empty_tools(self) -> List[MatonTool]:
67
+ """Return empty list of tools."""
68
+ return []
69
+
70
+ def _convert_tools(
71
+ self,
72
+ mcp_tools: List[McpTool]
73
+ ) -> List[MatonTool]:
74
+ """Convert MCP tools to CrewAI MatonTool instances."""
75
+ tools = []
76
+ for mcp_tool in mcp_tools:
77
+ # Convert JSON Schema to Pydantic model
78
+ args_schema = json_schema_to_pydantic_model(
79
+ mcp_tool.get("inputSchema"),
80
+ model_name=f"{mcp_tool['name']}_args"
81
+ )
82
+
83
+ tools.append(MatonTool(
84
+ run_tool=self.run_tool,
85
+ method=mcp_tool["name"],
86
+ name=mcp_tool["name"],
87
+ description=mcp_tool.get("description", mcp_tool["name"]),
88
+ args_schema=args_schema,
89
+ ))
90
+ return tools
91
+
92
+ @property
93
+ def tools(self) -> List[MatonTool]:
94
+ """
95
+ The tools available in the toolkit.
96
+
97
+ .. deprecated::
98
+ Access tools via get_tools() after calling initialize().
99
+ """
100
+ return self._get_tools_with_warning()
101
+
102
+
103
+ async def create_maton_agent_toolkit(
104
+ api_key: str | None = None,
105
+ configuration: Configuration | None = None
106
+ ) -> MatonAgentToolkit:
107
+ """
108
+ Factory function to create and initialize a MatonAgentToolkit.
109
+
110
+ This is the recommended way to create a toolkit as it handles
111
+ async initialization automatically.
112
+
113
+ Example:
114
+ toolkit = await create_maton_agent_toolkit(
115
+ api_key='YOUR_MATON_API_KEY',
116
+ )
117
+ tools = toolkit.get_tools()
118
+
119
+ # Use with CrewAI agent
120
+ agent = Agent(role="Maton Agent", tools=tools)
121
+
122
+ # Clean up when done
123
+ await toolkit.close()
124
+
125
+ Args:
126
+ api_key: Maton API key. Create one at https://maton.ai
127
+ configuration: Optional configuration for context
128
+
129
+ Returns:
130
+ Initialized MatonAgentToolkit ready to use
131
+ """
132
+ toolkit = MatonAgentToolkit(api_key, configuration)
133
+ await toolkit.initialize()
134
+ return toolkit
@@ -0,0 +1,5 @@
1
+ """Maton Agent Toolkit for LangChain."""
2
+
3
+ from .toolkit import MatonAgentToolkit, create_maton_agent_toolkit
4
+
5
+ __all__ = ["MatonAgentToolkit", "create_maton_agent_toolkit"]
@@ -0,0 +1,134 @@
1
+ """Maton Agent Toolkit for LangChain."""
2
+
3
+ import asyncio
4
+ from typing import List, Any, Type, Callable, Awaitable
5
+
6
+ from pydantic import BaseModel
7
+ from langchain_core.tools import BaseTool
8
+
9
+ from ..shared.toolkit_core import ToolkitCore
10
+ from ..shared.mcp_client import McpTool
11
+ from ..shared.schema_utils import json_schema_to_pydantic_model
12
+ from ..configuration import Configuration
13
+
14
+
15
+ class MatonTool(BaseTool):
16
+ """Tool for interacting with Maton via MCP."""
17
+
18
+ run_tool: Callable[..., Awaitable[str]]
19
+ method: str
20
+ name: str = ""
21
+ description: str = ""
22
+ args_schema: Type[BaseModel] | None = None
23
+
24
+ def _run(self, **kwargs: Any) -> str:
25
+ """Synchronous execution - wraps async call."""
26
+ loop = asyncio.get_event_loop()
27
+ if loop.is_running():
28
+ # If we're already in an async context, create a new loop
29
+ import concurrent.futures
30
+ with concurrent.futures.ThreadPoolExecutor() as pool:
31
+ future = pool.submit(
32
+ asyncio.run,
33
+ self.run_tool(self.method, kwargs)
34
+ )
35
+ return future.result()
36
+ else:
37
+ return loop.run_until_complete(
38
+ self.run_tool(self.method, kwargs)
39
+ )
40
+
41
+ async def _arun(self, **kwargs: Any) -> str:
42
+ """Async execution via MCP."""
43
+ return await self.run_tool(self.method, kwargs)
44
+
45
+
46
+ class MatonAgentToolkit(ToolkitCore[List[MatonTool]]):
47
+ """
48
+ Maton Agent Toolkit for LangChain.
49
+
50
+ Example:
51
+ toolkit = await create_maton_agent_toolkit(
52
+ api_key='YOUR_MATON_API_KEY',
53
+ )
54
+ tools = toolkit.get_tools()
55
+ agent = create_react_agent(llm, tools, prompt)
56
+ await toolkit.close()
57
+ """
58
+
59
+ def __init__(
60
+ self,
61
+ api_key: str | None = None,
62
+ configuration: Configuration | None = None
63
+ ):
64
+ super().__init__(api_key, configuration)
65
+
66
+ def _empty_tools(self) -> List[MatonTool]:
67
+ """Return empty list of tools."""
68
+ return []
69
+
70
+ def _convert_tools(
71
+ self,
72
+ mcp_tools: List[McpTool]
73
+ ) -> List[MatonTool]:
74
+ """Convert MCP tools to LangChain MatonTool instances."""
75
+ tools = []
76
+ for mcp_tool in mcp_tools:
77
+ # Convert JSON Schema to Pydantic model
78
+ args_schema = json_schema_to_pydantic_model(
79
+ mcp_tool.get("inputSchema"),
80
+ model_name=f"{mcp_tool['name']}_args"
81
+ )
82
+
83
+ tools.append(MatonTool(
84
+ run_tool=self.run_tool,
85
+ method=mcp_tool["name"],
86
+ name=mcp_tool["name"],
87
+ description=mcp_tool.get("description", mcp_tool["name"]),
88
+ args_schema=args_schema,
89
+ ))
90
+ return tools
91
+
92
+ @property
93
+ def tools(self) -> List[MatonTool]:
94
+ """
95
+ The tools available in the toolkit.
96
+
97
+ .. deprecated::
98
+ Access tools via get_tools() after calling initialize().
99
+ """
100
+ return self._get_tools_with_warning()
101
+
102
+
103
+ async def create_maton_agent_toolkit(
104
+ api_key: str | None = None,
105
+ configuration: Configuration | None = None
106
+ ) -> MatonAgentToolkit:
107
+ """
108
+ Factory function to create and initialize a MatonAgentToolkit.
109
+
110
+ This is the recommended way to create a toolkit as it handles
111
+ async initialization automatically.
112
+
113
+ Example:
114
+ toolkit = await create_maton_agent_toolkit(
115
+ api_key='YOUR_MATON_API_KEY',
116
+ )
117
+ tools = toolkit.get_tools()
118
+
119
+ # Use with LangChain agent
120
+ agent = create_react_agent(llm, tools, prompt)
121
+
122
+ # Clean up when done
123
+ await toolkit.close()
124
+
125
+ Args:
126
+ api_key: Maton API key. Create one at https://maton.ai
127
+ configuration: Optional configuration for context
128
+
129
+ Returns:
130
+ Initialized MatonAgentToolkit ready to use
131
+ """
132
+ toolkit = MatonAgentToolkit(api_key, configuration)
133
+ await toolkit.initialize()
134
+ return toolkit
@@ -0,0 +1,5 @@
1
+ """Maton Agent Toolkit for OpenAI Agents SDK."""
2
+
3
+ from .toolkit import MatonAgentToolkit, create_maton_agent_toolkit
4
+
5
+ __all__ = ["MatonAgentToolkit", "create_maton_agent_toolkit"]
@@ -0,0 +1,125 @@
1
+ """Maton Agent Toolkit for OpenAI Agents SDK."""
2
+
3
+ import json
4
+ from typing import List, Any
5
+
6
+ from agents import FunctionTool
7
+ from agents.run_context import RunContextWrapper
8
+
9
+ from ..shared.toolkit_core import ToolkitCore
10
+ from ..shared.mcp_client import McpTool
11
+ from ..configuration import Configuration
12
+
13
+
14
+ class MatonAgentToolkit(ToolkitCore[List[FunctionTool]]):
15
+ """
16
+ Maton Agent Toolkit for OpenAI Agents SDK.
17
+
18
+ Example:
19
+ toolkit = await create_maton_agent_toolkit(
20
+ api_key='YOUR_MATON_API_KEY',
21
+ )
22
+ tools = toolkit.get_tools()
23
+ agent = Agent(name="Maton Agent", tools=tools)
24
+ await toolkit.close()
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ api_key: str | None = None,
30
+ configuration: Configuration | None = None
31
+ ):
32
+ super().__init__(api_key, configuration)
33
+
34
+ def _empty_tools(self) -> List[FunctionTool]:
35
+ """Return empty list of tools."""
36
+ return []
37
+
38
+ def _convert_tools(
39
+ self,
40
+ mcp_tools: List[McpTool]
41
+ ) -> List[FunctionTool]:
42
+ """Convert MCP tools to OpenAI FunctionTool instances."""
43
+ tools = []
44
+ for mcp_tool in mcp_tools:
45
+ tools.append(self._create_function_tool(mcp_tool))
46
+ return tools
47
+
48
+ def _create_function_tool(self, mcp_tool: McpTool) -> FunctionTool:
49
+ """Create a FunctionTool from an MCP tool definition."""
50
+ toolkit = self
51
+ tool_name = mcp_tool["name"]
52
+
53
+ async def on_invoke_tool(
54
+ ctx: RunContextWrapper[Any],
55
+ input_str: str
56
+ ) -> str:
57
+ args = json.loads(input_str)
58
+ return await toolkit.run_tool(tool_name, args)
59
+
60
+ # Prepare parameters schema
61
+ parameters = dict(mcp_tool.get("inputSchema", {}))
62
+ parameters["additionalProperties"] = False
63
+ parameters["type"] = "object"
64
+
65
+ # Clean up schema - remove fields not needed in OpenAI function schema
66
+ for key in ["description", "title"]:
67
+ parameters.pop(key, None)
68
+
69
+ if "properties" in parameters:
70
+ for prop in parameters["properties"].values():
71
+ for key in ["title", "default"]:
72
+ if isinstance(prop, dict):
73
+ prop.pop(key, None)
74
+
75
+ return FunctionTool(
76
+ name=tool_name,
77
+ description=mcp_tool.get("description", tool_name),
78
+ params_json_schema=parameters,
79
+ on_invoke_tool=on_invoke_tool,
80
+ strict_json_schema=False
81
+ )
82
+
83
+ @property
84
+ def tools(self) -> List[FunctionTool]:
85
+ """
86
+ The tools available in the toolkit.
87
+
88
+ .. deprecated::
89
+ Access tools via get_tools() after calling initialize().
90
+ """
91
+ return self._get_tools_with_warning()
92
+
93
+
94
+ async def create_maton_agent_toolkit(
95
+ api_key: str | None = None,
96
+ configuration: Configuration | None = None
97
+ ) -> MatonAgentToolkit:
98
+ """
99
+ Factory function to create and initialize a MatonAgentToolkit.
100
+
101
+ This is the recommended way to create a toolkit as it handles
102
+ async initialization automatically.
103
+
104
+ Example:
105
+ toolkit = await create_maton_agent_toolkit(
106
+ api_key='YOUR_MATON_API_KEY',
107
+ )
108
+ tools = toolkit.get_tools()
109
+
110
+ # Use with agent
111
+ agent = Agent(name="Maton Agent", tools=tools)
112
+
113
+ # Clean up when done
114
+ await toolkit.close()
115
+
116
+ Args:
117
+ api_key: Maton API key. Create one at https://maton.ai
118
+ configuration: Optional configuration for context
119
+
120
+ Returns:
121
+ Initialized MatonAgentToolkit ready to use
122
+ """
123
+ toolkit = MatonAgentToolkit(api_key, configuration)
124
+ await toolkit.initialize()
125
+ return toolkit
@@ -0,0 +1,21 @@
1
+ """Shared infrastructure for Maton Agent Toolkit MCP integration."""
2
+
3
+ from .constants import VERSION, MCP_SERVER_URL, TOOLKIT_HEADER, MCP_HEADER
4
+ from .async_initializer import AsyncInitializer
5
+ from .mcp_client import MatonMcpClient, McpTool, McpToolInputSchema
6
+ from .schema_utils import json_schema_to_pydantic_model, json_schema_to_pydantic_fields
7
+ from .toolkit_core import ToolkitCore
8
+
9
+ __all__ = [
10
+ "VERSION",
11
+ "MCP_SERVER_URL",
12
+ "TOOLKIT_HEADER",
13
+ "MCP_HEADER",
14
+ "AsyncInitializer",
15
+ "MatonMcpClient",
16
+ "McpTool",
17
+ "McpToolInputSchema",
18
+ "json_schema_to_pydantic_model",
19
+ "json_schema_to_pydantic_fields",
20
+ "ToolkitCore",
21
+ ]
@@ -0,0 +1,71 @@
1
+ """Async initialization utility for Maton Agent Toolkit."""
2
+
3
+ import asyncio
4
+ from typing import Callable, Awaitable
5
+
6
+
7
+ class AsyncInitializer:
8
+ """
9
+ A reusable utility for async initialization with future locking.
10
+ Ensures initialization runs only once, even if called concurrently.
11
+ """
12
+
13
+ def __init__(self) -> None:
14
+ self._initialized: bool = False
15
+ self._init_future: asyncio.Future[None] | None = None
16
+ self._lock: asyncio.Lock = asyncio.Lock()
17
+
18
+ async def initialize(
19
+ self, do_initialize: Callable[[], Awaitable[None]]
20
+ ) -> None:
21
+ """
22
+ Initialize using the provided coroutine function.
23
+
24
+ - If already initialized, returns immediately
25
+ - If initialization in progress, awaits existing future
26
+ - If initialization fails, allows retry on next call
27
+
28
+ Args:
29
+ do_initialize: Async function that performs the actual
30
+ initialization work.
31
+
32
+ Raises:
33
+ Exception: Re-raises any exception from do_initialize,
34
+ allowing retry on next call.
35
+ """
36
+ if self._initialized:
37
+ return
38
+
39
+ async with self._lock:
40
+ # Double-check after acquiring lock
41
+ if self._initialized:
42
+ return
43
+
44
+ if self._init_future is not None:
45
+ # Another coroutine is initializing, wait for it
46
+ await self._init_future
47
+ return
48
+
49
+ # Create a new future for this initialization attempt
50
+ loop = asyncio.get_running_loop()
51
+ self._init_future = loop.create_future()
52
+
53
+ try:
54
+ await do_initialize()
55
+ self._initialized = True
56
+ self._init_future.set_result(None)
57
+ except Exception as e:
58
+ # Reset future on failure to allow retry
59
+ self._init_future.set_exception(e)
60
+ self._init_future = None
61
+ raise
62
+
63
+ @property
64
+ def is_initialized(self) -> bool:
65
+ """Check if initialization has completed successfully."""
66
+ return self._initialized
67
+
68
+ def reset(self) -> None:
69
+ """Reset the initializer state. Used during close/cleanup."""
70
+ self._initialized = False
71
+ self._init_future = None
@@ -0,0 +1,6 @@
1
+ """Shared constants for Maton Agent Toolkit."""
2
+
3
+ VERSION = "0.1.0"
4
+ MCP_SERVER_URL = "https://mcp.maton.ai"
5
+ TOOLKIT_HEADER = "maton-agent-toolkit-python"
6
+ MCP_HEADER = "maton-mcp-python"