universal-mcp 0.1.24rc21__py3-none-any.whl → 0.1.24rc23__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.
@@ -14,29 +14,30 @@ pip install universal-mcp
14
14
 
15
15
  ## Usage
16
16
 
17
- The AgentR platform is designed to seamlessly integrate a wide array of tools into your agentic applications. The primary entry point for this is the `Agentr` class, which provides a high-level interface for loading and listing tools.
17
+ The AgentR platform is designed to seamlessly integrate a wide array of tools into your agentic applications. The primary entry point for this is the `AgentrRegistry` class, which provides a high-level interface for loading and listing tools.
18
18
 
19
- ### High-Level Client (`Agentr`)
19
+ ### High-Level Client (`AgentrRegistry`)
20
20
 
21
- This is the recommended way to get started. It abstracts away the details of the registry and tool management.
21
+ This is the recommended way to get started. It abstracts away the details of the tool management.
22
22
 
23
23
  ```python
24
24
  import os
25
- from universal_mcp.agentr import Agentr
25
+ from universal_mcp.agentr import AgentrRegistry
26
26
  from universal_mcp.tools import ToolFormat
27
27
 
28
28
  # Initialize the main client
29
29
  # It reads from environment variables by default (AGENTR_API_KEY, AGENTR_BASE_URL)
30
- agentr = Agentr(
30
+ registry = AgentrRegistry(
31
31
  api_key=os.environ.get("AGENTR_API_KEY")
32
32
  )
33
33
 
34
34
  # Load specific tools from the AgentR server into the tool manager
35
- agentr.load_tools(["reddit__search_subreddits", "google-drive__list_files"])
36
-
37
- # List the tools that are now loaded and ready to be used
38
- # You can specify a format compatible with your LLM (e.g., OPENAI)
39
- tools = agentr.list_tools(format=ToolFormat.OPENAI)
35
+ # The export_tools method loads the tools and then exports them to the specified format.
36
+ tools_config = {
37
+ "reddit": ["search_subreddits"],
38
+ "google-drive": ["list_files"]
39
+ }
40
+ tools = await registry.export_tools(tools_config, format=ToolFormat.OPENAI)
40
41
  print(tools)
41
42
  ```
42
43
 
@@ -59,7 +60,7 @@ client = AgentrClient(
59
60
  )
60
61
 
61
62
  # Fetch a list of available applications from the AgentR server
62
- apps = client.list_apps()
63
+ apps = client.list_all_apps()
63
64
  print("Available Apps:", apps)
64
65
 
65
66
  # Get credentials for a specific app by its ID (e.g., 'reddit')
@@ -71,7 +72,7 @@ except NotAuthorizedError as e:
71
72
  print(e) # "Please ask the user to visit the following url to authorize..."
72
73
 
73
74
  # List all available tools globally
74
- all_tools = client.list_tools()
75
+ all_tools = client.list_all_tools()
75
76
  print("All Available Tools:", all_tools)
76
77
 
77
78
  # Example of fetching a single app and a single tool
@@ -80,14 +81,14 @@ if apps:
80
81
  app_id = apps[0]['id']
81
82
 
82
83
  # Fetch a single app's details
83
- app_details = client.get_app(app_id)
84
+ app_details = client.get_app_details(app_id)
84
85
  print(f"Fetched details for app '{app_id}':", app_details)
85
86
 
86
87
  if all_tools:
87
88
  tool_id = all_tools[0]['id']
88
89
 
89
90
  # Fetch a single tool's details
90
- tool_details = client.get_tool(tool_id)
91
+ tool_details = client.get_tool_details(tool_id)
91
92
  print(f"Fetched details for tool '{tool_id}':", tool_details)
92
93
  ```
93
94
 
@@ -134,7 +135,7 @@ registry = AgentrRegistry(client=client)
134
135
 
135
136
  async def main():
136
137
  # List all apps available on the AgentR platform
137
- available_apps = await registry.list_apps()
138
+ available_apps = await registry.list_all_apps()
138
139
  print(available_apps)
139
140
 
140
141
  if available_apps:
@@ -143,14 +144,6 @@ async def main():
143
144
  app_details = await registry.get_app_details(app_id)
144
145
  print(f"Details for {app_id}:", app_details)
145
146
 
146
- # The load_tools method is used internally by the high-level Agentr client
147
- # but can be called directly if needed.
148
- # from universal_mcp.tools import ToolManager
149
- # tool_manager = ToolManager()
150
- # registry.load_tools(["reddit_search_subreddits"], tool_manager)
151
- # print(tool_manager.list_tools())
152
-
153
-
154
147
  if __name__ == "__main__":
155
148
  asyncio.run(main())
156
149
  ```
