diff --git a/mcp_browser/__main__.py b/mcp_browser/__main__.py
index b4f49e1..a36c7b9 100644
--- a/mcp_browser/__main__.py
+++ b/mcp_browser/__main__.py
@@ -3,17 +3,158 @@
 MCP Browser command-line interface.
 """
 
+import os
 import sys
 import asyncio
 import argparse
 import json
+import signal
 from pathlib import Path
-from typing import Optional
+from typing import Optional, Dict, Any
 import yaml
 
 from .proxy import MCPBrowser
 from .config import ConfigLoader
 from .default_configs import ConfigManager
+from .daemon import MCPBrowserDaemon, MCPBrowserClient, get_socket_path, is_daemon_running
+from .utils import debug_print, debug_json
+
+
+def build_mcp_request(args) -> Dict[str, Any]:
+    """Build JSON-RPC request from command line arguments."""
+    if args.command == "tools-list":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "tools/list",
+            "params": {}
+        }
+    
+    elif args.command == "tools-call":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "tools/call",
+            "params": {
+                "name": args.name,
+                "arguments": json.loads(args.arguments)
+            }
+        }
+    
+    elif args.command == "resources-list":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "resources/list",
+            "params": {}
+        }
+    
+    elif args.command == "resources-read":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "resources/read",
+            "params": {
+                "uri": args.uri
+            }
+        }
+    
+    elif args.command == "prompts-list":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "prompts/list",
+            "params": {}
+        }
+    
+    elif args.command == "prompts-get":
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "prompts/get",
+            "params": {
+                "name": args.name,
+                "arguments": json.loads(args.arguments)
+            }
+        }
+    
+    elif args.command == "completion":
+        params = {}
+        if args.ref:
+            params["ref"] = {"type": "ref/resource", "uri": args.ref}
+        if args.argument:
+            params["argument"] = args.argument
+            
+        return {
+            "jsonrpc": "2.0",
+            "id": 1,
+            "method": "completion/complete",
+            "params": params
+        }
+    
+    elif args.command == "jsonrpc":
+        request = json.loads(args.request)
+        if "jsonrpc" not in request:
+            request["jsonrpc"] = "2.0"
+        if "id" not in request:
+            request["id"] = 1
+        return request
+    
+    else:
+        raise ValueError(f"Unknown command: {args.command}")
+
+
+def format_mcp_response(args, request: Dict[str, Any], response: Dict[str, Any]):
+    """Format and print MCP response based on command."""
+    if args.debug:
+        debug_json("Request", request)
+        debug_json("Response", response)
+    
+    # Format output based on command
+    if args.command == "tools-list" and "result" in response:
+        tools = response["result"].get("tools", [])
+        print(f"Found {len(tools)} tools:")
+        for tool in tools:
+            print(f"  - {tool['name']}: {tool.get('description', 'No description')}")
+    
+    elif args.command == "tools-call" and "result" in response:
+        # Format tool response
+        result = response["result"]
+        if "content" in result:
+            for content in result["content"]:
+                if content.get("type") == "text":
+                    print(content.get("text", ""))
+                else:
+                    print(json.dumps(content, indent=2))
+        else:
+            print(json.dumps(result, indent=2))
+    
+    elif args.command == "resources-list" and "result" in response:
+        resources = response["result"].get("resources", [])
+        print(f"Found {len(resources)} resources:")
+        for res in resources:
+            print(f"  - {res['uri']}: {res.get('name', 'Unnamed')}")
+    
+    elif args.command == "prompts-list" and "result" in response:
+        prompts = response["result"].get("prompts", [])
+        print(f"Found {len(prompts)} prompts:")
+        for prompt in prompts:
+            print(f"  - {prompt['name']}: {prompt.get('description', 'No description')}")
+    
+    elif args.command == "jsonrpc":
+        # For raw JSON-RPC, output the full response as JSON
+        print(json.dumps(response))
+    
+    else:
+        # Default: pretty print result
+        if "result" in response:
+            print(json.dumps(response["result"], indent=2))
+        elif "error" in response:
+            print(f"Error: {response['error'].get('message', 'Unknown error')}")
+            if args.debug:
+                debug_json("Error details", response["error"])
+        else:
+            print(json.dumps(response, indent=2))
 
 
 async def interactive_mode(browser: MCPBrowser):
@@ -161,6 +302,130 @@ async def test_server_connection(browser: MCPBrowser, server_name: Optional[str]
     print("\nConnection test completed successfully!")
 
 
+async def handle_mcp_command(args):
+    """Handle MCP method commands by simulating JSON-RPC calls."""
+    # Check if we should use daemon mode
+    socket_path = get_socket_path(args.server)
+    
+    if hasattr(args, 'use_daemon') and args.use_daemon and is_daemon_running(socket_path):
+        # Use daemon client
+        async with MCPBrowserClient(socket_path) as client:
+            request = build_mcp_request(args)
+            response = await client.call(request)
+            format_mcp_response(args, request, response)
+        return
+    
+    # Create browser directly
+    config_path = Path(args.config) if args.config else None
+    
+    # Set debug in config if requested
+    if args.debug and config_path is None:
+        from .config import ConfigLoader
+        loader = ConfigLoader()
+        config = loader.load()
+        config.debug = True
+    
+    browser = MCPBrowser(
+        server_name=args.server,
+        config_path=config_path,
+        enable_builtin_servers=not args.no_builtin
+    )
+    
+    try:
+        await browser.initialize()
+        
+        # Build and send request
+        request = build_mcp_request(args)
+        response = await browser.call(request)
+        
+        # Format response
+        format_mcp_response(args, request, response)
+        
+    except Exception as e:
+        print(f"Error: {e}")
+        if args.debug:
+            import traceback
+            traceback.print_exc(file=sys.stderr)
+    finally:
+        await browser.close()
+
+
+async def run_daemon_mode(browser: MCPBrowser, socket_path: Path):
+    """Run MCP Browser in daemon mode."""
+    daemon = MCPBrowserDaemon(browser, socket_path)
+    await daemon.start()
+
+
+async def start_daemon_background(args):
+    """Start daemon in background."""
+    socket_path = get_socket_path(args.server)
+    
+    if is_daemon_running(socket_path):
+        print(f"Daemon already running for server: {args.server or 'default'}")
+        return
+    
+    # Fork to background
+    pid = os.fork()
+    if pid > 0:
+        # Parent process
+        print(f"Starting daemon in background (PID: {pid})")
+        return
+    
+    # Child process
+    # Detach from terminal
+    os.setsid()
+    
+    # Redirect stdout/stderr to log file
+    log_dir = socket_path.parent / "logs"
+    log_dir.mkdir(exist_ok=True)
+    log_file = log_dir / f"mcp-browser-{args.server or 'default'}.log"
+    
+    with open(log_file, 'a') as log:
+        sys.stdout = log
+        sys.stderr = log
+        
+        # Create browser
+        config_path = Path(args.config) if args.config else None
+        browser = MCPBrowser(
+            server_name=args.server,
+            config_path=config_path,
+            enable_builtin_servers=not args.no_builtin
+        )
+        
+        # Run daemon
+        asyncio.run(run_daemon_mode(browser, socket_path))
+
+
+def stop_daemon(args):
+    """Stop running daemon."""
+    socket_path = get_socket_path(args.server)
+    
+    if not is_daemon_running(socket_path):
+        print(f"No daemon running for server: {args.server or 'default'}")
+        return
+    
+    pid_file = socket_path.with_suffix('.pid')
+    try:
+        pid = int(pid_file.read_text().strip())
+        os.kill(pid, signal.SIGTERM)
+        print(f"Sent SIGTERM to daemon (PID: {pid})")
+    except Exception as e:
+        print(f"Error stopping daemon: {e}")
+
+
+def show_daemon_status(args):
+    """Show daemon status."""
+    socket_path = get_socket_path(args.server)
+    
+    if is_daemon_running(socket_path):
+        pid_file = socket_path.with_suffix('.pid')
+        pid = pid_file.read_text().strip()
+        print(f"Daemon running (PID: {pid})")
+        print(f"Socket: {socket_path}")
+    else:
+        print(f"No daemon running for server: {args.server or 'default'}")
+
+
 async def run_server_mode(browser: MCPBrowser):
     """Run MCP Browser as an MCP server (stdin/stdout)."""
     import sys
@@ -193,16 +458,116 @@ async def run_server_mode(browser: MCPBrowser):
             break
 
 
+async def run_server_mode_with_daemon(socket_path: Path):
+    """Run as MCP server but forward to daemon."""
+    import sys
+    
+    async with MCPBrowserClient(socket_path) as client:
+        # Read JSON-RPC from stdin, forward to daemon, write to stdout
+        buffer = ""
+        while True:
+            try:
+                chunk = sys.stdin.read(4096)
+                if not chunk:
+                    break
+                    
+                buffer += chunk
+                while '\n' in buffer:
+                    line, buffer = buffer.split('\n', 1)
+                    if line.strip():
+                        try:
+                            request = json.loads(line)
+                            response = await client.call(request)
+                            print(json.dumps(response))
+                            sys.stdout.flush()
+                        except json.JSONDecodeError:
+                            pass
+                            
+            except KeyboardInterrupt:
+                break
+            except EOFError:
+                break
+
+
+async def interactive_mode_with_daemon(socket_path: Path):
+    """Run interactive mode connected to daemon."""
+    async with MCPBrowserClient(socket_path) as client:
+        print("MCP Browser Interactive Mode (Daemon)")
+        print("=" * 50)
+        print(f"Connected to daemon at: {socket_path}")
+        print("Type 'help' for commands, 'exit' to quit\n")
+        
+        while True:
+            try:
+                command = input("> ").strip()
+                
+                if command == "exit":
+                    break
+                elif command == "help":
+                    print("\nCommands:")
+                    print("  list              - List available tools (sparse mode)")
+                    print("  discover <path>   - Discover tools using JSONPath") 
+                    print("  call <json>       - Execute JSON-RPC call")
+                    print("  exit              - Exit interactive mode")
+                    continue
+                    
+                elif command.startswith("call "):
+                    json_str = command[5:]
+                    request = json.loads(json_str)
+                    if "jsonrpc" not in request:
+                        request["jsonrpc"] = "2.0"
+                    if "id" not in request:
+                        request["id"] = 1
+                    response = await client.call(request)
+                    print(json.dumps(response, indent=2))
+                    
+                elif command == "list":
+                    response = await client.call({
+                        "jsonrpc": "2.0",
+                        "id": 1,
+                        "method": "tools/list"
+                    })
+                    if "result" in response:
+                        tools = response["result"]["tools"]
+                        for tool in tools:
+                            print(f"- {tool['name']}: {tool['description']}")
+                            
+                else:
+                    print("Unknown command. Type 'help' for available commands.")
+                    
+            except KeyboardInterrupt:
+                print("\nUse 'exit' to quit")
+            except Exception as e:
+                print(f"Error: {e}")
+
+
 def main():
     """Main entry point."""
     parser = argparse.ArgumentParser(
         description="MCP Browser - Universal Model Context Protocol Interface",
         epilog="""
 Examples:
