Skip to main content
Glama

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