Skip to content

Built-in Tools

Reference guide for Preloop's built-in MCP tools.


Overview

Preloop provides two categories of built-in tools:

  1. Always-Available Tools - Available to all users immediately
  2. Tracker-Dependent Tools - Only available when trackers are connected

All built-in tools can be protected by the Safety Layer with access rules and approval workflows.

Access Rules & Tool Configuration

Each tool supports multiple access rules with fine-grained control:

  • Actions: allow, deny, or require_approval — determine whether a tool call proceeds, is blocked, or needs human approval
  • CEL conditions: Match rule application to specific argument values (e.g. production vs staging, high-value transactions)
  • Priority ordering: Rules are evaluated in order; the first matching rule applies

See CEL Expressions for condition syntax and examples.


Always-Available Tools

These tools work immediately without any setup.

request_approval

Request approval for any action with custom context.

Purpose: Let agents explicitly request approval before risky operations

Arguments:

  • reason (string, required) - Why approval is needed
  • context (object, optional) - Additional context
  • approval_workflow_id (string, optional) - Specific approval workflow to use

Returns:

{
  "approved": true,
  "approved_by": "alice@acme.com",
  "approved_at": "2025-01-25T10:30:00Z",
  "approval_request_id": "req_abc123"
}

Example:

result = request_approval(
    reason="About to deploy version 2.3.0 to production",
    context={
        "version": "2.3.0",
        "environment": "production",
        "changes": ["Added new API", "Fixed bug #123"]
    }
)

if result.approved:
    deploy(version="2.3.0", env="production")

When to use:

  • Agent needs to decide when to request approval
  • Want to provide rich context about WHY approval is needed
  • Multi-step workflows where timing matters

Difference from policy-gated tools:

  • Policy-gated tools: Automatic interception
  • request_approval: Explicit agent decision

See MCP Tool Integration for details.


Tracker-Dependent Tools

These tools only appear when you've connected at least one tracker (GitHub, GitLab, or Jira).

Why Tracker-Dependent?

Built-in issue tools operate on tracker data: - No tracker = No issues to query - Connect GitHub → tools work with GitHub issues - Connect Jira → tools work with Jira tickets

Connect GitHub, GitLab, or Jira from the console before using tracker-dependent built-in tools.


Issue Management Tools

get_issue

Fetch full details for a single issue.

Arguments:

  • issue_id (string, required) - Issue ID (e.g., "PROJ-123", "#456")

Returns:

{
  "id": "PROJ-123",
  "title": "Fix login bug",
  "description": "Users unable to login...",
  "status": "in_progress",
  "priority": "high",
  "assignee": "alice@acme.com",
  "labels": ["bug", "security"],
  "created_at": "2025-01-20T10:00:00Z",
  "updated_at": "2025-01-25T14:30:00Z"
}

Example:

issue = get_issue(issue_id="PROJ-123")
print(f"Issue: {issue.title}")
print(f"Status: {issue.status}")

When to preloop:

  • ⚪ Usually NOT needed (read-only operation)
  • ✅ Preloop if reading sensitive/confidential issues

create_issue

Create a new issue in connected tracker.

Arguments:

  • title (string, required) - Issue title
  • description (string, optional) - Detailed description
  • priority (string, optional) - Priority level
  • labels (list, optional) - Labels/tags
  • assignee (string, optional) - Assign to user
  • project (string, optional) - Project/repo name

Returns:

{
  "id": "PROJ-124",
  "url": "https://github.com/acme/repo/issues/124",
  "created_at": "2025-01-25T15:00:00Z"
}

Example:

issue = create_issue(
    title="Add user authentication",
    description="Implement OAuth2 authentication",
    priority="high",
    labels=["feature", "security"],
    assignee="bob@acme.com"
)
print(f"Created issue: {issue.url}")

When to preloop:

  • Always - Creating issues can spam your tracker
  • ✅ Especially for bulk operations
  • ✅ When AI agents create issues automatically

Recommended policy:

tool: create_issue
approval: required
approvers: [team_lead@acme.com]
notification:
  email: true
  slack: true

update_issue

Modify an existing issue.

Arguments:

  • issue_id (string, required) - Issue to update
  • title (string, optional) - New title
  • description (string, optional) - New description
  • status (string, optional) - New status
  • priority (string, optional) - New priority
  • labels (list, optional) - Update labels
  • assignee (string, optional) - Reassign

Returns:

{
  "id": "PROJ-123",
  "updated_fields": ["status", "priority"],
  "updated_at": "2025-01-25T15:30:00Z"
}

Example:

result = update_issue(
    issue_id="PROJ-123",
    status="closed",
    priority="low"
)

When to preloop:

  • High priority/critical issues - Require approval for status changes
  • Bulk operations - Updating many issues at once
  • ⚪ Low priority issues - Usually safe without approval

Recommended policies:

