#!/usr/bin/env python3 """ Playwright MCP Configuration Tool Configures Playwright MCP server in Claude's .claude.json to use different profile storage states for isolated browser sessions. Usage: python playwright_mcp_tool.py Example: python playwright_mcp_tool.py j1 This will configure Playwright to use the storage state at: ~/.playwright-mcp/storage-states/j1/storage-state.json """ import argparse import getpass import json from pathlib import Path def parse_args(): """Parse command line arguments.""" parser = argparse.ArgumentParser(description="Playwright MCP tool") parser.add_argument( "profile_name", nargs="?", help="Profile name to use (optional)" ) return parser.parse_args() def load_claude_config() -> dict: """Load .claude.json configuration from home directory.""" claude_config_path = Path.home() / ".claude.json" with open(claude_config_path, "r") as f: config = json.load(f) return config def get_project_root(current_path: Path) -> Path: """Get the Claude project directory by finding the root directory based on directory structure.""" # Check if path contains "glockenspiel" anywhere in the full path if "glockenspiel" not in str(current_path): return current_path # Return the folder that contains "glockenspiel" parts = current_path.parts for i, part in enumerate(parts): if "glockenspiel" in part: return Path(*parts[: i + 1]) # If no "glockenspiel" is found, return the current path return current_path def update_claude_config(config: dict, project_root: Path, profile_name: str): """Update the Claude config to use the project root.""" storage_state_path = f"/Users/{getpass.getuser()}/.playwright-mcp/storage-states/{profile_name}/storage-state.json" if not Path(storage_state_path).exists(): raise ValueError(f"Storage state path does not exist: {storage_state_path}") config["projects"][str(project_root)]["mcpServers"]["playwright"]["args"] = [ "@playwright/mcp@latest", "--isolated", f"--storage-state={storage_state_path}", ] def write_claude_config(config: dict): """Write the updated Claude config to the file.""" claude_config_path = Path.home() / ".claude.json" with open(claude_config_path, "w") as f: json.dump(config, f, indent=2) def print_all_playwright_storage_states(config: dict): """Print which glockenspiel project has which storage state profile name.""" for project_path, project_config in config.get("projects", {}).items(): if "glockenspiel" in project_path and project_path.endswith("glockenspiel"): playwright_config = project_config.get("mcpServers", {}).get( "playwright", {} ) args = playwright_config.get("args", []) # Find storage state argument storage_state_profile = None for arg in args: if arg.startswith("--storage-state="): # Extract profile name from path like: /Users/user/.playwright-mcp/storage-states/j2/storage-state.json storage_state_path = arg.split("=", 1)[1] parts = storage_state_path.split("/") if "storage-states" in parts: idx = parts.index("storage-states") if idx + 1 < len(parts): storage_state_profile = parts[idx + 1] break print(f"{project_path}: {storage_state_profile}") if __name__ == "__main__": args = parse_args() config = load_claude_config() if not args.profile_name: print_all_playwright_storage_states(config) exit(0) current_path = Path.cwd() project_root = get_project_root(current_path) update_claude_config(config, project_root, args.profile_name) write_claude_config(config) print(f"Updated Claude config to use profile: {args.profile_name}") print(f"Project root: {project_root}")