update format

This commit is contained in:
gantnocap 2025-03-11 13:09:49 +08:00
parent 6e45490412
commit 5ae32c91e5
4 changed files with 80 additions and 62 deletions

View File

@ -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())

View File

@ -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()