Conditional (only high priority):

tool: update_issue
condition: args.priority in ["critical", "high"]
approval: required
approvers: [product_team]

Status-based:

tool: update_issue
condition: has(args.status) && args.status == "closed"
approval: required
approvers: [team_lead@acme.com]

Search across all issues in connected trackers.

Arguments:

  • query (string, required) - Search query
  • filters (object, optional) - Additional filters
  • status - Filter by status
  • priority - Filter by priority
  • assignee - Filter by assignee
  • labels - Filter by labels
  • created_after - Filter by creation date
  • limit (number, optional) - Max results (default: 20)

Returns:

{
  "results": [
    {
      "id": "PROJ-123",
      "title": "Fix login bug",
      "score": 0.95,
      "tracker": "github"
    },
    ...
  ],
  "total": 42,
  "query": "login bug"
}

Example:

results = search(
    query="authentication bug",
    filters={
        "status": "open",
        "priority": ["high", "critical"]
    },
    limit=10
)

for issue in results.results:
    print(f"{issue.id}: {issue.title}")

When to preloop:

  • ⚪ Usually NOT needed (read-only)
  • ✅ Preloop if searching sensitive/confidential data

Issue Intelligence Tools

estimate_compliance

Check if an issue meets "Definition of Ready" criteria.

Arguments:

  • issue_id (string, required) - Issue to check

Returns:

{
  "compliance_score": 0.75,
  "missing_fields": ["acceptance_criteria", "story_points"],
  "suggestions": [
    "Add acceptance criteria to clarify done state",
    "Estimate story points for sprint planning"
  ],
  "compliant": false
}

Example:

compliance = estimate_compliance(issue_id="PROJ-123")

if not compliance.compliant:
    print(f"Missing: {', '.join(compliance.missing_fields)}")
    print("Suggestions:")
    for suggestion in compliance.suggestions:
        print(f"  - {suggestion}")

When to preloop:

  • ⚪ Usually NOT needed (analysis only, no modifications)

Use cases:

  • Automated issue quality checks
  • Pre-sprint grooming
  • Compliance reporting

improve_compliance

Get AI-powered suggestions to improve issue compliance.

Arguments:

  • issue_id (string, required) - Issue to improve

Returns:

{
  "suggestions": [
    {
      "field": "acceptance_criteria",
      "current": null,
      "suggested": "- User can log in with email\n- User can log in with OAuth\n- Error messages are clear"
    },
    {
      "field": "story_points",
      "current": null,
      "suggested": 5
    }
  ]
}

Example:

improvements = improve_compliance(issue_id="PROJ-123")

for suggestion in improvements.suggestions:
    print(f"Field: {suggestion.field}")
    print(f"Suggested: {suggestion.suggested}")

When to preloop:

  • If auto-applying - Require approval before updating issue
  • ⚪ If just showing suggestions - No approval needed

Recommended policy (if auto-apply):

tool: improve_compliance
condition: args.auto_apply == true
approval: required
approvers: [team_lead@acme.com]

Tool Availability Matrix

Tool Always Available Requires Tracker Read-Only Should Preloop?
request_approval ⚪ N/A
get_issue ⚪ Usually no
create_issue ✅ Yes
update_issue ✅ Conditionally
search ⚪ Usually no
estimate_compliance ⚪ No
improve_compliance ✅ If auto-apply

Prelooping Strategies

Read-Only Tools (Low Risk)

Tools: get_issue, search, estimate_compliance

Strategy: Usually don't preloop - No side effects - No data modification - Fast and safe

Exception: Sensitive data

tool: get_issue
condition: args.issue_id.startsWith("CONFIDENTIAL-")
approval: required

Write Tools (Medium-High Risk)

Tools: create_issue, update_issue, improve_compliance

Strategy: Preloop conditionally

create_issue:

# Always require approval
tool: create_issue
approval: required
approvers: [team_lead@acme.com]

update_issue:

# Only for high-priority or status changes
tool: update_issue
condition: |
  args.priority in ["critical", "high"] ||
  has(args.status)
approval: required

improve_compliance:

# Only if auto-applying
tool: improve_compliance
condition: has(args.auto_apply) && args.auto_apply == true
approval: required

Error Handling

Common Errors

Tool not available:

{
  "error": "Tool not found: create_issue",
  "code": -32601,
  "message": "No trackers connected. Connect GitHub, GitLab, or Jira to use this tool."
}

Solution: Connect a tracker in SettingsTrackers

Invalid issue ID:

{
  "error": "Issue not found: INVALID-123",
  "code": -32000,
  "message": "Issue INVALID-123 does not exist in any connected tracker"
}

Solution: Verify issue ID format matches your tracker

Permission denied:

{
  "error": "Permission denied",
  "code": -32002,
  "message": "User lacks permission to create issues in project PROJ"
}

Solution: Check tracker permissions or contact admin