+  # Interactive mode
   mcp-browser                          # Start interactive mode with default server
   mcp-browser --server brave-search    # Use Brave Search server
+  
+  # Configuration
   mcp-browser --list-servers           # List configured servers
   mcp-browser --show-config            # Show current configuration
+  mcp-browser --test                   # Test server connection
+  
+  # MCP method commands
+  mcp-browser tools-list               # List available tools
+  mcp-browser tools-call brave_web_search '{"query": "MCP protocol"}'
+  mcp-browser resources-list           # List available resources
+  mcp-browser resources-read "file:///path/to/file"
+  mcp-browser prompts-list             # List available prompts
+  mcp-browser prompts-get "greeting" --arguments '{"name": "Alice"}'
+  
+  # Raw JSON-RPC
+  mcp-browser jsonrpc '{"method": "tools/list", "params": {}}'
+  
+  # Server mode
   mcp-browser --mode server            # Run as MCP server (stdin/stdout)
   
 Configuration:
@@ -217,7 +582,7 @@ Environment:
     )
     parser.add_argument("--server", "-s", help="Target MCP server name (see --list-servers)")
     parser.add_argument("--config", "-c", help="Custom configuration file path")
-    parser.add_argument("--mode", choices=["interactive", "server"], 
+    parser.add_argument("--mode", choices=["interactive", "server", "daemon"], 
                        default="interactive", help="Operating mode (default: interactive)")
     parser.add_argument("--no-sparse", action="store_true", 
                        help="Disable sparse mode (show all tools)")
@@ -231,6 +596,49 @@ Environment:
                        help="Test connection to specified server")
     parser.add_argument("--debug", action="store_true",
                        help="Enable debug output")
