Skip to main content
Glama

get_job

Read-onlyIdempotent

Retrieve detailed job information including options, requirements, defaults, and allowed values from Rundeck.

Instructions

Get detailed information about a specific job.

Returns the full job definition including all options displayed in a table
showing required status, defaults, and allowed values.

Args:
    job_id: The job UUID

Returns:
    Formatted string with job details and options table

Examples:
    >>> result = get_job("abc-123-def")
    >>> print(result)
    '## Deploy Application...'

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
job_idYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The get_job tool handler: fetches job details from Rundeck API by job_id, handles response format, parses into Job model, and returns formatted markdown with job info and options table.
    def get_job(job_id: str) -> str:
        """Get detailed information about a specific job.
    
        Returns the full job definition including all options displayed in a table
        showing required status, defaults, and allowed values.
    
        Args:
            job_id: The job UUID
    
        Returns:
            Formatted string with job details and options table
    
        Examples:
            >>> result = get_job("abc-123-def")
            >>> print(result)
            '## Deploy Application...'
        """
        client = get_client()
        response = client.get(f"/job/{job_id}")
    
        # Handle list response (API returns list for single job lookup)
        if isinstance(response, list):
            if not response:
                raise ValueError("Job not found")
            response = response[0]
    
        job = _parse_job(response)
        return _format_job_details(job)
  • Exports get_job from jobs.py and registers it in the read_tools list for safe, read-only operations.
    from .jobs import (
        get_job,
        list_jobs,
        run_job,
    )
    
    # Read-only tools (safe, non-destructive operations)
    read_tools = [
        # Jobs
        list_jobs,
        get_job,
        # Executions
        list_executions,
        get_execution,
        get_execution_output,
    ]
  • Registers all tools from read_tools (including get_job) as read-only MCP tools with appropriate safety annotations.
    for tool in read_tools:
        add_read_only_tool(mcp, tool)
  • Helper function called by get_job to format the Job object into a detailed markdown string with options table.
        return _format_job_details(job)
    
    
    def run_job(job_id: str, request: JobRunRequest | None = None, *, confirmed: bool = False) -> str:
        """Execute a Rundeck job with optional parameters.
    
        IMPORTANT: This is a two-step process:
        1. First call without confirmed=True shows options and asks for confirmation
        2. Second call with confirmed=True actually executes the job
    
        Before running, this tool validates that:
        - All required options are provided (or have defaults)
        - Option values match allowed values for enforced options
    
        Args:
            job_id: The job UUID to execute
            request: Optional execution parameters including options
            confirmed: Set to True to actually execute (after user confirms)
    
        Returns:
            Formatted string with options preview (step 1) or execution result (step 2)
    
        Examples:
            Step 1 - Preview options:
            >>> result = run_job("abc-123-def", JobRunRequest(options={"env": "prod"}))
            # Shows options table, asks user to confirm
    
            Step 2 - Execute after confirmation:
            >>> result = run_job("abc-123-def", JobRunRequest(options={"env": "prod"}), confirmed=True)
        """
        client = get_client()
    
        # Fetch job to validate options
        job_response = client.get(f"/job/{job_id}")
    
        # Handle list response (API returns list for single job lookup)
        if isinstance(job_response, list):
            if not job_response:
                raise ValueError("Job not found")
            job_response = job_response[0]
    
        job = _parse_job(job_response)
        job_options = job_response.get("options")
    
        provided_options = request.options if request else None
    
        # Validate options
        is_valid, errors = validate_job_options(job_options, provided_options)
    
        if not is_valid:
            return _format_validation_error(job, errors, provided_options)
    
        # If not confirmed, show preview and ask for confirmation
        if not confirmed:
            return _format_run_preview(job, provided_options)
    
        # Build request body
        body = request.to_request_body() if request else {}
    
        # Execute job
        response = client.post(f"/job/{job_id}/run", json=body)
    
        return _format_run_response(_parse_run_response(response))
    
    
    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)
    
    
    def _format_job_details(job: Job) -> str:
  • Helper function to parse raw API job response into Job model instance, used by get_job.
    def _parse_job(data: dict[str, Any] | list) -> Job:
        """Parse job data from API response.
    
        Handles both single job responses (dict) and list responses.
        Converts option data to JobOption models.
    
        Args:
            data: Raw API response data
    
        Returns:
            Parsed Job model
        """
        # Handle list response (take first item)
        if isinstance(data, list):
            if not data:
                raise ValueError("Empty job response")
            data = data[0]
    
        # Parse options if present
        options = None
        if data.get("options"):
            options = [_parse_job_option(opt) for opt in data["options"]]
    
        return Job(
            id=data["id"],
            name=data["name"],
            group=data.get("group"),
            project=data.get("project"),  # May be None from /job/{id} endpoint
            description=data.get("description"),
            href=data.get("href"),
            permalink=data.get("permalink"),
            scheduled=data.get("scheduled", False),
            schedule_enabled=data.get("scheduleEnabled", True),
            enabled=data.get("enabled", True),
            average_duration=data.get("averageDuration"),
            options=options,
        )
Behavior4/5

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

Annotations already indicate read-only, idempotent, and non-destructive behavior. The description adds valuable context beyond this: it specifies that the output includes 'all options displayed in a table showing required status, defaults, and allowed values', which clarifies the return format and depth of information provided. No contradictions with annotations.

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

Conciseness4/5

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

The description is well-structured with clear sections (purpose, returns, examples) and front-loaded key information. It's appropriately sized, but the example section could be slightly condensed as it repeats the purpose. Most sentences earn their place by adding value.

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

Completeness4/5

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

Given the tool's low complexity (1 parameter), rich annotations, and presence of an output schema, the description is largely complete. It explains the parameter, output format, and includes an example. However, it doesn't mention error cases or prerequisites, leaving minor gaps.

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

Parameters4/5

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

With 0% schema description coverage, the description compensates by explaining the single parameter 'job_id' as 'The job UUID', adding semantic meaning beyond the schema's title 'Job Id'. This clarifies the expected format and purpose, though it doesn't detail validation or constraints.

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

Purpose4/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: 'Get detailed information about a specific job' with the verb 'get' and resource 'job'. It distinguishes from siblings like 'list_jobs' (which lists multiple jobs) by specifying retrieval of a single job, but doesn't explicitly contrast with 'get_execution' or 'get_execution_output'.

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

Usage Guidelines3/5

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

The description implies usage when detailed information about a specific job is needed, as opposed to listing jobs. However, it doesn't explicitly state when to use this versus alternatives like 'get_execution' or provide exclusions (e.g., not for modifying jobs). The context is clear but lacks explicit guidance on sibling differentiation.

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