Skip to main content
Glama
mcp_config_builder.py13.4 kB
#!/usr/bin/env python3 """ MCP Configuration Builder - Multi-Repo & Single-Repo Support Generates MCP configurations for: 1. Single-repo isolation (one workspace at a time) 2. Multi-repo orchestration (linked workspaces) Usage: # Interactive mode python scripts/mcp_config_builder.py # Single repo python scripts/mcp_config_builder.py --single --workspace C:\Projects\MyApp # Multi-repo orchestration python scripts/mcp_config_builder.py --multi --core C:\AIStack-MCP --repos C:\Projects\RepoA C:\Projects\RepoB """ import argparse import json from pathlib import Path from typing import List, Dict, Optional import sys import shutil from datetime import datetime def build_single_repo_config(workspace_path: Path) -> Dict: """Generate single-repo MCP config (portable via ${workspaceFolder}).""" return { "mcpServers": { "code-intelligence": { "command": "cmd", "args": [ "/c", "python", "${workspaceFolder}\\mcp_intelligence_server.py", "--workspace", "${workspaceFolder}" ], "env": { "OLLAMA_URL": "http://localhost:11434", "QDRANT_URL": "http://localhost:6333" } }, "filesystem": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}" ] }, "git": { "command": "npx", "args": [ "-y", "@modelcontextprotocol/server-git", "--repository", "${workspaceFolder}" ] } } } def build_multi_repo_config( core_path: Path, repo_paths: List[Path], use_relative_paths: bool = True ) -> Dict: """ Generate multi-repo orchestration config. Args: core_path: Path to CORE orchestration repository repo_paths: List of repository paths to link use_relative_paths: Use relative paths from CORE (recommended for portability) """ servers = {} # Build paths list for git and filesystem git_args = ["-y", "@modelcontextprotocol/server-git"] fs_args = ["-y", "@modelcontextprotocol/server-filesystem"] for repo_path in repo_paths: if use_relative_paths: # Use forward slashes for cross-platform compatibility in the config rel_path = f"${{workspaceFolder}}/workspaces/{repo_path.name}" else: rel_path = str(repo_path).replace("\\", "/") git_args.extend(["--repository", rel_path]) fs_args.append(rel_path) # Multi-repo Git server (official support as of 2025) servers["git-multi"] = { "command": "npx", "args": git_args } # Multi-repo Filesystem server servers["filesystem-multi"] = { "command": "npx", "args": fs_args } # Per-repo intelligence servers for repo_path in repo_paths: if use_relative_paths: workspace_arg = f"${{workspaceFolder}}/workspaces/{repo_path.name}" # The server script lives in CORE server_script = "${workspaceFolder}\\mcp_intelligence_server.py" else: workspace_arg = str(repo_path).replace("\\", "/") server_script = str(core_path / "mcp_intelligence_server.py") # Sanitize repo name for server identifier safe_name = repo_path.name.lower().replace(" ", "-").replace(".", "-") servers[f"code-intelligence-{safe_name}"] = { "command": "cmd", "args": [ "/c", "python", server_script, "--workspace", workspace_arg ], "env": { "OLLAMA_URL": "http://localhost:11434", "QDRANT_URL": "http://localhost:6333" } } return {"mcpServers": servers} def write_config(config: Dict, output_path: Path, backup: bool = True) -> bool: """Write config with optional backup of existing.""" try: if output_path.exists() and backup: timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") backup_path = output_path.with_suffix(f".json.backup_{timestamp}") shutil.copy2(output_path, backup_path) print(f" [OK] Backed up existing config to: {backup_path.name}") output_path.parent.mkdir(parents=True, exist_ok=True) with open(output_path, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2) print(f" [OK] Generated config: {output_path}") return True except Exception as e: print(f" [ERROR] Failed to write config: {e}") return False def validate_repo_path(path: Path) -> bool: """Validate that a path is a valid repository.""" if not path.exists(): return False if not path.is_dir(): return False # Check for common repo indicators return (path / ".git").exists() or (path / "package.json").exists() or (path / "requirements.txt").exists() def interactive_mode(): """Interactive configuration builder.""" print("=" * 70) print(" MCP CONFIGURATION BUILDER - INTERACTIVE MODE") print("=" * 70) print() print(" Select mode:") print(" 1. Single-repo (portable, isolated)") print(" 2. Multi-repo orchestration (CORE workspace)") print() mode = input(" Choice [1/2]: ").strip() if mode == "1": print() workspace = input(" Workspace path: ").strip().strip('"') workspace_path = Path(workspace).resolve() if not workspace_path.exists(): print(f"\n [ERROR] Path does not exist: {workspace_path}") return config = build_single_repo_config(workspace_path) output_path = workspace_path / ".cursor" / "mcp.json" print() success = write_config(config, output_path) if success: print() print("=" * 70) print(" SINGLE-REPO CONFIG GENERATED") print("=" * 70) print(f" Workspace: {workspace_path}") print(f" Config: {output_path}") print() print(" Next steps:") print(" 1. Open this workspace in Cursor") print(" 2. MCP servers will auto-configure for this repo") print(" 3. Run: validate_workspace_config in Cursor chat") elif mode == "2": print() core_path_str = input(" CORE orchestration repo path: ").strip().strip('"') core_path = Path(core_path_str).resolve() if not core_path.exists(): print(f"\n [ERROR] CORE path does not exist: {core_path}") return print() print(" Enter repository paths to link (one per line, empty line to finish):") repo_paths = [] while True: repo = input(f" Repo #{len(repo_paths) + 1}: ").strip().strip('"') if not repo: break repo_path = Path(repo).resolve() if not repo_path.exists(): print(f" [WARN] Path does not exist: {repo_path}") continue repo_paths.append(repo_path) print(f" [OK] Added: {repo_path.name}") if not repo_paths: print("\n [ERROR] No repositories specified") return print() use_rel = input(" Use relative paths (recommended)? [Y/n]: ").strip().lower() use_relative = use_rel != 'n' config = build_multi_repo_config(core_path, repo_paths, use_relative) output_path = core_path / ".cursor" / "mcp.json" print() success = write_config(config, output_path) if success: # Create workspaces directory if needed workspaces_dir = core_path / "workspaces" workspaces_dir.mkdir(exist_ok=True) print() print("=" * 70) print(" MULTI-REPO CONFIG GENERATED") print("=" * 70) print(f" CORE repo: {core_path}") print(f" Linked repos ({len(repo_paths)}):") for repo in repo_paths: link_path = workspaces_dir / repo.name status = "[linked]" if link_path.exists() else "[needs link]" print(f" - {repo.name} [{status}]") print() print(f" Config: {output_path}") print() print(" Next steps:") print(f" 1. Link/clone repos into: {workspaces_dir}") # Show link commands for repos that need linking unlinked = [r for r in repo_paths if not (workspaces_dir / r.name).exists()] if unlinked: print() print(" Link commands (run in PowerShell as Admin):") for repo in unlinked: target = workspaces_dir / repo.name print(f' cmd /c mklink /D "{target}" "{repo}"') print() print(" 2. Open CORE workspace in Cursor") print(" 3. All MCP servers will launch with multi-repo access") else: print("\n [ERROR] Invalid choice") def main(): parser = argparse.ArgumentParser( description="Generate MCP configurations for single-repo or multi-repo modes", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: Interactive mode: python scripts/mcp_config_builder.py Single-repo mode: python scripts/mcp_config_builder.py --single --workspace C:\\Projects\\MyApp Multi-repo mode: python scripts/mcp_config_builder.py --multi --core C:\\AIStack-MCP --repos C:\\Projects\\RepoA C:\\Projects\\RepoB """ ) parser.add_argument("--single", action="store_true", help="Generate single-repo config") parser.add_argument("--multi", action="store_true", help="Generate multi-repo config") parser.add_argument("--workspace", help="Workspace path (for single mode)") parser.add_argument("--core", help="CORE repository path (for multi mode)") parser.add_argument("--repos", nargs="+", help="Repository paths (for multi mode)") parser.add_argument("--absolute", action="store_true", help="Use absolute paths instead of relative") parser.add_argument("--no-backup", action="store_true", help="Don't backup existing config") args = parser.parse_args() if not args.single and not args.multi: # Interactive mode interactive_mode() return if args.single: if not args.workspace: print("[ERROR] --workspace required for single mode") sys.exit(1) workspace_path = Path(args.workspace).resolve() if not workspace_path.exists(): print(f"[ERROR] Workspace path does not exist: {workspace_path}") sys.exit(1) config = build_single_repo_config(workspace_path) output_path = workspace_path / ".cursor" / "mcp.json" print() print("Generating single-repo config...") success = write_config(config, output_path, backup=not args.no_backup) if success: print() print(f"[OK] Single-repo config written to: {output_path}") else: sys.exit(1) elif args.multi: if not args.core or not args.repos: print("[ERROR] --core and --repos required for multi mode") sys.exit(1) core_path = Path(args.core).resolve() if not core_path.exists(): print(f"[ERROR] CORE path does not exist: {core_path}") sys.exit(1) repo_paths = [Path(r).resolve() for r in args.repos] # Validate repo paths for repo_path in repo_paths: if not repo_path.exists(): print(f"[ERROR] Repository path does not exist: {repo_path}") sys.exit(1) config = build_multi_repo_config(core_path, repo_paths, use_relative_paths=not args.absolute) output_path = core_path / ".cursor" / "mcp.json" print() print("Generating multi-repo config...") success = write_config(config, output_path, backup=not args.no_backup) if success: # Ensure workspaces directory exists workspaces_dir = core_path / "workspaces" workspaces_dir.mkdir(exist_ok=True) print(f" [OK] Ensured workspaces directory: {workspaces_dir}") print() print(f"[OK] Multi-repo config written to: {output_path}") print(f" Linked repos: {len(repo_paths)}") for repo in repo_paths: print(f" - {repo.name}") else: sys.exit(1) if __name__ == "__main__": main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mjdevaccount/AIStack-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server