ChrisSacrumCor commited on
Commit
e72ea01
Β·
verified Β·
1 Parent(s): 0add29f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +490 -67
app.py CHANGED
@@ -1,81 +1,454 @@
1
  """
2
- Linux MCP Server using Gradio's built-in MCP support.
3
- This creates both the MCP server and a web interface for tool management.
4
  """
5
 
6
  import gradio as gr
7
  import os
8
  import sys
 
 
 
9
  from pathlib import Path
 
10
 
11
- # Add project root to path
12
- project_root = Path(__file__).parent
13
- sys.path.insert(0, str(project_root))
14
 
15
- # Import our tools
16
- from tools.linux_tools import (
17
- add_user,
18
- create_file,
19
- change_permission,
20
- run_safe_command
21
- )
22
- from shared.config import config
23
- import logging
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  # Set up logging
26
  logging.basicConfig(level=logging.INFO)
27
  logger = logging.getLogger(__name__)
28
 
29
- def create_linux_mcp_server():
30
  """
31
- Create the Linux MCP server with Gradio.
32
- Gradio automatically converts @gr.tool functions into MCP tools.
33
  """
34
 
35
- # Define the tools list for Gradio
36
- tools = [
37
- run_safe_command, # Safe operations (low risk)
38
- add_user, # Sensitive operations (high risk)
39
- create_file, # Sensitive operations (high risk)
40
- change_permission # Sensitive operations (high risk)
41
- ]
42
 
43
- # Create the MCP server interface
44
  with gr.Blocks(
45
  title=config.gradio.title,
46
- theme=config.gradio.theme
 
47
  ) as demo:
48
 
49
  gr.Markdown(f"""
50
  # {config.gradio.title}
51
 
52
- ## πŸ› οΈ Available MCP Tools
53
 
54
- This server exposes Linux administration tools via the MCP (Model Context Protocol):
55
 
56
  ### 🟒 Safe Operations (Direct Execution)
57
- - **run_safe_command**: Execute whitelisted read-only commands
58
- - Whitelist: `{', '.join(config.security.safe_commands[:10])}...`
 
 
59
 
60
  ### πŸ”΄ Sensitive Operations (Require Validation)
61
- - **add_user**: Create new system users
62
- - **create_file**: Create files with specified content and permissions
63
- - **change_permission**: Modify file/directory permissions
64
 
65
- ## πŸ”Œ MCP Connection
66
 
67
- Connect MCP clients to this server to access these tools programmatically.
68
- Each tool includes proper validation and security checks.
69
 
70
- ## πŸ“Š Tool Status
71
- - Total Tools: {len(tools)}
72
- - Safe Commands: {len(config.security.safe_commands)}
73
- - Command Timeout: {config.security.command_timeout}s
74
  """)
75
 
76
- # Tool testing interface (optional)
77
- with gr.Tab("Test Tools"):
78
- gr.Markdown("### Test MCP Tools Directly")
79
 
80
  with gr.Row():
81
  with gr.Column():
@@ -109,7 +482,7 @@ def create_linux_mcp_server():
109
  content = gr.Textbox(label="File Content", lines=3, placeholder="Hello, World!")
110
  permissions = gr.Textbox(label="Permissions", value="644", placeholder="644")
111
 
112
- test_button = gr.Button("Test Tool", variant="primary")
113
 
114
  with gr.Column():
115
  test_output = gr.JSON(label="Tool Output")
@@ -129,8 +502,10 @@ def create_linux_mcp_server():
129
  )
130
 
131
  # Test tool execution
132
- def test_tool(tool_name, cmd, args, user, grps, home, path, cont, perms):
133
  try:
 
 
134
  if tool_name == "run_safe_command":
135
  args_list = args.split() if args else []
136
  return run_safe_command(cmd, args_list)
@@ -146,13 +521,14 @@ def create_linux_mcp_server():
146
  return change_permission(path, perms)
147
 
148
  else:
