Spaces:
Paused
Paused
| """ | |
| Universal IDE MCP Server - Hugging Face Spaces Compatible | |
| No permission errors, no WebSockets | |
| """ | |
| import gradio as gr | |
| import subprocess | |
| import os | |
| import json | |
| import shutil | |
| from pathlib import Path | |
| import sys | |
| import traceback | |
| from typing import Dict, List, Optional, Tuple | |
| import uuid | |
| import tempfile | |
| # Set matplotlib config to temp directory to avoid permission errors | |
| os.environ['MPLCONFIGDIR'] = tempfile.gettempdir() | |
| class CodeExecutor: | |
| def __init__(self): | |
| # Use temp directory - always writable in HF Spaces | |
| self.work_dir = Path(tempfile.gettempdir()) / "code_executor" | |
| try: | |
| self.work_dir.mkdir(parents=True, exist_ok=True) | |
| except: | |
| # Fallback to system temp if mkdir fails | |
| self.work_dir = Path(tempfile.mkdtemp()) | |
| def execute_code(self, code: str, language: str) -> Tuple[str, str, bool]: | |
| """Execute code in specified language""" | |
| # Create unique session directory | |
| session_id = str(uuid.uuid4())[:8] | |
| # Use tempfile.mkdtemp() for guaranteed writable directory | |
| session_dir = Path(tempfile.mkdtemp(prefix=f"session_{session_id}_")) | |
| try: | |
| if language == "python": | |
| return self._execute_python(code, session_dir) | |
| elif language == "javascript": | |
| return self._execute_javascript(code, session_dir) | |
| elif language == "bash": | |
| return self._execute_bash(code, session_dir) | |
| elif language == "html": | |
| return self._preview_html(code, session_dir) | |
| else: | |
| return "", f"Language '{language}' not supported", False | |
| except Exception as e: | |
| return "", f"Error: {str(e)}", False | |
| finally: | |
| # Clean up session directory | |
| try: | |
| shutil.rmtree(session_dir, ignore_errors=True) | |
| except: | |
| pass | |
| def _execute_python(self, code: str, session_dir: Path) -> Tuple[str, str, bool]: | |
| """Execute Python code""" | |
| file_path = session_dir / "script.py" | |
| file_path.write_text(code) | |
| try: | |
| result = subprocess.run( | |
| [sys.executable, str(file_path)], | |
| capture_output=True, | |
| text=True, | |
| timeout=30, | |
| cwd=str(session_dir), | |
| env={**os.environ, 'MPLCONFIGDIR': str(session_dir)} | |
| ) | |
| return result.stdout, result.stderr, result.returncode == 0 | |
| except subprocess.TimeoutExpired: | |
| return "", "Execution timeout (30 seconds)", False | |
| except Exception as e: | |
| return "", f"Python execution error: {str(e)}", False | |
| def _execute_javascript(self, code: str, session_dir: Path) -> Tuple[str, str, bool]: | |
| """Execute JavaScript code if Node.js is available""" | |
| # Check if Node.js is installed | |
| try: | |
| node_version = subprocess.run( | |
| ["node", "--version"], | |
| capture_output=True, | |
| text=True, | |
| timeout=5 | |
| ) | |
| if node_version.returncode != 0: | |
| return "", "Node.js is not available in this environment", False | |
| except: | |
| return "", "Node.js is not installed. Please use Python instead.", False | |
| file_path = session_dir / "script.js" | |
| file_path.write_text(code) | |
| try: | |
| result = subprocess.run( | |
| ["node", str(file_path)], | |
| capture_output=True, | |
| text=True, | |
| timeout=30, | |
| cwd=str(session_dir) | |
| ) | |
| return result.stdout, result.stderr, result.returncode == 0 | |
| except subprocess.TimeoutExpired: | |
| return "", "Execution timeout (30 seconds)", False | |
| except Exception as e: | |
| return "", f"JavaScript execution error: {str(e)}", False | |
| def _execute_bash(self, code: str, session_dir: Path) -> Tuple[str, str, bool]: | |
| """Execute limited bash commands for security""" | |
| # Whitelist safe commands | |
| safe_commands = ['echo', 'date', 'pwd', 'ls', 'cat', 'head', 'tail', 'wc', 'sort', 'uniq'] | |
| first_cmd = code.strip().split()[0] if code.strip() else "" | |
| if first_cmd not in safe_commands: | |
| return "", f"Command '{first_cmd}' not allowed. Allowed: {', '.join(safe_commands)}", False | |
| try: | |
| result = subprocess.run( | |
| code, | |
| shell=True, | |
| capture_output=True, | |
| text=True, | |
| timeout=10, | |
| cwd=str(session_dir) | |
| ) | |
| return result.stdout, result.stderr, result.returncode == 0 | |
| except subprocess.TimeoutExpired: | |
| return "", "Execution timeout (10 seconds)", False | |
| except Exception as e: | |
| return "", f"Bash execution error: {str(e)}", False | |
| def _preview_html(self, code: str, session_dir: Path) -> Tuple[str, str, bool]: | |
| """Generate HTML preview""" | |
| file_path = session_dir / "index.html" | |
| file_path.write_text(code) | |
| # Extract basic info from HTML | |
| import re | |
| title = "Untitled" | |
| title_match = re.search(r'<title>(.*?)</title>', code, re.IGNORECASE) | |
| if title_match: | |
| title = title_match.group(1) | |
| # Count elements | |
| elements = { | |
| 'divs': len(re.findall(r'<div', code, re.IGNORECASE)), | |
| 'links': len(re.findall(r'<a\s', code, re.IGNORECASE)), | |
| 'images': len(re.findall(r'<img\s', code, re.IGNORECASE)), | |
| 'scripts': len(re.findall(r'<script', code, re.IGNORECASE)) | |
| } | |
| preview = f"π HTML Preview\n" | |
| preview += f"Title: {title}\n" | |
| preview += f"Elements: {elements['divs']} divs, {elements['links']} links, " | |
| preview += f"{elements['images']} images, {elements['scripts']} scripts\n" | |
| preview += f"Total size: {len(code)} bytes" | |
| return preview, "", True | |
| # Create Gradio Interface | |
| def create_interface(): | |
| executor = CodeExecutor() | |
| def run_code(code, language): | |
| """Execute code and return output""" | |
| if not code.strip(): | |
| return "β οΈ Please enter some code to execute", "No code provided" | |
| stdout, stderr, success = executor.execute_code(code, language) | |
| # Format output | |
| output = "" | |
| if stdout: | |
| output = "π€ Output:\n" + stdout | |
| if stderr: | |
| if output: | |
| output += "\n" | |
| output += "β οΈ Warnings/Errors:\n" + stderr | |
| if not output: | |
| output = "β Code executed successfully (no output)" | |
| status = "β Success" if success else "β Failed" | |
| return output, status | |
| # Build Gradio interface | |
| with gr.Blocks( | |
| title="Universal IDE MCP Server", | |
| theme=gr.themes.Soft() | |
| ) as app: | |
| gr.Markdown(""" | |
| # π Universal IDE MCP Server | |
| **Multi-language code execution environment for Hugging Face Spaces** | |
| Supported: Python β | JavaScript β οΈ | Bash π | HTML π | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=3): | |
| code_input = gr.Code( | |
| label="Code Editor", | |
| language="python", | |
| value="""# Welcome! Try running this Python code | |
| def fibonacci(n): | |
| if n <= 1: | |
| return n | |
| return fibonacci(n-1) + fibonacci(n-2) | |
| # Calculate first 10 Fibonacci numbers | |
| for i in range(10): | |
| print(f"F({i}) = {fibonacci(i)}") | |
| """, | |
| lines=15 | |
| ) | |
| with gr.Row(): | |
| language_select = gr.Dropdown( | |
| choices=["python", "javascript", "bash", "html"], | |
| value="python", | |
| label="Language", | |
| interactive=True | |
| ) | |
| run_button = gr.Button("βΆοΈ Run Code", variant="primary", size="lg") | |
| with gr.Column(scale=2): | |
| output_text = gr.Textbox( | |
| label="Output", | |
| lines=12, | |
| max_lines=20, | |
| interactive=False, | |
| show_copy_button=True | |
| ) | |
| status_text = gr.Textbox( | |
| label="Status", | |
| lines=1, | |
| interactive=False | |
| ) | |
| # Examples | |
| gr.Examples( | |
| examples=[ | |
| ["""# Python: Data Analysis | |
| import json | |
| from datetime import datetime | |
| data = { | |
| "name": "Sample Analysis", | |
| "timestamp": str(datetime.now()), | |
| "values": [10, 20, 30, 40, 50] | |
| } | |
| # Calculate statistics | |
| values = data["values"] | |
| total = sum(values) | |
| average = total / len(values) | |
| maximum = max(values) | |
| minimum = min(values) | |
| print(f"Analysis: {data['name']}") | |
| print(f"Time: {data['timestamp']}") | |
| print(f"\\nStatistics:") | |
| print(f" Count: {len(values)}") | |
| print(f" Sum: {total}") | |
| print(f" Average: {average:.2f}") | |
| print(f" Min: {minimum}") | |
| print(f" Max: {maximum}") | |
| """, "python"], | |
| ["""// JavaScript: Array Operations | |
| const numbers = [1, 2, 3, 4, 5]; | |
| // Map, filter, reduce examples | |
| const doubled = numbers.map(n => n * 2); | |
| const evens = numbers.filter(n => n % 2 === 0); | |
| const sum = numbers.reduce((a, b) => a + b, 0); | |
| console.log('Original:', numbers); | |
| console.log('Doubled:', doubled); | |
| console.log('Even numbers:', evens); | |
| console.log('Sum:', sum); | |
| // Object manipulation | |
| const user = { | |
| name: 'Alice', | |
| age: 30, | |
| skills: ['Python', 'JavaScript'] | |
| }; | |
| console.log('\\nUser Info:'); | |
| console.log(JSON.stringify(user, null, 2)); | |
| """, "javascript"], | |
| ["""echo "System Information" | |
| echo "==================" | |
| date | |
| echo "" | |
| echo "Working Directory:" | |
| pwd | |
| echo "" | |
| echo "Directory Contents:" | |
| ls -la | |
| echo "" | |
| echo "Environment Sample:" | |
| echo "USER: $USER" | |
| echo "HOME: $HOME" | |
| """, "bash"], | |
| ["""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Sample Dashboard</title> | |
| <style> | |
| body { | |
| font-family: Arial, sans-serif; | |
| margin: 20px; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| } | |
| h1 { | |
| color: #333; | |
| } | |
| .card { | |
| border: 1px solid #ddd; | |
| padding: 15px; | |
| margin: 10px 0; | |
| border-radius: 5px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>Dashboard</h1> | |
| <div class="card"> | |
| <h2>Statistics</h2> | |
| <p>Users: 1,234</p> | |
| <p>Active: 89%</p> | |
| </div> | |
| <div class="card"> | |
| <h2>Recent Activity</h2> | |
| <ul> | |
| <li>User login: 10:30 AM</li> | |
| <li>Data updated: 10:15 AM</li> | |
| <li>Report generated: 9:45 AM</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </body> | |
| </html>""", "html"] | |
| ], | |
| inputs=[code_input, language_select], | |
| label="Example Code" | |
| ) | |
| # Connect events | |
| run_button.click( | |
| run_code, | |
| inputs=[code_input, language_select], | |
| outputs=[output_text, status_text] | |
| ) | |
| # Update code highlighting when language changes | |
| def update_language(lang): | |
| return gr.Code(language=lang) | |
| language_select.change( | |
| update_language, | |
| inputs=[language_select], | |
| outputs=[code_input] | |
| ) | |
| gr.Markdown(""" | |
| --- | |
| ### π Features & Limitations | |
| - **Python**: Full support with standard library | |
| - **JavaScript**: Requires Node.js (may not be available) | |
| - **Bash**: Limited to safe commands only | |
| - **HTML**: Preview mode, shows structure analysis | |
| ### π Security | |
| - Sandboxed execution with 30-second timeout | |
| - Isolated sessions with automatic cleanup | |
| - Restricted bash commands for safety | |
| ### π MCP Integration | |
| This server can be extended with MCP protocol support for AI assistants. | |
| """) | |
| return app | |
| # Launch the app | |
| if __name__ == "__main__": | |
| app = create_interface() | |
| app.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False | |
| ) |