set_project_path
Define the base directory for code indexing operations to enable repository search and analysis.
Instructions
Set the base project path for indexing.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes |
Implementation Reference
- src/code_index_mcp/server.py:139-144 (handler)The primary MCP tool handler and registration for 'set_project_path'. This function is decorated with @mcp.tool() and delegates the logic to ProjectManagementService.initialize_project(path).@mcp.tool() @handle_mcp_tool_errors(return_type='str') def set_project_path(path: str, ctx: Context) -> str: """Set the base project path for indexing.""" return ProjectManagementService(ctx).initialize_project(path)
- Helper method in ProjectManagementService that orchestrates the full project initialization, including validation, cleanup, shallow index setup via _shallow_manager.set_project_path, file monitoring, and result formatting.def initialize_project(self, path: str) -> str: """ Initialize a project with comprehensive business logic. This is the main business method that orchestrates the project initialization workflow, handling validation, cleanup, setup, and coordination of all project components. Args: path: Project directory path to initialize Returns: Success message with project information Raises: ValueError: If path is invalid or initialization fails """ # Business validation self._validate_initialization_request(path) # Business workflow: Execute initialization result = self._execute_initialization_workflow(path) # Business result formatting return self._format_initialization_result(result) def _validate_initialization_request(self, path: str) -> None: """ Validate the project initialization request according to business rules. Args: path: Project path to validate Raises: ValueError: If validation fails """ # Business rule: Path must be valid error = self._config_tool.validate_project_path(path) if error: raise ValueError(error) def _execute_initialization_workflow(self, path: str) -> ProjectInitializationResult: """ Execute the core project initialization business workflow. Args: path: Project path to initialize Returns: ProjectInitializationResult with initialization data """ # Business step 1: Initialize config tool self._config_tool.initialize_settings(path) # Normalize path for consistent processing normalized_path = self._config_tool.normalize_project_path(path) # Business step 2: Cleanup existing project state self._cleanup_existing_project() # Business step 3: Initialize shallow index by default (fast path) index_result = self._initialize_shallow_index_manager(normalized_path) # Business step 3.1: Store index manager in context for other services self.helper.update_index_manager(self._index_manager) # Business step 4: Setup file monitoring monitoring_result = self._setup_file_monitoring(normalized_path) # Business step 4: Update system state self._update_project_state(normalized_path, index_result['file_count']) # Business step 6: Get search capabilities info search_info = self._get_search_capabilities_info() return ProjectInitializationResult( project_path=normalized_path, file_count=index_result['file_count'], index_source=index_result['source'], search_capabilities=search_info, monitoring_status=monitoring_result, message=f"Project initialized: {normalized_path}" ) def _cleanup_existing_project(self) -> None: """Business logic to cleanup existing project state.""" with self._noop_operation(): # Stop existing file monitoring self._watcher_tool.stop_existing_watcher() # Clear existing index cache self.helper.clear_index_cache() # Clear any existing index state pass def _initialize_shallow_index_manager(self, project_path: str) -> Dict[str, Any]: """ Business logic to initialize the shallow index manager by default. Args: project_path: Project path Returns: Dictionary with initialization results """ # Get user-configured exclude patterns excludes = self._get_exclude_patterns() # Set project path in shallow manager with exclusions if not self._shallow_manager.set_project_path(project_path, excludes): raise RuntimeError(f"Failed to set project path (shallow): {project_path}") # Update context self.helper.update_base_path(project_path) # Try to load existing shallow index or build new one if self._shallow_manager.load_index(): source = "loaded_existing" else: if not self._shallow_manager.build_index(): raise RuntimeError("Failed to build shallow index") source = "built_new" # Determine file count from shallow list try: files = self._shallow_manager.get_file_list() file_count = len(files) except Exception: # noqa: BLE001 - safe fallback file_count = 0 return { 'file_count': file_count, 'source': source, 'total_symbols': 0, 'languages': [] } def _is_valid_existing_index(self, index_data: Dict[str, Any]) -> bool: """ Business rule to determine if existing index is valid and usable. Args: index_data: Index data to validate Returns: True if index is valid and usable, False otherwise """ if not index_data or not isinstance(index_data, dict): return False # Business rule: Must have new format metadata if 'index_metadata' not in index_data: return False # Business rule: Must be compatible version version = index_data.get('index_metadata', {}).get('version', '') return version >= '3.0' def _load_existing_index(self, index_data: Dict[str, Any]) -> Dict[str, Any]: """ Business logic to load and use existing index. Args: index_data: Existing index data Returns: Dictionary with loading results """ # Note: Legacy index loading is now handled by UnifiedIndexManager # This method is kept for backward compatibility but functionality moved # Extract file count from metadata file_count = index_data.get('project_metadata', {}).get('total_files', 0) return { 'file_count': file_count, 'source': 'loaded_existing' } def _setup_file_monitoring(self, project_path: str) -> str: """ Business logic to setup file monitoring for the project. Args: project_path: Project path to monitor Returns: String describing monitoring setup result """ try: # Create rebuild callback that uses the JSON index manager def rebuild_callback(): logger.info("File watcher triggered rebuild callback") try: logger.debug(f"Starting shallow index rebuild for: {project_path}") # Business logic: File changed, rebuild using SHALLOW index manager try: if not self._shallow_manager.set_project_path(project_path): logger.warning("Shallow manager set_project_path failed") return False if self._shallow_manager.build_index(): files = self._shallow_manager.get_file_list() logger.info(f"File watcher shallow rebuild completed successfully - files {len(files)}") return True else: logger.warning("File watcher shallow rebuild failed") return False except Exception as e: import traceback logger.error(f"File watcher shallow rebuild failed: {e}") logger.error(f"Traceback: {traceback.format_exc()}") return False except Exception as e: import traceback logger.error(f"File watcher rebuild failed: {e}") logger.error(f"Traceback: {traceback.format_exc()}") return False # Start monitoring using watcher tool success = self._watcher_tool.start_monitoring(project_path, rebuild_callback) if success: # Store watcher in context for later access self._watcher_tool.store_in_context() # No logging return "monitoring_active" else: self._watcher_tool.record_error("Failed to start file monitoring") return "monitoring_failed" except Exception as e: error_msg = f"File monitoring setup failed: {e}" self._watcher_tool.record_error(error_msg) return "monitoring_error" def _update_project_state(self, project_path: str, file_count: int) -> None: """Business logic to update system state after project initialization.""" # Update context with file count self.helper.update_file_count(file_count) # No logging def _get_search_capabilities_info(self) -> str: """Business logic to get search capabilities information.""" search_info = self._config_tool.get_search_tool_info() if search_info['available']: return f"Advanced search enabled ({search_info['name']})" else: return "Basic search available" def _format_initialization_result(self, result: ProjectInitializationResult) -> str: """ Format the initialization result according to business requirements. Args: result: Initialization result data Returns: Formatted result string for MCP response """ if result.index_source == 'unified_manager': message = (f"Project path set to: {result.project_path}. " f"Initialized unified index with {result.file_count} files. " f"{result.search_capabilities}.") elif result.index_source == 'failed': message = (f"Project path set to: {result.project_path}. " f"Index initialization failed. Some features may be limited. " f"{result.search_capabilities}.") else: message = (f"Project path set to: {result.project_path}. " f"Indexed {result.file_count} files. " f"{result.search_capabilities}.") if result.monitoring_status != "monitoring_active": message += " (File monitoring unavailable - use manual refresh)" return message
- Core helper implementation in ShallowIndexManager that validates the project path, sets up the JSONIndexBuilder with excludes, configures temp directory and index path for shallow indexing.def set_project_path(self, project_path: str, additional_excludes: Optional[List[str]] = None) -> bool: """Configure project path for shallow indexing. Args: project_path: Path to the project directory to index additional_excludes: Optional list of additional directory/file patterns to exclude from indexing (e.g., ['vendor', 'custom_deps']) Returns: True if configuration succeeded, False otherwise """ with self._lock: try: if not isinstance(project_path, str) or not project_path.strip(): logger.error("Invalid project path for shallow index") return False project_path = project_path.strip() if not os.path.isdir(project_path): logger.error(f"Project path does not exist: {project_path}") return False self.project_path = project_path self.index_builder = JSONIndexBuilder(project_path, additional_excludes) project_hash = hashlib.md5(project_path.encode()).hexdigest()[:12] self.temp_dir = os.path.join(tempfile.gettempdir(), SETTINGS_DIR, project_hash) os.makedirs(self.temp_dir, exist_ok=True) self.index_path = os.path.join(self.temp_dir, INDEX_FILE_SHALLOW) if additional_excludes: logger.info("Shallow index additional excludes: %s", additional_excludes) return True except Exception as e: # noqa: BLE001 - centralized logging logger.error(f"Failed to set project path (shallow): {e}") return False
- src/code_index_mcp/server.py:351-353 (registration)CLI argument registration that allows setting project path on server startup, equivalent to the set_project_path tool."--project-path", dest="project_path", help="Set the project path on startup (equivalent to calling set_project_path)."