Fix MCP initialization timeout and add daemon management

- Fix protocol version mismatch (0.1.0 -> 2024-11-05)
- Fix server mode blocking on startup causing Claude Desktop timeout
- Add --version flag to show version information
- Implement proper daemon cleanup when starting new daemon
- Add kill_daemon_with_children() to properly terminate process tree
- Fix dictionary iteration error during shutdown
- Ensure sparse mode is always enabled (3 tools only)
- Fix async stdin reading in base server to prevent EOF loops
- Add syslog support for server mode logging
- Switch from stdin.read() to readline() for proper JSON-RPC handling
- Add comprehensive MCP protocol test suite

The tool now works correctly as an MCP proxy between Claude Desktop
and MCP servers with additional built-in tools.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Claude4Ξlope 2025-06-27 22:00:32 +02:00
parent 6df97a9dcf
commit 5aacf468a4
13 changed files with 1156 additions and 91 deletions

381
.tags
View File

@ -5,184 +5,537 @@
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
!_TAG_PROGRAM_VERSION Development //
AIAssistant examples/ai_optimized.py /^class AIAssistant:$/;" c
BaseMCPServer build/lib/mcp_servers/base.py /^class BaseMCPServer(ABC):$/;" c
BaseMCPServer mcp_servers/base.py /^class BaseMCPServer(ABC):$/;" c
ConfigLoader build/lib/mcp_browser/config.py /^class ConfigLoader:$/;" c
ConfigLoader mcp_browser/config.py /^class ConfigLoader:$/;" c
ConfigManager build/lib/mcp_browser/default_configs.py /^class ConfigManager:$/;" c
ConfigManager mcp_browser/default_configs.py /^class ConfigManager:$/;" c
DEFAULT_CONFIG build/lib/mcp_browser/config.py /^ DEFAULT_CONFIG = {$/;" v class:ConfigLoader
DEFAULT_CONFIG mcp_browser/config.py /^ DEFAULT_CONFIG = {$/;" v class:ConfigLoader
DEFAULT_CONFIGS build/lib/mcp_browser/default_configs.py /^DEFAULT_CONFIGS = {$/;" v
DEFAULT_CONFIGS mcp_browser/default_configs.py /^DEFAULT_CONFIGS = {$/;" v
Decision build/lib/mcp_servers/memory/memory_server.py /^class Decision:$/;" c
Decision mcp_servers/memory/memory_server.py /^class Decision:$/;" c
GenerateAIDocs setup.py /^class GenerateAIDocs(Command):$/;" c
JSONRPCTestClient tests/test_integration.py /^class JSONRPCTestClient:$/;" c
JsonRpcBuffer build/lib/mcp_browser/buffer.py /^class JsonRpcBuffer:$/;" c
JsonRpcBuffer mcp_browser/buffer.py /^class JsonRpcBuffer:$/;" c
MCPBrowser build/lib/mcp_browser/proxy.py /^class MCPBrowser:$/;" c
MCPBrowser mcp_browser/proxy.py /^class MCPBrowser:$/;" c
MCPBrowserClient build/lib/mcp_browser/daemon.py /^class MCPBrowserClient:$/;" c
MCPBrowserClient mcp_browser/daemon.py /^class MCPBrowserClient:$/;" c
MCPBrowserConfig build/lib/mcp_browser/config.py /^class MCPBrowserConfig:$/;" c
MCPBrowserConfig mcp_browser/config.py /^class MCPBrowserConfig:$/;" c
MCPBrowserDaemon build/lib/mcp_browser/daemon.py /^class MCPBrowserDaemon:$/;" c
MCPBrowserDaemon mcp_browser/daemon.py /^class MCPBrowserDaemon:$/;" c
MCPServer build/lib/mcp_browser/server.py /^class MCPServer:$/;" c
MCPServer mcp_browser/server.py /^class MCPServer:$/;" c
MCPServerConfig build/lib/mcp_browser/config.py /^class MCPServerConfig:$/;" c
MCPServerConfig mcp_browser/config.py /^class MCPServerConfig:$/;" c
MemoryServer build/lib/mcp_servers/memory/memory_server.py /^class MemoryServer(BaseMCPServer):$/;" c
MemoryServer mcp_servers/memory/memory_server.py /^class MemoryServer(BaseMCPServer):$/;" c
MessageFilter build/lib/mcp_browser/filter.py /^class MessageFilter:$/;" c
MessageFilter mcp_browser/filter.py /^class MessageFilter:$/;" c
MultiServerManager build/lib/mcp_browser/multi_server.py /^class MultiServerManager:$/;" c
MultiServerManager mcp_browser/multi_server.py /^class MultiServerManager:$/;" c
OnboardingServer build/lib/mcp_servers/onboarding/onboarding_server.py /^class OnboardingServer(BaseMCPServer):$/;" c
OnboardingServer mcp_servers/onboarding/onboarding_server.py /^class OnboardingServer(BaseMCPServer):$/;" c
Pattern build/lib/mcp_servers/memory/memory_server.py /^class Pattern:$/;" c
Pattern mcp_servers/memory/memory_server.py /^class Pattern:$/;" c
PatternServer build/lib/mcp_servers/pattern_manager/pattern_server.py /^class PatternServer(BaseMCPServer):$/;" c
PatternServer mcp_servers/pattern_manager/pattern_server.py /^class PatternServer(BaseMCPServer):$/;" c
RawIOFilter build/lib/mcp_browser/logging_config.py /^class RawIOFilter(logging.Filter):$/;" c
RawIOFilter mcp_browser/logging_config.py /^class RawIOFilter(logging.Filter):$/;" c
ScreenServer build/lib/mcp_servers/screen/screen_server.py /^class ScreenServer(BaseMCPServer):$/;" c
ScreenServer mcp_servers/screen/screen_server.py /^class ScreenServer(BaseMCPServer):$/;" c
ServerNameAdapter build/lib/mcp_browser/logging_config.py /^class ServerNameAdapter(logging.LoggerAdapter):$/;" c
ServerNameAdapter mcp_browser/logging_config.py /^class ServerNameAdapter(logging.LoggerAdapter):$/;" c
TRACE build/lib/mcp_browser/logging_config.py /^TRACE = 5$/;" v
TRACE mcp_browser/logging_config.py /^TRACE = 5$/;" v
Task build/lib/mcp_servers/memory/memory_server.py /^class Task:$/;" c
Task mcp_servers/memory/memory_server.py /^class Task:$/;" c
TestCommand setup.py /^class TestCommand(Command):$/;" c
TestMCPBrowser tests/test_basic.py /^class TestMCPBrowser:$/;" c
TestMessageFilter tests/test_basic.py /^class TestMessageFilter:$/;" c
TestToolRegistry tests/test_basic.py /^class TestToolRegistry:$/;" c
ToolRegistry build/lib/mcp_browser/registry.py /^class ToolRegistry:$/;" c
ToolRegistry mcp_browser/registry.py /^class ToolRegistry:$/;" c
VirtualToolHandler build/lib/mcp_browser/filter.py /^class VirtualToolHandler:$/;" c
VirtualToolHandler mcp_browser/filter.py /^class VirtualToolHandler:$/;" c
__aenter__ build/lib/mcp_browser/daemon.py /^ async def __aenter__(self):$/;" m class:MCPBrowserClient file:
__aenter__ build/lib/mcp_browser/proxy.py /^ async def __aenter__(self):$/;" m class:MCPBrowser file:
__aenter__ mcp_browser/daemon.py /^ async def __aenter__(self):$/;" m class:MCPBrowserClient file:
__aenter__ mcp_browser/proxy.py /^ async def __aenter__(self):$/;" m class:MCPBrowser file:
__aenter__ tests/test_integration.py /^ async def __aenter__(self):$/;" m class:JSONRPCTestClient file:
__aexit__ build/lib/mcp_browser/daemon.py /^ async def __aexit__(self, exc_type, exc_val, exc_tb):$/;" m class:MCPBrowserClient file:
__aexit__ build/lib/mcp_browser/proxy.py /^ async def __aexit__(self, exc_type, exc_val, exc_tb):$/;" m class:MCPBrowser file:
__aexit__ mcp_browser/daemon.py /^ async def __aexit__(self, exc_type, exc_val, exc_tb):$/;" m class:MCPBrowserClient file:
__aexit__ mcp_browser/proxy.py /^ async def __aexit__(self, exc_type, exc_val, exc_tb):$/;" m class:MCPBrowser file:
__aexit__ tests/test_integration.py /^ async def __aexit__(self, exc_type, exc_val, exc_tb):$/;" m class:JSONRPCTestClient file:
__all__ build/lib/mcp_browser/__init__.py /^__all__ = ["MCPBrowser"]/;" v
__all__ mcp_browser/__init__.py /^__all__ = ["MCPBrowser"]/;" v
__author__ build/lib/mcp_browser/__init__.py /^__author__ = "Claude4Ξlope"$/;" v
__author__ mcp_browser/__init__.py /^__author__ = "Claude4Ξlope"$/;" v
__email__ build/lib/mcp_browser/__init__.py /^__email__ = "xilope@esus.name"$/;" v
__email__ mcp_browser/__init__.py /^__email__ = "xilope@esus.name"$/;" v
__init__ build/lib/mcp_browser/buffer.py /^ def __init__(self):$/;" m class:JsonRpcBuffer
__init__ build/lib/mcp_browser/config.py /^ def __init__(self, config_path: Optional[Path] = None):$/;" m class:ConfigLoader
__init__ build/lib/mcp_browser/daemon.py /^ def __init__(self, browser: MCPBrowser, socket_path: Path):$/;" m class:MCPBrowserDaemon
__init__ build/lib/mcp_browser/daemon.py /^ def __init__(self, socket_path: Path):$/;" m class:MCPBrowserClient
__init__ build/lib/mcp_browser/default_configs.py /^ def __init__(self, config_dir: Optional[Path] = None):$/;" m class:ConfigManager
__init__ build/lib/mcp_browser/filter.py /^ def __init__(self, registry: ToolRegistry, server_callback: Callable):$/;" m class:VirtualToolHandler
__init__ build/lib/mcp_browser/filter.py /^ def __init__(self, registry: ToolRegistry, sparse_mode: bool = True):$/;" m class:MessageFilter
__init__ build/lib/mcp_browser/multi_server.py /^ def __init__(self, logger=None):$/;" m class:MultiServerManager
__init__ build/lib/mcp_browser/proxy.py /^ def __init__(self, config_path: Optional[Path] = None, server_name: Optional[str] = None,$/;" m class:MCPBrowser
__init__ build/lib/mcp_browser/registry.py /^ def __init__(self):$/;" m class:ToolRegistry
__init__ build/lib/mcp_browser/server.py /^ def __init__(self, config: MCPServerConfig, logger: Optional[logging.Logger] = None):$/;" m class:MCPServer
__init__ build/lib/mcp_servers/base.py /^ def __init__(self, name: str, version: str = "1.0.0"):$/;" m class:BaseMCPServer
__init__ build/lib/mcp_servers/memory/memory_server.py /^ def __init__(self):$/;" m class:MemoryServer
__init__ build/lib/mcp_servers/onboarding/onboarding_server.py /^ def __init__(self):$/;" m class:OnboardingServer
__init__ build/lib/mcp_servers/pattern_manager/pattern_server.py /^ def __init__(self):$/;" m class:PatternServer
__init__ build/lib/mcp_servers/screen/screen_server.py /^ def __init__(self):$/;" m class:ScreenServer
__init__ examples/ai_optimized.py /^ def __init__(self):$/;" m class:AIAssistant
__init__ mcp_browser/buffer.py /^ def __init__(self):$/;" m class:JsonRpcBuffer
__init__ mcp_browser/config.py /^ def __init__(self, config_path: Optional[Path] = None):$/;" m class:ConfigLoader
__init__ mcp_browser/daemon.py /^ def __init__(self, browser: MCPBrowser, socket_path: Path):$/;" m class:MCPBrowserDaemon
__init__ mcp_browser/daemon.py /^ def __init__(self, socket_path: Path):$/;" m class:MCPBrowserClient
__init__ mcp_browser/default_configs.py /^ def __init__(self, config_dir: Optional[Path] = None):$/;" m class:ConfigManager
__init__ mcp_browser/filter.py /^ def __init__(self, registry: ToolRegistry, server_callback: Callable):$/;" m class:VirtualToolHandler
__init__ mcp_browser/filter.py /^ def __init__(self, registry: ToolRegistry, sparse_mode: bool = True):$/;" m class:MessageFilter
__init__ mcp_browser/multi_server.py /^ def __init__(self, debug: bool = False):$/;" m class:MultiServerManager
__init__ mcp_browser/multi_server.py /^ def __init__(self, logger=None):$/;" m class:MultiServerManager
__init__ mcp_browser/proxy.py /^ def __init__(self, config_path: Optional[Path] = None, server_name: Optional[str] = None,$/;" m class:MCPBrowser
__init__ mcp_browser/registry.py /^ def __init__(self):$/;" m class:ToolRegistry
__init__ mcp_browser/server.py /^ def __init__(self, config: MCPServerConfig, debug: bool = False):$/;" m class:MCPServer
__init__ mcp_browser/server.py /^ def __init__(self, config: MCPServerConfig, logger: Optional[logging.Logger] = None):$/;" m class:MCPServer
__init__ mcp_servers/base.py /^ def __init__(self, name: str, version: str = "1.0.0"):$/;" m class:BaseMCPServer
__init__ mcp_servers/memory/memory_server.py /^ def __init__(self):$/;" m class:MemoryServer
__init__ mcp_servers/onboarding/onboarding_server.py /^ def __init__(self):$/;" m class:OnboardingServer
__init__ mcp_servers/pattern_manager/pattern_server.py /^ def __init__(self):$/;" m class:PatternServer
__init__ mcp_servers/screen/screen_server.py /^ def __init__(self):$/;" m class:ScreenServer
__init__ tests/test_integration.py /^ def __init__(self, timeout: float = 5.0):$/;" m class:JSONRPCTestClient
__license__ build/lib/mcp_browser/__init__.py /^__license__ = "GPLv3+"$/;" v
__license__ mcp_browser/__init__.py /^__license__ = "GPLv3+"$/;" v
__version__ build/lib/mcp_browser/__init__.py /^__version__ = "0.1.0"$/;" v
__version__ mcp_browser/__init__.py /^__version__ = "0.1.0"$/;" v
_add_pattern build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _add_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_add_pattern mcp_servers/pattern_manager/pattern_server.py /^ async def _add_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_calculate_checksum build/lib/mcp_browser/default_configs.py /^ def _calculate_checksum(self, filepath: Path) -> str:$/;" m class:ConfigManager
_calculate_checksum mcp_browser/default_configs.py /^ def _calculate_checksum(self, filepath: Path) -> str:$/;" m class:ConfigManager
_create_session build/lib/mcp_servers/screen/screen_server.py /^ async def _create_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_create_session mcp_servers/screen/screen_server.py /^ async def _create_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_decision_add build/lib/mcp_servers/memory/memory_server.py /^ async def _decision_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_decision_add mcp_servers/memory/memory_server.py /^ async def _decision_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_delete_onboarding build/lib/mcp_servers/onboarding/onboarding_server.py /^ async def _delete_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_delete_onboarding mcp_servers/onboarding/onboarding_server.py /^ async def _delete_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_ensure_config_file build/lib/mcp_browser/default_configs.py /^ def _ensure_config_file(self, filename: str, config_data: Dict[str, str]) -> None:$/;" m class:ConfigManager
_ensure_config_file mcp_browser/default_configs.py /^ def _ensure_config_file(self, filename: str, config_data: Dict[str, str]) -> None:$/;" m class:ConfigManager
_execute_command build/lib/mcp_servers/screen/screen_server.py /^ async def _execute_command(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_execute_command mcp_servers/screen/screen_server.py /^ async def _execute_command(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_execute_pattern build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _execute_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_execute_pattern mcp_servers/pattern_manager/pattern_server.py /^ async def _execute_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_export_onboarding build/lib/mcp_servers/onboarding/onboarding_server.py /^ async def _export_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_export_onboarding mcp_servers/onboarding/onboarding_server.py /^ async def _export_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_filter_tools_response build/lib/mcp_browser/filter.py /^ def _filter_tools_response(self, message: dict) -> dict:$/;" m class:MessageFilter
_filter_tools_response mcp_browser/filter.py /^ def _filter_tools_response(self, message: dict) -> dict:$/;" m class:MessageFilter
_find_config_file mcp_browser/config.py /^ def _find_config_file(self) -> Optional[Path]:$/;" m class:ConfigLoader
_format_onboarding build/lib/mcp_servers/onboarding/onboarding_server.py /^ def _format_onboarding(self, identity: str, data: Dict[str, Any]) -> str:$/;" m class:OnboardingServer
_format_onboarding mcp_servers/onboarding/onboarding_server.py /^ def _format_onboarding(self, identity: str, data: Dict[str, Any]) -> str:$/;" m class:OnboardingServer
_forward_to_server build/lib/mcp_browser/proxy.py /^ async def _forward_to_server(self, request: dict) -> dict:$/;" m class:MCPBrowser
_forward_to_server mcp_browser/proxy.py /^ async def _forward_to_server(self, request: dict) -> dict:$/;" m class:MCPBrowser
_get_builtin_servers build/lib/mcp_browser/multi_server.py /^ def _get_builtin_servers(self) -> Dict[str, MCPServerConfig]:$/;" m class:MultiServerManager
_get_builtin_servers mcp_browser/multi_server.py /^ def _get_builtin_servers(self) -> Dict[str, MCPServerConfig]:$/;" m class:MultiServerManager
_handle_call build/lib/mcp_browser/filter.py /^ async def _handle_call(self, message: dict) -> dict:$/;" m class:VirtualToolHandler
_handle_call mcp_browser/filter.py /^ async def _handle_call(self, message: dict) -> dict:$/;" m class:VirtualToolHandler
_handle_client build/lib/mcp_browser/daemon.py /^ async def _handle_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):$/;" m class:MCPBrowserDaemon
_handle_client mcp_browser/daemon.py /^ async def _handle_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter):$/;" m class:MCPBrowserDaemon
_handle_discover build/lib/mcp_browser/filter.py /^ async def _handle_discover(self, message: dict) -> dict:$/;" m class:VirtualToolHandler
_handle_discover mcp_browser/filter.py /^ async def _handle_discover(self, message: dict) -> dict:$/;" m class:VirtualToolHandler
_handle_message build/lib/mcp_browser/server.py /^ async def _handle_message(self, message: dict):$/;" m class:MCPServer
_handle_message mcp_browser/server.py /^ async def _handle_message(self, message: dict):$/;" m class:MCPServer
_handle_onboarding build/lib/mcp_servers/onboarding/onboarding_server.py /^ async def _handle_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_handle_onboarding mcp_servers/onboarding/onboarding_server.py /^ async def _handle_onboarding(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
_handle_server_message build/lib/mcp_browser/proxy.py /^ def _handle_server_message(self, message: dict):$/;" m class:MCPBrowser
_handle_server_message mcp_browser/proxy.py /^ def _handle_server_message(self, message: dict):$/;" m class:MCPBrowser
_initialize_connection build/lib/mcp_browser/proxy.py /^ async def _initialize_connection(self):$/;" m class:MCPBrowser
_initialize_connection mcp_browser/proxy.py /^ async def _initialize_connection(self):$/;" m class:MCPBrowser
_kill_session build/lib/mcp_servers/screen/screen_server.py /^ async def _kill_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_kill_session mcp_servers/screen/screen_server.py /^ async def _kill_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_knowledge_add build/lib/mcp_servers/memory/memory_server.py /^ async def _knowledge_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_knowledge_add mcp_servers/memory/memory_server.py /^ async def _knowledge_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_knowledge_get build/lib/mcp_servers/memory/memory_server.py /^ async def _knowledge_get(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_knowledge_get mcp_servers/memory/memory_server.py /^ async def _knowledge_get(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_list_identities build/lib/mcp_servers/onboarding/onboarding_server.py /^ async def _list_identities(self) -> Dict[str, Any]:$/;" m class:OnboardingServer
_list_identities mcp_servers/onboarding/onboarding_server.py /^ async def _list_identities(self) -> Dict[str, Any]:$/;" m class:OnboardingServer
_list_patterns build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _list_patterns(self) -> Dict[str, Any]:$/;" m class:PatternServer
_list_patterns mcp_servers/pattern_manager/pattern_server.py /^ async def _list_patterns(self) -> Dict[str, Any]:$/;" m class:PatternServer
_list_sessions build/lib/mcp_servers/screen/screen_server.py /^ async def _list_sessions(self) -> Dict[str, Any]:$/;" m class:ScreenServer
_list_sessions mcp_servers/screen/screen_server.py /^ async def _list_sessions(self) -> Dict[str, Any]:$/;" m class:ScreenServer
_load_json build/lib/mcp_servers/memory/memory_server.py /^ def _load_json(self, filename: str, default: Any) -> Any:$/;" m class:MemoryServer
_load_json mcp_servers/memory/memory_server.py /^ def _load_json(self, filename: str, default: Any) -> Any:$/;" m class:MemoryServer
_load_memory build/lib/mcp_servers/memory/memory_server.py /^ def _load_memory(self):$/;" m class:MemoryServer
_load_memory mcp_servers/memory/memory_server.py /^ def _load_memory(self):$/;" m class:MemoryServer
_load_patterns build/lib/mcp_servers/pattern_manager/pattern_server.py /^ def _load_patterns(self) -> Dict[str, Dict[str, Any]]:$/;" m class:PatternServer
_load_patterns mcp_servers/pattern_manager/pattern_server.py /^ def _load_patterns(self) -> Dict[str, Dict[str, Any]]:$/;" m class:PatternServer
_mark_offline build/lib/mcp_browser/server.py /^ def _mark_offline(self):$/;" m class:MCPServer
_mark_offline mcp_browser/server.py /^ def _mark_offline(self):$/;" m class:MCPServer
_matches_pattern build/lib/mcp_servers/pattern_manager/pattern_server.py /^ def _matches_pattern(self, text: str, trigger: List[str]) -> bool:$/;" m class:PatternServer
_matches_pattern mcp_servers/pattern_manager/pattern_server.py /^ def _matches_pattern(self, text: str, trigger: List[str]) -> bool:$/;" m class:PatternServer
_memory_summary build/lib/mcp_servers/memory/memory_server.py /^ async def _memory_summary(self) -> Dict[str, Any]:$/;" m class:MemoryServer
_memory_summary mcp_servers/memory/memory_server.py /^ async def _memory_summary(self) -> Dict[str, Any]:$/;" m class:MemoryServer
_merge_configs build/lib/mcp_browser/config.py /^ def _merge_configs(self, base: Dict[str, Any], override: Dict[str, Any]):$/;" m class:ConfigLoader
_merge_configs mcp_browser/config.py /^ def _merge_configs(self, base: Dict[str, Any], override: Dict[str, Any]):$/;" m class:ConfigLoader
_pattern_add build/lib/mcp_servers/memory/memory_server.py /^ async def _pattern_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_pattern_add mcp_servers/memory/memory_server.py /^ async def _pattern_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_pattern_resolve build/lib/mcp_servers/memory/memory_server.py /^ async def _pattern_resolve(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_pattern_resolve mcp_servers/memory/memory_server.py /^ async def _pattern_resolve(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_peek_session build/lib/mcp_servers/screen/screen_server.py /^ async def _peek_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_peek_session mcp_servers/screen/screen_server.py /^ async def _peek_session(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
_process_request build/lib/mcp_browser/daemon.py /^ async def _process_request(self, line: str, writer: asyncio.StreamWriter):$/;" m class:MCPBrowserDaemon
_process_request mcp_browser/daemon.py /^ async def _process_request(self, line: str, writer: asyncio.StreamWriter):$/;" m class:MCPBrowserDaemon
_process_response build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _process_response(self, response: Any, context: Dict[str, Any]) -> str:$/;" m class:PatternServer
_process_response mcp_servers/pattern_manager/pattern_server.py /^ async def _process_response(self, response: Any, context: Dict[str, Any]) -> str:$/;" m class:PatternServer
_process_single_response build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _process_single_response(self, response: str, context: Dict[str, Any]) -> str:$/;" m class:PatternServer
_process_single_response mcp_servers/pattern_manager/pattern_server.py /^ async def _process_single_response(self, response: str, context: Dict[str, Any]) -> str:$/;" m class:PatternServer
_project_switch build/lib/mcp_servers/memory/memory_server.py /^ async def _project_switch(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_project_switch mcp_servers/memory/memory_server.py /^ async def _project_switch(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_read_stderr build/lib/mcp_browser/server.py /^ async def _read_stderr(self):$/;" m class:MCPServer
_read_stderr mcp_browser/server.py /^ async def _read_stderr(self):$/;" m class:MCPServer
_read_stdout build/lib/mcp_browser/server.py /^ async def _read_stdout(self):$/;" m class:MCPServer
_read_stdout mcp_browser/server.py /^ async def _read_stdout(self):$/;" m class:MCPServer
_register_tools build/lib/mcp_servers/memory/memory_server.py /^ def _register_tools(self):$/;" m class:MemoryServer
_register_tools build/lib/mcp_servers/onboarding/onboarding_server.py /^ def _register_tools(self):$/;" m class:OnboardingServer
_register_tools build/lib/mcp_servers/pattern_manager/pattern_server.py /^ def _register_tools(self):$/;" m class:PatternServer
_register_tools build/lib/mcp_servers/screen/screen_server.py /^ def _register_tools(self):$/;" m class:ScreenServer
_register_tools mcp_servers/memory/memory_server.py /^ def _register_tools(self):$/;" m class:MemoryServer
_register_tools mcp_servers/onboarding/onboarding_server.py /^ def _register_tools(self):$/;" m class:OnboardingServer
_register_tools mcp_servers/pattern_manager/pattern_server.py /^ def _register_tools(self):$/;" m class:PatternServer
_register_tools mcp_servers/screen/screen_server.py /^ def _register_tools(self):$/;" m class:ScreenServer
_remove_pattern build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _remove_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_remove_pattern mcp_servers/pattern_manager/pattern_server.py /^ async def _remove_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_run_command build/lib/mcp_servers/screen/screen_server.py /^ async def _run_command(self, cmd: List[str]) -> subprocess.CompletedProcess:$/;" m class:ScreenServer
_run_command mcp_servers/screen/screen_server.py /^ async def _run_command(self, cmd: List[str]) -> subprocess.CompletedProcess:$/;" m class:ScreenServer
_sanitize_identity build/lib/mcp_servers/onboarding/onboarding_server.py /^ def _sanitize_identity(self, identity: str) -> str:$/;" m class:OnboardingServer
_sanitize_identity mcp_servers/onboarding/onboarding_server.py /^ def _sanitize_identity(self, identity: str) -> str:$/;" m class:OnboardingServer
_save_json build/lib/mcp_servers/memory/memory_server.py /^ def _save_json(self, filename: str, data: Any):$/;" m class:MemoryServer
_save_json mcp_servers/memory/memory_server.py /^ def _save_json(self, filename: str, data: Any):$/;" m class:MemoryServer
_save_patterns build/lib/mcp_servers/pattern_manager/pattern_server.py /^ def _save_patterns(self):$/;" m class:PatternServer
_save_patterns mcp_servers/pattern_manager/pattern_server.py /^ def _save_patterns(self):$/;" m class:PatternServer
_signal_handler build/lib/mcp_browser/daemon.py /^ def _signal_handler(self, signum, frame):$/;" m class:MCPBrowserDaemon
_signal_handler mcp_browser/daemon.py /^ def _signal_handler(self, signum, frame):$/;" m class:MCPBrowserDaemon
_task_add build/lib/mcp_servers/memory/memory_server.py /^ async def _task_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_task_add mcp_servers/memory/memory_server.py /^ async def _task_add(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_task_list build/lib/mcp_servers/memory/memory_server.py /^ async def _task_list(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_task_list mcp_servers/memory/memory_server.py /^ async def _task_list(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_task_update build/lib/mcp_servers/memory/memory_server.py /^ async def _task_update(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_task_update mcp_servers/memory/memory_server.py /^ async def _task_update(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
_test_pattern build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def _test_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
_test_pattern mcp_servers/pattern_manager/pattern_server.py /^ async def _test_pattern(self, args: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
add_message_handler build/lib/mcp_browser/server.py /^ def add_message_handler(self, handler: Callable[[dict], None]):$/;" m class:MCPServer
add_message_handler mcp_browser/server.py /^ def add_message_handler(self, handler: Callable[[dict], None]):$/;" m class:MCPServer
add_server build/lib/mcp_browser/multi_server.py /^ async def add_server(self, name: str, config: MCPServerConfig):$/;" m class:MultiServerManager
add_server mcp_browser/multi_server.py /^ async def add_server(self, name: str, config: MCPServerConfig):$/;" m class:MultiServerManager
append build/lib/mcp_browser/buffer.py /^ def append(self, data: str) -> List[dict]:$/;" m class:JsonRpcBuffer
append mcp_browser/buffer.py /^ def append(self, data: str) -> List[dict]:$/;" m class:JsonRpcBuffer
args build/lib/mcp_browser/__main__.py /^ args = parser.parse_args()$/;" v
args mcp_browser/__main__.py /^ args = parser.parse_args()$/;" v
async_main build/lib/mcp_browser/__main__.py /^async def async_main(browser: MCPBrowser):$/;" f
async_main mcp_browser/__main__.py /^async def async_main(browser: MCPBrowser):$/;" f
author setup.py /^ author="AI Assistant",$/;" v
author_email setup.py /^ author_email="ai@anthropic.com",$/;" v
author setup.py /^ author="Claude4Ξlope",$/;" v
author_email setup.py /^ author_email="xilope@esus.name",$/;" v
browser build/lib/mcp_browser/__main__.py /^ browser = MCPBrowser($/;" v
browser mcp_browser/__main__.py /^ browser = MCPBrowser($/;" v
build_mcp_request build/lib/mcp_browser/__main__.py /^def build_mcp_request(args) -> Dict[str, Any]:$/;" f
build_mcp_request mcp_browser/__main__.py /^def build_mcp_request(args) -> Dict[str, Any]:$/;" f
build_request build/lib/mcp_browser/client_main.py /^def build_request(args) -> Dict[str, Any]:$/;" f
build_request mcp_browser/client_main.py /^def build_request(args) -> Dict[str, Any]:$/;" f
call build/lib/mcp_browser/daemon.py /^ async def call(self, request: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MCPBrowserClient
call build/lib/mcp_browser/proxy.py /^ async def call(self, jsonrpc_object: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MCPBrowser
call mcp_browser/daemon.py /^ async def call(self, request: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MCPBrowserClient
call mcp_browser/proxy.py /^ async def call(self, jsonrpc_object: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MCPBrowser
call_tool build/lib/mcp_browser/__main__.py /^ call_tool = subparsers.add_parser("tools-call", help="Call a tool")$/;" v
call_tool mcp_browser/__main__.py /^ call_tool = subparsers.add_parser("tools-call", help="Call a tool")$/;" v
classifiers setup.py /^ classifiers=[$/;" v
clear build/lib/mcp_browser/buffer.py /^ def clear(self):$/;" m class:JsonRpcBuffer
clear mcp_browser/buffer.py /^ def clear(self):$/;" m class:JsonRpcBuffer
close build/lib/mcp_browser/daemon.py /^ async def close(self):$/;" m class:MCPBrowserClient
close build/lib/mcp_browser/proxy.py /^ async def close(self):$/;" m class:MCPBrowser
close examples/ai_optimized.py /^ async def close(self):$/;" m class:AIAssistant
close mcp_browser/daemon.py /^ async def close(self):$/;" m class:MCPBrowserClient
close mcp_browser/proxy.py /^ async def close(self):$/;" m class:MCPBrowser
cmdclass setup.py /^ cmdclass={$/;" v
completion build/lib/mcp_browser/__main__.py /^ completion = subparsers.add_parser("completion", help="Get completion")$/;" v
completion mcp_browser/__main__.py /^ completion = subparsers.add_parser("completion", help="Get completion")$/;" v
config build/lib/mcp_browser/__main__.py /^ config = loader.load()$/;" v
config mcp_browser/__main__.py /^ config = loader.load()$/;" v
config_path build/lib/mcp_browser/__main__.py /^ config_path=config_path,$/;" v
config_path build/lib/mcp_browser/__main__.py /^ config_path = Path(args.config) if args.config else None$/;" v
config_path mcp_browser/__main__.py /^ config_path=config_path,$/;" v
config_path mcp_browser/__main__.py /^ config_path = Path(args.config) if args.config else None$/;" v
connect build/lib/mcp_browser/daemon.py /^ async def connect(self):$/;" m class:MCPBrowserClient
connect mcp_browser/daemon.py /^ async def connect(self):$/;" m class:MCPBrowserClient
content_text build/lib/mcp_servers/base.py /^ def content_text(self, text: str) -> Dict[str, Any]:$/;" m class:BaseMCPServer
content_text mcp_servers/base.py /^ def content_text(self, text: str) -> Dict[str, Any]:$/;" m class:BaseMCPServer
create_browser build/lib/mcp_browser/proxy.py /^async def create_browser(config_path: Optional[Path] = None, $/;" f
create_browser mcp_browser/proxy.py /^async def create_browser(config_path: Optional[Path] = None, $/;" f
debug_json build/lib/mcp_browser/utils.py /^def debug_json(label: str, data: Any):$/;" f
debug_print build/lib/mcp_browser/utils.py /^def debug_print(message: str):$/;" f
demo_builtin_servers examples/builtin_servers_demo.py /^async def demo_builtin_servers():$/;" f
demonstrate_mcp_browser examples/complete_demo.py /^async def demonstrate_mcp_browser():$/;" f
description setup.py /^ description = 'Generate documentation for AI navigation'$/;" v class:GenerateAIDocs
description setup.py /^ description = 'Run unit and integration tests'$/;" v class:TestCommand
description setup.py /^ description="A generic MCP browser with context optimization for AI systems",$/;" v
discover build/lib/mcp_browser/proxy.py /^ def discover(self, jsonpath: str) -> Any:$/;" m class:MCPBrowser
discover build/lib/mcp_browser/registry.py /^ def discover(self, jsonpath: str) -> Union[List[Any], Any, None]:$/;" m class:ToolRegistry
discover mcp_browser/proxy.py /^ def discover(self, jsonpath: str) -> Any:$/;" m class:MCPBrowser
discover mcp_browser/registry.py /^ def discover(self, jsonpath: str) -> Union[List[Any], Any, None]:$/;" m class:ToolRegistry
enable_builtin_servers build/lib/mcp_browser/__main__.py /^ enable_builtin_servers=not args.no_builtin$/;" v
enable_builtin_servers mcp_browser/__main__.py /^ enable_builtin_servers=not args.no_builtin$/;" v
ensure_config_directory build/lib/mcp_browser/default_configs.py /^ def ensure_config_directory(self) -> None:$/;" m class:ConfigManager
ensure_config_directory mcp_browser/default_configs.py /^ def ensure_config_directory(self) -> None:$/;" m class:ConfigManager
entry_points setup.py /^ entry_points={$/;" v
execute_user_request examples/ai_optimized.py /^ async def execute_user_request(self, user_request: str):$/;" m class:AIAssistant
extras_require setup.py /^ extras_require={$/;" v
filter build/lib/mcp_browser/logging_config.py /^ def filter(self, record):$/;" m class:RawIOFilter
filter mcp_browser/logging_config.py /^ def filter(self, record):$/;" m class:RawIOFilter
filter_incoming build/lib/mcp_browser/filter.py /^ def filter_incoming(self, message: dict) -> Optional[dict]:$/;" m class:MessageFilter
filter_incoming mcp_browser/filter.py /^ def filter_incoming(self, message: dict) -> Optional[dict]:$/;" m class:MessageFilter
filter_outgoing build/lib/mcp_browser/filter.py /^ def filter_outgoing(self, message: dict) -> Optional[dict]:$/;" m class:MessageFilter
filter_outgoing mcp_browser/filter.py /^ def filter_outgoing(self, message: dict) -> Optional[dict]:$/;" m class:MessageFilter
finalize_options setup.py /^ def finalize_options(self):$/;" m class:GenerateAIDocs
finalize_options setup.py /^ def finalize_options(self):$/;" m class:TestCommand
format_mcp_response build/lib/mcp_browser/__main__.py /^def format_mcp_response(args, request: Dict[str, Any], response: Dict[str, Any]):$/;" f
format_mcp_response mcp_browser/__main__.py /^def format_mcp_response(args, request: Dict[str, Any], response: Dict[str, Any]):$/;" f
format_response build/lib/mcp_browser/client_main.py /^def format_response(args, response: Dict[str, Any]):$/;" f
format_response mcp_browser/client_main.py /^def format_response(args, response: Dict[str, Any]):$/;" f
formatter_class build/lib/mcp_browser/__main__.py /^ formatter_class=argparse.RawDescriptionHelpFormatter$/;" v
formatter_class mcp_browser/__main__.py /^ formatter_class=argparse.RawDescriptionHelpFormatter$/;" v
generate_api_summary setup.py /^ def generate_api_summary(self):$/;" m class:GenerateAIDocs
generate_structure_doc setup.py /^ def generate_structure_doc(self):$/;" m class:GenerateAIDocs
get_all_tool_names build/lib/mcp_browser/registry.py /^ def get_all_tool_names(self) -> List[str]:$/;" m class:ToolRegistry
get_all_tool_names mcp_browser/registry.py /^ def get_all_tool_names(self) -> List[str]:$/;" m class:ToolRegistry
get_all_tools build/lib/mcp_browser/multi_server.py /^ async def get_all_tools(self) -> List[Dict[str, Any]]:$/;" m class:MultiServerManager
get_all_tools mcp_browser/multi_server.py /^ async def get_all_tools(self) -> List[Dict[str, Any]]:$/;" m class:MultiServerManager
get_config_path build/lib/mcp_browser/default_configs.py /^ def get_config_path(self) -> Path:$/;" m class:ConfigManager
get_config_path mcp_browser/default_configs.py /^ def get_config_path(self) -> Path:$/;" m class:ConfigManager
get_logger build/lib/mcp_browser/logging_config.py /^def get_logger(name: str, server: Optional[str] = None) -> logging.Logger:$/;" f
get_logger mcp_browser/logging_config.py /^def get_logger(name: str, server: Optional[str] = None) -> logging.Logger:$/;" f
get_onboarding_path build/lib/mcp_browser/default_configs.py /^ def get_onboarding_path(self) -> Path:$/;" m class:ConfigManager
get_onboarding_path mcp_browser/default_configs.py /^ def get_onboarding_path(self) -> Path:$/;" m class:ConfigManager
get_onboarding_text build/lib/mcp_browser/default_configs.py /^ def get_onboarding_text(self, identity: Optional[str] = None) -> str:$/;" m class:ConfigManager
get_onboarding_text mcp_browser/default_configs.py /^ def get_onboarding_text(self, identity: Optional[str] = None) -> str:$/;" m class:ConfigManager
get_patterns_dir build/lib/mcp_browser/default_configs.py /^ def get_patterns_dir(self) -> Path:$/;" m class:ConfigManager
get_patterns_dir mcp_browser/default_configs.py /^ def get_patterns_dir(self) -> Path:$/;" m class:ConfigManager
get_prompt build/lib/mcp_browser/__main__.py /^ get_prompt = subparsers.add_parser("prompts-get", help="Get a prompt")$/;" v
get_prompt mcp_browser/__main__.py /^ get_prompt = subparsers.add_parser("prompts-get", help="Get a prompt")$/;" v
get_socket_path build/lib/mcp_browser/daemon.py /^def get_socket_path(server_name: Optional[str] = None) -> Path:$/;" f
get_socket_path mcp_browser/daemon.py /^def get_socket_path(server_name: Optional[str] = None) -> Path:$/;" f
get_sparse_tools build/lib/mcp_browser/registry.py /^ def get_sparse_tools(self) -> List[Dict[str, Any]]:$/;" m class:ToolRegistry
get_sparse_tools mcp_browser/registry.py /^ def get_sparse_tools(self) -> List[Dict[str, Any]]:$/;" m class:ToolRegistry
get_tool build/lib/mcp_browser/registry.py /^ def get_tool(self, name: str) -> Optional[Dict[str, Any]]:$/;" m class:ToolRegistry
get_tool mcp_browser/registry.py /^ def get_tool(self, name: str) -> Optional[Dict[str, Any]]:$/;" m class:ToolRegistry
handle_mcp_command build/lib/mcp_browser/__main__.py /^async def handle_mcp_command(args):$/;" f
handle_mcp_command mcp_browser/__main__.py /^async def handle_mcp_command(args):$/;" f
handle_request build/lib/mcp_servers/base.py /^ async def handle_request(self, request: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:BaseMCPServer
handle_request mcp_servers/base.py /^ async def handle_request(self, request: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:BaseMCPServer
handle_systemd_socket build/lib/mcp_browser/daemon_main.py /^def handle_systemd_socket():$/;" f
handle_systemd_socket mcp_browser/daemon_main.py /^def handle_systemd_socket():$/;" f
handle_tool_call build/lib/mcp_browser/filter.py /^ async def handle_tool_call(self, message: dict) -> Optional[dict]:$/;" m class:VirtualToolHandler
handle_tool_call build/lib/mcp_servers/base.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:BaseMCPServer
handle_tool_call build/lib/mcp_servers/memory/memory_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
handle_tool_call build/lib/mcp_servers/onboarding/onboarding_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
handle_tool_call build/lib/mcp_servers/pattern_manager/pattern_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
handle_tool_call build/lib/mcp_servers/screen/screen_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
handle_tool_call mcp_browser/filter.py /^ async def handle_tool_call(self, message: dict) -> Optional[dict]:$/;" m class:VirtualToolHandler
handle_tool_call mcp_servers/base.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:BaseMCPServer
handle_tool_call mcp_servers/memory/memory_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MemoryServer
handle_tool_call mcp_servers/onboarding/onboarding_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:OnboardingServer
handle_tool_call mcp_servers/pattern_manager/pattern_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:PatternServer
handle_tool_call mcp_servers/screen/screen_server.py /^ async def handle_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:ScreenServer
help build/lib/mcp_browser/__main__.py /^ help="Automatically use daemon if available")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Check daemon status")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Disable built-in servers (screen, memory, patterns)")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Disable sparse mode (show all tools)")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Enable debug output")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="List available MCP servers from config")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Set logging level")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Show current configuration path and content")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Show program version and exit")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Start daemon in background")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Stop running daemon")$/;" v
help build/lib/mcp_browser/__main__.py /^ help="Test connection to specified server")$/;" v
help mcp_browser/__main__.py /^ help="Automatically use daemon if available")$/;" v
help mcp_browser/__main__.py /^ help="Check daemon status")$/;" v
help mcp_browser/__main__.py /^ help="Disable built-in servers (screen, memory, patterns)")$/;" v
help mcp_browser/__main__.py /^ help="Disable sparse mode (show all tools)")$/;" v
help mcp_browser/__main__.py /^ help="Enable debug output")$/;" v
help mcp_browser/__main__.py /^ help="List available MCP servers from config")$/;" v
help mcp_browser/__main__.py /^ help="Set logging level")$/;" v
help mcp_browser/__main__.py /^ help="Show current configuration path and content")$/;" v
help mcp_browser/__main__.py /^ help="Show program version and exit")$/;" v
help mcp_browser/__main__.py /^ help="Start daemon in background")$/;" v
help mcp_browser/__main__.py /^ help="Stop running daemon")$/;" v
help mcp_browser/__main__.py /^ help="Test connection to specified server")$/;" v
include_package_data setup.py /^ include_package_data=True,$/;" v
initialize build/lib/mcp_browser/proxy.py /^ async def initialize(self):$/;" m class:MCPBrowser
initialize examples/ai_optimized.py /^ async def initialize(self):$/;" m class:AIAssistant
initialize mcp_browser/proxy.py /^ async def initialize(self):$/;" m class:MCPBrowser
initialize_options setup.py /^ def initialize_options(self):$/;" m class:GenerateAIDocs
initialize_options setup.py /^ def initialize_options(self):$/;" m class:TestCommand
install_requires setup.py /^ install_requires=[$/;" v
interactive_mode build/lib/mcp_browser/__main__.py /^async def interactive_mode(browser: MCPBrowser):$/;" f
interactive_mode mcp_browser/__main__.py /^async def interactive_mode(browser: MCPBrowser):$/;" f
interactive_mode_with_daemon build/lib/mcp_browser/__main__.py /^async def interactive_mode_with_daemon(socket_path: Path):$/;" f
interactive_mode_with_daemon mcp_browser/__main__.py /^async def interactive_mode_with_daemon(socket_path: Path):$/;" f
is_daemon_running build/lib/mcp_browser/daemon.py /^def is_daemon_running(socket_path: Path) -> bool:$/;" f
is_daemon_running mcp_browser/daemon.py /^def is_daemon_running(socket_path: Path) -> bool:$/;" f
is_virtual_tool build/lib/mcp_browser/filter.py /^ def is_virtual_tool(self, tool_name: str) -> bool:$/;" m class:MessageFilter
is_virtual_tool mcp_browser/filter.py /^ def is_virtual_tool(self, tool_name: str) -> bool:$/;" m class:MessageFilter
jsonrpc build/lib/mcp_browser/__main__.py /^ jsonrpc = subparsers.add_parser("jsonrpc", help="Send raw JSON-RPC request")$/;" v
jsonrpc mcp_browser/__main__.py /^ jsonrpc = subparsers.add_parser("jsonrpc", help="Send raw JSON-RPC request")$/;" v
keywords setup.py /^ keywords="mcp model-context-protocol ai llm tools json-rpc",$/;" v
kill_daemon_with_children build/lib/mcp_browser/daemon.py /^def kill_daemon_with_children(socket_path: Path) -> bool:$/;" f
kill_daemon_with_children mcp_browser/daemon.py /^def kill_daemon_with_children(socket_path: Path) -> bool:$/;" f
list_prompts build/lib/mcp_browser/__main__.py /^ list_prompts = subparsers.add_parser("prompts-list", help="List available prompts")$/;" v
list_prompts mcp_browser/__main__.py /^ list_prompts = subparsers.add_parser("prompts-list", help="List available prompts")$/;" v
list_resources build/lib/mcp_browser/__main__.py /^ list_resources = subparsers.add_parser("resources-list", help="List available resources")$/;" v
list_resources mcp_browser/__main__.py /^ list_resources = subparsers.add_parser("resources-list", help="List available resources")$/;" v
list_tools build/lib/mcp_browser/__main__.py /^ list_tools = subparsers.add_parser("tools-list", help="List available tools")$/;" v
list_tools mcp_browser/__main__.py /^ list_tools = subparsers.add_parser("tools-list", help="List available tools")$/;" v
load build/lib/mcp_browser/config.py /^ def load(self) -> MCPBrowserConfig:$/;" m class:ConfigLoader
load mcp_browser/config.py /^ def load(self) -> MCPBrowserConfig:$/;" m class:ConfigLoader
long_description setup.py /^ long_description = fh.read()$/;" v class:GenerateAIDocs
load_config build/lib/mcp_browser/default_configs.py /^ def load_config(self) -> dict:$/;" m class:ConfigManager
load_config mcp_browser/default_configs.py /^ def load_config(self) -> dict:$/;" m class:ConfigManager
loader build/lib/mcp_browser/__main__.py /^ loader = ConfigLoader()$/;" v
loader mcp_browser/__main__.py /^ loader = ConfigLoader()$/;" v
long_description setup.py /^ long_description = fh.read()$/;" v
long_description setup.py /^ long_description=long_description,$/;" v
long_description_content_type setup.py /^ long_description_content_type="text\/markdown",$/;" v
main build/lib/mcp_browser/__main__.py /^def main():$/;" f
main build/lib/mcp_browser/client_main.py /^def main():$/;" f
main build/lib/mcp_browser/daemon_main.py /^def main():$/;" f
main examples/ai_optimized.py /^async def main():$/;" f
main examples/basic_usage.py /^async def main():$/;" f
main mcp_browser/__main__.py /^def main():$/;" f
main mcp_browser/client_main.py /^def main():$/;" f
main mcp_browser/daemon_main.py /^def main():$/;" f
main tests/test_browser_functionality.py /^def main():$/;" f
main tests/test_integration.py /^async def main():$/;" f
mark_handled build/lib/mcp_browser/filter.py /^ def mark_handled(self, request_id: Union[str, int]):$/;" m class:MessageFilter
mark_handled mcp_browser/filter.py /^ def mark_handled(self, request_id: Union[str, int]):$/;" m class:MessageFilter
name setup.py /^ name="mcp-browser",$/;" v
package_data setup.py /^ package_data={$/;" v
packages setup.py /^ packages=find_packages(),$/;" v
packages setup.py /^ packages=find_packages(include=['mcp_browser*', 'mcp_servers*']),$/;" v
pid_exists build/lib/mcp_browser/daemon.py /^ def pid_exists(pid):$/;" m class:psutil
pid_exists mcp_browser/daemon.py /^ def pid_exists(pid):$/;" m class:psutil
process build/lib/mcp_browser/logging_config.py /^ def process(self, msg, kwargs):$/;" m class:ServerNameAdapter
process mcp_browser/logging_config.py /^ def process(self, msg, kwargs):$/;" m class:ServerNameAdapter
psutil build/lib/mcp_browser/daemon.py /^ class psutil:$/;" c
psutil mcp_browser/daemon.py /^ class psutil:$/;" c
read_resource build/lib/mcp_browser/__main__.py /^ read_resource = subparsers.add_parser("resources-read", help="Read a resource")$/;" v
read_resource mcp_browser/__main__.py /^ read_resource = subparsers.add_parser("resources-read", help="Read a resource")$/;" v
register_tool build/lib/mcp_servers/base.py /^ def register_tool(self, name: str, description: str, input_schema: Dict[str, Any], $/;" m class:BaseMCPServer
register_tool mcp_servers/base.py /^ def register_tool(self, name: str, description: str, input_schema: Dict[str, Any], $/;" m class:BaseMCPServer
route_tool_call build/lib/mcp_browser/multi_server.py /^ async def route_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MultiServerManager
route_tool_call mcp_browser/multi_server.py /^ async def route_tool_call(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:$/;" m class:MultiServerManager
run build/lib/mcp_browser/client_main.py /^ async def run():$/;" f function:main
run build/lib/mcp_servers/base.py /^ async def run(self):$/;" m class:BaseMCPServer
run mcp_browser/client_main.py /^ async def run():$/;" f function:main
run mcp_servers/base.py /^ async def run(self):$/;" m class:BaseMCPServer
run setup.py /^ def run(self):$/;" m class:GenerateAIDocs
run setup.py /^ def run(self):$/;" m class:TestCommand
run_command build/lib/mcp_browser/client_main.py /^async def run_command(args, request: Dict[str, Any]):$/;" f
run_command mcp_browser/client_main.py /^async def run_command(args, request: Dict[str, Any]):$/;" f
run_daemon build/lib/mcp_browser/daemon_main.py /^async def run_daemon(args):$/;" f
run_daemon mcp_browser/daemon_main.py /^async def run_daemon(args):$/;" f
run_daemon_mode build/lib/mcp_browser/__main__.py /^async def run_daemon_mode(browser: MCPBrowser, socket_path: Path):$/;" f
run_daemon_mode mcp_browser/__main__.py /^async def run_daemon_mode(browser: MCPBrowser, socket_path: Path):$/;" f
run_mcp_server_mode build/lib/mcp_browser/client_main.py /^async def run_mcp_server_mode(args):$/;" f
run_mcp_server_mode mcp_browser/client_main.py /^async def run_mcp_server_mode(args):$/;" f
run_server_mode build/lib/mcp_browser/__main__.py /^async def run_server_mode(browser: MCPBrowser):$/;" f
run_server_mode mcp_browser/__main__.py /^async def run_server_mode(browser: MCPBrowser):$/;" f
run_server_mode_with_daemon build/lib/mcp_browser/__main__.py /^async def run_server_mode_with_daemon(socket_path: Path):$/;" f
run_server_mode_with_daemon mcp_browser/__main__.py /^async def run_server_mode_with_daemon(socket_path: Path):$/;" f
save_config build/lib/mcp_browser/default_configs.py /^ def save_config(self, config: dict) -> None:$/;" m class:ConfigManager
save_config mcp_browser/default_configs.py /^ def save_config(self, config: dict) -> None:$/;" m class:ConfigManager
send_raw build/lib/mcp_browser/server.py /^ def send_raw(self, message: str):$/;" m class:MCPServer
send_raw mcp_browser/server.py /^ def send_raw(self, message: str):$/;" m class:MCPServer
send_request build/lib/mcp_browser/server.py /^ async def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:$/;" m class:MCPServer
send_request mcp_browser/server.py /^ async def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:$/;" m class:MCPServer
send_request tests/test_integration.py /^ async def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:$/;" m class:JSONRPCTestClient
server build/lib/mcp_servers/memory/memory_server.py /^ server = MemoryServer()$/;" v class:MemoryServer
server build/lib/mcp_servers/onboarding/onboarding_server.py /^ server = OnboardingServer()$/;" v class:OnboardingServer
server build/lib/mcp_servers/pattern_manager/pattern_server.py /^ server = PatternServer()$/;" v class:PatternServer
server build/lib/mcp_servers/screen/screen_server.py /^ server = ScreenServer()$/;" v class:ScreenServer
server mcp_servers/memory/memory_server.py /^ server = MemoryServer()$/;" v class:MemoryServer
server mcp_servers/onboarding/onboarding_server.py /^ server = OnboardingServer()$/;" v class:OnboardingServer
server mcp_servers/pattern_manager/pattern_server.py /^ server = PatternServer()$/;" v class:PatternServer
server mcp_servers/screen/screen_server.py /^ server = ScreenServer()$/;" v class:ScreenServer
server_name build/lib/mcp_browser/__main__.py /^ server_name=args.server,$/;" v
server_name mcp_browser/__main__.py /^ server_name=args.server,$/;" v
set_metadata build/lib/mcp_browser/registry.py /^ def set_metadata(self, key: str, value: Any):$/;" m class:ToolRegistry
set_metadata mcp_browser/registry.py /^ def set_metadata(self, key: str, value: Any):$/;" m class:ToolRegistry
simulate_response tests/test_basic.py /^ async def simulate_response():$/;" f function:TestMCPBrowser.test_call_method
set_onboarding_text build/lib/mcp_browser/default_configs.py /^ def set_onboarding_text(self, text: str, identity: Optional[str] = None) -> None:$/;" m class:ConfigManager
set_onboarding_text mcp_browser/default_configs.py /^ def set_onboarding_text(self, text: str, identity: Optional[str] = None) -> None:$/;" m class:ConfigManager
setup_logging build/lib/mcp_browser/logging_config.py /^def setup_logging(debug: bool = False, log_file: Optional[Path] = None, $/;" f
setup_logging mcp_browser/logging_config.py /^def setup_logging(debug: bool = False, log_file: Optional[Path] = None, $/;" f
show_available_servers build/lib/mcp_browser/__main__.py /^def show_available_servers(config_path: Optional[str] = None):$/;" f
show_available_servers mcp_browser/__main__.py /^def show_available_servers(config_path: Optional[str] = None):$/;" f
show_configuration build/lib/mcp_browser/__main__.py /^def show_configuration(config_path: Optional[str] = None):$/;" f
show_configuration mcp_browser/__main__.py /^def show_configuration(config_path: Optional[str] = None):$/;" f
show_daemon_status build/lib/mcp_browser/__main__.py /^def show_daemon_status(args):$/;" f
show_daemon_status mcp_browser/__main__.py /^def show_daemon_status(args):$/;" f
signal_handler build/lib/mcp_browser/daemon_main.py /^ def signal_handler(signum):$/;" f function:run_daemon
signal_handler mcp_browser/daemon_main.py /^ def signal_handler(signum):$/;" f function:run_daemon
socket_path build/lib/mcp_browser/__main__.py /^ socket_path = get_socket_path(args.server)$/;" v
socket_path mcp_browser/__main__.py /^ socket_path = get_socket_path(args.server)$/;" v
start build/lib/mcp_browser/daemon.py /^ async def start(self):$/;" m class:MCPBrowserDaemon
start build/lib/mcp_browser/server.py /^ async def start(self):$/;" m class:MCPServer
start mcp_browser/daemon.py /^ async def start(self):$/;" m class:MCPBrowserDaemon
start mcp_browser/server.py /^ async def start(self):$/;" m class:MCPServer
start_builtin_servers build/lib/mcp_browser/multi_server.py /^ async def start_builtin_servers(self):$/;" m class:MultiServerManager
start_builtin_servers mcp_browser/multi_server.py /^ async def start_builtin_servers(self):$/;" m class:MultiServerManager
start_daemon_background build/lib/mcp_browser/__main__.py /^async def start_daemon_background(args):$/;" f
start_daemon_background mcp_browser/__main__.py /^async def start_daemon_background(args):$/;" f
start_daemon_if_needed build/lib/mcp_browser/client_main.py /^def start_daemon_if_needed(server_name: Optional[str] = None, timeout: float = 5.0) -> bool:$/;" f
start_daemon_if_needed mcp_browser/client_main.py /^def start_daemon_if_needed(server_name: Optional[str] = None, timeout: float = 5.0) -> bool:$/;" f
stop build/lib/mcp_browser/daemon.py /^ async def stop(self):$/;" m class:MCPBrowserDaemon
stop build/lib/mcp_browser/server.py /^ async def stop(self):$/;" m class:MCPServer
stop mcp_browser/daemon.py /^ async def stop(self):$/;" m class:MCPBrowserDaemon
stop mcp_browser/server.py /^ async def stop(self):$/;" m class:MCPServer
stop_all build/lib/mcp_browser/multi_server.py /^ async def stop_all(self):$/;" m class:MultiServerManager
stop_all mcp_browser/multi_server.py /^ async def stop_all(self):$/;" m class:MultiServerManager
test_call_method tests/test_basic.py /^ async def test_call_method(self):$/;" m class:TestMCPBrowser
test_claude_connection test_claude_connection.py /^async def test_claude_connection():$/;" f
stop_daemon build/lib/mcp_browser/__main__.py /^def stop_daemon(args):$/;" f
stop_daemon mcp_browser/__main__.py /^def stop_daemon(args):$/;" f
subparsers build/lib/mcp_browser/__main__.py /^ subparsers = parser.add_subparsers(dest="command", help="MCP methods")$/;" v
subparsers mcp_browser/__main__.py /^ subparsers = parser.add_subparsers(dest="command", help="MCP methods")$/;" v
test_basic_flow tests/test_integration.py /^async def test_basic_flow():$/;" f
test_brave_search_integration tests/test_brave_search.py /^async def test_brave_search_integration():$/;" f
test_browser_without_servers tests/test_basic.py /^ async def test_browser_without_servers(self):$/;" m class:TestMCPBrowser
test_browser_without_servers tests/test_browser_functionality.py /^async def test_browser_without_servers():$/;" f
test_claude_connection tests/test_claude_connection.py /^async def test_claude_connection():$/;" f
test_discover_jsonpath tests/test_basic.py /^ def test_discover_jsonpath(self):$/;" m class:TestToolRegistry
test_discover_method tests/test_basic.py /^ async def test_discover_method(self):$/;" m class:TestMCPBrowser
test_duplicate_error_filtering tests/test_basic.py /^ def test_duplicate_error_filtering(self):$/;" m class:TestMessageFilter
test_initialization tests/test_basic.py /^ async def test_initialization(self):$/;" m class:TestMCPBrowser
test_onboarding test_onboarding.py /^async def test_onboarding():$/;" f
test_error_handling tests/test_integration.py /^async def test_error_handling():$/;" f
test_message_filter tests/test_simple.py /^def test_message_filter():$/;" f
test_onboarding tests/test_onboarding.py /^async def test_onboarding():$/;" f
test_server_connection build/lib/mcp_browser/__main__.py /^async def test_server_connection(browser: MCPBrowser, server_name: Optional[str] = None):$/;" f
test_server_connection mcp_browser/__main__.py /^async def test_server_connection(browser: MCPBrowser, server_name: Optional[str] = None):$/;" f
test_sparse_mode tests/test_simple.py /^def test_sparse_mode():$/;" f
test_sparse_mode_filtering tests/test_basic.py /^ def test_sparse_mode_filtering(self):$/;" m class:TestMessageFilter
test_sparse_tools tests/test_basic.py /^ def test_sparse_tools(self):$/;" m class:TestToolRegistry
test_tool_registry tests/test_simple.py /^def test_tool_registry():$/;" f
test_update_tools tests/test_basic.py /^ def test_update_tools(self):$/;" m class:TestToolRegistry
test_virtual_tool_handling tests/test_basic.py /^ async def test_virtual_tool_handling(self):$/;" m class:TestMCPBrowser
to_json build/lib/mcp_browser/registry.py /^ def to_json(self) -> str:$/;" m class:ToolRegistry
to_json mcp_browser/registry.py /^ def to_json(self) -> str:$/;" m class:ToolRegistry
trace build/lib/mcp_browser/logging_config.py /^def trace(self, message, *args, **kwargs):$/;" f
trace mcp_browser/logging_config.py /^def trace(self, message, *args, **kwargs):$/;" f
update_checksums build/lib/mcp_browser/default_configs.py /^def update_checksums():$/;" f
update_checksums mcp_browser/default_configs.py /^def update_checksums():$/;" f
update_tools build/lib/mcp_browser/registry.py /^ def update_tools(self, tools: List[Dict[str, Any]]):$/;" m class:ToolRegistry
update_tools mcp_browser/registry.py /^ def update_tools(self, tools: List[Dict[str, Any]]):$/;" m class:ToolRegistry
url setup.py /^ url="https:\/\/github.com\/anthropics\/mcp-browser",$/;" v
url setup.py /^ url="https:\/\/github.com\/Xilope0\/mcp-browser",$/;" v
user_options setup.py /^ user_options = []$/;" v class:GenerateAIDocs
user_options setup.py /^ user_options = []$/;" v class:TestCommand
version build/lib/mcp_browser/__main__.py /^ version=f"%(prog)s {__version__}",$/;" v
version mcp_browser/__main__.py /^ version=f"%(prog)s {__version__}",$/;" v
version setup.py /^ version="0.1.0",$/;" v

View File

@ -3,33 +3,84 @@
```
./
setup.py
test_claude_connection.py
test_onboarding.py
mcp_browser.egg-info/
systemd/
build/
lib/
mcp_servers/
__init__.py
base.py
screen/
__init__.py
screen_server.py
memory/
__init__.py
memory_server.py
pattern_manager/
__init__.py
pattern_server.py
onboarding/
__init__.py
onboarding_server.py
mcp_browser/
__init__.py
__main__.py
buffer.py
client_main.py
config.py
daemon.py
daemon_main.py
default_configs.py
filter.py
logging_config.py
multi_server.py
proxy.py
registry.py
server.py
utils.py
bdist.linux-x86_64/
docs/
examples/
ai_optimized.py
basic_usage.py
builtin_servers_demo.py
complete_demo.py
dist/
tests/
test_basic.py
test_brave_search.py
test_browser_functionality.py
test_claude_connection.py
test_integration.py
test_onboarding.py
test_simple.py
config/
mcp_servers/
__init__.py
base.py
screen/
__init__.py
screen_server.py
memory/
__init__.py
memory_server.py
pattern_manager/
__init__.py
pattern_server.py
onboarding/
__init__.py
onboarding_server.py
mcp_browser/
__init__.py
__main__.py
buffer.py
client_main.py
config.py
daemon.py
daemon_main.py
default_configs.py
filter.py
logging_config.py
multi_server.py
proxy.py
registry.py

1
init-cmd.json Normal file
View File

@ -0,0 +1 @@
{"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"claude-ai","version":"0.1.0"}},"jsonrpc":"2.0","id":0}

View File

@ -274,12 +274,23 @@ def main():
# Setup logging
log_file = Path(args.log_file) if args.log_file else None
# In server mode, use syslog unless a log file is specified
use_syslog = args.mode == "server" and not log_file
setup_logging(
debug=args.debug,
log_file=log_file,
log_level=args.log_level
log_level=args.log_level,
use_syslog=use_syslog
)
# Log startup message
logger = get_logger(__name__)
if args.mode == "server":
logger.debug("mcp-browser client started in server mode")
# Handle modes
if args.mode == "server":
# Run as MCP server

View File

@ -275,3 +275,72 @@ def is_daemon_running(socket_path: Path) -> bool:
return psutil.pid_exists(pid)
except (ValueError, psutil.Error):
return False
def kill_daemon_with_children(socket_path: Path) -> bool:
"""Kill the daemon and all its child processes."""
pid_file = socket_path.with_suffix('.pid')
if not pid_file.exists():
return False
try:
pid = int(pid_file.read_text().strip())
# Try to use psutil to kill the process tree
if hasattr(psutil, 'Process'):
try:
parent = psutil.Process(pid)
children = parent.children(recursive=True)
# Kill children first
for child in children:
try:
child.terminate()
except psutil.NoSuchProcess:
pass
# Kill parent
parent.terminate()
# Wait a bit for graceful termination
import time
time.sleep(0.5)
# Force kill any remaining processes
for child in children:
try:
child.kill()
except psutil.NoSuchProcess:
pass
try:
parent.kill()
except psutil.NoSuchProcess:
pass
return True
except (psutil.NoSuchProcess, psutil.AccessDenied):
pass
# Fallback to simple kill
try:
os.kill(pid, signal.SIGTERM)
import time
time.sleep(0.5)
os.kill(pid, signal.SIGKILL)
except OSError:
pass
return True
except (ValueError, OSError):
return False
finally:
# Clean up socket and PID file
try:
socket_path.unlink()
except FileNotFoundError:
pass
try:
pid_file.unlink()
except FileNotFoundError:
pass

View File

@ -5,17 +5,18 @@ Intercepts and modifies JSON-RPC messages to implement
sparse mode and virtual tool injection.
"""
import sys
import json
from typing import Dict, Any, Optional, List, Callable, Union
from .registry import ToolRegistry
class MessageFilter:
"""Filter and transform JSON-RPC messages for sparse mode."""
"""Filter and transform JSON-RPC messages to always show sparse tools."""
def __init__(self, registry: ToolRegistry, sparse_mode: bool = True):
self.registry = registry
self.sparse_mode = sparse_mode
# Ignore sparse_mode parameter - always use sparse mode
self._handled_ids: set = set()
def filter_outgoing(self, message: dict) -> Optional[dict]:
@ -48,9 +49,8 @@ class MessageFilter:
self._handled_ids.discard(message.get("id"))
return None
# Intercept tools/list responses for sparse mode
if (self.sparse_mode and
message.get("id") and
# ALWAYS intercept tools/list responses to show only sparse tools
if (message.get("id") and
message.get("result", {}).get("tools")):
return self._filter_tools_response(message)
@ -66,7 +66,8 @@ class MessageFilter:
# Replace with sparse tools
message = message.copy()
message["result"] = message["result"].copy()
message["result"]["tools"] = self.registry.get_sparse_tools()
sparse_tools = self.registry.get_sparse_tools()
message["result"]["tools"] = sparse_tools
return message

View File

@ -4,6 +4,7 @@ Logging configuration for MCP Browser.
import logging
import sys
import os
from pathlib import Path
from typing import Optional
from datetime import datetime
@ -17,7 +18,8 @@ class ServerNameAdapter(logging.LoggerAdapter):
return f"[{server}] {msg}", kwargs
def setup_logging(debug: bool = False, log_file: Optional[Path] = None, log_level: Optional[str] = None):
def setup_logging(debug: bool = False, log_file: Optional[Path] = None,
log_level: Optional[str] = None, use_syslog: bool = False):
"""
Configure logging for MCP Browser.
@ -25,6 +27,7 @@ def setup_logging(debug: bool = False, log_file: Optional[Path] = None, log_leve
debug: Enable debug logging
log_file: Optional file to write logs to
log_level: Override log level (DEBUG, INFO, WARNING, ERROR)
use_syslog: Use syslog instead of console/file (for server mode)
"""
# Determine log level
if log_level:
@ -52,17 +55,52 @@ def setup_logging(debug: bool = False, log_file: Optional[Path] = None, log_leve
# Remove existing handlers
root_logger.handlers.clear()
# Console handler (stderr)
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
if use_syslog:
# Use syslog for server mode - NEVER write to stdout/stderr
from logging.handlers import SysLogHandler
try:
# Try Unix socket first (most common on Linux)
syslog_handler = SysLogHandler(
facility=SysLogHandler.LOG_DAEMON,
address='/dev/log'
)
except (OSError, FileNotFoundError):
# Fall back to UDP socket (for macOS, some Linux distros)
try:
syslog_handler = SysLogHandler(
facility=SysLogHandler.LOG_DAEMON,
address=('localhost', 514)
)
except Exception:
# If syslog is not available, log to a file instead
import tempfile
fallback_log = Path(tempfile.gettempdir()) / 'mcp-browser-server.log'
file_handler = logging.FileHandler(fallback_log, mode='a')
file_handler.setFormatter(formatter)
root_logger.addHandler(file_handler)
return
# Syslog has its own format, but we can prepend our app name
syslog_formatter = logging.Formatter('mcp-browser[%(process)d]: %(name)s - %(levelname)s - %(message)s')
syslog_handler.setFormatter(syslog_formatter)
root_logger.addHandler(syslog_handler)
elif log_file:
# File handler if requested
if log_file:
file_handler = logging.FileHandler(log_file, mode='a')
file_handler.setFormatter(formatter)
root_logger.addHandler(file_handler)
# Only add console handler if not logging to /dev/null
if str(log_file) != '/dev/null':
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
else:
# Console handler (stderr) only if no file specified
console_handler = logging.StreamHandler(sys.stderr)
console_handler.setFormatter(formatter)
root_logger.addHandler(console_handler)
# Set levels for specific loggers
# Suppress some noisy libraries unless in debug mode
if level > logging.DEBUG:

View File

@ -62,7 +62,7 @@ class MultiServerManager:
# Initialize each server
await server.send_request("initialize", {
"protocolVersion": "0.1.0",
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "mcp-browser",
@ -84,7 +84,7 @@ class MultiServerManager:
# Initialize
await server.send_request("initialize", {
"protocolVersion": "0.1.0",
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "mcp-browser",
@ -148,8 +148,14 @@ class MultiServerManager:
async def stop_all(self):
"""Stop all servers."""
for name, server in self.servers.items():
# Create a copy of the dictionary to avoid iteration errors
servers_copy = dict(self.servers)
for name, server in servers_copy.items():
self.logger.info(f"Stopping server: {name}")
try:
await server.stop()
except Exception as e:
self.logger.error(f"Error stopping server {name}: {e}")
self.servers.clear()

View File

@ -129,9 +129,6 @@ class MCPBrowser:
}
})
"""
if not self._initialized:
await self.initialize()
# Ensure request has an ID
if "id" not in jsonrpc_object:
jsonrpc_object = jsonrpc_object.copy()
@ -140,6 +137,32 @@ class MCPBrowser:
request_id = jsonrpc_object["id"]
# Handle initialize request specially when acting as a server
if jsonrpc_object.get("method") == "initialize":
# Initialize ourselves if needed
if not self._initialized:
await self.initialize()
# Return our capabilities
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "mcp-browser",
"version": "0.1.0"
}
}
}
# Initialize if needed for other requests
if not self._initialized:
await self.initialize()
# Check if this is a virtual tool call
if jsonrpc_object.get("method") == "tools/call":
tool_name = jsonrpc_object.get("params", {}).get("name")
@ -173,16 +196,21 @@ class MCPBrowser:
# 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
method = jsonrpc_object.get("method")
if method == "tools/list":
# Get all tools and apply sparse filter
tools = await self.multi_server.get_all_tools()
filtered_tools = self.filter.filter_outgoing({
response = {
"jsonrpc": "2.0",
"id": request_id,
"result": {"tools": tools}
})
return filtered_tools
elif jsonrpc_object.get("method") == "tools/call":
}
# Always filter to show only sparse tools
filtered_response = self.filter.filter_incoming(response)
return filtered_response
elif method == "tools/call":
# Route tool call to multi-server
tool_name = jsonrpc_object.get("params", {}).get("name")
args = jsonrpc_object.get("params", {}).get("arguments", {})
@ -200,6 +228,57 @@ class MCPBrowser:
"error": {"code": -32603, "message": str(e)}
}
elif method == "prompts/list":
# No prompts in builtin-only mode
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {"prompts": []}
}
elif method == "prompts/get":
# No prompts available
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {"code": -32602, "message": "Prompt not found"}
}
elif method == "resources/list":
# No resources in builtin-only mode
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {"resources": []}
}
elif method == "resources/read":
# No resources available
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {"code": -32602, "message": "Resource not found"}
}
elif method == "completion/complete":
# No completions in builtin-only mode
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {"completion": {"values": []}}
}
else:
# Unknown method
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32601,
"message": f"Method '{method}' not found"
}
}
# No server available
return {
"jsonrpc": "2.0",
@ -269,7 +348,7 @@ class MCPBrowser:
# Send initialize request directly to server
init_response = await self.server.send_request("initialize", {
"protocolVersion": "0.1.0",
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "mcp-browser",

View File

@ -105,40 +105,50 @@ class BaseMCPServer(ABC):
"""Run the MCP server, reading from stdin and writing to stdout."""
self._running = True
# Platform-specific non-blocking setup
# Log server startup
print(f"DEBUG: {self.name} server starting", file=sys.stderr, flush=True)
# Use asyncio for stdin reading
loop = asyncio.get_event_loop()
stdin_reader = asyncio.StreamReader()
stdin_protocol = asyncio.StreamReaderProtocol(stdin_reader)
try:
import fcntl
import os
flags = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
except ImportError:
# Windows doesn't have fcntl
pass
buffer = ""
# Connect stdin to async reader
await loop.connect_read_pipe(lambda: stdin_protocol, sys.stdin)
except Exception as e:
print(f"ERROR: {self.name} failed to setup async stdin: {e}", file=sys.stderr, flush=True)
return
# Main server loop
while self._running:
try:
# Try to read available data
chunk = sys.stdin.read(4096)
if not chunk:
# EOF reached
# Read a line with timeout to prevent hanging
line = await asyncio.wait_for(
stdin_reader.readline(),
timeout=None # No timeout - we want to wait indefinitely for commands
)
if not line:
# Empty bytes means EOF
print(f"DEBUG: {self.name} detected EOF on stdin", file=sys.stderr, flush=True)
break
buffer += chunk
# Process complete lines
while '\n' in buffer:
line, buffer = buffer.split('\n', 1)
line = line.strip()
# Decode and process line
line_str = line.decode('utf-8').strip()
if not line_str:
continue
print(f"DEBUG: {self.name} received: {line_str}", file=sys.stderr, flush=True)
if line:
try:
request = json.loads(line)
request = json.loads(line_str)
response = await self.handle_request(request)
print(json.dumps(response), flush=True)
except json.JSONDecodeError:
pass
except Exception as e:
response_str = json.dumps(response)
print(f"DEBUG: {self.name} sending: {response_str}", file=sys.stderr, flush=True)
print(response_str, flush=True)
except json.JSONDecodeError as e:
print(f"ERROR: {self.name} JSON decode error: {e}", file=sys.stderr, flush=True)
error_response = {
"jsonrpc": "2.0",
"id": None,
@ -148,15 +158,30 @@ class BaseMCPServer(ABC):
}
}
print(json.dumps(error_response), flush=True)
except Exception as e:
print(f"ERROR: {self.name} request handling error: {e}", file=sys.stderr, flush=True)
error_response = {
"jsonrpc": "2.0",
"id": None,
"error": {
"code": -32603,
"message": str(e)
}
}
print(json.dumps(error_response), flush=True)
except BlockingIOError:
# No data available, sleep briefly
await asyncio.sleep(0.01)
except EOFError:
# stdin closed
except asyncio.CancelledError:
print(f"DEBUG: {self.name} cancelled", file=sys.stderr, flush=True)
break
except KeyboardInterrupt:
print(f"DEBUG: {self.name} interrupted", file=sys.stderr, flush=True)
break
except Exception as e:
print(f"ERROR: {self.name} unexpected error: {e}", file=sys.stderr, flush=True)
# Continue running despite errors
await asyncio.sleep(0.1)
print(f"DEBUG: {self.name} server exiting", file=sys.stderr, flush=True)
def content_text(self, text: str) -> Dict[str, Any]:
"""Helper to create text content response."""

View File

@ -205,9 +205,9 @@ setup(
python_requires=">=3.8",
entry_points={
"console_scripts": [
"mcp-browser=mcp_browser.client_main:main",
"mcp-browser=mcp_browser.__main__:main",
"mcp-browser-daemon=mcp_browser.daemon_main:main",
"mcp-browser-legacy=mcp_browser.__main__:main",
"mcp-browser-client=mcp_browser.client_main:main",
],
},
cmdclass={

171
test_claude_desktop_flow.py Normal file
View File

@ -0,0 +1,171 @@
#!/usr/bin/env python3
"""
Test the exact Claude Desktop flow to identify the timeout issue.
"""
import asyncio
import json
import subprocess
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
async def test_server_mode_timeout():
"""Test server mode with proper timeout handling."""
print("Testing Claude Desktop flow with timeout...")
# Start mcp-browser in server mode
proc = subprocess.Popen(
[sys.executable, "-m", "mcp_browser", "--mode", "server"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
try:
# Send initialize request like Claude Desktop does
init_request = {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "claude-desktop",
"version": "0.7.2"
}
}
}
print(f"Sending: {json.dumps(init_request)}")
proc.stdin.write(json.dumps(init_request) + "\n")
proc.stdin.flush()
# Wait for response with timeout
response_received = False
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < 5.0: # 5 second timeout
try:
# Non-blocking read
line = proc.stdout.readline()
if line:
response = json.loads(line.strip())
print(f"Received: {json.dumps(response, indent=2)}")
response_received = True
break
except:
await asyncio.sleep(0.1)
continue
await asyncio.sleep(0.1)
if not response_received:
print("ERROR: No response received within 5 seconds!")
# Check stderr for errors
stderr_output = proc.stderr.read()
if stderr_output:
print(f"STDERR: {stderr_output}")
else:
# Send initialized notification
initialized = {
"jsonrpc": "2.0",
"method": "initialized"
}
print(f"\nSending: {json.dumps(initialized)}")
proc.stdin.write(json.dumps(initialized) + "\n")
proc.stdin.flush()
# Test tools/list
tools_request = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
print(f"\nSending: {json.dumps(tools_request)}")
proc.stdin.write(json.dumps(tools_request) + "\n")
proc.stdin.flush()
# Wait for tools response
start_time = asyncio.get_event_loop().time()
while asyncio.get_event_loop().time() - start_time < 2.0:
line = proc.stdout.readline()
if line:
response = json.loads(line.strip())
print(f"Received: {json.dumps(response, indent=2)}")
break
await asyncio.sleep(0.1)
finally:
proc.terminate()
proc.wait()
async def test_with_logging():
"""Test with debug logging enabled."""
print("\n\nTesting with debug logging...")
# Start mcp-browser in server mode with debug
proc = subprocess.Popen(
[sys.executable, "-m", "mcp_browser", "--mode", "server", "--debug", "--log-file", "/tmp/mcp-test.log"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
try:
# Send initialize
init_request = {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "test-client",
"version": "1.0.0"
}
}
}
proc.stdin.write(json.dumps(init_request) + "\n")
proc.stdin.flush()
# Read with timeout
await asyncio.sleep(1.0)
# Try to read response
output = proc.stdout.read()
if output:
print(f"STDOUT: {output}")
stderr = proc.stderr.read()
if stderr:
print(f"STDERR: {stderr}")
# Check log file
try:
with open("/tmp/mcp-test.log", "r") as f:
log_content = f.read()
if log_content:
print(f"\nLOG FILE:\n{log_content}")
except:
pass
finally:
proc.terminate()
proc.wait()
if __name__ == "__main__":
asyncio.run(test_server_mode_timeout())
asyncio.run(test_with_logging())

260
test_mcp_protocol.py Normal file
View File

@ -0,0 +1,260 @@
#!/usr/bin/env python3
"""
Test MCP Protocol flow to understand and verify the initialization handshake.
This test will:
1. Create a minimal MCP server that logs all interactions
2. Create an MCP browser client
3. Verify the complete initialization flow
4. Test tools/list and tools/call
"""
import asyncio
import json
import sys
import os
import tempfile
from pathlib import Path
# Add project to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from mcp_browser import MCPBrowser
from mcp_browser.daemon import MCPBrowserDaemon, MCPBrowserClient, get_socket_path
def log_test(msg):
"""Log test messages with timestamp."""
import datetime
timestamp = datetime.datetime.now().strftime("%H:%M:%S.%f")[:-3]
print(f"[{timestamp}] {msg}")
async def test_direct_initialization():
"""Test direct initialization without daemon."""
log_test("=== TEST 1: Direct Initialization ===")
# Create browser with correct config
browser = MCPBrowser(enable_builtin_servers=True)
try:
log_test("Initializing browser...")
await browser.initialize()
log_test("✓ Browser initialized successfully")
# Test tools/list
log_test("Calling tools/list...")
response = await browser.call({
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
})
if "result" in response:
tools = response["result"].get("tools", [])
log_test(f"✓ Got {len(tools)} tools: {[t['name'] for t in tools]}")
else:
log_test(f"✗ Error in tools/list: {response}")
except Exception as e:
log_test(f"✗ Error: {e}")
import traceback
traceback.print_exc()
finally:
await browser.close()
async def test_daemon_initialization():
"""Test initialization through daemon."""
log_test("\n=== TEST 2: Daemon Initialization ===")
# Use a temporary socket
with tempfile.TemporaryDirectory() as tmpdir:
socket_path = Path(tmpdir) / "test-mcp.sock"
# Create browser and daemon
browser = MCPBrowser(enable_builtin_servers=True)
daemon = MCPBrowserDaemon(browser, socket_path)
# Start daemon in background
daemon_task = asyncio.create_task(daemon.start())
try:
# Give daemon time to start
await asyncio.sleep(0.1)
# Connect as client
async with MCPBrowserClient(socket_path) as client:
log_test("Connected to daemon")
# Send initialize - this should be handled by the proxy
log_test("Sending initialize request...")
init_request = {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "test-client",
"version": "1.0.0"
}
}
}
response = await client.call(init_request)
log_test(f"Initialize response: {json.dumps(response, indent=2)}")
# Check response
if "result" in response:
result = response["result"]
if result.get("protocolVersion") == "2024-11-05":
log_test("✓ Got correct protocol version")
else:
log_test(f"✗ Wrong protocol version: {result.get('protocolVersion')}")
else:
log_test(f"✗ Error in initialize: {response}")
# Test tools/list
log_test("\nSending tools/list request...")
tools_request = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
response = await client.call(tools_request)
if "result" in response:
tools = response["result"].get("tools", [])
log_test(f"✓ Got {len(tools)} tools: {[t['name'] for t in tools]}")
else:
log_test(f"✗ Error in tools/list: {response}")
finally:
# Stop daemon
await daemon.stop()
daemon_task.cancel()
try:
await daemon_task
except asyncio.CancelledError:
pass
async def test_server_mode_initialization():
"""Test server mode (stdin/stdout) initialization."""
log_test("\n=== TEST 3: Server Mode Initialization ===")
# This simulates what Claude Desktop does
browser = MCPBrowser(enable_builtin_servers=True)
await browser.initialize()
# Simulate initialize request from Claude Desktop
init_request = {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "claude-desktop",
"version": "0.7.2"
}
}
}
log_test("Processing initialize request from Claude Desktop...")
response = await browser.call(init_request)
log_test(f"Response: {json.dumps(response, indent=2)}")
# Check if we need to send initialized notification
if "result" in response:
log_test("✓ Initialize successful")
# Claude Desktop would send initialized notification
initialized_notif = {
"jsonrpc": "2.0",
"method": "initialized"
}
log_test("Sending initialized notification...")
# Notifications don't expect responses
await browser.call(initialized_notif)
# Now test tools/list
tools_request = {
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
response = await browser.call(tools_request)
if "result" in response:
tools = response["result"].get("tools", [])
log_test(f"✓ Got {len(tools)} tools in sparse mode")
else:
log_test(f"✗ Error in tools/list: {response}")
await browser.close()
async def test_double_handshake_issue():
"""Test the specific issue: Claude Desktop -> mcp-browser -> MCP servers."""
log_test("\n=== TEST 4: Double Handshake Issue ===")
# When Claude Desktop connects to mcp-browser in server mode:
# 1. Claude Desktop sends initialize to mcp-browser
# 2. mcp-browser should respond with its capabilities
# 3. mcp-browser internally initializes connections to MCP servers
# 4. But it should NOT forward the initialize request to MCP servers
browser = MCPBrowser(enable_builtin_servers=True)
# The browser should initialize its internal servers first
log_test("Browser initializing internal servers...")
await browser.initialize()
# Now simulate Claude Desktop connecting
init_from_claude = {
"jsonrpc": "2.0",
"id": 0,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {
"name": "claude-desktop",
"version": "0.7.2"
}
}
}
log_test("Claude Desktop sends initialize...")
response = await browser.call(init_from_claude)
if "result" in response:
log_test("✓ mcp-browser responded to initialize")
log_test(f" Protocol: {response['result'].get('protocolVersion')}")
log_test(f" Server: {response['result'].get('serverInfo', {}).get('name')}")
else:
log_test(f"✗ Error: {response}")
await browser.close()
async def main():
"""Run all tests."""
log_test("Starting MCP Protocol Tests")
log_test("=" * 60)
# Run tests
await test_direct_initialization()
await test_daemon_initialization()
await test_server_mode_initialization()
await test_double_handshake_issue()
log_test("\n" + "=" * 60)
log_test("Tests completed!")
if __name__ == "__main__":
asyncio.run(main())