mcp-browser/mcp_browser/default_configs.py

462 lines
14 KiB
Python

#!/usr/bin/env python3
"""
Default configuration files for MCP Browser.
Creates and manages default config directory at ~/.claude/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 <jsonpath>` - Discover tools using JSONPath
- `call <json>` - Execute any JSON-RPC call
- `onboard <identity>` - 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: `~/.claude/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 `~/.claude/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() / ".claude" / "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()