+    parser.add_argument("--use-daemon", action="store_true",
+                       help="Automatically use daemon if available")
+    parser.add_argument("--daemon-start", action="store_true",
+                       help="Start daemon in background")
+    parser.add_argument("--daemon-stop", action="store_true",
+                       help="Stop running daemon")
+    parser.add_argument("--daemon-status", action="store_true",
+                       help="Check daemon status")
+    
+    # MCP method commands
+    subparsers = parser.add_subparsers(dest="command", help="MCP methods")
+    
+    # tools/list command
+    list_tools = subparsers.add_parser("tools-list", help="List available tools")
+    
+    # tools/call command
+    call_tool = subparsers.add_parser("tools-call", help="Call a tool")
+    call_tool.add_argument("name", help="Tool name")
+    call_tool.add_argument("arguments", help="Tool arguments as JSON")
+    
+    # resources/list command
+    list_resources = subparsers.add_parser("resources-list", help="List available resources")
+    
+    # resources/read command
+    read_resource = subparsers.add_parser("resources-read", help="Read a resource")
+    read_resource.add_argument("uri", help="Resource URI")
+    
+    # prompts/list command
+    list_prompts = subparsers.add_parser("prompts-list", help="List available prompts")
+    
+    # prompts/get command
+    get_prompt = subparsers.add_parser("prompts-get", help="Get a prompt")
+    get_prompt.add_argument("name", help="Prompt name")
+    get_prompt.add_argument("--arguments", "-a", help="Prompt arguments as JSON", default="{}")
+    
+    # completion command
+    completion = subparsers.add_parser("completion", help="Get completion")
+    completion.add_argument("--ref", help="Reference for completion")
+    completion.add_argument("--argument", help="Argument name")
+    
+    # Generic JSON-RPC command
+    jsonrpc = subparsers.add_parser("jsonrpc", help="Send raw JSON-RPC request")
+    jsonrpc.add_argument("request", help="JSON-RPC request")
     
     args = parser.parse_args()
     
