diff --git a/docker/Dockerfile b/docker/Dockerfile
index aa702f2a6..277d55751 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,6 +1,6 @@
FROM python:3.11-slim
WORKDIR /app
COPY . .
-RUN pip install flask praisonai==2.2.0 gunicorn markdown
+RUN pip install flask praisonai==2.2.1 gunicorn markdown
EXPOSE 8080
CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]
diff --git a/docker/Dockerfile.chat b/docker/Dockerfile.chat
index 0157ce181..10a9e8b00 100644
--- a/docker/Dockerfile.chat
+++ b/docker/Dockerfile.chat
@@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
- "praisonai==2.2.0" \
+ "praisonai==2.2.1" \
"praisonai[chat]" \
"embedchain[github,youtube]"
diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev
index e86e365cd..c0130b5cc 100644
--- a/docker/Dockerfile.dev
+++ b/docker/Dockerfile.dev
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
- "praisonai==2.2.0" \
+ "praisonai==2.2.1" \
"praisonai[ui]" \
"praisonai[chat]" \
"praisonai[realtime]" \
diff --git a/docker/Dockerfile.ui b/docker/Dockerfile.ui
index a4f566904..8a92e9b16 100644
--- a/docker/Dockerfile.ui
+++ b/docker/Dockerfile.ui
@@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
RUN pip install --no-cache-dir \
praisonaiagents>=0.0.4 \
praisonai_tools \
- "praisonai==2.2.0" \
+ "praisonai==2.2.1" \
"praisonai[ui]" \
"praisonai[crewai]"
diff --git a/docs/api/praisonai/deploy.html b/docs/api/praisonai/deploy.html
index 49d95c40e..d53fd43dd 100644
--- a/docs/api/praisonai/deploy.html
+++ b/docs/api/praisonai/deploy.html
@@ -110,7 +110,7 @@
Raises
file.write("FROM python:3.11-slim\n")
file.write("WORKDIR /app\n")
file.write("COPY . .\n")
- file.write("RUN pip install flask praisonai==2.2.0 gunicorn markdown\n")
+ file.write("RUN pip install flask praisonai==2.2.1 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
diff --git a/docs/developers/local-development.mdx b/docs/developers/local-development.mdx
index b919b2116..56f730d42 100644
--- a/docs/developers/local-development.mdx
+++ b/docs/developers/local-development.mdx
@@ -27,7 +27,7 @@ WORKDIR /app
COPY . .
-RUN pip install flask praisonai==2.2.0 watchdog
+RUN pip install flask praisonai==2.2.1 watchdog
EXPOSE 5555
diff --git a/docs/ui/chat.mdx b/docs/ui/chat.mdx
index d884788e2..50859cbba 100644
--- a/docs/ui/chat.mdx
+++ b/docs/ui/chat.mdx
@@ -155,7 +155,7 @@ To facilitate local development with live reload, you can use Docker. Follow the
COPY . .
- RUN pip install flask praisonai==2.2.0 watchdog
+ RUN pip install flask praisonai==2.2.1 watchdog
EXPOSE 5555
diff --git a/docs/ui/code.mdx b/docs/ui/code.mdx
index c5afbbbae..3d73a83aa 100644
--- a/docs/ui/code.mdx
+++ b/docs/ui/code.mdx
@@ -208,7 +208,7 @@ To facilitate local development with live reload, you can use Docker. Follow the
COPY . .
- RUN pip install flask praisonai==2.2.0 watchdog
+ RUN pip install flask praisonai==2.2.1 watchdog
EXPOSE 5555
diff --git a/praisonai/deploy.py b/praisonai/deploy.py
index e25ac6a9e..084bbc99f 100644
--- a/praisonai/deploy.py
+++ b/praisonai/deploy.py
@@ -56,7 +56,7 @@ def create_dockerfile(self):
file.write("FROM python:3.11-slim\n")
file.write("WORKDIR /app\n")
file.write("COPY . .\n")
- file.write("RUN pip install flask praisonai==2.2.0 gunicorn markdown\n")
+ file.write("RUN pip install flask praisonai==2.2.1 gunicorn markdown\n")
file.write("EXPOSE 8080\n")
file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
diff --git a/pyproject.toml b/pyproject.toml
index 55041349f..ee7655b67 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "PraisonAI"
-version = "2.2.0"
+version = "2.2.1"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
readme = "README.md"
license = ""
@@ -12,7 +12,7 @@ dependencies = [
"rich>=13.7",
"markdown>=3.5",
"pyparsing>=3.0.0",
- "praisonaiagents>=0.0.83",
+ "praisonaiagents>=0.0.85",
"python-dotenv>=0.19.0",
"instructor>=1.3.3",
"PyYAML>=6.0",
@@ -89,7 +89,7 @@ autogen = ["pyautogen>=0.2.19", "praisonai-tools>=0.0.15", "crewai"]
[tool.poetry]
name = "PraisonAI"
-version = "2.2.0"
+version = "2.2.1"
description = "PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration."
authors = ["Mervin Praison"]
license = ""
@@ -107,7 +107,7 @@ python = ">=3.10,<3.13"
rich = ">=13.7"
markdown = ">=3.5"
pyparsing = ">=3.0.0"
-praisonaiagents = ">=0.0.83"
+praisonaiagents = ">=0.0.85"
python-dotenv = ">=0.19.0"
instructor = ">=1.3.3"
PyYAML = ">=6.0"
diff --git a/src/praisonai-agents/mcp-sse.py b/src/praisonai-agents/mcp-sse.py
index 7cb92b995..bd60f4f0f 100644
--- a/src/praisonai-agents/mcp-sse.py
+++ b/src/praisonai-agents/mcp-sse.py
@@ -1,9 +1,8 @@
from praisonaiagents import Agent, MCP
-qa_agent = Agent(
- instructions="""You are a Question Answering Agent.""",
- llm="openai/gpt-4o-mini",
- tools=MCP("http://localhost:8080/agents/sse")
+tweet_agent = Agent(
+ instructions="""You are a Tweet Formatter Agent.""",
+ tools=MCP("http://localhost:8080/sse")
)
-qa_agent.start("AI in 2025")
\ No newline at end of file
+tweet_agent.start("AI in Healthcare")
\ No newline at end of file
diff --git a/src/praisonai-agents/openai-mcp.py b/src/praisonai-agents/openai-mcp.py
index c03e86c0c..5ed2bf32e 100644
--- a/src/praisonai-agents/openai-mcp.py
+++ b/src/praisonai-agents/openai-mcp.py
@@ -2,8 +2,7 @@
search_agent = Agent(
instructions="""You help book apartments on Airbnb.""",
- llm="openai/gpt-4o-mini",
tools=MCP("npx -y @openbnb/mcp-server-airbnb --ignore-robots-txt")
)
-search_agent.start("I want to book an apartment in Paris for 2 nights. 03/28 - 03/30 for 2 adults")
\ No newline at end of file
+search_agent.start("Search apartment in Paris for 2 nights. 07/28 - 07/30 for 2 adults")
\ No newline at end of file
diff --git a/src/praisonai-agents/praisonaiagents/mcp/mcp.py b/src/praisonai-agents/praisonaiagents/mcp/mcp.py
index 6233e07a4..a31639001 100644
--- a/src/praisonai-agents/praisonaiagents/mcp/mcp.py
+++ b/src/praisonai-agents/praisonaiagents/mcp/mcp.py
@@ -16,13 +16,14 @@
class MCPToolRunner(threading.Thread):
"""A dedicated thread for running MCP operations."""
- def __init__(self, server_params):
+ def __init__(self, server_params, timeout=60):
super().__init__(daemon=True)
self.server_params = server_params
self.queue = queue.Queue()
self.result_queue = queue.Queue()
self.initialized = threading.Event()
self.tools = []
+ self.timeout = timeout
self.start()
def run(self):
@@ -74,9 +75,9 @@ async def _run_async(self):
def call_tool(self, tool_name, arguments):
"""Call an MCP tool and wait for the result."""
if not self.initialized.is_set():
- self.initialized.wait(timeout=30)
+ self.initialized.wait(timeout=self.timeout)
if not self.initialized.is_set():
- return "Error: MCP initialization timed out"
+ return f"Error: MCP initialization timed out after {self.timeout} seconds"
# Put request in queue
self.queue.put((tool_name, arguments))
@@ -189,7 +190,7 @@ def __init__(self, command_or_string=None, args=None, *, command=None, timeout=6
if isinstance(command_or_string, str) and re.match(r'^https?://', command_or_string):
# Import the SSE client implementation
from .mcp_sse import SSEMCPClient
- self.sse_client = SSEMCPClient(command_or_string, debug=debug)
+ self.sse_client = SSEMCPClient(command_or_string, debug=debug, timeout=timeout)
self._tools = list(self.sse_client.tools)
self.is_sse = True
self.is_npx = False
@@ -216,11 +217,11 @@ def __init__(self, command_or_string=None, args=None, *, command=None, timeout=6
args=arguments,
**kwargs
)
- self.runner = MCPToolRunner(self.server_params)
+ self.runner = MCPToolRunner(self.server_params, timeout)
# Wait for initialization
- if not self.runner.initialized.wait(timeout=30):
- print("Warning: MCP initialization timed out")
+ if not self.runner.initialized.wait(timeout=self.timeout):
+ print(f"Warning: MCP initialization timed out after {self.timeout} seconds")
# Automatically detect if this is an NPX command
self.is_npx = cmd == 'npx' or (isinstance(cmd, str) and os.path.basename(cmd) == 'npx')
diff --git a/src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py b/src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py
index 67f0f22c8..beb56a713 100644
--- a/src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py
+++ b/src/praisonai-agents/praisonaiagents/mcp/mcp_sse.py
@@ -31,7 +31,7 @@ def get_event_loop():
class SSEMCPTool:
"""A wrapper for an MCP tool that can be used with praisonaiagents."""
- def __init__(self, name: str, description: str, session: ClientSession, input_schema: Optional[Dict[str, Any]] = None):
+ def __init__(self, name: str, description: str, session: ClientSession, input_schema: Optional[Dict[str, Any]] = None, timeout: int = 60):
self.name = name
self.__name__ = name # Required for Agent to recognize it as a tool
self.__qualname__ = name # Required for Agent to recognize it as a tool
@@ -39,6 +39,7 @@ def __init__(self, name: str, description: str, session: ClientSession, input_sc
self.description = description
self.session = session
self.input_schema = input_schema or {}
+ self.timeout = timeout
# Create a signature based on input schema
params = []
@@ -66,7 +67,7 @@ def __call__(self, **kwargs):
future = asyncio.run_coroutine_threadsafe(self._async_call(**kwargs), loop)
try:
# Wait for the result with a timeout
- return future.result(timeout=30)
+ return future.result(timeout=self.timeout)
except Exception as e:
logger.error(f"Error calling tool {self.name}: {e}")
return f"Error: {str(e)}"
@@ -102,16 +103,18 @@ def to_openai_tool(self):
class SSEMCPClient:
"""A client for connecting to an MCP server over SSE."""
- def __init__(self, server_url: str, debug: bool = False):
+ def __init__(self, server_url: str, debug: bool = False, timeout: int = 60):
"""
Initialize an SSE MCP client.
Args:
server_url: The URL of the SSE MCP server
debug: Whether to enable debug logging
+ timeout: Timeout in seconds for operations (default: 60)
"""
self.server_url = server_url
self.debug = debug
+ self.timeout = timeout
self.session = None
self.tools = []
@@ -139,7 +142,7 @@ def run_event_loop():
# Run the initialization in the event loop
future = asyncio.run_coroutine_threadsafe(self._async_initialize(), loop)
- self.tools = future.result(timeout=30)
+ self.tools = future.result(timeout=self.timeout)
async def _async_initialize(self):
"""Asynchronously initialize the connection and tools."""
@@ -169,7 +172,8 @@ async def _async_initialize(self):
name=tool.name,
description=tool.description if hasattr(tool, 'description') else f"Call the {tool.name} tool",
session=self.session,
- input_schema=input_schema
+ input_schema=input_schema,
+ timeout=self.timeout
)
tools.append(wrapper)
diff --git a/src/praisonai-agents/pyproject.toml b/src/praisonai-agents/pyproject.toml
index f51527d5a..90d73cbc1 100644
--- a/src/praisonai-agents/pyproject.toml
+++ b/src/praisonai-agents/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "praisonaiagents"
-version = "0.0.83"
+version = "0.0.85"
description = "Praison AI agents for completing complex tasks with Self Reflection Agents"
authors = [
{ name="Mervin Praison" }
diff --git a/src/praisonai-agents/simple-mcp-server.py b/src/praisonai-agents/simple-mcp-server.py
index 74b20f5ec..39430aabf 100644
--- a/src/praisonai-agents/simple-mcp-server.py
+++ b/src/praisonai-agents/simple-mcp-server.py
@@ -1,4 +1,4 @@
from praisonaiagents import Agent
-agent = Agent(name="TweetAgent", instructions="Create a Tweet based on the topic provided")
+agent = Agent(instructions="Create a Tweet")
agent.launch(port=8080, protocol="mcp")
\ No newline at end of file
diff --git a/src/praisonai-agents/uv.lock b/src/praisonai-agents/uv.lock
index 4eb08e917..fc8410b67 100644
--- a/src/praisonai-agents/uv.lock
+++ b/src/praisonai-agents/uv.lock
@@ -1457,7 +1457,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
-version = "0.0.83"
+version = "0.0.85"
source = { editable = "." }
dependencies = [
{ name = "mcp" },
diff --git a/uv.lock b/uv.lock
index cd76b3458..f63796b02 100644
--- a/uv.lock
+++ b/uv.lock
@@ -3614,7 +3614,7 @@ wheels = [
[[package]]
name = "praisonai"
-version = "2.2.0"
+version = "2.2.1"
source = { editable = "." }
dependencies = [
{ name = "instructor" },
@@ -3756,7 +3756,7 @@ requires-dist = [
{ name = "plotly", marker = "extra == 'realtime'", specifier = ">=5.24.0" },
{ name = "praisonai-tools", marker = "extra == 'autogen'", specifier = ">=0.0.15" },
{ name = "praisonai-tools", marker = "extra == 'crewai'", specifier = ">=0.0.15" },
- { name = "praisonaiagents", specifier = ">=0.0.83" },
+ { name = "praisonaiagents", specifier = ">=0.0.85" },
{ name = "pyautogen", marker = "extra == 'autogen'", specifier = ">=0.2.19" },
{ name = "pydantic", marker = "extra == 'chat'", specifier = "<=2.10.1" },
{ name = "pydantic", marker = "extra == 'code'", specifier = "<=2.10.1" },
@@ -3813,7 +3813,7 @@ wheels = [
[[package]]
name = "praisonaiagents"
-version = "0.0.83"
+version = "0.0.85"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "mcp" },
@@ -3821,9 +3821,9 @@ dependencies = [
{ name = "pydantic" },
{ name = "rich" },
]
-sdist = { url = "https://files.pythonhosted.org/packages/ae/b5/f5d93d8d57149d32918d419eb5a36dcdc30ae17dfc4f82c21287a25103a6/praisonaiagents-0.0.83.tar.gz", hash = "sha256:2356aa349562ea69cb8e717726dcda557c808c0ae160aad1f216565978a1bd61", size = 124557 }
+sdist = { url = "https://files.pythonhosted.org/packages/58/18/5984f440ec48f2238bdbd166c2347e8ae2a9e4c3b1782be07a3e0ecc626e/praisonaiagents-0.0.85.tar.gz", hash = "sha256:a4f2c0317a25e04a76b8b0a61921fbe79b309b6031ed4a2c02898951ae58c922", size = 125623 }
wheels = [
- { url = "https://files.pythonhosted.org/packages/b3/9b/e766de5c0ef4017189986994373accad3a1ad761980aee0f2e1f0e8a9edb/praisonaiagents-0.0.83-py3-none-any.whl", hash = "sha256:fa3bf621b1c729283215ced83d13f1519ca0e676ed3a1ad7e17e07af2fbf3a72", size = 144238 },
+ { url = "https://files.pythonhosted.org/packages/70/13/46b86b7962c5b74360b8d4a1678fd8b3f4b59be1d4e620418d6ad41761a4/praisonaiagents-0.0.85-py3-none-any.whl", hash = "sha256:91ac555747726a83fff565e76a57ffa7dda9813e745958d8e5ea279eb0777b3c", size = 145314 },
]
[[package]]