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;detailfor thediffsfacet; facet-scoped pagination fornotes. - 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(withDiffExclusionPolicy),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
- Map each
includevalue to its underlying REST call; fetch base MR always. - Apply
detailto the diffs facet; carryDiffExclusionPolicyinto the response. - Route
notes_*pagination to the notes call only; document conditional applicability. - Cross-validate
urlvsproject_id+merge_request_iid. - Write thorough per-
include-value descriptions so the model knows each facet's return shape.