universal-mcp-agents 0.1.4__py3-none-any.whl → 0.1.5__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 (41) hide show
  1. universal_mcp/agents/__init__.py +19 -0
  2. universal_mcp/agents/autoagent/__init__.py +1 -1
  3. universal_mcp/agents/autoagent/__main__.py +1 -1
  4. universal_mcp/agents/autoagent/graph.py +2 -2
  5. universal_mcp/agents/autoagent/studio.py +2 -1
  6. universal_mcp/agents/base.py +25 -13
  7. universal_mcp/agents/bigtool/__init__.py +10 -8
  8. universal_mcp/agents/bigtool/__main__.py +6 -7
  9. universal_mcp/agents/bigtool/graph.py +18 -27
  10. universal_mcp/agents/bigtool/prompts.py +3 -3
  11. universal_mcp/agents/bigtool2/__init__.py +13 -5
  12. universal_mcp/agents/bigtool2/__main__.py +7 -6
  13. universal_mcp/agents/bigtool2/agent.py +2 -1
  14. universal_mcp/agents/bigtool2/graph.py +14 -16
  15. universal_mcp/agents/bigtool2/prompts.py +1 -1
  16. universal_mcp/agents/bigtoolcache/__init__.py +2 -2
  17. universal_mcp/agents/bigtoolcache/__main__.py +1 -1
  18. universal_mcp/agents/bigtoolcache/agent.py +3 -2
  19. universal_mcp/agents/bigtoolcache/graph.py +11 -10
  20. universal_mcp/agents/bigtoolcache/prompts.py +1 -2
  21. universal_mcp/agents/builder.py +43 -15
  22. universal_mcp/agents/cli.py +19 -5
  23. universal_mcp/agents/codeact/test.py +2 -1
  24. universal_mcp/agents/llm.py +7 -3
  25. universal_mcp/agents/planner/__init__.py +8 -2
  26. universal_mcp/agents/planner/__main__.py +10 -8
  27. universal_mcp/agents/planner/graph.py +6 -2
  28. universal_mcp/agents/planner/prompts.py +14 -1
  29. universal_mcp/agents/planner/state.py +0 -1
  30. universal_mcp/agents/react.py +35 -25
  31. universal_mcp/agents/shared/tool_node.py +2 -3
  32. universal_mcp/agents/simple.py +19 -3
  33. universal_mcp/agents/tools.py +0 -1
  34. universal_mcp/agents/ui_tools.py +305 -0
  35. universal_mcp/agents/utils.py +46 -36
  36. {universal_mcp_agents-0.1.4.dist-info → universal_mcp_agents-0.1.5.dist-info}/METADATA +2 -1
  37. universal_mcp_agents-0.1.5.dist-info/RECORD +52 -0
  38. universal_mcp/agents/bigtool/context.py +0 -24
  39. universal_mcp/agents/bigtool2/context.py +0 -32
  40. universal_mcp_agents-0.1.4.dist-info/RECORD +0 -53
  41. {universal_mcp_agents-0.1.4.dist-info → universal_mcp_agents-0.1.5.dist-info}/WHEEL +0 -0
@@ -8,12 +8,12 @@ from langgraph.checkpoint.base import BaseCheckpointSaver
8
8
  from langgraph.graph import END, START, StateGraph
9
9
  from langgraph.graph.message import add_messages
10
10
  from pydantic import BaseModel, Field
11
+ from universal_mcp.tools.registry import ToolRegistry
12
+ from universal_mcp.types import ToolConfig
11
13
 
12
14
  from universal_mcp.agents.base import BaseAgent
13
15
  from universal_mcp.agents.llm import load_chat_model
14
16
  from universal_mcp.agents.shared.tool_node import build_tool_node_graph
15
- from universal_mcp.tools.registry import ToolRegistry
16
- from universal_mcp.types import ToolConfig
17
17
 
18
18
 
19
19
  class Agent(BaseModel):
@@ -35,17 +35,46 @@ class BuilderState(TypedDict):
35
35
  messages: Annotated[Sequence[BaseMessage], add_messages]
