Skip to main content
Glama

list_jobs

Read-onlyIdempotent

Retrieve and filter jobs from a Rundeck project to display them in a numbered table for reference in subsequent operations.

Instructions

List jobs in a Rundeck project with optional filtering.

Returns a numbered markdown table of jobs. Use the # column to reference
jobs in subsequent commands (e.g., "run job 3").

Args:
    query: Query parameters for filtering jobs

Returns:
    Markdown table with numbered jobs

Examples:
    List all jobs in a project:
    >>> result = list_jobs(JobQuery(project="myproject"))

    Filter by group:
    >>> result = list_jobs(JobQuery(project="myproject", group_path="deploy/prod"))

    Search by name:
    >>> result = list_jobs(JobQuery(project="myproject", job_filter="backup"))

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'list_jobs' tool. It queries the Rundeck API using the provided JobQuery, parses the job data, and returns a formatted markdown table of jobs.
    def list_jobs(query: JobQuery) -> str:
        """List jobs in a Rundeck project with optional filtering.
    
        Returns a numbered markdown table of jobs. Use the # column to reference
        jobs in subsequent commands (e.g., "run job 3").
    
        Args:
            query: Query parameters for filtering jobs
    
        Returns:
            Markdown table with numbered jobs
    
        Examples:
            List all jobs in a project:
            >>> result = list_jobs(JobQuery(project="myproject"))
    
            Filter by group:
            >>> result = list_jobs(JobQuery(project="myproject", group_path="deploy/prod"))
    
            Search by name:
            >>> result = list_jobs(JobQuery(project="myproject", job_filter="backup"))
        """
        client = get_client()
        params = query.to_params()
    
        response = client.get(f"/project/{query.project}/jobs", params=params)
    
        if not response:
            return "No jobs found."
    
        jobs = []
        for job_data in response:
            jobs.append(_parse_job(job_data))
    
        return _format_jobs_table(jobs)
  • Pydantic model defining the input schema for the list_jobs tool, including query parameters and method to convert to API params.
    class JobQuery(BaseModel):
        """Query parameters for listing jobs."""
    
        model_config = ConfigDict(extra="forbid")
    
        project: str = Field(description="Project name (required)")
        group_path: str | None = Field(
            default=None,
            description="Filter by group path. Use '*' for all groups, '' for root level only.",
        )
        job_filter: str | None = Field(
            default=None,
            description="Filter by job name (substring match)",
        )
        job_exact_filter: str | None = Field(
            default=None,
            description="Filter by exact job name",
        )
        group_path_exact: str | None = Field(
            default=None,
            description="Filter by exact group path",
        )
        scheduled_filter: bool | None = Field(
            default=None,
            description="Filter to only scheduled jobs (true) or only non-scheduled (false)",
        )
        tags: str | None = Field(
            default=None,
            description="Filter by tags (comma-separated)",
        )
        limit: int = Field(
            default=MAX_RESULTS,
            ge=1,
            le=MAX_RESULTS,
            description="Maximum number of results to return",
        )
    
        def to_params(self) -> dict[str, Any]:
            """Convert query to API parameters."""
            params: dict[str, Any] = {}
            if self.group_path is not None:
                params["groupPath"] = self.group_path
            if self.job_filter:
                params["jobFilter"] = self.job_filter
            if self.job_exact_filter:
                params["jobExactFilter"] = self.job_exact_filter
            if self.group_path_exact:
                params["groupPathExact"] = self.group_path_exact
            if self.scheduled_filter is not None:
                params["scheduledFilter"] = self.scheduled_filter
            if self.tags:
                params["tags"] = self.tags
            if self.limit:
                params["max"] = self.limit
            return params
  • The list_jobs tool is imported and added to the read_tools list, which is later registered with the MCP server.
    read_tools = [
        # Jobs
        list_jobs,
        get_job,
        # Executions
        list_executions,
        get_execution,
        get_execution_output,
  • Registration of read_tools (including list_jobs) to the FastMCP server instance with read-only annotations.
    # Register read-only tools (always available)
    for tool in read_tools:
        add_read_only_tool(mcp, tool)
  • Helper function to format the list of jobs into a numbered markdown table returned by the handler.
    def _format_jobs_table(jobs: list[Job]) -> str:
        """Format jobs as a numbered markdown table.
    
        Args:
            jobs: List of Job objects to format
    
        Returns:
            Markdown table string with numbered jobs
        """
        lines = []
        lines.append("IMPORTANT: Display this markdown table exactly as shown - do not summarize or reformat.\n")
        lines.append(f"**{len(jobs)} jobs found.** Use # to reference jobs (e.g., 'run job 3'):\n")
        lines.append("| # | Name | Group | Job ID |")
        lines.append("|---|------|-------|--------|")
    
        for idx, job in enumerate(jobs, start=1):
            group = job.group or "-"
            lines.append(f"| {idx} | {job.name} | {group} | {job.id} |")
    
        lines.append("\n---")
        lines.append("STOP: You must show the table above to the user exactly as formatted. Do not summarize.")
    
        return "\n".join(lines)
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds valuable behavioral context beyond what annotations provide. While annotations indicate read-only, idempotent, and non-destructive operations, the description reveals that results are returned as a 'numbered markdown table' and explains how to reference jobs using the '# column' in subsequent commands. This output format guidance is crucial for agent interaction but doesn't cover aspects like rate limits or authentication requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly structured and concise. It begins with a clear purpose statement, immediately explains the return format and how to use it, then provides parameter documentation and practical examples. Every sentence serves a specific purpose with zero wasted words, and the information is front-loaded appropriately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that this is a read-only listing tool with comprehensive annotations (readOnlyHint, idempotentHint, destructiveHint), a well-documented input schema, and an output schema indicated in context signals, the description provides exactly what's needed. It explains the purpose, output format, parameter usage with examples, and how to interpret results for subsequent operations - making it complete for this tool's complexity level.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description mentions 'optional filtering' and documents the single 'query' parameter with examples showing different filtering scenarios. However, with 0% schema description coverage in the context signals, the detailed parameter documentation (project, group_path, job_filter, etc.) comes entirely from the input schema. The description provides basic guidance but doesn't add significant semantic value beyond what's already in the well-documented schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'List jobs in a Rundeck project with optional filtering.' It specifies the verb ('List'), resource ('jobs'), and context ('in a Rundeck project'), distinguishing it from sibling tools like get_job (which retrieves a single job) or list_executions (which lists executions rather than jobs).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: for listing jobs with optional filtering in a Rundeck project. It includes examples that demonstrate different filtering scenarios. However, it doesn't explicitly state when NOT to use it or mention alternatives like get_job for single job retrieval, which would have earned a perfect score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/justynroberts/rundeck-mcp'

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