@@ -243,6 +651,24 @@ Environment:
         show_configuration(args.config)
         return
     
+    # Handle daemon management commands
+    if args.daemon_start:
+        asyncio.run(start_daemon_background(args))
+        return
+    
+    if args.daemon_stop:
+        stop_daemon(args)
+        return
+    
+    if args.daemon_status:
+        show_daemon_status(args)
+        return
+    
+    # Handle MCP method commands
+    if args.command:
+        asyncio.run(handle_mcp_command(args))
+        return
+    
     # Create browser
     config_path = Path(args.config) if args.config else None
     browser = MCPBrowser(
@@ -258,9 +684,24 @@ Environment:
     
     # Run in appropriate mode
     if args.mode == "server":
-        asyncio.run(run_server_mode(browser))
+        # Run as MCP server (stdin/stdout) - can connect to daemon
+        socket_path = get_socket_path(args.server)
+        if args.use_daemon and is_daemon_running(socket_path):
+            # Use daemon as backend
+            asyncio.run(run_server_mode_with_daemon(socket_path))
+        else:
+            asyncio.run(run_server_mode(browser))
+    elif args.mode == "daemon":
+        # Run as daemon
+        socket_path = get_socket_path(args.server)
+        asyncio.run(run_daemon_mode(browser, socket_path))
     else:
-        asyncio.run(async_main(browser))
+        # Interactive mode - can use daemon if available
+        socket_path = get_socket_path(args.server)
+        if args.use_daemon and is_daemon_running(socket_path):
+            asyncio.run(interactive_mode_with_daemon(socket_path))
+        else:
+            asyncio.run(async_main(browser))
 
 
 async def async_main(browser: MCPBrowser):
diff --git a/mcp_browser/daemon.py b/mcp_browser/daemon.py
new file mode 100644
index 0000000..d2ce6e3
--- /dev/null
+++ b/mcp_browser/daemon.py
@@ -0,0 +1,276 @@
+"""
+MCP Browser daemon implementation using Unix domain sockets.
+
+Provides a persistent MCP Browser instance that multiple clients can connect to,
+allowing shared state and better performance.
+"""
+
+import os
+import json
+import asyncio
+import socket
+from pathlib import Path
+from typing import Optional, Dict, Any
+import signal
+import sys
+
+try:
+    import psutil
+except ImportError:
+    # Fallback if psutil is not available
+    class psutil:
+        @staticmethod
+        def pid_exists(pid):
+            try:
+                os.kill(pid, 0)
+                return True
+            except OSError:
+                return False
+
+from .proxy import MCPBrowser
+from .utils import debug_print, debug_json
+
+
+class MCPBrowserDaemon:
+    """Daemon mode for MCP Browser using Unix domain sockets."""
+    
+    def __init__(self, browser: MCPBrowser, socket_path: Path):
+        self.browser = browser
+        self.socket_path = socket_path
+        self.server: Optional[asyncio.Server] = None
+        self._running = False
+        self._clients: set = set()
+        
+    async def start(self):
+        """Start the daemon server."""
+        # Ensure socket directory exists
+        self.socket_path.parent.mkdir(parents=True, exist_ok=True)
+        
+        # Remove existing socket if present
+        if self.socket_path.exists():
+            self.socket_path.unlink()
+        
+        # Create Unix domain socket server
+        self.server = await asyncio.start_unix_server(
+            self._handle_client,
+            path=str(self.socket_path)
+        )
+        
+        # Set permissions
+        os.chmod(self.socket_path, 0o600)
+        
+        # Write PID file
+        pid_file = self.socket_path.with_suffix('.pid')
+        pid_file.write_text(str(os.getpid()))
+        
+        self._running = True
+        
+        # Set up signal handlers
+        signal.signal(signal.SIGTERM, self._signal_handler)
+        signal.signal(signal.SIGINT, self._signal_handler)
+        
+        debug_print(f"MCP Browser daemon started on {self.socket_path}")
+        debug_print(f"PID: {os.getpid()}")
+        
+        # Initialize browser
+        await self.browser.initialize()
+        
+        # Run server
+        async with self.server:
+            await self.server.serve_forever()
+    
+    def _signal_handler(self, signum, frame):
+        """Handle shutdown signals."""
+        debug_print(f"\nReceived signal {signum}, shutting down...")
+        self._running = False
+        if self.server:
+            self.server.close()
+        sys.exit(0)
+    
+    async def _handle_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
+        """Handle a client connection."""
+        client_addr = writer.get_extra_info('peername')
+        debug_print(f"Client connected: {client_addr}")
+        self._clients.add(writer)
+        
+        try:
+            buffer = ""
+            while self._running:
+                # Read data from client
+                data = await reader.read(4096)
+                if not data:
+                    break
+                
+                buffer += data.decode('utf-8')
+                
+                # Process complete JSON objects
+                while '\n' in buffer:
+                    line, buffer = buffer.split('\n', 1)
+                    if line.strip():
+                        await self._process_request(line, writer)
+                        
+        except asyncio.CancelledError:
+            pass
+        except Exception as e:
+            debug_print(f"Client error: {e}")
+        finally:
+            self._clients.discard(writer)
+            writer.close()
+            await writer.wait_closed()
+            debug_print(f"Client disconnected: {client_addr}")
+    
+    async def _process_request(self, line: str, writer: asyncio.StreamWriter):
+        """Process a JSON-RPC request from client."""
+        try:
+            request = json.loads(line)
+            
+            # Add debug output if configured
+            if self.browser.config and self.browser.config.debug:
+                debug_json("Daemon received", request)
+            
+            # Forward to browser
+            response = await self.browser.call(request)
+            
+            # Send response back to client
+            response_str = json.dumps(response) + '\n'
+            writer.write(response_str.encode('utf-8'))
+            await writer.drain()
+            
+            if self.browser.config and self.browser.config.debug:
+                debug_print(f"Daemon sent: {response_str.strip()}")
+                
+        except json.JSONDecodeError as e:
+            error_response = {
+                "jsonrpc": "2.0",
+                "id": None,
+                "error": {
+                    "code": -32700,
+                    "message": f"Parse error: {e}"
+                }
+            }
+            writer.write((json.dumps(error_response) + '\n').encode('utf-8'))
+            await writer.drain()
+        except Exception as e:
+            error_response = {
+                "jsonrpc": "2.0",
+                "id": request.get("id") if 'request' in locals() else None,
+                "error": {
+                    "code": -32603,
+                    "message": f"Internal error: {e}"
+                }
+            }
+            writer.write((json.dumps(error_response) + '\n').encode('utf-8'))
+            await writer.drain()
+    
+    async def stop(self):
+        """Stop the daemon server."""
+        self._running = False
+        
+        # Close all client connections
+        for writer in list(self._clients):
+            writer.close()
+            await writer.wait_closed()
+        
+        # Close server
+        if self.server:
+            self.server.close()
+            await self.server.wait_closed()
+        
+        # Clean up socket and PID files
+        if self.socket_path.exists():
+            self.socket_path.unlink()
+        
+        pid_file = self.socket_path.with_suffix('.pid')
+        if pid_file.exists():
+            pid_file.unlink()
+        
+        # Close browser
+        await self.browser.close()
+
+
+class MCPBrowserClient:
+    """Client for connecting to MCP Browser daemon."""
+    
+    def __init__(self, socket_path: Path):
+        self.socket_path = socket_path
+        self.reader: Optional[asyncio.StreamReader] = None
+        self.writer: Optional[asyncio.StreamWriter] = None
+        
+    async def connect(self):
+        """Connect to the daemon."""
+        if not self.socket_path.exists():
+            raise ConnectionError(f"Daemon socket not found: {self.socket_path}")
+        
+        # Check if daemon is alive
+        pid_file = self.socket_path.with_suffix('.pid')
+        if pid_file.exists():
+            try:
+                pid = int(pid_file.read_text().strip())
+                if not psutil.pid_exists(pid):
+                    # Stale socket/PID file
+                    self.socket_path.unlink()
+                    pid_file.unlink()
+                    raise ConnectionError("Daemon not running (stale PID file)")
+            except (ValueError, psutil.Error):
+                pass
+        
+        # Connect to socket
+        self.reader, self.writer = await asyncio.open_unix_connection(str(self.socket_path))
+    
+    async def call(self, request: Dict[str, Any]) -> Dict[str, Any]:
+        """Send a JSON-RPC request and get response."""
+        if not self.writer:
+            await self.connect()
+        
+        # Send request
+        request_str = json.dumps(request) + '\n'
+        self.writer.write(request_str.encode('utf-8'))
+        await self.writer.drain()
+        
+        # Read response
+        response_line = await self.reader.readline()
+        if not response_line:
+            raise ConnectionError("Connection closed by daemon")
+        
+        return json.loads(response_line.decode('utf-8'))
+    
+    async def close(self):
+        """Close the connection."""
+        if self.writer:
+            self.writer.close()
+            await self.writer.wait_closed()
+    
+    async def __aenter__(self):
+        """Async context manager entry."""
+        await self.connect()
+        return self
+    
+    async def __aexit__(self, exc_type, exc_val, exc_tb):
+        """Async context manager exit."""
+        await self.close()
+
+
+def get_socket_path(server_name: Optional[str] = None) -> Path:
+    """Get the socket path for a given server name."""
+    runtime_dir = os.environ.get('XDG_RUNTIME_DIR')
+    if not runtime_dir:
+        runtime_dir = f"/tmp/mcp-browser-{os.getuid()}"
+    
+    socket_name = f"mcp-browser-{server_name}.sock" if server_name else "mcp-browser.sock"
+    return Path(runtime_dir) / socket_name
+
+
+def is_daemon_running(socket_path: Path) -> bool:
+    """Check if a daemon is running for the given socket."""
+    if not socket_path.exists():
+        return False
+    
+    pid_file = socket_path.with_suffix('.pid')
+    if not pid_file.exists():
+        return False
+    
+    try:
+        pid = int(pid_file.read_text().strip())
+        return psutil.pid_exists(pid)
+    except (ValueError, psutil.Error):
+        return False
\ No newline at end of file
diff --git a/mcp_browser/proxy.py b/mcp_browser/proxy.py
index 3b76786..3e1a8e9 100644
--- a/mcp_browser/proxy.py
+++ b/mcp_browser/proxy.py
@@ -16,6 +16,7 @@ from .multi_server import MultiServerManager
 from .registry import ToolRegistry
 from .filter import MessageFilter, VirtualToolHandler
 from .buffer import JsonRpcBuffer
+from .utils import debug_print, debug_json
 
 
 class MCPBrowser:
@@ -166,6 +167,52 @@ class MCPBrowser:
                         "error": {"code": -32603, "message": str(e)}
                     }
         
