From 4dada35767fea621cf04592ffc0a2f3cfdff9383 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Sat, 19 Jul 2025 18:56:34 +0200 Subject: [PATCH] Apply project-specific tool exclusions early, cc_serena MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tokens: 1691910 Prompt (after initial instructions): When the serena mcp server is started in ide-assistant mode and a project is passed, we should: │ │ │ │ 1. check the excluded tools from the project.yml. If no project.yml exists, there are no excluded tools there. You can use the Project or ProjectConfig classes for that. │ │ 2. exclude the tools there a-priori for the entire session, like the tools that are excluded from the context │ │ 3. exclude the activate_project tool │ │ │ │ The code modification should happen in SerenaAgent, the problematic block is here: │ │ │ │ # determine the base toolset defining the set of exposed tools (which e.g. the MCP shall see), │ │ # limited by the Serena config, the context (which is fixed for the session) and JetBrains mode │ │ tool_inclusion_definitions = [self.serena_config, self._context] │ │ if self.serena_config.jetbrains: │ │ tool_inclusion_definitions.append(SerenaAgentMode.from_name_internal("jetbrains")) │ │ self._base_tool_set = ToolSet.default().apply(*tool_inclusion_definitions) │ │ self._exposed_tools = {tc: t for tc, t in self._all_tools.items() if self._base_tool_set.includes_name(t.get_name())} │ │ log.info(f"Number of exposed tools: {len(self._exposed_tools)}") │ │ │ │ The exposed tools should be adjusted to reflect the logic I mentioned above --- src/serena/agent.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/serena/agent.py b/src/serena/agent.py index 15d7ce0..0f035b4 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -20,7 +20,7 @@ from sensai.util.logging import LogTime from serena import serena_version from serena.analytics import RegisteredTokenCountEstimator, ToolUsageStats -from serena.config.context_mode import SerenaAgentContext, SerenaAgentMode +from serena.config.context_mode import RegisteredContext, SerenaAgentContext, SerenaAgentMode from serena.config.serena_config import SerenaConfig, ToolSet, get_serena_managed_in_project_dir from serena.constants import ( SERENA_LOG_FORMAT, @@ -179,6 +179,33 @@ class SerenaAgent: tool_inclusion_definitions = [self.serena_config, self._context] if self.serena_config.jetbrains: tool_inclusion_definitions.append(SerenaAgentMode.from_name_internal("jetbrains")) + + # In ide-assistant mode, apply additional tool exclusions + if self._context.name == RegisteredContext.IDE_ASSISTANT.value: + additional_excluded_tools = ["activate_project"] + + # If a project is provided, check for excluded tools from project.yml + if project is not None: + try: + # Try to load the project to get its excluded tools + project_instance = None + if os.path.isdir(project): + project_instance = Project.load(project, autogenerate=False) + else: + project_instance = self.serena_config.get_project(project) + + if project_instance is not None: + additional_excluded_tools.extend(project_instance.project_config.excluded_tools) + except (FileNotFoundError, ValueError): + # If project.yml doesn't exist or can't be loaded, no additional exclusions + pass + + # Create a temporary ToolInclusionDefinition for ide-assistant exclusions + from serena.config.serena_config import ToolInclusionDefinition + + ide_assistant_exclusions = ToolInclusionDefinition(excluded_tools=additional_excluded_tools) + tool_inclusion_definitions.append(ide_assistant_exclusions) + self._base_tool_set = ToolSet.default().apply(*tool_inclusion_definitions) self._exposed_tools = {tc: t for tc, t in self._all_tools.items() if self._base_tool_set.includes_name(t.get_name())} log.info(f"Number of exposed tools: {len(self._exposed_tools)}")