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
from typing import Optional
from contextlib import AsyncExitStack
import os
from contextlib import AsyncExitStack
from typing import Optional
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
class OpenManusClient:
def __init__(self):
# Initialize session and client objects
@ -20,7 +21,7 @@ class OpenManusClient:
Args:
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")
# Get the current directory to add to PYTHONPATH
@ -31,21 +32,27 @@ class OpenManusClient:
env = os.environ.copy() # Copy current environment
# Add current directory and project root to PYTHONPATH
path_separator = ';' if os.name == 'nt' else ':' # Use ; for Windows, : for Unix
if 'PYTHONPATH' in env:
env['PYTHONPATH'] = f"{current_dir}{path_separator}{project_root}{path_separator}{env['PYTHONPATH']}"
path_separator = (
";" if os.name == "nt" else ":"
) # Use ; for Windows, : for Unix
if "PYTHONPATH" in env:
env[
"PYTHONPATH"
] = f"{current_dir}{path_separator}{project_root}{path_separator}{env['PYTHONPATH']}"
else:
env['PYTHONPATH'] = f"{current_dir}{path_separator}{project_root}"
env["PYTHONPATH"] = f"{current_dir}{path_separator}{project_root}"
server_params = StdioServerParameters(
command="python",
args=[server_script_path],
env=env
command="python", 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.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()
# List available tools
@ -59,8 +66,7 @@ class OpenManusClient:
try:
print("\nExample 1: Google Search")
search_result = await self.session.call_tool(
"google_search",
{"query": "Model Context Protocol", "num_results": 5}
"google_search", {"query": "Model Context Protocol", "num_results": 5}
)
print(f"Search results: {search_result.content}")
@ -73,8 +79,7 @@ for i in range(1, 10):
print(f"Calculation result: {result}")
"""
python_result = await self.session.call_tool(
"python_execute",
{"code": code, "timeout": 3}
"python_execute", {"code": code, "timeout": 3}
)
print(f"Python execution result: {python_result.content}")
@ -83,24 +88,20 @@ print(f"Calculation result: {result}")
"file_saver",
{
"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("\nExample 4: Browser Usage")
# Navigate to webpage
browser_result = await self.session.call_tool(
"browser_use",
{"action": "navigate", "url": "https://www.example.com"}
"browser_use", {"action": "navigate", "url": "https://www.example.com"}
)
print(f"Browser navigation result: {browser_result.content}")
# Get browser state
state_result = await self.session.call_tool(
"get_browser_state",
{}
)
state_result = await self.session.call_tool("get_browser_state", {})
print(f"Browser state: {state_result.content}")
except Exception as e:
@ -110,13 +111,15 @@ print(f"Calculation result: {result}")
"""Run an interactive chat loop for testing tools"""
print("\nOpenManus MCP Client Started!")
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:
try:
command = input("\nCommand: ").strip()
if command.lower() == 'quit':
if command.lower() == "quit":
break
# Parse command and parameters
@ -130,7 +133,9 @@ print(f"Calculation result: {result}")
try:
tool_args = eval(parts[1]) # Convert string to dict
except:
print("Invalid arguments format. Please provide a valid Python dictionary.")
print(
"Invalid arguments format. Please provide a valid Python dictionary."
)
continue
result = await self.session.call_tool(tool_name, tool_args)
@ -146,6 +151,7 @@ print(f"Calculation result: {result}")
await self.exit_stack.aclose()
print("\nClosed MCP client connection")
async def main():
"""Main entry point"""
import sys
@ -170,5 +176,6 @@ async def main():
finally:
await client.cleanup()
if __name__ == "__main__":
asyncio.run(main())

View File

@ -1,11 +1,13 @@
from typing import Optional
import argparse
import asyncio
import json
import argparse
from mcp.server.fastmcp import FastMCP
import logging
import os
import sys
from typing import Optional
from mcp.server.fastmcp import FastMCP
# Add current directory to Python path
current_dir = os.path.dirname(os.path.abspath(__file__))
@ -15,18 +17,18 @@ sys.path.insert(0, current_dir)
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger("mcp-server")
# Import OpenManus tools
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.python_execute import PythonExecute
from app.tool.file_saver import FileSaver
from app.tool.terminate import Terminate
# Initialize FastMCP server
openmanus = FastMCP("openmanus")
@ -37,6 +39,7 @@ python_execute_tool = PythonExecute()
file_saver_tool = FileSaver()
terminate_tool = Terminate()
# Browser tool
@openmanus.tool()
async def browser_use(
@ -79,10 +82,11 @@ async def browser_use(
text=text,
script=script,
scroll_amount=scroll_amount,
tab_id=tab_id
tab_id=tab_id,
)
return json.dumps(result.model_dump())
@openmanus.tool()
async def get_browser_state() -> str:
"""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()
return json.dumps(result.model_dump())
# Google search tool
@openmanus.tool()
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)
return json.dumps(results)
# Python execution tool
@openmanus.tool()
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)
return json.dumps(result)
# File saver tool
@openmanus.tool()
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')
"""
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
# Terminate tool
@openmanus.tool()
async def terminate(status: str) -> str:
@ -142,16 +152,21 @@ async def terminate(status: str) -> str:
result = await terminate_tool.execute(status=status)
return result
# Clean up resources
async def cleanup():
"""Clean up all tool resources"""
logger.info("Cleaning up resources")
await browser_tool.cleanup()
# Register cleanup function
import atexit
atexit.register(lambda: asyncio.run(cleanup()))
def parse_args():
"""Parse command line arguments"""
parser = argparse.ArgumentParser(description="OpenManus MCP Server")
@ -159,21 +174,17 @@ def parse_args():
"--transport",
choices=["stdio", "http"],
default="stdio",
help="Communication method: stdio or http (default: stdio)"
help="Communication method: stdio or http (default: stdio)",
)
parser.add_argument(
"--host",
default="127.0.0.1",
help="HTTP server host (default: 127.0.0.1)"
"--host", default="127.0.0.1", help="HTTP server host (default: 127.0.0.1)"
)
parser.add_argument(
"--port",
type=int,
default=8000,
help="HTTP server port (default: 8000)"
"--port", type=int, default=8000, help="HTTP server port (default: 8000)"
)
return parser.parse_args()
if __name__ == "__main__":
args = parse_args()