149
- return {"error": f"Unknown tool: {tool_name}"}
150
 
151
  except Exception as e:
152
- return {"error": str(e)}
 
153
 
154
  test_button.click(
155
- test_tool,
156
  inputs=[
157
  tool_selector, safe_command, safe_args,
158
  username, groups, create_home,
@@ -161,45 +537,92 @@ def create_linux_mcp_server():
161
  outputs=[test_output]
162
  )
163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  # System info tab
165
- with gr.Tab("System Info"):
166
  gr.Markdown(f"""
167
  ### Server Configuration
168
 
169
- - **MCP Tools**: {len(tools)} available
170
- - **Safe Commands**: {len(config.security.safe_commands)} whitelisted
171
- - **Command Timeout**: {config.security.command_timeout} seconds
172
- - **OpenAI Model**: {config.openai.model}
 
173
 
174
- ### Security Settings
 
 
 
 
 
175
 
176
  **Safe Commands Whitelist:**
177
  ```
178
  {', '.join(config.security.safe_commands)}
179
  ```
180
 
181
- **Sensitive Operations:**
182
- - User management (add_user)
183
- - File operations (create_file, change_permission)
184
- - All require proper validation and logging
 
 
185
  """)
186
 
187
- # Configure MCP server
188
- demo.mcp_tools = tools # Gradio automatically exposes these as MCP tools
189
-
190
  return demo
191
 
192
  def main():
193
- """Main entry point for the Linux MCP server"""
194
 
195
- logger.info("Starting Linux MCP Server with Gradio")
196
- logger.info(f"OpenAI API configured: {'βœ…' if config.openai.api_key else '❌'}")
197
- logger.info(f"Safe commands: {len(config.security.safe_commands)}")
198
 
199
  # Create and launch the server
200
- demo = create_linux_mcp_server()
201
 
202
- # Launch with MCP server enabled
203
  demo.launch(
204
  share=config.gradio.share,
205
  server_name="0.0.0.0", # For HF Spaces
 
1
  """
2
+ Linux Administration Server using Gradio interface.
3
+ Provides both a web interface and functions that can be called by clients.
4
  """
5
 
6
  import gradio as gr
7
  import os
8
  import sys
9
+ import json
10
+ import subprocess
11
+ import logging
12
  from pathlib import Path
13
+ from typing import List, Optional
14
 
15
+ # Set up logging
16
+ logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger(__name__)
18
 
19
+ # Simple configuration (inline to avoid import issues)
20
+ SAFE_COMMANDS = ["ls", "df", "ps", "whoami", "pwd", "date", "uptime", "free", "cat", "head", "tail"]
21
+ COMMAND_TIMEOUT = 30
22
+
23
+ # Mock functions for HF Spaces (since real Linux commands won't work)
24
+ def run_safe_command(command: str, args: Optional[List[str]] = None,
25
+ working_directory: Optional[str] = None) -> dict:
26
+ """
27
+ Execute safe, whitelisted system commands.
28
+ NOTE: In HF Spaces, this will be simulated since container restrictions apply.
29
+ """
30
+ if command not in SAFE_COMMANDS:
31
+ return {
32
+ "success": False,
33
+ "error": f"Command '{command}' not in whitelist",
34
+ "whitelist": SAFE_COMMANDS,
35
+ "tool_type": "safe_command"
36
+ }
37
+
38
+ # Simulate command output for HF Spaces
39
+ try:
40
+ if command == "ls":
41
+ # Try real command first, fallback to simulation
42
+ try:
43
+ result = subprocess.run([command] + (args or []),
44
+ capture_output=True, text=True, timeout=5)
45
+ if result.returncode == 0:
46
+ return {
47
+ "success": True,
48
+ "output": result.stdout,
49
+ "command": f"{command} {' '.join(args or [])}",
50
+ "tool_type": "safe_command"
51
+ }
52
+ except:
53
+ pass
54
+
55
+ # Fallback simulation
56
+ return {
57
+ "success": True,
58
+ "output": "app.py\nrequirements.txt\nshared/\ntools/\nREADME.md",
59
+ "command": f"{command} {' '.join(args or [])}",
60
+ "tool_type": "safe_command",
61
+ "simulated": True
62
+ }
63
+
64
+ elif command == "df":
65
+ return {
66
+ "success": True,
67
+ "output": "Filesystem Size Used Avail Use% Mounted on\n/dev/sda1 20G 8.5G 10G 46% /\ntmpfs 2.0G 0 2.0G 0% /dev/shm",
68
+ "command": f"{command} {' '.join(args or [])}",
69
+ "tool_type": "safe_command",
70
+ "simulated": True
71
+ }
72
+
73
+ elif command == "ps":
74
+ return {
75
+ "success": True,
76
+ "output": "PID TTY TIME CMD\n1234 pts/0 00:00:01 python\n5678 pts/0 00:00:00 gradio",
77
+ "command": f"{command} {' '.join(args or [])}",
78
+ "tool_type": "safe_command",
79
+ "simulated": True
80
+ }
81
+
82
+ elif command == "whoami":
83
+ return {
84
+ "success": True,
85
+ "output": "user",
86
+ "command": command,
87
+ "tool_type": "safe_command",
88
+ "simulated": True
89
+ }
90
+
91
+ elif command == "pwd":
92
+ return {
93
+ "success": True,
94
+ "output": "/home/user/app",
95
+ "command": command,
96
+ "tool_type": "safe_command",
97
+ "simulated": True
98
+ }
99
+
100
+ elif command == "uptime":
101
+ return {
102
+ "success": True,
103
+ "output": "10:35:42 up 2 days, 14:23, 1 user, load average: 0.15, 0.10, 0.05",
104
+ "command": command,
105
+ "tool_type": "safe_command",
106
+ "simulated": True
107
+ }
108
+
109
+ else:
110
+ return {
111
+ "success": True,
112
+ "output": f"Command '{command}' executed successfully (simulated in HF Spaces)",
113
+ "command": f"{command} {' '.join(args or [])}",
114
+ "tool_type": "safe_command",
115
+ "simulated": True
116
+ }
117
+
118
+ except Exception as e:
119
+ return {
120
+ "success": False,
121
+ "error": f"Execution error: {str(e)}",
122
+ "tool_type": "safe_command"
123
+ }
124
+
125
+ def add_user(username: str, groups: Optional[List[str]] = None,
126
+ create_home: bool = True, shell: str = "/bin/bash") -> dict:
127
+ """
128
+ Simulate user addition (real commands won't work in HF Spaces).
129
+ """
130
+ if not username or len(username) < 2:
131
+ return {
132
+ "success": False,
133
+ "error": "Username must be at least 2 characters",
134
+ "tool_type": "sensitive_operation"
135
+ }
136
+
137
+ return {
138
+ "success": True,
139
+ "message": f"User '{username}' would be created successfully",
140
+ "details": {
141
+ "username": username,
142
+ "groups": groups or [],
143
+ "home_created": create_home,
144
+ "shell": shell
145
+ },
146
+ "tool_type": "sensitive_operation",
147
+ "simulated": True,
148
+ "note": "This is simulated in HF Spaces - real user creation requires system privileges"
149
+ }
150
+
151
+ def create_file(filepath: str, content: str, permissions: str = "644",
152
+ owner: Optional[str] = None) -> dict:
153
+ """
154
+ Simulate file creation (restricted in HF Spaces).
155
+ """
156
+ if not filepath or not content:
157
+ return {
158
+ "success": False,
159
+ "error": "Filepath and content are required",
160
+ "tool_type": "sensitive_operation"
161
+ }
162
+
163
+ return {
164
+ "success": True,
165
+ "message": f"File '{filepath}' would be created successfully",
166
+ "details": {
167
+ "path": filepath,
168
+ "permissions": permissions,
169
+ "owner": owner,
170
+ "size": len(content)
171
+ },
172
+ "tool_type": "sensitive_operation",
173
+ "simulated": True,
174
+ "note": "File creation is restricted in HF Spaces"
175
+ }
176
+
177
+ def change_permission(path: str, permissions: str, recursive: bool = False,
178
+ owner: Optional[str] = None) -> dict:
179
+ """
180
+ Simulate permission changes (not allowed in HF Spaces).
181
+ """
182
+ if not path or not permissions:
183
+ return {
184
+ "success": False,
185
+ "error": "Path and permissions are required",
186
+ "tool_type": "sensitive_operation"
187
+ }
188
+
189
+ return {
190
+ "success": True,
191
+ "message": f"Permissions for '{path}' would be changed to {permissions}",
192
+ "details": {
193
+ "path": path,
194
+ "permissions": permissions,
195
+ "recursive": recursive,
196
+ "owner": owner
197
+ },
198
+ "tool_type": "sensitive_operation",
199
+ "simulated": True,
200
+ "note": "Permission changes are restricted in HF Spaces"
201
+ }
202
+
203
+ def create_linux_server_interface():
204
+ """Create the Linux administration server interface."""
205
+
206
+ css = """
207
+ .gradio-container {
208
+ max-width: 1200px;
209
+ margin: auto;
210
+ }
211
+ .note-box {
212
+ background-color: #fff3cd;
213
+ border: 1px solid #ffeaa7;
214
+ border-radius: 5px;
215
+ padding: 10px;
216
+ margin: 10px 0;
217
+ }
218
+ """
219
+
220
+ with gr.Blocks(
221
+ title="Linux Administration Server",
222
+ theme="soft",
223
+ css=css
224
+ ) as demo:
225
+
226
+ gr.Markdown("""
227
+ # 🐧 Linux Administration Server
228
+
229
+ ## ⚠️ HF Spaces Demo Mode
230
+
231
+ **Note**: This is running in HuggingFace Spaces, so actual system commands are simulated for security.
232
+ In a real Linux environment, these tools would execute actual system operations.
233
+
234
+ ## πŸ› οΈ Available Tools
235
+
236
+ ### 🟒 Safe Operations (Read-Only)
237
+ - **List Files**: Show directory contents
238
+ - **Disk Space**: Check storage usage
239
+ - **Processes**: View running processes
240
+ - **System Info**: Uptime, current user, etc.
241
+
242
+ ### πŸ”΄ Sensitive Operations (Simulated)
243
+ - **User Management**: Add users (requires root privileges)
244
+ - **File Operations**: Create files with permissions
245
+ - **Permission Changes**: Modify file/directory access
246
+ """)
247
+
248
+ # Tool testing interface
249
+ with gr.Tab("πŸ§ͺ Test Tools"):
250
+ with gr.Row():
251
+ with gr.Column():
252
+ tool_selector = gr.Dropdown(
253
+ choices=["run_safe_command", "add_user", "create_file", "change_permission"],
254
+ label="Select Tool",
255
+ value="run_safe_command"
256
+ )
257
+
258
+ # Safe command inputs
259
+ with gr.Group(visible=True) as safe_inputs:
260
+ safe_command = gr.Dropdown(
261
+ choices=SAFE_COMMANDS,
262
+ label="Command",
263
+ value="ls"
264
+ )
265
+ safe_args = gr.Textbox(
266
+ label="Arguments (space-separated)",
267
+ placeholder="-la"
268
+ )
269
+
270
+ # User inputs
271
+ with gr.Group(visible=False) as user_inputs:
272
+ username = gr.Textbox(label="Username", placeholder="john")
273
+ groups = gr.Textbox(label="Groups (comma-separated)", placeholder="sudo,users")
274
+ create_home = gr.Checkbox(label="Create Home Directory", value=True)
275
+
276
+ # File inputs
277
+ with gr.Group(visible=False) as file_inputs:
278
+ filepath = gr.Textbox(label="File Path", placeholder="/tmp/test.txt")
279
+ content = gr.Textbox(label="File Content", lines=3, placeholder="Hello, World!")
280
+ permissions = gr.Textbox(label="Permissions", value="644")
281
+
282
+ test_button = gr.Button("πŸš€ Execute Tool", variant="primary")
283
+
284
+ with gr.Column():
285
+ test_output = gr.JSON(label="Tool Output")
286
+
287
+ # Event handlers
288
+ def update_inputs(tool_name):
289
+ return {
290
+ safe_inputs: gr.update(visible=(tool_name == "run_safe_command")),
291
+ user_inputs: gr.update(visible=(tool_name == "add_user")),
292
+ file_inputs: gr.update(visible=(tool_name in ["create_file", "change_permission"]))
293
+ }
294
+
295
+ tool_selector.change(
296
+ update_inputs,
297
+ inputs=[tool_selector],
298
+ outputs=[safe_inputs, user_inputs, file_inputs]
299
+ )
300
+
301
+ def execute_tool(tool_name, cmd, args, user, grps, home, path, cont, perms):
302
+ try:
303
+ logger.info(f"Executing tool: {tool_name}")
304
+
305
+ if tool_name == "run_safe_command":
306
+ args_list = args.split() if args else []
307
+ return run_safe_command(cmd, args_list)
308
+
309
+ elif tool_name == "add_user":
310
+ groups_list = [g.strip() for g in grps.split(",")] if grps else []
311
+ return add_user(user, groups_list, home)
312
+
313
+ elif tool_name == "create_file":
314
+ return create_file(path, cont, perms)
315
+
316
+ elif tool_name == "change_permission":
317
+ return change_permission(path, perms)
318
+
319
+ else:
320
+ return {"success": False, "error": f"Unknown tool: {tool_name}"}
321
+
322
+ except Exception as e:
323
+ logger.error(f"Tool execution error: {e}")
324
+ return {"success": False, "error": str(e)}
325
+
326
+ test_button.click(
327
+ execute_tool,
328
+ inputs=[
329
+ tool_selector, safe_command, safe_args,
330
+ username, groups, create_home,
331
+ filepath, content, permissions
332
+ ],
333
+ outputs=[test_output]
334
+ )
335
+
336
+ # Quick Actions
337
+ with gr.Tab("⚑ Quick Actions"):
338
+ with gr.Row():
339
+ with gr.Column():
340
+ gr.Markdown("#### 🟒 Safe Operations")
341
+ ls_btn = gr.Button("πŸ“ List Files")
342
+ df_btn = gr.Button("πŸ’Ύ Disk Space")
343
+ ps_btn = gr.Button("βš™οΈ Processes")
344
+ uptime_btn = gr.Button("⏰ Uptime")
345
+
346
+ with gr.Column():
347
+ quick_output = gr.Textbox(
348
+ label="Output",
349
+ lines=10,
350
+ placeholder="Command output will appear here..."
351
+ )
352
+
353
+ # Quick action handlers
354
+ ls_btn.click(lambda: run_safe_command("ls", ["-la"]).get("output", "Error"), outputs=quick_output)
355
+ df_btn.click(lambda: run_safe_command("df", ["-h"]).get("output", "Error"), outputs=quick_output)
356
+ ps_btn.click(lambda: run_safe_command("ps", ["aux"]).get("output", "Error"), outputs=quick_output)
357
+ uptime_btn.click(lambda: run_safe_command("uptime", []).get("output", "Error"), outputs=quick_output)
358
+
359
+ # System info
360
+ with gr.Tab("πŸ“Š System Info"):
361
+ gr.Markdown(f"""
362
+ ### Server Configuration
363
+
364
+ - **Environment**: HuggingFace Spaces (containerized)
365
+ - **Safe Commands**: {len(SAFE_COMMANDS)} available
366
+ - **Command Timeout**: {COMMAND_TIMEOUT} seconds
367
+ - **Security**: All operations validated and logged
368
+
369
+ ### Available Commands
370
+ ```
371
+ {', '.join(SAFE_COMMANDS)}
372
+ ```
373
+
374
+ ### Important Notes
375
+ - **Simulation Mode**: Real system commands are restricted in HF Spaces
376
+ - **Security**: Container isolation prevents actual system modifications
377
+ - **Demo Purpose**: Shows tool interfaces and validation logic
378
+ - **Production Use**: Deploy to full Linux environment for real operations
379
+ """)
380
+
381
+ return demo
382
+
383
+ def main():
384
+ """Main entry point"""
385
+ logger.info("πŸš€ Starting Linux Administration Server (HF Spaces Demo)")
386
+
387
+ demo = create_linux_server_interface()
388
+ demo.launch(
389
+ server_name="0.0.0.0",
390
+ server_port=7860,
391
+ show_error=True
392
+ )
393
+
394
+ if __name__ == "__main__":
395
+ main()
396
 
397
  # Set up logging
398
  logging.basicConfig(level=logging.INFO)
399
  logger = logging.getLogger(__name__)
400
 
401
+ def create_linux_server_interface():
402
  """
403
+ Create the Linux administration server interface.
404
+ Provides both web UI and callable functions.
405
  """
406
 
407
+ # Custom CSS for better appearance
408
+ css = """
409
+ .gradio-container {
410
+ max-width: 1200px;
411
+ margin: auto;
412
+ }
413
+ """
414
 
 
415
  with gr.Blocks(
416
  title=config.gradio.title,
417
+ theme=config.gradio.theme,
418
+ css=css
419
  ) as demo:
420
 
421
  gr.Markdown(f"""
422
  # {config.gradio.title}
423
 
424
+ ## πŸ› οΈ Linux Administration Tools
425
 
426
+ This server provides Linux administration capabilities with built-in security:
427
 
428
  ### 🟒 Safe Operations (Direct Execution)
429
+ - **List Files**: Show directory contents
430
+ - **Disk Space**: Check storage usage
431
+ - **Processes**: View running processes
432
+ - **System Info**: Uptime, users, etc.
433
 
434
  ### πŸ”΄ Sensitive Operations (Require Validation)
435
+ - **User Management**: Add/modify users
436
+ - **File Operations**: Create files with permissions
437
+ - **Permission Changes**: Modify file/directory access
438
 
439
+ ## πŸ”Œ API Integration
440
 
441
+ Connect external clients to use these tools programmatically.
 
442
 
443
+ ## πŸ“Š System Status
444
+ - **Available Tools**: 4 (safe + sensitive operations)
445
+ - **Safe Commands**: {len(config.security.safe_commands)} whitelisted
446
+ - **Security**: All operations validated and logged
447
  """)
448
 
449
+ # Tool testing interface
450
+ with gr.Tab("πŸ§ͺ Test Tools"):
451
+ gr.Markdown("### Test Linux Administration Tools")
452
 
453
  with gr.Row():
454
  with gr.Column():
 
482
  content = gr.Textbox(label="File Content", lines=3, placeholder="Hello, World!")
483
  permissions = gr.Textbox(label="Permissions", value="644", placeholder="644")
484
 
485
+ test_button = gr.Button("πŸš€ Execute Tool", variant="primary")
486
 
487
  with gr.Column():
488
  test_output = gr.JSON(label="Tool Output")
 
502
  )
503
 
504
  # Test tool execution
505
+ def execute_tool(tool_name, cmd, args, user, grps, home, path, cont, perms):
506
  try:
507
+ logger.info(f"Executing tool: {tool_name}")
508
+
509
  if tool_name == "run_safe_command":
510
  args_list = args.split() if args else []
511
  return run_safe_command(cmd, args_list)
 
521
  return change_permission(path, perms)
522
 
523
  else:
524
+ return {"success": False, "error": f"Unknown tool: {tool_name}"}
525
 
526
  except Exception as e:
527
+ logger.error(f"Tool execution error: {e}")
528
+ return {"success": False, "error": str(e)}
529
 
530
  test_button.click(
531
+ execute_tool,
532
  inputs=[
533
  tool_selector, safe_command, safe_args,
534
  username, groups, create_home,
 
537
  outputs=[test_output]
538
  )
539
 
540
+ # Quick Actions tab
541
+ with gr.Tab("⚑ Quick Actions"):
542
+ gr.Markdown("### Common Administration Tasks")
543
+
544
+ with gr.Row():
545
+ with gr.Column():
546
+ gr.Markdown("#### 🟒 Safe Operations")
547
+
548
+ ls_btn = gr.Button("πŸ“ List Files", size="sm")
549
+ df_btn = gr.Button("πŸ’Ύ Disk Space", size="sm")
550
+ ps_btn = gr.Button("βš™οΈ Processes", size="sm")
551
+ uptime_btn = gr.Button("⏰ Uptime", size="sm")
552
+
553
+ with gr.Column():
554
+ quick_output = gr.Textbox(
555
+ label="Output",
556
+ lines=10,
557
+ placeholder="Command output will appear here..."
558
+ )
559
+
560
+ # Quick action handlers
561
+ def quick_ls():
562
+ result = run_safe_command("ls", ["-la"])
563
+ return result.get("output", result.get("error", "No output"))
564
+
565
+ def quick_df():
566
+ result = run_safe_command("df", ["-h"])
567
+ return result.get("output", result.get("error", "No output"))
568
+
569
+ def quick_ps():
570
+ result = run_safe_command("ps", ["aux"])
571
+ return result.get("output", result.get("error", "No output"))
572
+
573
+ def quick_uptime():
574
+ result = run_safe_command("uptime", [])
575
+ return result.get("output", result.get("error", "No output"))
576
+
577
+ ls_btn.click(quick_ls, outputs=quick_output)
578
+ df_btn.click(quick_df, outputs=quick_output)
579
+ ps_btn.click(quick_ps, outputs=quick_output)
580
+ uptime_btn.click(quick_uptime, outputs=quick_output)
581
+
582
  # System info tab
583
+ with gr.Tab("πŸ“Š System Info"):
584
  gr.Markdown(f"""
585
  ### Server Configuration
586
 
587
+ **Tool Capabilities:**
588
+ - 🟒 **Safe Commands**: {len(config.security.safe_commands)} available
589
+ - πŸ”΄ **Sensitive Operations**: 3 available (user, file, permission management)
590
+ - ⏱️ **Command Timeout**: {config.security.command_timeout} seconds
591
+ - πŸ€– **AI Integration**: {config.openai.model}
592
 
593
+ **Security Features:**
594
+ - βœ… Command whitelisting for safe operations
595
+ - βœ… Input validation for all operations
596
+ - βœ… Path traversal protection
597
+ - βœ… User permission validation
598
+ - βœ… Comprehensive logging
599
 
600
  **Safe Commands Whitelist:**
601
  ```
602
  {', '.join(config.security.safe_commands)}
603
  ```
604
 
605
+ ### Usage Notes
606
+
607
+ - **Safe operations** execute immediately with validation
608
+ - **Sensitive operations** require careful parameter validation
609
+ - **All operations** are logged for security auditing
610
+ - **External clients** can call these functions programmatically
611
  """)
612
 
 
 
 
613
  return demo
614
 
615
  def main():
616
+ """Main entry point for the Linux administration server"""
617
 
618
+ logger.info("πŸš€ Starting Linux Administration Server")
619
+ logger.info(f"OpenAI configured: {'βœ…' if config.openai.api_key else '❌'}")
620
+ logger.info(f"Safe commands available: {len(config.security.safe_commands)}")
621
 
622
  # Create and launch the server
623
+ demo = create_linux_server_interface()
624
 
625
+ # Launch the interface
626
  demo.launch(
627
  share=config.gradio.share,
628
  server_name="0.0.0.0", # For HF Spaces