get_merge_request MCP tool

Note

Before picking up this work: this issue adds an MCP tool. Please follow the Adding a new tool guidance first. That includes creating an MCP Tool Proposal, using verb_object naming (get_ / list_ / save_ / delete_), and the shared resource-identification input base classes.

Problem Statement / Use Case

Agents and users frequently need to inspect a merge request and its associated data (diffs, commits, notes, pipelines, conflicts, discussions). Today the DAP surface exposes these as six separate tools (get_merge_request + list_merge_request_diffs/commits/notes/pipelines/conflicts + list_mr_discussions), which bloats the tool list, raises token overhead, and forces the model to chain calls to assemble a full picture of one MR.

get_merge_request consolidates all MR-scoped reads into a single facet reader. The caller fetches the base MR and opts into exactly the associated data it needs via an include knob, with a detail knob to control diff payload size. This mirrors GitHub's proven pull_request_read shape (MR facets behind one reader, general collections as their own list_ tools).

Scope and Non-Goals

  • In scope: single-MR metadata; facets diffs, commits, notes, pipelines, conflicts, discussions; detail for the diffs facet; facet-scoped pagination for notes.
  • Non-goals: listing/searching MRs (list_merge_requests), mutating MR fields (save_merge_request), review/discussion writes (save_merge_request_review).
  • Follow-ups: build_review_merge_request_context (CSV row 40) may fold in as a composite facet later.

Data Shape and Context Engineering

Three saturation guards: include (nothing beyond base MR is fetched unless requested), the detail enum (none/stats/full_patch) on diffs, and facet-scoped notes_* pagination (applies only when notes is in include). The diffs facet carries the shipped DiffExclusionPolicy (excluded files reported with a reason) so oversized diffs are filtered, not truncated blindly.

  • Input schema (example):
{
  "tool": "get_merge_request",
  "description": "Get a merge request and optionally its diffs, commits, notes, pipelines, conflicts, or discussions.",
  "parameters": {
    "url": "string (optional; encodes project + iid)",
    "project_id": "int | string (optional)",
    "merge_request_iid": "integer (optional; requires project_id)",
    "include": "string (optional; one of: diffs, commits, notes, pipelines, conflicts, discussions)",
    "detail": "enum (optional; none | stats | full_patch — applies to diffs facet only)",
    "notes_page": "integer (optional; applies only when 'notes' in include)",
    "notes_per_page": "integer (optional, 1-100; applies only when 'notes' in include)"
  }
}
  • Output schema (JSON example):
{
  "iid": 42,
  "title": "Add dark mode",
  "state": "opened",
  "author": "jane",
  "source_branch": "dark-mode",
  "target_branch": "main",
  "diffs": {
    "detail": "stats",
    "stats": { "additions": 120, "deletions": 8 },
    "excluded_files": [ { "path": "yarn.lock", "reason": "generated/lockfile" } ]
  },
  "notes": { "metadata": { "page": 1, "per_page": 20, "has_more": true }, "items": [] }
}

Backward compatibility

Consolidates the shipped MR read tools into this one facet reader: get_merge_request plus list_merge_request_diffs (Python merge_request.py), list_all_merge_request_notes (merge_request_notes.py), list_mr_discussions (mr_discussions.py), and the MR commits/pipelines/conflicts reads. The base get_merge_request name is unchanged, but the sub-reads become include facets, so their call shapes change and name aliases cannot reproduce them. Keep the superseded sub-read tools available during migration and document the facet mapping. Follow the tool-renaming guidance in doc/development/duo_agent_platform/mcp/_index.md.

Resources (already implemented similar tools etc.)

  • Shipped DAP/MCP tools: get_merge_request, list_merge_request_diffs (with DiffExclusionPolicy), get_merge_request_commits, get_merge_request_notes, get_merge_request_pipelines, get_merge_request_conflicts, list_mr_discussions.
  • GitHub pull_request_read (method-enum reader) as prior art.
  • MCP dev guidelines: doc/development/duo_agent_platform/mcp/_index.md (facet readers, detail, facet-scoped pagination, resource identification).

Implementation Plan

  1. Map each include value to its underlying REST call; fetch base MR always.
  2. Apply detail to the diffs facet; carry DiffExclusionPolicy into the response.
  3. Route notes_* pagination to the notes call only; document conditional applicability.
  4. Cross-validate url vs project_id + merge_request_iid.
  5. Write thorough per-include-value descriptions so the model knows each facet's return shape.
Edited by Amanda Rueda