36
36
 
37
37
 
38
- AGENT_BUILDER_INSTRUCTIONS = """
39
- You are an agent builder. Your goal is to create an agent that can accomplish the user's task.
40
- Your will be given a task and you need to generate an agent that can accomplish the task.
41
- The agent should have a name, role, instructions, and a model.
42
- - The name should be a short and descriptive name for the agent.
43
- - The description should be a small description of the agent. For example, research a stock and write a buy sell analysis report.
44
- - The expertise should be the expertise of the agent. For example, GTM Expert, SEO Expert, etc.
45
- - The instructions should be a detailed description of what the agent should do. This should include the input, the output, and the tool usage. The agent will be provided a set of tools, you can use that to give a more accurate response.
46
- - The model should be the model to use for the agent.
47
- - The reasoning should be a detailed explanation of why you are creating this agent with these parameters.
48
- - If the user specifies a schedule, you should also provide a cron expression for the agent to run on. The schedule should be in a proper cron expression and nothing more.
38
+ AGENT_BUILDER_INSTRUCTIONS = r"""
39
+ You are a specialized Agent Generation AI, tasked with creating intelligent, effective, and context-aware AI agents based on user requests.
40
+
41
+ When given a user's request, immediately follow this structured process:
42
+
43
+ # 1. Intent Breakdown
44
+ - Clearly identify the primary goal the user wants the agent to achieve.
45
+ - Recognize any special requirements, constraints, formatting requests, or interaction rules.
46
+ - Summarize your understanding briefly to ensure alignment with user intent.
47
+
48
+ # 2. Agent Profile Definition
49
+ - **Name (2-4 words)**: Concise, clear, and memorable name reflecting core functionality.
50
+ - **Description (1-2 sentences)**: Captures the unique value and primary benefit to users.
51
+ - **Expertise**: Precise domain-specific expertise area. Avoid vague or overly general titles.
52
+ - **Instructions**: Compose detailed, highly actionable system instructions that directly command the agent's behavior. Respond in markdown as this text will be rendered in a rich text editor. Write instructions as clear imperatives, without preamble, assuming the agent identity is already established externally.
53
+ - **Schedule**: If the user specifies a schedule, you should also provide a cron expression for the agent to run on. The schedule should be in a proper cron expression and nothing more. Do not respond with any other information or explain your reasoning for the schedule, otherwise this will cause a parsing error that is undesirable.
54
+
55
+ ## ROLE & RESPONSIBILITY
56
+ - Clearly state the agent's primary mission, e.g., "Your primary mission is...", "Your core responsibility is...".
57
+ - Outline the exact tasks it handles, specifying expected input/output clearly.
58
+
59
+ ## INTERACTION STYLE
60
+ - Define exactly how to communicate with users: tone, format, response structure.
61
+ - Include explicit commands, e.g., "Always wrap responses in \`\`\`text\`\`\` blocks.", "Never add greetings or meta-information.", "Always provide outputs in user's requested languages."
62
+
63
+ ## OUTPUT FORMATTING RULES
64
+ - Clearly specify formatting standards required by the user (e.g., JSON, plain text, markdown).
65
+ - Include explicit examples to illustrate correct formatting.
66
+
67
+ ## LIMITATIONS & CONSTRAINTS
68
+ - Explicitly define boundaries of the agent's capabilities.
69
+ - Clearly state what the agent must never do or say.
70
+ - Include exact phrases for declining requests outside scope.
71
+
72
+ ## REAL-WORLD EXAMPLES
73
+ Provide two explicit interaction examples showing:
74
+ - User's typical request.
75
+ - Final agent response demonstrating perfect compliance.
76
+
77
+ Create an agent that feels thoughtfully designed, intelligent, and professionally reliable, perfectly matched to the user's original intent.
49
78
  """
50
79
 
51
80
 
@@ -150,10 +179,9 @@ async def main():
150
179
  model="gemini/gemini-1.5-pro",
151
180
  registry=registry,
152
181
  )
153
- result = await agent.invoke(
182
+ await agent.invoke(
154
183
  "Send a daily email to manoj@agentr.dev with daily agenda of the day",
155
184
  )
156
- print(result)
157
185
 
158
186
 
159
187
  if __name__ == "__main__":
@@ -1,8 +1,11 @@
1
+ from langgraph.checkpoint.memory import MemorySaver
1
2
  from typer import Typer
2
-
3
- from universal_mcp.agents import ReactAgent
3
+ from universal_mcp.agentr.client import AgentrClient
4
+ from universal_mcp.agentr.registry import AgentrRegistry
4
5
  from universal_mcp.logger import setup_logger
5
6
 
7
+ from universal_mcp.agents import get_agent
8
+
6
9
  app = Typer()
7
10
 
8
11
 
@@ -13,13 +16,24 @@ app = Typer()
13
16
  mcp client run --config client_config.json
14
17
  """,
