Spaces:
Sleeping
Sleeping
| """ | |
| Linux MCP Server using Gradio's built-in MCP support. | |
| This creates both the MCP server and a web interface for tool management. | |
| """ | |
| import gradio as gr | |
| import os | |
| import sys | |
| from pathlib import Path | |
| # Add project root to path | |
| project_root = Path(__file__).parent | |
| sys.path.insert(0, str(project_root)) | |
| # Import our tools | |
| from tools.linux_tools import ( | |
| add_user, | |
| create_file, | |
| change_permission, | |
| run_safe_command | |
| ) | |
| from shared.config import config | |
| import logging | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| def create_linux_mcp_server(): | |
| """ | |
| Create the Linux MCP server with Gradio. | |
| Gradio automatically converts @gr.tool functions into MCP tools. | |
| """ | |
| # Define the tools list for Gradio | |
| tools = [ | |
| run_safe_command, # Safe operations (low risk) | |
| add_user, # Sensitive operations (high risk) | |
| create_file, # Sensitive operations (high risk) | |
| change_permission # Sensitive operations (high risk) | |
| ] | |
| # Create the MCP server interface | |
| with gr.Blocks( | |
| title=config.gradio.title, | |
| theme=config.gradio.theme | |
| ) as demo: | |
| gr.Markdown(f""" | |
| # {config.gradio.title} | |
| ## π οΈ Available MCP Tools | |
| This server exposes Linux administration tools via the MCP (Model Context Protocol): | |
| ### π’ Safe Operations (Direct Execution) | |
| - **run_safe_command**: Execute whitelisted read-only commands | |
| - Whitelist: `{', '.join(config.security.safe_commands[:10])}...` | |
| ### π΄ Sensitive Operations (Require Validation) | |
| - **add_user**: Create new system users | |
| - **create_file**: Create files with specified content and permissions | |
| - **change_permission**: Modify file/directory permissions | |
| ## π MCP Connection | |
| Connect MCP clients to this server to access these tools programmatically. | |
| Each tool includes proper validation and security checks. | |
| ## π Tool Status | |
| - Total Tools: {len(tools)} | |
| - Safe Commands: {len(config.security.safe_commands)} | |
| - Command Timeout: {config.security.command_timeout}s | |
| """) | |
| # Tool testing interface (optional) | |
| with gr.Tab("Test Tools"): | |
| gr.Markdown("### Test MCP Tools Directly") | |
| with gr.Row(): | |
| with gr.Column(): | |
| tool_selector = gr.Dropdown( | |
| choices=["run_safe_command", "add_user", "create_file", "change_permission"], | |
| label="Select Tool", | |
| value="run_safe_command" | |
| ) | |
| # Safe command inputs | |
| with gr.Group(visible=True) as safe_inputs: | |
| safe_command = gr.Dropdown( | |
| choices=config.security.safe_commands, | |
| label="Command", | |
| value="ls" | |
| ) | |
| safe_args = gr.Textbox( | |
| label="Arguments (space-separated)", | |
| placeholder="-la /home" | |
| ) | |
| # User inputs | |
| with gr.Group(visible=False) as user_inputs: | |
| username = gr.Textbox(label="Username", placeholder="john") | |
| groups = gr.Textbox(label="Groups (comma-separated)", placeholder="sudo,users") | |
| create_home = gr.Checkbox(label="Create Home Directory", value=True) | |
| # File inputs | |
| with gr.Group(visible=False) as file_inputs: | |
| filepath = gr.Textbox(label="File Path", placeholder="/tmp/test.txt") | |
| content = gr.Textbox(label="File Content", lines=3, placeholder="Hello, World!") | |
| permissions = gr.Textbox(label="Permissions", value="644", placeholder="644") | |
| test_button = gr.Button("Test Tool", variant="primary") | |
| with gr.Column(): | |
| test_output = gr.JSON(label="Tool Output") | |
| # Tool selector event handler | |
| def update_inputs(tool_name): | |
| return { | |
| safe_inputs: gr.update(visible=(tool_name == "run_safe_command")), | |
| user_inputs: gr.update(visible=(tool_name == "add_user")), | |
| file_inputs: gr.update(visible=(tool_name in ["create_file", "change_permission"])) | |
| } | |
| tool_selector.change( | |
| update_inputs, | |
| inputs=[tool_selector], | |
| outputs=[safe_inputs, user_inputs, file_inputs] | |
| ) | |
| # Test tool execution | |
| def test_tool(tool_name, cmd, args, user, grps, home, path, cont, perms): | |
| try: | |
| if tool_name == "run_safe_command": | |
| args_list = args.split() if args else [] | |
| return run_safe_command(cmd, args_list) | |
| elif tool_name == "add_user": | |
| groups_list = [g.strip() for g in grps.split(",")] if grps else [] | |
| return add_user(user, groups_list, home) | |
| elif tool_name == "create_file": | |
| return create_file(path, cont, perms) | |
| elif tool_name == "change_permission": | |
| return change_permission(path, perms) | |
| else: | |
| return {"error": f"Unknown tool: {tool_name}"} | |
| except Exception as e: | |
| return {"error": str(e)} | |
| test_button.click( | |
| test_tool, | |
| inputs=[ | |
| tool_selector, safe_command, safe_args, | |
| username, groups, create_home, | |
| filepath, content, permissions | |
| ], | |
| outputs=[test_output] | |
| ) | |
| # System info tab | |
| with gr.Tab("System Info"): | |
| gr.Markdown(f""" | |
| ### Server Configuration | |
| - **MCP Tools**: {len(tools)} available | |
| - **Safe Commands**: {len(config.security.safe_commands)} whitelisted | |
| - **Command Timeout**: {config.security.command_timeout} seconds | |
| - **OpenAI Model**: {config.openai.model} | |
| ### Security Settings | |
| **Safe Commands Whitelist:** | |
| ``` | |
| {', '.join(config.security.safe_commands)} | |
| ``` | |
| **Sensitive Operations:** | |
| - User management (add_user) | |
| - File operations (create_file, change_permission) | |
| - All require proper validation and logging | |
| """) | |
| # Configure MCP server | |
| demo.mcp_tools = tools # Gradio automatically exposes these as MCP tools | |
| return demo | |
| def main(): | |
| """Main entry point for the Linux MCP server""" | |
| logger.info("Starting Linux MCP Server with Gradio") | |
| logger.info(f"OpenAI API configured: {'β ' if config.openai.api_key else 'β'}") | |
| logger.info(f"Safe commands: {len(config.security.safe_commands)}") | |
| # Create and launch the server | |
| demo = create_linux_mcp_server() | |
| # Launch with MCP server enabled | |
| demo.launch( | |
| share=config.gradio.share, | |
| server_name="0.0.0.0", # For HF Spaces | |
| server_port=7860, # Standard HF Spaces port | |
| show_error=True | |
| ) | |
| if __name__ == "__main__": | |
| main() |