@@ -179,27 +172,30 @@ print(tool_manager.list_tools())
179
172
 
180
173
  ## Executing Tools
181
174
 
182
- Once tools are loaded, you can execute them using the `call_tool` method on the `ToolManager` instance, which is available via `agentr.manager`.
175
+ Once tools are loaded, you can execute them using the `call_tool` method on the `AgentrRegistry` instance.
183
176
 
184
177
  ```python
185
178
  import os
186
179
  import asyncio
187
- from universal_mcp.agentr import Agentr
180
+ from universal_mcp.agentr import AgentrRegistry
181
+ from universal_mcp.tools import ToolFormat
188
182
 
189
183
  async def main():
190
- # 1. Initialize Agentr
191
- agentr = Agentr(api_key=os.environ.get("AGENTR_API_KEY"))
184
+ # 1. Initialize AgentrRegistry
185
+ registry = AgentrRegistry(api_key=os.environ.get("AGENTR_API_KEY"))
192
186
 
193
- # 2. Load the tool(s) you want to use
187
+ # 2. Load the tool(s) you want to use by exporting them
194
188
  tool_name = "reddit__search_subreddits"
195
- agentr.load_tools([tool_name])
189
+ tools_config = {"reddit": ["search_subreddits"]}
190
+ await registry.export_tools(tools_config, format=ToolFormat.OPENAI)
191
+
196
192
 
197
- # 3. Execute the tool using the tool manager
193
+ # 3. Execute the tool using the registry's call_tool method
198
194
  try:
199
195
  # Note the 'await' since call_tool is an async method
200
- result = await agentr.manager.call_tool(
201
- name=tool_name,
202
- arguments={"query": "elon musk", "limit": 5, "sort": "relevance"}
196
+ result = await registry.call_tool(
197
+ tool_name=tool_name,
198
+ tool_args={"query": "elon musk", "limit": 5, "sort": "relevance"}
203
199
  )
204
200
  print("Execution result:", result)
205
201
  except Exception as e:
@@ -207,4 +203,4 @@ async def main():
207
203
 
208
204
  if __name__ == "__main__":
209
205
  asyncio.run(main())
210
- ```
206
+ ```
@@ -183,7 +183,7 @@ class AgentrClient:
183
183
  response.raise_for_status()
184
184
  return response.json()
185
185
 
186
- def search_all_apps(self, query: str, limit: int = 2):
186
+ def search_all_apps(self, query: str, limit: int = 2, distance_threshold: float = 0.6):
187
187
  """Search for apps from the AgentR API.
188
188
 
189
189
  Args:
@@ -193,11 +193,13 @@ class AgentrClient:
193
193
  Returns:
194
194
  List[Dict[str, Any]]: A list of app data dictionaries.
195
195
  """
196
- response = self.client.get("/apps/", params={"search": query, "limit": limit})
196
+ response = self.client.get(
197
+ "/apps/", params={"search": query, "limit": limit, "distance_threshold": distance_threshold}
198
+ )
197
199
  response.raise_for_status()
198
200
  return response.json().get("items", [])
199
201
 
200
- def search_all_tools(self, query: str, limit: int = 2, app_id: str | None = None):
202
+ def search_all_tools(self, query: str, limit: int = 2, app_id: str | None = None, distance_threshold: float = 0.6):
201
203
  """Search for tools from the AgentR API.
202
204
 
203
205
  Args:
@@ -205,7 +207,7 @@ class AgentrClient:
205
207
  limit (int, optional): The number of tools to return. Defaults to 2.
206
208
  app_id (str, optional): The ID of the app to search tools for.
207
209
  """
208
- params = {"search": query, "limit": limit}
210
+ params = {"search": query, "limit": limit, "distance_threshold": distance_threshold}
209
211
  if app_id:
210
212
  params["app_id"] = app_id
211
213
  response = self.client.get("/tools/", params=params)
@@ -72,7 +72,7 @@ class AgentrRegistry(ToolRegistry):
72
72
  Dictionary containing app details
73
73
  """
74
74
  try:
75
- app_info = self.client.get_app_details(app_id)
75
+ app_info = self.client.get_app_details(app_id=app_id)
76
76
  return app_info
77
77
  except Exception as e:
78
78
  logger.error(f"Error getting details for app {app_id}: {e}")
@@ -82,6 +82,7 @@ class AgentrRegistry(ToolRegistry):
82
82
  self,
83
83
  query: str,
84
84
  limit: int = 10,
85
+ distance_threshold: float = 0.6,
85
86
  ) -> list[dict[str, Any]]:
86
87
  """Search for apps by a query.
87
88
 
@@ -93,7 +94,7 @@ class AgentrRegistry(ToolRegistry):
93
94
  List of app dictionaries matching the query
94
95
  """
95
96
  try:
96
- apps = self.client.search_all_apps(query, limit)
97
+ apps = self.client.search_all_apps(query=query, limit=limit, distance_threshold=distance_threshold)
97
98
  return apps
98
99
  except Exception as e:
99
100
  logger.error(f"Error searching apps from AgentR: {e}")
@@ -123,6 +124,7 @@ class AgentrRegistry(ToolRegistry):
123
124
  query: str,
124
125
  limit: int = 2,
125
126
  app_id: str | None = None,
127
+ distance_threshold: float = 0.6,
126
128
  ) -> list[dict[str, Any]]:
127
129
  """Search for tools by a query.
128
130
 
@@ -134,7 +136,9 @@ class AgentrRegistry(ToolRegistry):
134
136
  List of tool dictionaries matching the query
135
137
  """
136
138
  try:
137
- tools = self.client.search_all_tools(query, limit, app_id)
139
+ tools = self.client.search_all_tools(
140
+ query=query, limit=limit, app_id=app_id, distance_threshold=distance_threshold
141
+ )
138
142
  return tools
139
143
  except Exception as e:
140
144
  logger.error(f"Error searching tools from AgentR: {e}")
@@ -230,6 +234,6 @@ class AgentrRegistry(ToolRegistry):
230
234
  except Exception as e:
231
235
  raise e
232
236
 
233
- async def list_connected_apps(self) -> list[str]:
237
+ async def list_connected_apps(self) -> list[dict[str, Any]]:
234
238
  """List all apps that the user has connected."""
235
239
  return self.client.list_my_connections()
@@ -11,6 +11,8 @@ from loguru import logger
11
11
 
12
12
  from universal_mcp.integrations.integration import Integration
13
13
 
14
+ DEFAULT_API_TIMEOUT = 30 # seconds
15
+
14
16
 
15
17
  class BaseApplication(ABC):
16
18
  """Defines the foundational structure for applications in Universal MCP.
@@ -90,7 +92,7 @@ class APIApplication(BaseApplication):
90
92
  BaseApplication.
91
93
  """
92
94
  super().__init__(name, **kwargs)
93
- self.default_timeout: int = 180
95
+ self.default_timeout: int = DEFAULT_API_TIMEOUT
94
96
  self.integration = integration
95
97
  logger.debug(f"Initializing APIApplication '{name}' with integration: {integration}")
96
98
  self._client: httpx.Client | None = client
@@ -452,6 +454,7 @@ class GraphQLApplication(BaseApplication):
452
454
  super().__init__(name, **kwargs)
453
455
  self.base_url = base_url
454
456
  self.integration = integration
457
+ self.default_timeout: float = DEFAULT_API_TIMEOUT
455
458
  logger.debug(f"Initializing Application '{name}' with kwargs: {kwargs}")
456
459
  self._client: GraphQLClient | None = client
457
460
 
@@ -104,6 +104,6 @@ class LocalRegistry(ToolRegistry):
104
104
  result = await tool.run(tool_args)
105
105
  return self._handle_file_output(result)
106
106
 
107
- async def list_connected_apps(self) -> list[str]:
107
+ async def list_connected_apps(self) -> list[dict[str, Any]]:
108
108
  """Not implemented for LocalRegistry."""
109
109
  raise NotImplementedError("LocalRegistry does not support listing connected apps.")
@@ -32,7 +32,7 @@ class ToolRegistry(ABC):
32
32
  pass
33
33
 
34
34
  @abstractmethod
35
- async def search_apps(self, query: str, limit: int = 2) -> list[dict[str, Any]]:
35
+ async def search_apps(self, query: str, limit: int = 2, distance_threshold: float = 0.6) -> list[dict[str, Any]]:
36
36
  """Search for apps by a query."""
37
37
  pass
38
38
 
@@ -42,7 +42,9 @@ class ToolRegistry(ABC):
42
42
  pass
43
43
 
44
44
  @abstractmethod
45
- async def search_tools(self, query: str, limit: int = 2, app_id: str | None = None) -> list[dict[str, Any]]:
45
+ async def search_tools(
46
+ self, query: str, limit: int = 2, app_id: str | None = None, distance_threshold: float = 0.6
47
+ ) -> list[dict[str, Any]]:
46
48
  """Search for tools by a query, optionally filtered by an app."""
47
49
  pass
48
50
 
@@ -57,7 +59,7 @@ class ToolRegistry(ABC):
57
59
  pass
58
60
 
59
61
  @abstractmethod
60
- async def list_connected_apps(self) -> list[str]:
62
+ async def list_connected_apps(self) -> list[dict[str, Any]]:
61
63
  """List all apps that the user has connected."""
62
64
  pass
63
65
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp
3
- Version: 0.1.24rc21
3
+ Version: 0.1.24rc23
4
4
  Summary: Universal MCP acts as a middle ware for your API applications. It can store your credentials, authorize, enable disable apps on the fly and much more.
5
5
  Author-email: Manoj Bajaj <manojbajaj95@gmail.com>
6
6
  License: MIT
@@ -4,13 +4,13 @@ universal_mcp/exceptions.py,sha256=Uen8UFgLHGlSwXgRUyF-nhqTwdiBuL3okgBVRV2AgtA,2
4
4
  universal_mcp/logger.py,sha256=VmH_83efpErLEDTJqz55Dp0dioTXfGvMBLZUx5smOLc,2116
5
5
  universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  universal_mcp/types.py,sha256=DAzYyS7Zqdi38SpnhdOm08_JeN2CJiC0hDIpLLIhlSw,316
7
- universal_mcp/agentr/README.md,sha256=oF2Ou3czOCLZnRrfcko8xL7zt89j3Im3_wxwpSikz0A,6638
7
+ universal_mcp/agentr/README.md,sha256=ypsA_jD4Fgdg0wQ8bLFIFPmpFwYCCCv-29pNizJDCk4,6522
8
8
  universal_mcp/agentr/__init__.py,sha256=fv1ZnOCduIUiJ9oN4e6Ya_hA2oWQvcEuDU3Ek1vEufI,180
9
- universal_mcp/agentr/client.py,sha256=CwfmOAgWsApm0buxZPni3vW6MFgrwdddXsXmQA5UYrA,7882
9
+ universal_mcp/agentr/client.py,sha256=og1kfnOxtSTVtgYXg4AMcitX0nSX0t_r5D7A_HrcAG8,8054
10
10
  universal_mcp/agentr/integration.py,sha256=V5GjqocqS02tRoI8MeV9PL6m-BzejwBzgJhOHo4MxAE,4212
11
- universal_mcp/agentr/registry.py,sha256=VrB39dq3HMOrunPa9ruB8YbNyu1-18BtLaBUio_gCGk,8722
11
+ universal_mcp/agentr/registry.py,sha256=KBChYv7QkT9J7i-Xks9AN4vc_8NGQCI5hqMRRXdKYOc,8961
12
12
  universal_mcp/agentr/server.py,sha256=d_UaxCGTOzdOsIMiHiILgAjeZLbUASCyQkUqhd1x9wA,1911
13
- universal_mcp/applications/application.py,sha256=do45GC0jnNepZHL8US2yDNq9s0ZnE6bII4Xbw90GRTc,23727
13
+ universal_mcp/applications/application.py,sha256=Zxgrr0LVNUTnKxqnX11ScTd5IWEUPCsNYZO2URL6mbQ,23838
14
14
  universal_mcp/applications/utils.py,sha256=8Pp9lZU6IPt9z9BnuJ-vpv-NGuzryt1c4e4-ShDd2XI,1450
15
15
  universal_mcp/applications/sample/app.py,sha256=D9zPezC13xXVMlfO2A0fHgJQD_I-bnpf9UOOHveHMek,10537
16
16
  universal_mcp/client/oauth.py,sha256=O00zOUfQxINaruFU2zt-64DIR1_mAqrY8ykLQo-teJU,8679
@@ -26,9 +26,9 @@ universal_mcp/tools/__init__.py,sha256=jC8hsqfTdtn32yU57AVFUXiU3ZmUOCfCERSCaNEIH
26
26
  universal_mcp/tools/adapters.py,sha256=LmI5J6e-3TPVuyeDki7uHeZVeCES52y7TRcLpUurzNQ,4591
27
27
  universal_mcp/tools/docstring_parser.py,sha256=efEOE-ME7G5Jbbzpn7pN2xNuyu2M5zfZ1Tqu1lRB0Gk,8392
28
28
  universal_mcp/tools/func_metadata.py,sha256=F4jd--hoZWKPBbZihVtluYKUsIdXdq4a0VWRgMl5k-Q,10838
29
- universal_mcp/tools/local_registry.py,sha256=lvvpW_reF2lHSr3_s3txRU9b5Ps8rUwH-cZSApw46Ew,4236
29
+ universal_mcp/tools/local_registry.py,sha256=Gp3bXwLwJ1SBzS1ZSDXa5pHU6kapwAYx5lU41NfRKx4,4247
30
30
  universal_mcp/tools/manager.py,sha256=73x5RB5Sgew1hNqCOMmoxHZN2DYjiE7pjsytfi0Gj0g,8213
31
- universal_mcp/tools/registry.py,sha256=PTVDeVIdHDxMHlf5cNuBmvbmSTFBt_YencA6e79DH4s,3868
31
+ universal_mcp/tools/registry.py,sha256=5gXIcLy_ggCMF8RZ3gRyvqS6S9ERS6Vytp_iXdyUcr8,3959
32
32
  universal_mcp/tools/tools.py,sha256=Lk-wUO3rfhwdxaRANtC7lQr5fXi7nclf0oHzxNAb79Q,4927
33
33
  universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
34
34
  universal_mcp/utils/installation.py,sha256=PU_GfHPqzkumKk-xG4L9CkBzSmABxmchwblZkx-zY-I,7204
@@ -48,8 +48,8 @@ universal_mcp/utils/openapi/readme.py,sha256=R2Jp7DUXYNsXPDV6eFTkLiy7MXbSULUj1vH
48
48
  universal_mcp/utils/openapi/test_generator.py,sha256=vucBh9klWmQOUA740TFwfM9ry2nkwKWQiNRcsiZ9HbY,12229
49
49
  universal_mcp/utils/templates/README.md.j2,sha256=Mrm181YX-o_-WEfKs01Bi2RJy43rBiq2j6fTtbWgbTA,401
50
50
  universal_mcp/utils/templates/api_client.py.j2,sha256=DS1nczOOD8YkMexVSGpUGeyc0nYGKKTPadL_x1_if7k,900
51
- universal_mcp-0.1.24rc21.dist-info/METADATA,sha256=uMU2UHEiXuJZSI4-3DhheHEjz_IImx2YTN13upi82d8,3255
52
- universal_mcp-0.1.24rc21.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
- universal_mcp-0.1.24rc21.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
54
- universal_mcp-0.1.24rc21.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
55
- universal_mcp-0.1.24rc21.dist-info/RECORD,,
51
+ universal_mcp-0.1.24rc23.dist-info/METADATA,sha256=qZ4Rn4X_q_pg17d70czju8sIFdwho5diOPgC6XmhVeg,3255
52
+ universal_mcp-0.1.24rc23.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
53
+ universal_mcp-0.1.24rc23.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
54
+ universal_mcp-0.1.24rc23.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
55
+ universal_mcp-0.1.24rc23.dist-info/RECORD,,