Skip to main content
Glama
jermeyyy
by jermeyyy

list_project_tasks

Retrieve and organize Gradle project tasks by group, with optional filtering and descriptions to simplify task discovery and management.

Instructions

List all tasks available in a Gradle project.

Returns a nested structure grouped by task group. This is more compact than a flat list and avoids repeating project/group information for each task.

Args: project: Project path (e.g., ':app' or 'lib:module'). Use None, empty string, or ':' for root project. include_descriptions: If True, include task descriptions in the response. If False, return only task names for a more compact response. group: Optional group name to filter tasks (e.g., 'Build', 'Verification'). Case-insensitive. If not provided, all groups are returned.

Returns: List of grouped tasks. Each group contains a group name and list of tasks. If include_descriptions is True, tasks include name and description. If include_descriptions is False, tasks are just name strings.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectNo
include_descriptionsNo
groupNo

Implementation Reference

  • Main handler function for 'list_project_tasks' MCP tool. Decorated with @mcp.tool() for registration and execution. Calls GradleWrapper.list_tasks to fetch and parse tasks, converts to Pydantic models, and handles context logging.
    @mcp.tool()
    async def list_project_tasks(
        project: str | None = None,
        include_descriptions: bool = False,
        group: str | None = None,
        ctx: Context | None = None,
    ) -> list[GroupedTasksInfo]:
        """List all tasks available in a Gradle project.
    
        Returns a nested structure grouped by task group. This is more compact
        than a flat list and avoids repeating project/group information for each task.
    
        Args:
            project: Project path (e.g., ':app' or 'lib:module').
                    Use None, empty string, or ':' for root project.
            include_descriptions: If True, include task descriptions in the response.
                                 If False, return only task names for a more compact response.
            group: Optional group name to filter tasks (e.g., 'Build', 'Verification').
                   Case-insensitive. If not provided, all groups are returned.
    
        Returns:
            List of grouped tasks. Each group contains a group name and list of tasks.
            If include_descriptions is True, tasks include name and description.
            If include_descriptions is False, tasks are just name strings.
        """
        try:
            if ctx:
                await ctx.info(f"Listing tasks for project: {project or 'root'}")
            gradle = _get_gradle_wrapper(ctx)
            # Normalize root project: None, empty, or ":" all mean root
            project_arg = project if project and project != "" else ":"
            grouped_tasks = gradle.list_tasks(project_arg, include_descriptions, group)
            if ctx:
                total_tasks = sum(len(g.tasks) for g in grouped_tasks)
                group_info = f" (filtered by group '{group}')" if group else ""
                await ctx.info(
                    f"Found {total_tasks} tasks in {len(grouped_tasks)} groups for project {project_arg}{group_info}"
                )
    
            # Convert to response model
            result = []
            for group in grouped_tasks:
                if include_descriptions:
                    # Tasks are TaskWithDescription objects
                    tasks = [
                        TaskWithDescriptionInfo(name=t.name, description=t.description)
                        for t in group.tasks
                    ]
                else:
                    # Tasks are already strings
                    tasks = group.tasks
    
                result.append(GroupedTasksInfo(group=group.group, tasks=tasks))
    
            return result
        except Exception as e:
            raise ValueError(f"Failed to list tasks: {str(e)}") from e
  • Pydantic BaseModel classes defining the input parameters schema (via function signature) and output schema (list[GroupedTasksInfo]) for the list_project_tasks tool.
    class TaskWithDescriptionInfo(BaseModel):
        """Task with its description."""
    
        name: str
        description: str
    
    
    class GroupedTasksInfo(BaseModel):
        """Tasks grouped by their group name.
    
        When include_descriptions is True, tasks contains TaskWithDescriptionInfo objects.
        When include_descriptions is False, tasks contains task name strings.
        """
    
        group: str
        tasks: list[TaskWithDescriptionInfo] | list[str]
  • Utility function to create and configure a GradleWrapper instance, respecting environment variables and logging configuration details.
    def _get_gradle_wrapper(ctx: Context | None = None) -> GradleWrapper:
        """Get a GradleWrapper instance, optionally using context to determine project root.
    
        Respects the following environment variables:
        - GRADLE_PROJECT_ROOT: Root directory of Gradle project (default: current directory)
        - GRADLE_WRAPPER: Path to Gradle wrapper script (optional, auto-detected if not set)
        - GRADLE_OPTS: JVM options for the Gradle client (logged for visibility)
        - JAVA_OPTS: General Java options (logged for visibility)
    
        Args:
            ctx: MCP Context (optional).
    
        Returns:
            GradleWrapper instance.
    
        Raises:
            FileNotFoundError: If Gradle wrapper cannot be found.
        """
        import logging
    
        logger = logging.getLogger(__name__)
    
        project_root = os.getenv("GRADLE_PROJECT_ROOT") or os.getcwd()
        wrapper_path = os.getenv("GRADLE_WRAPPER")
    
        # Log environment variables for debugging visibility
        gradle_opts = os.getenv("GRADLE_OPTS")
        java_opts = os.getenv("JAVA_OPTS")
    
        if gradle_opts:
            logger.debug(f"GRADLE_OPTS is set: {gradle_opts}")
        if java_opts:
            logger.debug(f"JAVA_OPTS is set: {java_opts}")
        if wrapper_path:
            logger.debug(f"GRADLE_WRAPPER is set: {wrapper_path}")
    
        logger.debug(f"Using project root: {project_root}")
    
        gradle = GradleWrapper(project_root)
    
        # If a custom wrapper path is specified, override the auto-detected one
        if wrapper_path:
            wrapper_path_obj = Path(wrapper_path)
            if not wrapper_path_obj.exists():
                raise FileNotFoundError(
                    f"Gradle wrapper not found at specified path: {wrapper_path}. "
                    "Please verify GRADLE_WRAPPER environment variable."
                )
            gradle.wrapper_script = wrapper_path_obj
    
        return gradle
  • Core helper method in GradleWrapper class that executes 'gradle tasks --all', parses the output to group tasks by category, filters by group if specified, and returns structured data used by the MCP tool handler.
    def list_tasks(
        self,
        project: str = ":",
        include_descriptions: bool = True,
        group: str | None = None,
    ) -> list[GroupedTasks]:
        """List all available tasks for a specific Gradle project.
    
        Returns a nested structure grouped by task group. When include_descriptions
        is True, each task includes its description. When False, only task names
        are returned for a more compact response.
    
        Args:
            project: Project name (e.g., ':app'). Use ':' or empty string for root project.
            include_descriptions: If True, include task descriptions. If False, return
                                  only task names for a more compact response.
            group: Optional group name to filter tasks. If provided, only tasks from
                   this group will be returned. Case-insensitive matching.
    
        Returns:
            List of GroupedTasks objects, each containing a group name and its tasks.
            Tasks are either TaskWithDescription objects (if include_descriptions=True)
            or plain task name strings (if include_descriptions=False).
    
        Raises:
            subprocess.CalledProcessError: If Gradle command fails.
        """
        try:
            # Use tasks --all to get all tasks including inherited ones
            # For root project (: or empty), use just "tasks", for subprojects use "project:tasks"
            is_root = project == ":" or project == "" or project is None
            task_cmd = "tasks" if is_root else f"{project}:tasks"
            result = subprocess.run(
                [str(self.wrapper_script), task_cmd, "--all"],
                cwd=str(self.project_root),
                capture_output=True,
                text=True,
                check=True,
                env=self._build_execution_environment(),
            )
    
            # Use dict to group tasks by group name, preserving order
            groups: dict[str, list[TaskWithDescription] | list[str]] = {}
            in_task_section = False
            current_group: str | None = None
    
            for line in result.stdout.split("\n"):
                line_stripped = line.strip()
    
                # Skip empty lines
                if not line_stripped:
                    continue
    
                # Look for task group headers (end with "tasks")
                if line_stripped.endswith(" tasks") and line_stripped[0].isupper():
                    in_task_section = True
                    current_group = line_stripped.replace(" tasks", "").strip()
                    if current_group not in groups:
                        groups[current_group] = []
                    continue
    
                # Skip separators and rules
                if line_stripped.startswith("-") or "Pattern:" in line_stripped:
                    continue
    
                # Stop at help text
                if "To see all tasks" in line_stripped or line_stripped.startswith("BUILD"):
                    break
    
                # Parse task lines when in a task section
                if in_task_section and current_group is not None:
                    # Task lines format: "taskName - description"
                    task_match = re.match(r"^(\w+)\s+-\s+(.+)$", line_stripped)
                    if task_match:
                        task_name = task_match.group(1)
                        description = task_match.group(2)
    
                        if include_descriptions:
                            groups[current_group].append(
                                TaskWithDescription(name=task_name, description=description)
                            )
                        else:
                            groups[current_group].append(task_name)
                    # Also handle tasks without description
                    elif re.match(r"^(\w+)$", line_stripped):
                        task_name = line_stripped
                        if include_descriptions:
                            groups[current_group].append(
                                TaskWithDescription(name=task_name, description="")
                            )
                        else:
                            groups[current_group].append(task_name)
    
            # Convert to list of GroupedTasks, optionally filtering by group name
            result = []
            for group_name, task_list in groups.items():
                # Filter by group if specified (case-insensitive)
                if group is not None and group_name.lower() != group.lower():
                    continue
                result.append(GroupedTasks(group=group_name, tasks=task_list))
    
            return result
        except subprocess.CalledProcessError as e:
            raise RuntimeError(f"Failed to list tasks for project {project}: {e.stderr}") from e

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/jermeyyy/gradle-mcp'

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