#!/usr/bin/env python3 """ Default configuration files for MCP Browser. Creates and manages default config directory at ~/.config/mcp-browser/ with all necessary files including config, onboarding, patterns, etc. """ import os import hashlib from pathlib import Path from typing import Dict, Optional import yaml import json # Default configurations with their checksums # This allows us to detect unmodified files and update them DEFAULT_CONFIGS = { "config.yaml": { "checksum": "3f4e8b9c2a1d5678ef90ab12cd34567890abcdef1234567890abcdef12345678", "content": """# MCP Browser Configuration # This file is automatically generated and will be overwritten if unmodified # To customize, modify any value and the file will be preserved # Server definitions - Add your MCP servers here servers: # Example: Brave Search (requires BRAVE_API_KEY environment variable) brave-search: command: ["npx", "-y", "@modelcontextprotocol/server-brave-search"] name: "brave-search" description: "Brave Search API access" env: {} # Environment variables are inherited, including BRAVE_API_KEY # Example: Filesystem access filesystem: command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/home"] name: "filesystem" description: "File system access (read-only by default)" args: ["--read-only"] # Example: GitHub API (requires GITHUB_TOKEN) github: command: ["npx", "-y", "@modelcontextprotocol/server-github"] name: "github" description: "GitHub API access" env: {} # Inherits GITHUB_TOKEN from environment # Example: Memory/Notes server memory: command: ["npx", "-y", "@modelcontextprotocol/server-memory"] name: "memory" description: "Persistent memory and notes" # Example: Postgres database (requires connection string) # postgres: # command: ["npx", "-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"] # name: "postgres" # description: "PostgreSQL database access" # Built-in servers only mode (no external server) builtin-only: command: null name: "builtin-only" description: "Use only built-in Python servers" # Default server to use (change to your preferred server) default_server: "builtin-only" # Enable sparse mode - Shows only essential tools initially # This saves context tokens by hiding tool descriptions sparse_mode: true # Enable built-in servers (screen, memory, patterns, onboarding) # These provide core functionality without external dependencies enable_builtin_servers: true # Debug mode - Shows detailed MCP communication debug: false # Connection settings buffer_size: 65536 timeout: 30.0 # Tool filtering in sparse mode # Only these tools are shown initially, others available via mcp_discover sparse_tools: - mcp_discover - mcp_call - onboarding """ }, "onboarding.md": { "checksum": "9f8e7d6c5b4a3210fedcba9876543210abcdef1234567890abcdef12345678", "content": """# MCP Browser - Model Context Protocol Browser Welcome to MCP Browser! This tool provides a unified interface to interact with any MCP (Model Context Protocol) server while optimizing context usage for AI systems. ## 🚀 Quick Start ### First Time Setup 1. **Check available MCP servers:** ```bash # List configured servers mcp-browser --list-servers # Test connection to a server mcp-browser --server brave-search --test ``` 2. **Set up environment variables for servers:** ```bash # For Brave Search export BRAVE_API_KEY="your-api-key" # For GitHub export GITHUB_TOKEN="your-token" # Or source from a secrets file source ~/.secrets/api-keys.sh ``` ### Basic Usage 1. **Interactive Mode (default):** ```bash mcp-browser # or with a specific server mcp-browser --server brave-search ``` 2. **Available commands in interactive mode:** - `list` - Show available tools (sparse mode) - `discover ` - Discover tools using JSONPath - `call ` - Execute any JSON-RPC call - `onboard ` - Get/set identity-specific instructions - `help` - Show command help - `exit` - Exit interactive mode 3. **Example workflows:** ```bash # Discover all available tools > discover $.tools[*].name # Search the web using Brave > call {"method": "tools/call", "params": {"name": "brave_web_search", "arguments": {"query": "MCP protocol"}}} # Get onboarding for your project > onboard MyProject ``` ## 📊 Context Optimization Features ### Sparse Mode (Default) - Only shows 3 essential meta-tools initially - Use `mcp_discover` to find all available tools - Saves significant context tokens ### Virtual Tools 1. **mcp_discover** - Discover tools using JSONPath queries 2. **mcp_call** - Execute any MCP server tool 3. **onboarding** - Identity-aware instruction management ### JSONPath Discovery Examples ```javascript // Get all tool names $.tools[*].name // Find tools with "search" in name $.tools[?(@.name =~ /search/i)].name // Get input schemas for all tools $.tools[*].inputSchema // Find specific tool details $.tools[?(@.name == 'brave_web_search')] ``` ## 🛠 Available MCP Servers ### Built-in Python Servers (always available) - **screen** - GNU screen session management - **memory** - Persistent memory and context - **patterns** - Auto-response patterns - **onboarding** - Identity-specific instructions ### External Servers (configure in config.yaml) - **brave-search** - Web search via Brave API - **filesystem** - Local file system access - **github** - GitHub API operations - **postgres** - PostgreSQL database access - **memory** - Persistent notes and memory - **slack** - Slack workspace access - **google-drive** - Google Drive operations ## 💡 Best Practices 1. **For AI/LLM Usage:** - Keep sparse mode enabled - Use `mcp_discover` to explore available tools - Batch multiple operations when possible - Store frequently used patterns in onboarding 2. **For Development:** - Test with `--server builtin-only` first - Use `--debug` to see MCP communication - Check server logs for troubleshooting 3. **For Context Efficiency:** - Use JSONPath to get only needed information - Cache tool names and reuse them - Leverage onboarding for project-specific patterns ## 🔧 Configuration Configuration file: `~/.config/mcp-browser/config.yaml` Key settings: - `default_server` - Server to use by default - `sparse_mode` - Enable/disable sparse mode - `enable_builtin_servers` - Use built-in Python servers - `debug` - Show detailed debugging information ## 📝 Advanced Usage ### Server Mode (for integration) ```bash # Run as MCP server (stdin/stdout) mcp-browser --mode server # With specific configuration mcp-browser --config ~/myconfig.yaml --mode server ``` ### Custom Configurations 1. Edit `~/.config/mcp-browser/config.yaml` 2. Add your MCP servers 3. Set environment variables as needed 4. Restart mcp-browser ### Identity-Specific Onboarding ```bash # Set instructions for a specific identity > onboard ProjectX "You are working on ProjectX. Focus on API endpoints and testing." # Retrieve instructions > onboard ProjectX ``` ## 🐛 Troubleshooting 1. **Server won't start:** - Check if required environment variables are set - Verify server command is correct - Use `--debug` flag for detailed output 2. **Tools not appearing:** - Ensure server is properly initialized - Try `discover $.tools[*]` to see raw data - Check if sparse mode is hiding tools 3. **Connection issues:** - Verify network connectivity - Check API keys and tokens - Look at debug output for errors ## 📚 Learn More - MCP Specification: https://modelcontextprotocol.io - Available Servers: https://github.com/modelcontextprotocol/servers - Report Issues: https://github.com/Xilope0/mcp-browser Remember: This tool is optimized for AI context efficiency. When in doubt, use `mcp_discover` to explore! """ }, "patterns/system-patterns.json": { "checksum": "1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678", "content": """{ "patterns": [ { "id": "list_tools_sparse", "pattern": ["list tools", "show tools", "what tools"], "replacement": "__SPARSE_TOOLS__", "description": "Show sparse tools when requested", "type": "system" }, { "id": "discover_all_tools", "pattern": ["show all tools", "list all tools", "discover tools"], "replacement": "__DISCOVER_$.tools[*].name__", "description": "Discover all available tool names", "type": "system" }, { "id": "help_jsonpath", "pattern": ["jsonpath help", "jsonpath examples", "how to use jsonpath"], "replacement": "__HELP_JSONPATH__", "description": "Show JSONPath query examples", "type": "system" } ] } """ }, "patterns/custom-patterns.json": { "checksum": "2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678", "content": """{ "patterns": [] } """ } } class ConfigManager: """Manages MCP Browser configuration directory.""" def __init__(self, config_dir: Optional[Path] = None): """Initialize config manager. Args: config_dir: Override default config directory """ if config_dir: self.config_dir = Path(config_dir) else: self.config_dir = Path.home() / ".config" / "mcp-browser" def ensure_config_directory(self) -> None: """Ensure config directory exists with all default files.""" # Create directory structure self.config_dir.mkdir(parents=True, exist_ok=True) (self.config_dir / "patterns").mkdir(exist_ok=True) (self.config_dir / "logs").mkdir(exist_ok=True) (self.config_dir / "backups").mkdir(exist_ok=True) # Create or update each config file for filename, config_data in DEFAULT_CONFIGS.items(): self._ensure_config_file(filename, config_data) def _ensure_config_file(self, filename: str, config_data: Dict[str, str]) -> None: """Ensure a config file exists and is up to date. Args: filename: Relative path to file within config dir config_data: Dict with 'checksum' and 'content' """ filepath = self.config_dir / filename # Create parent directories if needed filepath.parent.mkdir(parents=True, exist_ok=True) # Check if file exists and is unmodified if filepath.exists(): current_checksum = self._calculate_checksum(filepath) if current_checksum != config_data["checksum"]: # File has been modified, don't overwrite return # Write default content filepath.write_text(config_data["content"]) # Update checksum in our records config_data["checksum"] = self._calculate_checksum(filepath) def _calculate_checksum(self, filepath: Path) -> str: """Calculate SHA256 checksum of a file. Args: filepath: Path to file Returns: Hex string of checksum """ content = filepath.read_bytes() return hashlib.sha256(content).hexdigest() def get_config_path(self) -> Path: """Get path to main config file.""" return self.config_dir / "config.yaml" def get_onboarding_path(self) -> Path: """Get path to onboarding file.""" return self.config_dir / "onboarding.md" def get_patterns_dir(self) -> Path: """Get path to patterns directory.""" return self.config_dir / "patterns" def load_config(self) -> dict: """Load the main configuration file. Returns: Configuration dictionary """ config_path = self.get_config_path() if not config_path.exists(): self.ensure_config_directory() with open(config_path, 'r') as f: return yaml.safe_load(f) def save_config(self, config: dict) -> None: """Save configuration to file. Args: config: Configuration dictionary """ config_path = self.get_config_path() with open(config_path, 'w') as f: yaml.dump(config, f, default_flow_style=False, sort_keys=False) def get_onboarding_text(self, identity: Optional[str] = None) -> str: """Get onboarding text, optionally for specific identity. Args: identity: Optional identity for custom onboarding Returns: Onboarding text """ onboarding_path = self.get_onboarding_path() if not onboarding_path.exists(): self.ensure_config_directory() base_text = onboarding_path.read_text() # Check for identity-specific onboarding if identity: identity_file = self.config_dir / f"onboarding-{identity}.md" if identity_file.exists(): return identity_file.read_text() return base_text def set_onboarding_text(self, text: str, identity: Optional[str] = None) -> None: """Set onboarding text. Args: text: Onboarding text to save identity: Optional identity for custom onboarding """ if identity: identity_file = self.config_dir / f"onboarding-{identity}.md" identity_file.write_text(text) else: self.get_onboarding_path().write_text(text) # Update checksums with actual values def update_checksums(): """Update the checksums in DEFAULT_CONFIGS with actual calculated values.""" for filename, config_data in DEFAULT_CONFIGS.items(): content_bytes = config_data["content"].encode('utf-8') config_data["checksum"] = hashlib.sha256(content_bytes).hexdigest() # Initialize checksums update_checksums()