+        # Check if we have a server
+        if not self.server:
+            # In builtin-only mode, try to route to multi-server
+            if self.multi_server:
+                # Try to route based on method
+                if jsonrpc_object.get("method") == "tools/list":
+                    # Apply filter to multi-server tools
+                    tools = await self.multi_server.get_all_tools()
+                    filtered_tools = self.filter.filter_outgoing({
+                        "jsonrpc": "2.0",
+                        "id": request_id,
+                        "result": {"tools": tools}
+                    })
+                    return filtered_tools
+                elif jsonrpc_object.get("method") == "tools/call":
+                    # Route tool call to multi-server
+                    tool_name = jsonrpc_object.get("params", {}).get("name")
+                    args = jsonrpc_object.get("params", {}).get("arguments", {})
+                    try:
+                        result = await self.multi_server.route_tool_call(tool_name, args)
+                        return {
+                            "jsonrpc": "2.0",
+                            "id": request_id,
+                            "result": result
+                        }
+                    except Exception as e:
+                        return {
+                            "jsonrpc": "2.0",
+                            "id": request_id,
+                            "error": {"code": -32603, "message": str(e)}
+                        }
+            
+            # No server available
+            return {
+                "jsonrpc": "2.0",
+                "id": request_id,
+                "error": {
+                    "code": -32603,
+                    "message": "No MCP server available"
+                }
+            }
+        
+        # Debug output
+        if self.config.debug:
+            debug_json("MCP Browser sending", jsonrpc_object)
+        
         # Create future for response
         future = asyncio.Future()
         self._response_buffer[request_id] = future
