universal-mcp 0.1.24rc12__py3-none-any.whl → 0.1.24rc14__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.
Files changed (37) hide show
  1. universal_mcp/agentr/registry.py +6 -0
  2. universal_mcp/agents/__init__.py +5 -1
  3. universal_mcp/agents/autoagent/__init__.py +1 -2
  4. universal_mcp/agents/autoagent/__main__.py +8 -5
  5. universal_mcp/agents/autoagent/graph.py +4 -7
  6. universal_mcp/agents/autoagent/prompts.py +1 -1
  7. universal_mcp/agents/base.py +2 -4
  8. universal_mcp/agents/bigtool/__init__.py +54 -0
  9. universal_mcp/agents/bigtool/__main__.py +24 -0
  10. universal_mcp/agents/bigtool/context.py +24 -0
  11. universal_mcp/agents/bigtool/graph.py +166 -0
  12. universal_mcp/agents/bigtool/prompts.py +31 -0
  13. universal_mcp/agents/bigtool/state.py +27 -0
  14. universal_mcp/agents/bigtool2/__init__.py +53 -0
  15. universal_mcp/agents/bigtool2/__main__.py +24 -0
  16. universal_mcp/agents/bigtool2/agent.py +11 -0
  17. universal_mcp/agents/bigtool2/context.py +33 -0
  18. universal_mcp/agents/bigtool2/graph.py +169 -0
  19. universal_mcp/agents/bigtool2/prompts.py +12 -0
  20. universal_mcp/agents/bigtool2/state.py +27 -0
  21. universal_mcp/agents/builder.py +80 -0
  22. universal_mcp/agents/llm.py +23 -16
  23. universal_mcp/agents/planner/__init__.py +37 -0
  24. universal_mcp/agents/planner/__main__.py +24 -0
  25. universal_mcp/agents/planner/graph.py +82 -0
  26. universal_mcp/agents/planner/prompts.py +1 -0
  27. universal_mcp/agents/planner/state.py +12 -0
  28. universal_mcp/agents/shared/agent_node.py +34 -0
  29. universal_mcp/agents/shared/tool_node.py +235 -0
  30. universal_mcp/tools/registry.py +5 -0
  31. universal_mcp/types.py +5 -2
  32. {universal_mcp-0.1.24rc12.dist-info → universal_mcp-0.1.24rc14.dist-info}/METADATA +3 -1
  33. {universal_mcp-0.1.24rc12.dist-info → universal_mcp-0.1.24rc14.dist-info}/RECORD +36 -16
  34. universal_mcp/agents/auto.py +0 -575
  35. {universal_mcp-0.1.24rc12.dist-info → universal_mcp-0.1.24rc14.dist-info}/WHEEL +0 -0
  36. {universal_mcp-0.1.24rc12.dist-info → universal_mcp-0.1.24rc14.dist-info}/entry_points.txt +0 -0
  37. {universal_mcp-0.1.24rc12.dist-info → universal_mcp-0.1.24rc14.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,235 @@
1
+ # tool_node.py
2
+
3
+ import asyncio
4
+ from typing import Annotated, TypedDict
5
+
6
+ from langchain_core.language_models import BaseChatModel
7
+ from langchain_core.messages import AIMessage, AnyMessage, HumanMessage
8
+ from langgraph.graph import END, StateGraph
9
+ from langgraph.graph.message import add_messages
10
+ from loguru import logger
11
+ from pydantic import BaseModel, Field
12
+
13
+ from universal_mcp.tools.registry import ToolRegistry
14
+ from universal_mcp.types import AgentrConnection, AgentrToolConfig
15
+
16
+ # --- LangGraph Agent ---
17
+
18
+
19
+ class AgentState(TypedDict):
20
+ task: str
21
+ apps_required: bool
22
+ relevant_apps: list[str]
23
+ apps_with_tools: AgentrToolConfig
24
+ messages: Annotated[list[AnyMessage], add_messages]
25
+ reasoning: str
26
+
27
+
28
+ class ToolSelectionOutput(BaseModel):
29
+ tool_ids: list[str] = Field(description="The ids of the tools to use")
30
+
31
+
32
+ def build_tool_node_graph(llm: BaseChatModel, registry: ToolRegistry) -> StateGraph:
33
+ """Builds the LangGraph workflow."""
34
+
35
+ async def _check_if_app_needed(state: AgentState) -> AgentState:
36
+ """Checks if an external application is needed for the given task."""
37
+ task = state["task"]
38
+ prompt = f"""
39
+ Given the user's task: "{task}"
40
+ Does this task require an external application to be completed?
41
+ Your answer should be a simple "Yes" or "No", followed by a brief explanation.
42
+ For example:
43
+ Yes, an external application is needed to send emails.
44
+ No, this is a general question that can be answered directly.
45
+ """
46
+ response = await llm.ainvoke(prompt)
47
+ content = response.content.strip()
48
+ reasoning = f"Initial check for app requirement. LLM response: {content}"
49
+
50
+ if content.lower().startswith("yes"):
51
+ return {
52
+ **state,
53
+ "messages": [AIMessage(content=content)],
54
+ "apps_required": True,
55
+ "reasoning": reasoning,
56
+ }
57
+ else:
58
+ return {
59
+ **state,
60
+ "messages": [AIMessage(content=content)],
61
+ "apps_required": False,
62
+ "reasoning": reasoning,
63
+ }
64
+
65
+ async def _find_relevant_apps(state: AgentState) -> AgentState:
66
+ """Identifies relevant apps for the given task, preferring connected apps."""
67
+ task = state["task"]
68
+ all_apps = await registry.list_all_apps()
69
+ connected_apps = await registry.list_connected_apps()
70
+ prompt = """
71
+ You are an expert at identifying which applications are needed to complete specific tasks.
72
+
73
+ TASK: "{task}"
74
+
75
+ AVAILABLE APPS:
76
+ {all_apps}
77
+
78
+ CONNECTED APPS (user has already authenticated these):
79
+ {connected_apps}
80
+
81
+ INSTRUCTIONS:
82
+ 1. Analyze the task carefully to understand what functionality is required.
83
+ 2. Review the available apps and their descriptions to identify which ones could help.
84
+ 3. If multiple apps can perform the task, prefer connected apps, but you MUST include all relevant apps.
85
+ 4. Consider apps that provide complementary functionality for complex tasks.
86
+ 5. Only suggest apps that are directly relevant to the core task requirements.
87
+ 6. Your output should be a list of app IDs.
88
+
89
+ """
90
+
91
+ class AppList(BaseModel):
92
+ app_list: list[str]
93
+ reasoning: str
94
+
95
+ response = await llm.with_structured_output(AppList).ainvoke(
96
+ input=prompt.format(task=task, all_apps=all_apps, connected_apps=connected_apps)
97
+ )
98
+ app_list = response.app_list
99
+ reasoning = f"Found relevant apps: {app_list}. Reasoning: {response.reasoning}"
100
+ logger.info(f"Found relevant apps: {app_list}.")
101
+
102
+ return {
103
+ **state,
104
+ "messages": [AIMessage(content=f"Identified relevant apps: {', '.join(app_list)}")],
105
+ "relevant_apps": app_list,
106
+ "reasoning": state.get("reasoning", "") + "\n" + reasoning,
107
+ }
108
+
109
+ async def _select_tools(task: str, tools: list[dict]) -> list[str]:
110
+ """Selects the most appropriate tools from a list for a given task."""
111
+ tool_candidates = [f"{tool['name']}: {tool['description']}" for tool in tools]
112
+
113
+ SELECT_TOOL_PROMPT = f"""You are an AI assistant that helps the user perform tasks using various apps (each app has multiple tools).
114
+ You will be provided with a task and a list of tools which might be relevant for this task.
115
+
116
+ Your goal is to select the most appropriate tool for the given task.
117
+ <task>
118
+ {task}
119
+ </task>
120
+
121
+ <tool_candidates>
122
+ - {tool_candidates}
123
+ </tool_candidates>
124
+
125
+ Only return tool ids.
126
+ """
127
+
128
+ response = await llm.with_structured_output(schema=ToolSelectionOutput).ainvoke(input=SELECT_TOOL_PROMPT)
129
+
130
+ selected_tool_ids = response.tool_ids
131
+ return selected_tool_ids
132
+
133
+ async def _generate_search_query(task: str) -> str:
134
+ """Generates a concise search query from the user's task."""
135
+ prompt = f"""
136
+ You are an expert at summarizing a user's task into a concise search query for finding relevant tools.
137
+ The query should capture all the main actions or intents of the task.
138
+
139
+ For example:
140
+ Task: "Send an email to abc@the-read-example.com with the subject 'Hello'"
141
+ Query: "send email"
142
+
143
+ Task: "Create a new contact in my CRM for John Doe"
144
+ Query: "create contact"
145
+
146
+ Task: "Find the latest news about artificial intelligence"
147
+ Query: "search news"
148
+
149
+ Task: "Post a message to the #general channel in Slack and create a new issue in Jira"
150
+ Query: "send message, create issue"
151
+
152
+ Task: "{task}"
153
+ """
154
+
155
+ class SearchQuery(BaseModel):
156
+ query: str
157
+
158
+ response = await llm.with_structured_output(SearchQuery).ainvoke(input=prompt.format(task=task))
159
+ query = response.query
160
+ logger.info(f"Generated search query '{query}' for task '{task}'")
161
+ return query
162
+
163
+ async def _search_tools(state: AgentState) -> AgentState:
164
+ """Searches for and filters tools in the relevant apps."""
165
+ task = state["task"]
166
+ logger.info(f"Searching for tools in relevant apps for task: {task}")
167
+ search_query = await _generate_search_query(task)
168
+ apps_with_tools_dict = {}
169
+ reasoning_steps = []
170
+ for app_name in state["relevant_apps"]:
171
+ logger.info(f"Searching for tools in {app_name} for task: {task} with query '{search_query}'")
172
+ found_tools = await registry.search_tools(query=search_query, app_id=app_name)
173
+ selected_tools = await _select_tools(task, found_tools)
174
+ apps_with_tools_dict[app_name] = selected_tools
175
+ reasoning_steps.append(f"For '{app_name}', selected tool(s): {', '.join(selected_tools)}.")
176
+
177
+ agentr_servers = {app_name: AgentrConnection(tools=tools) for app_name, tools in apps_with_tools_dict.items()}
178
+ tool_config = AgentrToolConfig(agentrServers=agentr_servers)
179
+
180
+ return {
181
+ **state,
182
+ "apps_with_tools": tool_config,
183
+ "reasoning": state.get("reasoning", "") + "\n" + "\n".join(reasoning_steps),
184
+ }
185
+
186
+ def _handle_no_apps_found(state: AgentState) -> AgentState:
187
+ """Handles the case where no relevant apps are found."""
188
+ reasoning = "No suitable application was found among the available apps."
189
+ return {
190
+ **state,
191
+ "apps_with_tools": AgentrToolConfig(agentrServers={}),
192
+ "reasoning": state.get("reasoning", "") + "\n" + reasoning,
193
+ }
194
+
195
+ workflow = StateGraph(AgentState)
196
+
197
+ workflow.add_node("check_if_app_needed", _check_if_app_needed)
198
+ workflow.add_node("find_relevant_apps", _find_relevant_apps)
199
+ workflow.add_node("search_tools", _search_tools)
200
+ workflow.add_node("handle_no_apps_found", _handle_no_apps_found)
201
+
202
+ workflow.set_entry_point("check_if_app_needed")
203
+
204
+ workflow.add_conditional_edges(
205
+ "check_if_app_needed",
206
+ lambda state: "find_relevant_apps" if state["apps_required"] else END,
207
+ )
208
+ workflow.add_conditional_edges(
209
+ "find_relevant_apps",
210
+ lambda state: "search_tools" if state["relevant_apps"] else "handle_no_apps_found",
211
+ )
212
+
213
+ workflow.add_edge("search_tools", END)
214
+ workflow.add_edge("handle_no_apps_found", END)
215
+
216
+ return workflow.compile()
217
+
218
+
219
+ async def main():
220
+ from universal_mcp.agentr.registry import AgentrRegistry
221
+ from universal_mcp.agents.llm import load_chat_model
222
+
223
+ registry = AgentrRegistry()
224
+ llm = load_chat_model("gemini/gemini-2.5-flash")
225
+ graph = build_tool_node_graph(llm, registry)
226
+ initial_state = {
227
+ "task": "Send an email to manoj@agentr.dev",
228
+ "messages": [HumanMessage(content="Send an email to manoj@agentr.dev")],
229
+ }
230
+ result = await graph.ainvoke(initial_state)
231
+ print(result)
232
+
233
+
234
+ if __name__ == "__main__":
235
+ asyncio.run(main())
@@ -81,3 +81,8 @@ class ToolRegistry(ABC):
81
81
  async def call_tool(self, tool_name: str, tool_args: dict[str, Any]) -> dict[str, Any]:
82
82
  """Call a tool with the given name and arguments."""
83
83
  pass
84
+
85
+ @abstractmethod
86
+ async def list_connected_apps(self) -> list[str]:
87
+ """List all apps that the user has connected."""
88
+ pass
universal_mcp/types.py CHANGED
@@ -30,6 +30,9 @@ class MCPConnection(BaseModel):
30
30
  headers: dict[str, str] | None = None
31
31
 
32
32
 
33
- class ToolConfig(BaseModel):
34
- mcpServers: dict[str, MCPConnection] | None = None
33
+ class AgentrToolConfig(BaseModel):
35
34
  agentrServers: dict[str, AgentrConnection] | None = None
35
+
36
+
37
+ class ToolConfig(AgentrToolConfig):
38
+ mcpServers: dict[str, MCPConnection] | None = None
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp
3
- Version: 0.1.24rc12
3
+ Version: 0.1.24rc14
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
7
7
  License-File: LICENSE
8
8
  Requires-Python: >=3.11
9
+ Requires-Dist: agentevals>=0.0.9
9
10
  Requires-Dist: black>=25.1.0
10
11
  Requires-Dist: cookiecutter>=2.6.0
11
12
  Requires-Dist: gql>=4.0.0
@@ -23,6 +24,7 @@ Requires-Dist: langgraph>=0.5.2
23
24
  Requires-Dist: langsmith>=0.4.5
24
25
  Requires-Dist: loguru>=0.7.3
25
26
  Requires-Dist: mcp>=1.10.0
27
+ Requires-Dist: openevals>=0.1.0
26
28
  Requires-Dist: posthog>=3.24.0
27
29
  Requires-Dist: pydantic-settings>=2.8.1
28
30
  Requires-Dist: pydantic>=2.11.1
@@ -5,35 +5,55 @@ universal_mcp/config.py,sha256=lOlDAgQMT7f6VymmsuCP9sYLlxGKj0hDF3hFcJ2nzS4,8135
5
5
  universal_mcp/exceptions.py,sha256=Uen8UFgLHGlSwXgRUyF-nhqTwdiBuL3okgBVRV2AgtA,2150
6
6
  universal_mcp/logger.py,sha256=VmH_83efpErLEDTJqz55Dp0dioTXfGvMBLZUx5smOLc,2116
7
7
  universal_mcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- universal_mcp/types.py,sha256=jeUEkUnwdGWo3T_qSRSF83u0fYpuydaWzdKlCYBlCQA,770
8
+ universal_mcp/types.py,sha256=zSKtth1Q9jR4_hrKZ6k9-9LYeM9zzPAvY3KJ6kYqFCM,814
9
9
  universal_mcp/agentr/README.md,sha256=t15pVgkCwZM5wzgLgrf0Zv6hVL7dPmKXvAeTf8CiXPQ,6641
10
10
  universal_mcp/agentr/__init__.py,sha256=fv1ZnOCduIUiJ9oN4e6Ya_hA2oWQvcEuDU3Ek1vEufI,180
11
11
  universal_mcp/agentr/client.py,sha256=TQgwrNc7dEMXuprELf0Q-fdYdrH92Ppd7PUDZoD-KcY,7429
12
12
  universal_mcp/agentr/integration.py,sha256=V5GjqocqS02tRoI8MeV9PL6m-BzejwBzgJhOHo4MxAE,4212
13
- universal_mcp/agentr/registry.py,sha256=GOCltEqVegBca_r-8ljxQqEJnNAlx3MF0DAw-cAUhbQ,6595
13
+ universal_mcp/agentr/registry.py,sha256=rC9n4t55Y9a6NLFtioYOECRp6l2YxlOYc1Pmvdqh2GE,6927
14
14
  universal_mcp/agentr/server.py,sha256=bIPmHMiKKwnUYnxmfZVRh1thcn7Rytm_-bNiXTfANzc,2098
15
- universal_mcp/agents/__init__.py,sha256=AMBDQs3p5PePjzdoHYNoPYEsUK_PLHGNVPGxK7yrKVo,270
16
- universal_mcp/agents/auto.py,sha256=zQHtWTL0L88j9zFN44xHbGhKzYZ_TEuzHMTVc0TzTRU,25433
17
- universal_mcp/agents/base.py,sha256=9jsC6ZenGJjYobRvQm48s2ZIXDBoe6SdOCUx9CTIFgs,5292
15
+ universal_mcp/agents/__init__.py,sha256=heSawqbhwOXHV3Rn2B0VBvPhizvsRX4VBrbJCVnHCPo,553
16
+ universal_mcp/agents/base.py,sha256=zNYbzV1KY0OM-lDvLBMpdDpueKc6Wy54kbuzjFmBa5w,5170
17
+ universal_mcp/agents/builder.py,sha256=XsPmGHQxAL9Mzs-8NHnnh2Ix8-vdcNdNm-EFwgNVK3A,2993
18
18
  universal_mcp/agents/cli.py,sha256=7GdRBpu9rhZPiC2vaNQXWI7K-0yCnvdlmE0IFpvy2Gk,539
19
19
  universal_mcp/agents/hil.py,sha256=6xi0hhK5g-rhCrAMcGbjcKMReLWPC8rnFZMBOF3N_cY,3687
20
- universal_mcp/agents/llm.py,sha256=xYMUYsEvDhFn0uzq-7XQ7Rs1EpbLb4W_lbycRddMd0g,1608
20
+ universal_mcp/agents/llm.py,sha256=1R8gMh1atZuUe99jUlxA0xLb62k3vCp1yHnqENHrLB0,1590
21
21
  universal_mcp/agents/react.py,sha256=bjTq1SzNUSeCCDMrrfXsUBu_F_mGzow_jRx5KrQ-HVg,3032
22
22
  universal_mcp/agents/simple.py,sha256=JL8TFyXlA1F4zcArgKhlqVIbLWXetwM05z4MPDJgFeI,1367
23
23
  universal_mcp/agents/tools.py,sha256=7Vdw0VZYxXVAzAYSpRKWHzVl9Ll6NOnVRlc4cTXguUQ,1335
24
24
  universal_mcp/agents/utils.py,sha256=7kwFpD0Rv6JqHG-LlNCVwSu_xRX-N119mUmiBroHJL4,4109
25
- universal_mcp/agents/autoagent/__init__.py,sha256=E_vMnFz8Z120qdqaKXPNP_--4Tes4jImen7m_iZvtVo,913
26
- universal_mcp/agents/autoagent/__main__.py,sha256=cnR5VuuTgcF4bE2XdpJGXVQtA7x_c5M1d-exAff4Mvw,651
25
+ universal_mcp/agents/autoagent/__init__.py,sha256=RruAbcjyMTB-dIRkzFZYtQxrTpZetynBRYd1xD9noj8,836
26
+ universal_mcp/agents/autoagent/__main__.py,sha256=HH5D5gSw6xirrSoj_0CCmQlVq_wfp--b6hZdiHGfXD8,654
27
27
  universal_mcp/agents/autoagent/context.py,sha256=RgjW1uCslucxYJpdmi4govd-0V1_9e6Y_kjWl3FpLrE,847
28
- universal_mcp/agents/autoagent/graph.py,sha256=IWJLV3PL-0dmPvDckrtjJkgO6Zgt47kRk8Yprnn52dY,6768
29
- universal_mcp/agents/autoagent/prompts.py,sha256=ptnXyOarigq96nVW-P1ceT2WRilKvh7NPfE_Cy0NTz4,719
28
+ universal_mcp/agents/autoagent/graph.py,sha256=zQ8XDPELK5MbdMy5hy9rkJtgd71I1RdPlpbNkqvXtuM,6645
29
+ universal_mcp/agents/autoagent/prompts.py,sha256=v-EwzZ_0XPuBNd_r8aWxmKMSQlZLTVBr0o-dmTQMN1w,892
30
30
  universal_mcp/agents/autoagent/state.py,sha256=TQeGZD99okclkoCh5oz-VYIlEsC9yLQyDpnBnm7QCN8,759
31
31
  universal_mcp/agents/autoagent/studio.py,sha256=nfVRzPXwBjDORHA0wln2k3Nz-zQXNKgZMvgeqBvkdtM,644
32
32
  universal_mcp/agents/autoagent/utils.py,sha256=AFq-8scw_WlSZxDnTzxSNrOSiGYsIlqkqtQLDWf_rMU,431
33
+ universal_mcp/agents/bigtool/__init__.py,sha256=gKSEOmOE5ZsIypxu1sUibzJ8acbk83DjApxE0Adawro,1853
34
+ universal_mcp/agents/bigtool/__main__.py,sha256=_4HBqnlmdJwXOgeMITjBgaDHihED-aEgQmSXL9xcj0Y,602
35
+ universal_mcp/agents/bigtool/context.py,sha256=KM_B-rvEulrvXSBrXAJpwxGHVMW0HgiYKMnmrL2pUEQ,688
36
+ universal_mcp/agents/bigtool/graph.py,sha256=fOr0p547kjpM_CkRyyEcDxmTZ5lEKaTAR98nRCkgsks,8284
37
+ universal_mcp/agents/bigtool/prompts.py,sha256=A6El6Qw9r_D8OD4IZKuYqvrJFJZZmUhrTKlyqFPf6c0,1666
38
+ universal_mcp/agents/bigtool/state.py,sha256=TQeGZD99okclkoCh5oz-VYIlEsC9yLQyDpnBnm7QCN8,759
39
+ universal_mcp/agents/bigtool2/__init__.py,sha256=uP52BOl0z1n_ECbybf6lxVvC0PAjNMrBUcXUOibXjvA,1779
40
+ universal_mcp/agents/bigtool2/__main__.py,sha256=C4Mi8vM9kuGa_CryzIc9nL4-u73ZvSK5tOTbMDMN54I,605
41
+ universal_mcp/agents/bigtool2/agent.py,sha256=iwn2kyC-Wft40f_QHlLtg7fPpFUpwkjk7I5LJrrS4i8,434
42
+ universal_mcp/agents/bigtool2/context.py,sha256=1DMp8g4Gb6UUxVh8bcqafV2WpTGKo6GlaDN6Ey7cAbo,930
43
+ universal_mcp/agents/bigtool2/graph.py,sha256=l6LBWmBCsjO0r1TZUXAQHXvz_iqkW_9tGJSlySkcG7A,8373
44
+ universal_mcp/agents/bigtool2/prompts.py,sha256=Kn1sDrjH2xb3js_MPPu5PJHMP45unl93CdOC97Q_hzw,1652
45
+ universal_mcp/agents/bigtool2/state.py,sha256=TQeGZD99okclkoCh5oz-VYIlEsC9yLQyDpnBnm7QCN8,759
33
46
  universal_mcp/agents/codeact/__init__.py,sha256=5D_I3lI_3tWjZERRoFav_bPe9UDaJ53pDzZYtyixg3E,10097
34
47
  universal_mcp/agents/codeact/sandbox.py,sha256=lGRzhuXTHCB1qauuOI3bH1-fPTsyL6Lf9EmMIz4C2xQ,1039
35
48
  universal_mcp/agents/codeact/test.py,sha256=AI3qWszpM46hF4wzuQm6A8g_UkhGmcg9KhHtk9u14ro,497
36
49
  universal_mcp/agents/codeact/utils.py,sha256=VuMvLTxBBh3pgaJk8RWj5AK8XZFF-1gnZJ6jFLeM_CI,1690
50
+ universal_mcp/agents/planner/__init__.py,sha256=VTLVqIWkVh5SAuFoFupxByoqyNS1vCuc14mdUSr-vKE,1090
51
+ universal_mcp/agents/planner/__main__.py,sha256=nAFabo6SVZh4_4GV-SWCpnGg5GsVXgiHYpm9mhCQ6zw,685
52
+ universal_mcp/agents/planner/graph.py,sha256=Ct6cFJqXXf8pcYoVrlq-76uITemFfyX-mODBafmkjKA,3309
53
+ universal_mcp/agents/planner/prompts.py,sha256=vLViZ4BeinqUe8gXACLl04UUnH-Hie5L2qDyhCmSNe0,32
54
+ universal_mcp/agents/planner/state.py,sha256=m1QF99n4GswqoggYoYvv67pV2zW7HPkjwtfc2z783SE,291
55
+ universal_mcp/agents/shared/agent_node.py,sha256=jXJ9MwysYk16tOwqvEtXBkcQhkK_PcPLnuXANTb9Z7g,1308
56
+ universal_mcp/agents/shared/tool_node.py,sha256=Mmwiy3nUJKU1kXE1JfPdCCxtmbLoA-9pwLg4TbuacOs,8722
37
57
  universal_mcp/applications/__init__.py,sha256=HrCnGdAT7w4puw2_VulBfjOLku9D5DuMaOwAuQzu6nI,2067
38
58
  universal_mcp/applications/application.py,sha256=pGF9Rb2D6qzlaSwlcfZ-dNqPtsLkQTqL3jpsRuJ6-qE,23835
39
59
  universal_mcp/applications/sample/app.py,sha256=E0JwaWD7qytwawb_iWc1pBnJ-Te7MMtab4MxOOebLdc,8972
@@ -51,7 +71,7 @@ universal_mcp/tools/adapters.py,sha256=YJ2oqgc8JgmtsdRRtvO-PO0Q0bKqTJ4Y3J6yxlESo
51
71
  universal_mcp/tools/docstring_parser.py,sha256=efEOE-ME7G5Jbbzpn7pN2xNuyu2M5zfZ1Tqu1lRB0Gk,8392
52
72
  universal_mcp/tools/func_metadata.py,sha256=F4jd--hoZWKPBbZihVtluYKUsIdXdq4a0VWRgMl5k-Q,10838
53
73
  universal_mcp/tools/manager.py,sha256=U2-OQY4FGTDKS4IEOZTLVLcdqMC2vVghS0p_iLXX2Gc,10507
54
- universal_mcp/tools/registry.py,sha256=etluwUwf2EfiGBoqQFZ1nf2xcPWtrJn0N4Qhcg7UGCU,2440
74
+ universal_mcp/tools/registry.py,sha256=LD0J_bPsd8PRTObyvXglqTW1jfZX98m7KBdyP8Yn7wA,2585
55
75
  universal_mcp/tools/tools.py,sha256=Lk-wUO3rfhwdxaRANtC7lQr5fXi7nclf0oHzxNAb79Q,4927
56
76
  universal_mcp/utils/__init__.py,sha256=8wi4PGWu-SrFjNJ8U7fr2iFJ1ktqlDmSKj1xYd7KSDc,41
57
77
  universal_mcp/utils/common.py,sha256=3aJK3AnBkmYf-dbsFLaEu_dGuXQ0Qi2HuqYTueLVhXQ,10968
@@ -72,8 +92,8 @@ universal_mcp/utils/openapi/readme.py,sha256=R2Jp7DUXYNsXPDV6eFTkLiy7MXbSULUj1vH
72
92
  universal_mcp/utils/openapi/test_generator.py,sha256=vucBh9klWmQOUA740TFwfM9ry2nkwKWQiNRcsiZ9HbY,12229
73
93
  universal_mcp/utils/templates/README.md.j2,sha256=Mrm181YX-o_-WEfKs01Bi2RJy43rBiq2j6fTtbWgbTA,401
74
94
  universal_mcp/utils/templates/api_client.py.j2,sha256=972Im7LNUAq3yZTfwDcgivnb-b8u6_JLKWXwoIwXXXQ,908
75
- universal_mcp-0.1.24rc12.dist-info/METADATA,sha256=H7WS2ppZuLiMG0Y_IaSWFfLC2z6ce0uI-xSJ_8SqD8I,3190
76
- universal_mcp-0.1.24rc12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
77
- universal_mcp-0.1.24rc12.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
78
- universal_mcp-0.1.24rc12.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
79
- universal_mcp-0.1.24rc12.dist-info/RECORD,,
95
+ universal_mcp-0.1.24rc14.dist-info/METADATA,sha256=XNtKBwcCdqSZT8Xhqmgc4PlufG0UVh_ezWMStlWZh9c,3255
96
+ universal_mcp-0.1.24rc14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
97
+ universal_mcp-0.1.24rc14.dist-info/entry_points.txt,sha256=QlBrVKmA2jIM0q-C-3TQMNJTTWOsOFQvgedBq2rZTS8,56
98
+ universal_mcp-0.1.24rc14.dist-info/licenses/LICENSE,sha256=NweDZVPslBAZFzlgByF158b85GR0f5_tLQgq1NS48To,1063
99
+ universal_mcp-0.1.24rc14.dist-info/RECORD,,