15
18
  )
16
- def run():
19
+ def run(name: str = "react"):
17
20
  """Run the agent CLI"""
18
21
  import asyncio
19
22
 
20
- setup_logger(log_file=None, level="WARNING")
21
23
 
22
- agent = ReactAgent("React Agent", "You are a helpful assistant", "openrouter/auto")
24
+ setup_logger(log_file=None, level="ERROR")
25
+ client = AgentrClient()
26
+ params = {
27
+ "instructions": "You are a helpful assistant",
28
+ "model": "anthropic/claude-sonnet-4-20250514",
29
+ "registry": AgentrRegistry(client=client),
30
+ "memory": MemorySaver(),
31
+ "tools": {
32
+ "google_mail": ["send_email"],
33
+ }
34
+ }
35
+ agent_cls = get_agent(name)
36
+ agent = agent_cls(name, **params)
23
37
  asyncio.run(agent.run_interactive())
24
38
 
25
39
 
@@ -1,8 +1,9 @@
1
1
  from universal_mcp.agentr import Agentr
2
+ from universal_mcp.tools.adapters import ToolFormat
3
+
2
4
  from universal_mcp.agents.codeact import create_codeact
3
5
  from universal_mcp.agents.codeact.sandbox import eval_unsafe
4
6
  from universal_mcp.agents.llm import load_chat_model
5
- from universal_mcp.tools.adapters import ToolFormat
6
7
 
7
8
  model = load_chat_model("gpt-4.1")
8
9
 
@@ -1,22 +1,26 @@
1
+ from functools import lru_cache
2
+
1
3
  from langchain_anthropic import ChatAnthropic
2
4
  from langchain_core.language_models import BaseChatModel
3
5
  from langchain_google_genai import ChatGoogleGenerativeAI
4
6
  from langchain_openai import AzureChatOpenAI
5
7
 
6
8
 
9
+ @lru_cache(maxsize=8)
7
10
  def load_chat_model(
8
- fully_specified_name: str, temperature: float = 1.0, tags: list[str] | None = None
11
+ fully_specified_name: str, temperature: float = 1.0, tags: list[str] | None = None, thinking: bool = True
9
12
  ) -> BaseChatModel:
10
13
  """Load a chat model from a fully specified name.
11
14
  Args:
12
15
  fully_specified_name (str): String in the format 'provider/model'.
13
16
  """
14
- provider, model = fully_specified_name.split("/", maxsplit=1)
17
+ fully_specified_name = fully_specified_name.replace("/", ":")
18
+ provider, model = fully_specified_name.split(":", maxsplit=1)
15
19
  if provider == "anthropic":