@@ -176,6 +223,8 @@ class MCPBrowser:
         # Wait for response
         try:
             response = await asyncio.wait_for(future, timeout=self.config.timeout)
+            if self.config.debug:
+                debug_json("MCP Browser received", response)
             return response
         except asyncio.TimeoutError:
             del self._response_buffer[request_id]
diff --git a/mcp_browser/server.py b/mcp_browser/server.py
index f0f6216..25f34c3 100644
--- a/mcp_browser/server.py
+++ b/mcp_browser/server.py
@@ -14,6 +14,7 @@ from pathlib import Path
 
 from .buffer import JsonRpcBuffer
 from .config import MCPServerConfig
+from .utils import debug_print, debug_json
 
 
 class MCPServer:
@@ -46,7 +47,7 @@ class MCPServer:
         cmd = self.config.command + self.config.args
         
         if self.debug:
-            print(f"Starting MCP server: {' '.join(cmd)}")
+            debug_print(f"Starting MCP server: {' '.join(cmd)}")
         
         # Start process
         self.process = subprocess.Popen(
@@ -116,7 +117,7 @@ class MCPServer:
         self.process.stdin.flush()
         
         if self.debug:
-            print(f"Sent: {request_str.strip()}")
+            debug_print(f"Sent: {request_str.strip()}")
         
         # Wait for response
         try:
@@ -134,6 +135,9 @@ class MCPServer:
         if not message.endswith('\n'):
             message += '\n'
         
+        if self.debug:
+            debug_print(f"MCP Server sending: {message.strip()}")
+        
         self.process.stdin.write(message)
         self.process.stdin.flush()
     
@@ -155,7 +159,7 @@ class MCPServer:
                     
             except Exception as e:
                 if self.debug:
-                    print(f"Error reading stdout: {e}")
+                    debug_print(f"Error reading stdout: {e}")
                 break
     
     async def _read_stderr(self):
@@ -166,7 +170,7 @@ class MCPServer:
                 if not line:
                     break
                 
-                print(f"MCP stderr: {line.strip()}")
+                debug_print(f"MCP stderr: {line.strip()}")
                     
             except Exception:
                 break
@@ -174,7 +178,7 @@ class MCPServer:
     async def _handle_message(self, message: dict):
         """Handle an incoming JSON-RPC message."""
         if self.debug:
-            print(f"Received: {json.dumps(message)}")
+            debug_json("Received", message)
         
         # Check if it's a response to a pending request
         msg_id = message.get("id")
@@ -192,4 +196,4 @@ class MCPServer:
                 handler(message)
             except Exception as e:
                 if self.debug:
-                    print(f"Handler error: {e}")
\ No newline at end of file
+                    debug_print(f"Handler error: {e}")
\ No newline at end of file
diff --git a/mcp_browser/utils.py b/mcp_browser/utils.py
new file mode 100644
index 0000000..3d2e98c
--- /dev/null
+++ b/mcp_browser/utils.py
@@ -0,0 +1,17 @@
+"""
+Utility functions for MCP Browser.
+"""
+
+import sys
+from typing import Any
+
+
+def debug_print(message: str):
+    """Print debug message to stderr."""
+    print(message, file=sys.stderr, flush=True)
+
+
+def debug_json(label: str, data: Any):
+    """Print JSON data to stderr for debugging."""
+    import json
+    print(f"{label}: {json.dumps(data)}", file=sys.stderr, flush=True)
\ No newline at end of file
