update format
This commit is contained in:
parent
6e45490412
commit
5ae32c91e5
@ -1,11 +1,12 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
from typing import Optional
|
|
||||||
from contextlib import AsyncExitStack
|
|
||||||
import os
|
import os
|
||||||
|
from contextlib import AsyncExitStack
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
from mcp import ClientSession, StdioServerParameters
|
from mcp import ClientSession, StdioServerParameters
|
||||||
from mcp.client.stdio import stdio_client
|
from mcp.client.stdio import stdio_client
|
||||||
|
|
||||||
|
|
||||||
class OpenManusClient:
|
class OpenManusClient:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Initialize session and client objects
|
# Initialize session and client objects
|
||||||
@ -20,7 +21,7 @@ class OpenManusClient:
|
|||||||
Args:
|
Args:
|
||||||
server_script_path: Path to the server script
|
server_script_path: Path to the server script
|
||||||
"""
|
"""
|
||||||
if not server_script_path.endswith('.py'):
|
if not server_script_path.endswith(".py"):
|
||||||
raise ValueError("Server script must be a .py file")
|
raise ValueError("Server script must be a .py file")
|
||||||
|
|
||||||
# Get the current directory to add to PYTHONPATH
|
# Get the current directory to add to PYTHONPATH
|
||||||
@ -31,21 +32,27 @@ class OpenManusClient:
|
|||||||
env = os.environ.copy() # Copy current environment
|
env = os.environ.copy() # Copy current environment
|
||||||
|
|
||||||
# Add current directory and project root to PYTHONPATH
|
# Add current directory and project root to PYTHONPATH
|
||||||
path_separator = ';' if os.name == 'nt' else ':' # Use ; for Windows, : for Unix
|
path_separator = (
|
||||||
if 'PYTHONPATH' in env:
|
";" if os.name == "nt" else ":"
|
||||||
env['PYTHONPATH'] = f"{current_dir}{path_separator}{project_root}{path_separator}{env['PYTHONPATH']}"
|
) # Use ; for Windows, : for Unix
|
||||||
|
if "PYTHONPATH" in env:
|
||||||
|
env[
|
||||||
|
"PYTHONPATH"
|
||||||
|
] = f"{current_dir}{path_separator}{project_root}{path_separator}{env['PYTHONPATH']}"
|
||||||
else:
|
else:
|
||||||
env['PYTHONPATH'] = f"{current_dir}{path_separator}{project_root}"
|
env["PYTHONPATH"] = f"{current_dir}{path_separator}{project_root}"
|
||||||
|
|
||||||
server_params = StdioServerParameters(
|
server_params = StdioServerParameters(
|
||||||
command="python",
|
command="python", args=[server_script_path], env=env
|
||||||
args=[server_script_path],
|
|
||||||
env=env
|
|
||||||
)
|
)
|
||||||
|
|
||||||
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
|
stdio_transport = await self.exit_stack.enter_async_context(
|
||||||
|
stdio_client(server_params)
|
||||||
|
)
|
||||||
self.stdio, self.write = stdio_transport
|
self.stdio, self.write = stdio_transport
|
||||||
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
|
self.session = await self.exit_stack.enter_async_context(
|
||||||
|
ClientSession(self.stdio, self.write)
|
||||||
|
)
|
||||||
await self.session.initialize()
|
await self.session.initialize()
|
||||||
|
|
||||||
# List available tools
|
# List available tools
|
||||||
@ -59,8 +66,7 @@ class OpenManusClient:
|
|||||||
try:
|
try:
|
||||||
print("\nExample 1: Google Search")
|
print("\nExample 1: Google Search")
|
||||||
search_result = await self.session.call_tool(
|
search_result = await self.session.call_tool(
|
||||||
"google_search",
|
"google_search", {"query": "Model Context Protocol", "num_results": 5}
|
||||||
{"query": "Model Context Protocol", "num_results": 5}
|
|
||||||
)
|
)
|
||||||
print(f"Search results: {search_result.content}")
|
print(f"Search results: {search_result.content}")
|
||||||
|
|
||||||
@ -73,8 +79,7 @@ for i in range(1, 10):
|
|||||||
print(f"Calculation result: {result}")
|
print(f"Calculation result: {result}")
|
||||||
"""
|
"""
|
||||||
python_result = await self.session.call_tool(
|
python_result = await self.session.call_tool(
|
||||||
"python_execute",
|
"python_execute", {"code": code, "timeout": 3}
|
||||||
{"code": code, "timeout": 3}
|
|
||||||
)
|
)
|
||||||
print(f"Python execution result: {python_result.content}")
|
print(f"Python execution result: {python_result.content}")
|
||||||
|
|
||||||
@ -83,24 +88,20 @@ print(f"Calculation result: {result}")
|
|||||||
"file_saver",
|
"file_saver",
|
||||||
{
|
{
|
||||||
"content": "This is a test file content saved through MCP",
|
"content": "This is a test file content saved through MCP",
|
||||||
"file_path": "mcp_test_file.txt"
|
"file_path": "mcp_test_file.txt",
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
print(f"File save result: {file_result.content}")
|
print(f"File save result: {file_result.content}")
|
||||||
|
|
||||||
print("\nExample 4: Browser Usage")
|
print("\nExample 4: Browser Usage")
|
||||||
# Navigate to webpage
|
# Navigate to webpage
|
||||||
browser_result = await self.session.call_tool(
|
browser_result = await self.session.call_tool(
|
||||||
"browser_use",
|
"browser_use", {"action": "navigate", "url": "https://www.example.com"}
|
||||||
{"action": "navigate", "url": "https://www.example.com"}
|
|
||||||
)
|
)
|
||||||
print(f"Browser navigation result: {browser_result.content}")
|
print(f"Browser navigation result: {browser_result.content}")
|
||||||
|
|
||||||
# Get browser state
|
# Get browser state
|
||||||
state_result = await self.session.call_tool(
|
state_result = await self.session.call_tool("get_browser_state", {})
|
||||||
"get_browser_state",
|
|
||||||
{}
|
|
||||||
)
|
|
||||||
print(f"Browser state: {state_result.content}")
|
print(f"Browser state: {state_result.content}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -110,13 +111,15 @@ print(f"Calculation result: {result}")
|
|||||||
"""Run an interactive chat loop for testing tools"""
|
"""Run an interactive chat loop for testing tools"""
|
||||||
print("\nOpenManus MCP Client Started!")
|
print("\nOpenManus MCP Client Started!")
|
||||||
print("Type your commands or 'quit' to exit.")
|
print("Type your commands or 'quit' to exit.")
|
||||||
print("Available commands: google_search, python_execute, file_saver, browser_use, get_browser_state")
|
print(
|
||||||
|
"Available commands: google_search, python_execute, file_saver, browser_use, get_browser_state"
|
||||||
|
)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
command = input("\nCommand: ").strip()
|
command = input("\nCommand: ").strip()
|
||||||
|
|
||||||
if command.lower() == 'quit':
|
if command.lower() == "quit":
|
||||||
break
|
break
|
||||||
|
|
||||||
# Parse command and parameters
|
# Parse command and parameters
|
||||||
@ -130,7 +133,9 @@ print(f"Calculation result: {result}")
|
|||||||
try:
|
try:
|
||||||
tool_args = eval(parts[1]) # Convert string to dict
|
tool_args = eval(parts[1]) # Convert string to dict
|
||||||
except:
|
except:
|
||||||
print("Invalid arguments format. Please provide a valid Python dictionary.")
|
print(
|
||||||
|
"Invalid arguments format. Please provide a valid Python dictionary."
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
result = await self.session.call_tool(tool_name, tool_args)
|
result = await self.session.call_tool(tool_name, tool_args)
|
||||||
@ -146,6 +151,7 @@ print(f"Calculation result: {result}")
|
|||||||
await self.exit_stack.aclose()
|
await self.exit_stack.aclose()
|
||||||
print("\nClosed MCP client connection")
|
print("\nClosed MCP client connection")
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
"""Main entry point"""
|
"""Main entry point"""
|
||||||
import sys
|
import sys
|
||||||
@ -170,5 +176,6 @@ async def main():
|
|||||||
finally:
|
finally:
|
||||||
await client.cleanup()
|
await client.cleanup()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
@ -1,11 +1,13 @@
|
|||||||
from typing import Optional
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import argparse
|
|
||||||
from mcp.server.fastmcp import FastMCP
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from mcp.server.fastmcp import FastMCP
|
||||||
|
|
||||||
|
|
||||||
# Add current directory to Python path
|
# Add current directory to Python path
|
||||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
@ -15,18 +17,18 @@ sys.path.insert(0, current_dir)
|
|||||||
|
|
||||||
# Configure logging
|
# Configure logging
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
level=logging.INFO,
|
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
|
||||||
)
|
)
|
||||||
logger = logging.getLogger("mcp-server")
|
logger = logging.getLogger("mcp-server")
|
||||||
|
|
||||||
# Import OpenManus tools
|
# Import OpenManus tools
|
||||||
from app.tool.browser_use_tool import BrowserUseTool
|
from app.tool.browser_use_tool import BrowserUseTool
|
||||||
|
from app.tool.file_saver import FileSaver
|
||||||
from app.tool.google_search import GoogleSearch
|
from app.tool.google_search import GoogleSearch
|
||||||
from app.tool.python_execute import PythonExecute
|
from app.tool.python_execute import PythonExecute
|
||||||
from app.tool.file_saver import FileSaver
|
|
||||||
from app.tool.terminate import Terminate
|
from app.tool.terminate import Terminate
|
||||||
|
|
||||||
|
|
||||||
# Initialize FastMCP server
|
# Initialize FastMCP server
|
||||||
openmanus = FastMCP("openmanus")
|
openmanus = FastMCP("openmanus")
|
||||||
|
|
||||||
@ -37,6 +39,7 @@ python_execute_tool = PythonExecute()
|
|||||||
file_saver_tool = FileSaver()
|
file_saver_tool = FileSaver()
|
||||||
terminate_tool = Terminate()
|
terminate_tool = Terminate()
|
||||||
|
|
||||||
|
|
||||||
# Browser tool
|
# Browser tool
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def browser_use(
|
async def browser_use(
|
||||||
@ -79,10 +82,11 @@ async def browser_use(
|
|||||||
text=text,
|
text=text,
|
||||||
script=script,
|
script=script,
|
||||||
scroll_amount=scroll_amount,
|
scroll_amount=scroll_amount,
|
||||||
tab_id=tab_id
|
tab_id=tab_id,
|
||||||
)
|
)
|
||||||
return json.dumps(result.model_dump())
|
return json.dumps(result.model_dump())
|
||||||
|
|
||||||
|
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def get_browser_state() -> str:
|
async def get_browser_state() -> str:
|
||||||
"""Get current browser state, including URL, title, tabs and interactive elements."""
|
"""Get current browser state, including URL, title, tabs and interactive elements."""
|
||||||
@ -90,6 +94,7 @@ async def get_browser_state() -> str:
|
|||||||
result = await browser_tool.get_current_state()
|
result = await browser_tool.get_current_state()
|
||||||
return json.dumps(result.model_dump())
|
return json.dumps(result.model_dump())
|
||||||
|
|
||||||
|
|
||||||
# Google search tool
|
# Google search tool
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def google_search(query: str, num_results: int = 10) -> str:
|
async def google_search(query: str, num_results: int = 10) -> str:
|
||||||
@ -103,6 +108,7 @@ async def google_search(query: str, num_results: int = 10) -> str:
|
|||||||
results = await google_search_tool.execute(query=query, num_results=num_results)
|
results = await google_search_tool.execute(query=query, num_results=num_results)
|
||||||
return json.dumps(results)
|
return json.dumps(results)
|
||||||
|
|
||||||
|
|
||||||
# Python execution tool
|
# Python execution tool
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def python_execute(code: str, timeout: int = 5) -> str:
|
async def python_execute(code: str, timeout: int = 5) -> str:
|
||||||
@ -116,6 +122,7 @@ async def python_execute(code: str, timeout: int = 5) -> str:
|
|||||||
result = await python_execute_tool.execute(code=code, timeout=timeout)
|
result = await python_execute_tool.execute(code=code, timeout=timeout)
|
||||||
return json.dumps(result)
|
return json.dumps(result)
|
||||||
|
|
||||||
|
|
||||||
# File saver tool
|
# File saver tool
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def file_saver(content: str, file_path: str, mode: str = "w") -> str:
|
async def file_saver(content: str, file_path: str, mode: str = "w") -> str:
|
||||||
@ -127,9 +134,12 @@ async def file_saver(content: str, file_path: str, mode: str = "w") -> str:
|
|||||||
mode: File open mode (default is 'w')
|
mode: File open mode (default is 'w')
|
||||||
"""
|
"""
|
||||||
logger.info(f"Saving file: {file_path}")
|
logger.info(f"Saving file: {file_path}")
|
||||||
result = await file_saver_tool.execute(content=content, file_path=file_path, mode=mode)
|
result = await file_saver_tool.execute(
|
||||||
|
content=content, file_path=file_path, mode=mode
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
# Terminate tool
|
# Terminate tool
|
||||||
@openmanus.tool()
|
@openmanus.tool()
|
||||||
async def terminate(status: str) -> str:
|
async def terminate(status: str) -> str:
|
||||||
@ -142,16 +152,21 @@ async def terminate(status: str) -> str:
|
|||||||
result = await terminate_tool.execute(status=status)
|
result = await terminate_tool.execute(status=status)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
# Clean up resources
|
# Clean up resources
|
||||||
async def cleanup():
|
async def cleanup():
|
||||||
"""Clean up all tool resources"""
|
"""Clean up all tool resources"""
|
||||||
logger.info("Cleaning up resources")
|
logger.info("Cleaning up resources")
|
||||||
await browser_tool.cleanup()
|
await browser_tool.cleanup()
|
||||||
|
|
||||||
|
|
||||||
# Register cleanup function
|
# Register cleanup function
|
||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
|
|
||||||
atexit.register(lambda: asyncio.run(cleanup()))
|
atexit.register(lambda: asyncio.run(cleanup()))
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
"""Parse command line arguments"""
|
"""Parse command line arguments"""
|
||||||
parser = argparse.ArgumentParser(description="OpenManus MCP Server")
|
parser = argparse.ArgumentParser(description="OpenManus MCP Server")
|
||||||
@ -159,21 +174,17 @@ def parse_args():
|
|||||||
"--transport",
|
"--transport",
|
||||||
choices=["stdio", "http"],
|
choices=["stdio", "http"],
|
||||||
default="stdio",
|
default="stdio",
|
||||||
help="Communication method: stdio or http (default: stdio)"
|
help="Communication method: stdio or http (default: stdio)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--host",
|
"--host", default="127.0.0.1", help="HTTP server host (default: 127.0.0.1)"
|
||||||
default="127.0.0.1",
|
|
||||||
help="HTTP server host (default: 127.0.0.1)"
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--port",
|
"--port", type=int, default=8000, help="HTTP server port (default: 8000)"
|
||||||
type=int,
|
|
||||||
default=8000,
|
|
||||||
help="HTTP server port (default: 8000)"
|
|
||||||
)
|
)
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = parse_args()
|
args = parse_args()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user