16
20
  return ChatAnthropic(
17
21
  model=model,
18
22
  temperature=temperature,
19
- # thinking={"type": "enabled", "budget_tokens": 2048},
23
+ thinking={"type": "enabled", "budget_tokens": 2048} if thinking else None,
20
24
  max_tokens=4096,
21
25
  tags=tags,
22
26
  stream_usage=True,
@@ -1,11 +1,12 @@
1
1
  from langgraph.checkpoint.base import BaseCheckpointSaver
2
+ from universal_mcp.tools.registry import ToolRegistry
2
3
 
3
4
  from universal_mcp.agents.base import BaseAgent
4
5
  from universal_mcp.agents.llm import load_chat_model
5
6
  from universal_mcp.agents.react import ReactAgent
6
- from universal_mcp.tools.registry import ToolRegistry
7
7
 
8
8
  from .graph import build_graph
9
+ from .prompts import DEVELOPER_PROMPT
9
10
 
10
11
 
11
12
  class PlannerAgent(BaseAgent):
@@ -24,11 +25,16 @@ class PlannerAgent(BaseAgent):
24
25
  self.llm = load_chat_model(model)
25
26
  self.executor_agent_cls = executor_agent_cls
26
27
 
28
+ def _build_system_message(self):
29
+ return DEVELOPER_PROMPT.format(
30
+ name=self.name, instructions=self.instructions
31
+ )
32
+
27
33
  async def _build_graph(self):
28
34
  return build_graph(
29
35
  self.llm,
30
36
  self.app_registry,
31
- self.instructions,
37
+ self._build_system_message(),
32
38
  self.model,
33
39
  self.executor_agent_cls,
34
40
  ).compile(checkpointer=self.memory)
@@ -1,7 +1,9 @@
1
1
  import asyncio
2
2
 
3
3
  from universal_mcp.agentr.registry import AgentrRegistry
4
+
4
5
  from universal_mcp.agents.planner import PlannerAgent
6
+ from universal_mcp.agents.utils import messages_to_list
5
7
 
6
8
 
7
9
  async def main():
@@ -9,17 +11,17 @@ async def main():
9
11
  agent = PlannerAgent(
10
12
  name="planner-agent",
11
13
  instructions="You are a helpful assistant.",
12
- model="gemini/gemini-2.5-flash",
14
+ model="azure/gpt-4o",
13
15
  registry=registry,
14
16
  )
15
- from rich.console import Console
17
+ from rich import print
16
18
 
17
- console = Console()
18
- console.print("Starting agent...", style="yellow")
19
- async for event in agent.stream(
20
- user_input="Send an email to manoj@agentr.dev'", thread_id="xyz"
21
- ):
22
- console.print(event.content, style="red")
19
+ print("Starting agent...")
20
+ result = await agent.invoke(
21
+ user_input="Send an email to manoj@agentr.dev with the subject 'testing planner' and body 'This is a test of the planner agent.'",
22
+ thread_id="xyz",
23
+ )
24
+ print(messages_to_list(result["messages"]))
23
25
 
24
26
 
25
27
  if __name__ == "__main__":
@@ -1,6 +1,6 @@
1
1
  from typing import Any
2
2
 
3
- from langchain_core.messages import AIMessage
3
+ from langchain_core.messages import AIMessage, SystemMessage
4
4
  from langgraph.graph import END, START, StateGraph
5
5
  from loguru import logger
6
6
 
@@ -61,7 +61,11 @@ def build_graph(llm, registry, instructions, model, executor_agent_cls):
61
61
  async def _no_tools_node(state: State) -> dict[str, Any]:
62
62
  """Handles tasks that don't require tools by invoking the LLM directly."""
63
63
  logger.info("No tools required. Invoking LLM directly.")
64
- response = await llm.ainvoke(state["messages"])
64
+ messages = [
65
+ SystemMessage(content=instructions),
66
+ *state["messages"],
67
+ ]
68
+ response = await llm.ainvoke(messages)
65
69
  return {"messages": [response]}
66
70
 
67
71
  graph_builder.add_node("tool_finder", _tool_finder_node)
@@ -1 +1,14 @@
1
- # Prompts for the planner agent
1
+ # prompts.py
2
+
3
+ DEVELOPER_PROMPT = """
4
+ You are a planner agent that orchestrates tasks by selecting the right tools.
5
+
6
+ Your primary goal is to analyze a user's request and determine the most effective sequence of tools to accomplish it. You have access to a registry of applications and their corresponding tools.
7
+
8
+ Here's your process:
9
+ 1. **Assess the Task**: Understand the user's intent and what they want to achieve.
10
+ 2. **Identify Necessary Tools**: Based on the task, identify which applications and tools are required.
11
+ 3. **Orchestrate Execution**: Pass the selected tools and instructions to an executor agent to perform the task.
12
+
13
+ {instructions}
14
+ """
@@ -2,7 +2,6 @@ from typing import Annotated
2
2
 
3
3
  from langgraph.graph.message import add_messages
4
4
  from typing_extensions import TypedDict
5
-
6
5
  from universal_mcp.types import ToolConfig
7
6
 
8
7
 
@@ -1,13 +1,28 @@
1
1
  from langgraph.checkpoint.base import BaseCheckpointSaver
2
2
  from langgraph.prebuilt import create_react_agent
3
3
  from loguru import logger
4
-
5
4
  from universal_mcp.agentr.registry import AgentrRegistry
6
- from universal_mcp.agents.base import BaseAgent
7
- from universal_mcp.agents.llm import load_chat_model
8
5
  from universal_mcp.tools.registry import ToolRegistry
9
6
  from universal_mcp.types import ToolConfig, ToolFormat
10
7
 
8
+ from universal_mcp.agents.base import BaseAgent
9
+ from universal_mcp.agents.llm import load_chat_model
10
+ from universal_mcp.agents.utils import initialize_ui_tools, messages_to_list
11
+
12
+ DEVELOPER_PROMPT = """You are {name}.
13
+
14
+ You have access to various tools that can help you answer questions and complete tasks. When you need to use a tool:
15
+
16
+ 1. Think about what information you need
17
+ 2. Call the appropriate tool with the right parameters
18
+ 3. Use the tool results to provide a comprehensive answer
19
+
20
+ Always explain your reasoning and be thorough in your responses. If you need to use multiple tools to answer a question completely, do so.
21
+
22
+ Adhere to the following instructions strictly:
23
+ {instructions}
24
+ """
25
+
11
26
 
12
27
  class ReactAgent(BaseAgent):
13
28
  def __init__(
@@ -24,6 +39,7 @@ class ReactAgent(BaseAgent):
24
39
  super().__init__(name, instructions, model, memory, **kwargs)
25
40
  self.llm = load_chat_model(model)
26
41
  self.tools = tools
42
+ self.ui_tools = initialize_ui_tools()
27
43
  self.max_iterations = max_iterations
28
44
  self.registry = registry
29
45
 
@@ -38,6 +54,8 @@ class ReactAgent(BaseAgent):
38
54
  else:
39
55
  tools = []
40
56
 
57
+ tools.extend(self.ui_tools)
58
+
41
59
  logger.debug(f"Initialized ReactAgent: name={self.name}, model={self.model}")
42
60
  return create_react_agent(
43
61
  self.llm,
@@ -47,34 +65,26 @@ class ReactAgent(BaseAgent):
47
65
  )
48
66
 
49
67
  def _build_system_message(self):
50
- system_message = f"""You are {self.name}.
51
-
52
- You have access to various tools that can help you answer questions and complete tasks. When you need to use a tool:
53
-
54
- 1. Think about what information you need
55
- 2. Call the appropriate tool with the right parameters
56
- 3. Use the tool results to provide a comprehensive answer
68
+ return DEVELOPER_PROMPT.format(name=self.name, instructions=self.instructions)
57
69
 
58
- Always explain your reasoning and be thorough in your responses. If you need to use multiple tools to answer a question completely, do so.
59
-
60
- {self.instructions}
61
- """
62
- return system_message
63
-
64
-
65
- if __name__ == "__main__":
66
- import asyncio
67
70
 
71
+ async def main():
68
72
  agent = ReactAgent(
69
73
  "Universal React Agent",
70
- instructions="",
74
+ instructions="Be very concise in your answers.",
71
75
  model="azure/gpt-4o",
72
76
  tools={"google-mail": ["send_email"]},
73
77
  registry=AgentrRegistry(),
74
78
  )
75
- result = asyncio.run(
76
- agent.invoke(
77
- "Send an email with the subject 'testing react agent' to manoj@agentr.dev"
78
- )
79
+ result = await agent.invoke(
80
+ "Send an email with the subject 'testing react agent' to manoj@agentr.dev"
79
81
  )
80
- logger.info(result["messages"][-1].content)
82
+ from rich import print
83
+
84
+ print(messages_to_list(result["messages"]))
85
+
86
+
87
+ if __name__ == "__main__":
88
+ import asyncio
89
+
90
+ asyncio.run(main())
@@ -9,7 +9,6 @@ from langgraph.graph import END, StateGraph
9
9
  from langgraph.graph.message import add_messages
10
10
  from loguru import logger
11
11
  from pydantic import BaseModel, Field
12
-
13
12
  from universal_mcp.tools.registry import ToolRegistry
14
13
  from universal_mcp.types import ToolConfig
15
14
 
@@ -235,6 +234,7 @@ Task: "{task}"
235
234
 
236
235
  async def main():
237
236
  from universal_mcp.agentr.registry import AgentrRegistry
237
+
238
238
  from universal_mcp.agents.llm import load_chat_model
239
239
 
240
240
  registry = AgentrRegistry()
@@ -244,8 +244,7 @@ async def main():
244
244
  "task": "Send an email to manoj@agentr.dev",
245
245
  "messages": [HumanMessage(content="Send an email to manoj@agentr.dev")],
246
246
  }
247
- result = await graph.ainvoke(initial_state)
248
- print(result)
247
+ await graph.ainvoke(initial_state)
249
248
 
250
249
 
251
250
  if __name__ == "__main__":
@@ -8,6 +8,14 @@ from typing_extensions import TypedDict
8
8
 
9
9
  from universal_mcp.agents.base import BaseAgent
10
10
  from universal_mcp.agents.llm import load_chat_model
11
+ from universal_mcp.agents.utils import messages_to_list
12
+
13
+ DEVELOPER_PROMPT = """
14
+ You are {name}, an helpful assistant who can answer simple questions.
15
+
16
+ Adhere to the following instructions strictly:
17
+ {instructions}
18
+ """
11
19
 
12
20
 
13
21
  class State(TypedDict):
@@ -26,12 +34,15 @@ class SimpleAgent(BaseAgent):
26
34
  super().__init__(name, instructions, model, memory, **kwargs)
27
35
  self.llm = load_chat_model(model)
28
36
 
37
+ def _build_system_message(self):
38
+ return DEVELOPER_PROMPT.format(name=self.name, instructions=self.instructions)
39
+
29
40
  async def _build_graph(self):
30
41
  graph_builder = StateGraph(State)
31
42
 
32
43
  async def chatbot(state: State):
33
44
  messages = [
34
- {"role": "system", "content": self.instructions},
45
+ {"role": "system", "content": self._build_system_message()},
35
46
  *state["messages"],
36
47
  ]
37
48
  return {"messages": [await self.llm.ainvoke(messages)]}
@@ -41,7 +52,12 @@ class SimpleAgent(BaseAgent):
41
52
  graph_builder.add_edge("chatbot", END)
42
53
  return graph_builder.compile(checkpointer=self.memory)
43
54
 
55
+ async def main():
56
+ agent = SimpleAgent("Simple Agent", "Act as a 14 year old kid, reply in Gen-Z lingo", "azure/gpt-5-mini")
57
+ output = await agent.invoke("What is the capital of France?")
58
+ from rich import print
59
+ print(messages_to_list(output["messages"]))
60
+
44
61
 
45
62
  if __name__ == "__main__":
46
- agent = SimpleAgent("Simple Agent", "You are a helpful assistant", "azure/gpt-4o")
47
- asyncio.run(agent.run_interactive())
63
+ asyncio.run(main())
@@ -1,7 +1,6 @@
1
1
  import json
2
2
 
3
3
  from langchain_mcp_adapters.client import MultiServerMCPClient
4
-
5
4
  from universal_mcp.agentr.integration import AgentrIntegration
6
5
  from universal_mcp.applications.utils import app_from_slug
7
6
  from universal_mcp.tools.adapters import ToolFormat