Skip to content

Resources & Prompts

Beyond tools, GitLab MCP Server exposes resources and prompts — two additional MCP primitives that provide context and reusable templates to AI assistants. Tools perform actions; resources supply read-only context on demand; prompts package a data-gathering workflow into a single reusable template.

MCP resources provide read-only context data that clients can request at any time without invoking a tool. Resources are useful for supplying background information — a project’s metadata, members, labels, or latest pipeline — that helps the LLM make better decisions before it acts.

The server exposes 45 resources across several categories:

The GitLab data resources and the two tool manifest resources return application/json; the five workflow guides return text/markdown. The Name column is the name a resource is listed under in resources/list or resources/templates/list, and each description below says what the server’s handler returns.

ResourceNameDescription
gitlab://user/currentcurrent_userThe authenticated user’s profile: username, display name, email, state (active/blocked), admin status and web URL
gitlab://groupsgroupsGroups the authenticated user can access, up to one page (100): each group’s ID, name, full path, description, visibility and web URL
gitlab://toolstool_manifestSurface-aware manifest of the tools and executable actions this server instance offers; gitlab://tools/{id} gives one entry’s call shape
ResourceNameDescription
gitlab://tools/{id}tool_detailAccepted call shape and input schema for one entry from gitlab://tools

Use the tool manifest resources when a client needs the exact parameter shape for an entry on any surface without expanding every schema in tools/list: canonical domain.action IDs on the default dynamic surface, gitlab_<domain>.<action> entries with GITLAB_MCP_TOOL_SURFACE=meta, and tool names with GITLAB_MCP_TOOL_SURFACE=individual.

  1. Read gitlab://tools to get the active surface, visible tools, and executable entries.
  2. Replace {id} in gitlab://tools/{id} to read the JSON Schema and call shape for that entry.
  3. Call the tool named in the returned call shape: gitlab_execute_action with { "action": "merge_request.create", "params": { ... } } on the dynamic surface, or the meta-tool with { "action": "create", "params": { ... } } when GITLAB_MCP_TOOL_SURFACE=meta.

For example, gitlab://tools/merge_request.create returns the parameter schema and call shape for merge_request.create on the default surface; with GITLAB_MCP_TOOL_SURFACE=meta the same action is gitlab://tools/gitlab_merge_request.create. These manifest resources are available with GITLAB_MCP_CAPABILITY_SURFACE=full or minimal, regardless of GITLAB_MCP_META_PARAM_SCHEMA mode. gitlab_find_action returns the same schema inline on the dynamic surface, with ranked discovery on top.

The canonical action ID resolves on every surface, not only on the dynamic one where it is the entry’s key: gitlab://tools/project.get also answers with GITLAB_MCP_TOOL_SURFACE=meta and with GITLAB_MCP_TOOL_SURFACE=individual, and the entry it returns names the call that surface really takes (gitlab_project.get on meta, the tool gitlab_project_get on individual). An ID taken from a hint, a cross-link or this documentation can therefore be looked up whatever surface is served.

FieldWhat it holds
id, kind, tool, actionThe entry’s key on this surface; its kind (dynamic_action, meta_action, individual_tool or visible_tool); the tool to call; and, on the dynamic and meta surfaces, the action to name
title, description, domainWhat the entry does and the catalog domain it belongs to
destructive, read_onlyWhether the action is destructive, and whether it only reads
required_params, required_params_any_ofThe parameters every call needs, each with its JSON Schema type, and the alternative groups of which a call must satisfy at least one
alias_ofThe primary entry, when this ID is a deliberate alias of another action kept for discovery
callThe tool to call and where each part goes: on dynamic the action in action, the parameters in params and the confirmation in a top-level confirm; on meta the action in action, and the parameters and the confirm flag both in params; on individual the parameters are the tool’s own arguments, confirm among them
input_schemaThe JSON Schema of the parameters the entry accepts
fine_grainedWhat a fine-grained personal access token needs to run the action (below)
withheldWhy a fine-grained session may not run the action, only for such a session (below)

call names a confirmation location only for a destructive entry. On the individual surface the arguments go to the tool directly, with no action or params wrapper.

The detail of a catalog action carries a fine_grained block in every session, classic tokens included, since the detail is where a model looks up what an action needs. It says what a fine-grained personal access token needs to run the action, as the GitLab release named in gitlab_version declares it, in the words GitLab’s token creation page uses. A classic token is not judged by it: its scopes decide what it can do.

FieldMeaning
gitlab_versionThe GitLab release the requirement was recorded at
any_ofThe ways of running the action, any one of which is enough, since the action sends a different request depending on its input. Each way lists its needs: the permissions GitLab checks, every permission of one need held at one of the boundaries in at
not_judged_by_grantSet on a way that sends a request GitLab leaves to the token’s other properties rather than to its grant
denied_waysThe ways no fine-grained token runs at that release, each with the cause, element and effect of its denial: the action runs, except with an input that makes it send one of those requests
always_emptyParts of the answer GitLab serves empty to every fine-grained token, each written as the GraphQL selection that reaches it from the field the action asks for
empty_withoutParts of the answer GitLab serves empty unless the grant also holds what each entry’s needs names, the part written in selection
deniedPresent instead of the rest when no fine-grained token can run the action at that release: the cause, the element that decides it (a route, a GraphQL type or a mutation) and the effect GitLab has on the request

The block is derived from the action’s handlers and from a record of what a booted GitLab declares, by cmd/gen_action_grants, and it is the same table that decides what a fine-grained session is shown. The standalone tools that the meta and individual surfaces register beside their catalog, the guided flows among them, carry the block of the action each one is; an entry that names no action, such as the dynamic surface’s two tools or a meta dispatcher, carries none.

A session on a fine-grained token reads both manifest resources narrowed to what it may run. gitlab://tools leaves out the entries and visible tools its tools/list leaves out. gitlab://tools/{id} of an action left out is served rather than answered not found, with a withheld block carrying the cause (not-granted when the token’s grant does not reach the action, or one of the denial causes when no fine-grained token does) and the message a call to the action is refused with. When the action is left out of the listing but a call to it is still passed to GitLab (a read GitLab serves on a public project or group, or, on the prerelease after the recorded release, a call not withheld from every fine-grained token), the message says so. On the meta surface the detail of a tool every action of which is withheld carries the block too, with no cause of its own and an actions list giving each action’s id, cause and message, since the actions of one group need not share a reason. A classic token’s reads are never narrowed. Reading a withheld answer quotes both refusal texts.

ResourceNameDescription
gitlab://project/{project_id}projectProject metadata, by numeric ID or URL-encoded path: name, namespace path, visibility, web URL, description and default branch
gitlab://project/{project_id}/membersproject_membersProject members, up to one page (100), with access levels (10=guest, 20=reporter, 30=developer, 40=maintainer, 50=owner), including members inherited from parent groups
gitlab://project/{project_id}/labelsproject_labelsProject labels, up to one page (100): name, color, description, and the counts of open issues and open merge requests using each label, which the server asks GitLab for with with_counts
gitlab://project/{project_id}/milestonesproject_milestonesProject milestones, up to one page (100): title, description, state (active/closed), due date and web URL
gitlab://project/{project_id}/branchesproject_branchesBranches, up to one page (100): name, protection status, merge status, default flag and web URL
gitlab://project/{project_id}/branch/{branch}branchOne branch by name: protection status, merge status, default flag and web URL
gitlab://project/{project_id}/issuesproject_issuesOpen issues, up to one page (100): IID, title, state, labels, assignees, author, web URL and creation date
gitlab://project/{project_id}/releasesproject_releasesReleases, up to one page (100): tag name, name, description, author, and creation and release dates
gitlab://project/{project_id}/release/{tag_name}releaseOne release by tag name: tag name, name, description, author, and creation and release dates
gitlab://project/{project_id}/tagsproject_tagsRepository tags, up to one page (100): name, message, target commit SHA, protection status and creation date
gitlab://project/{project_id}/tag/{tag_name}tagOne tag by name: target commit SHA, annotation message and protection status
gitlab://project/{project_id}/commit/{sha}commitOne commit by SHA: full and short ID, title, message, author and committer names and emails, authored and committed dates, parent commits, web URL, and stats (additions, deletions, total)
gitlab://project/{project_id}/file/{ref}/{+path}file_blobA file’s contents at a ref (branch, tag or SHA); the path may include slashes. Over 1 MiB, metadata only with truncated=true; a binary file, metadata with empty content
gitlab://project/{project_id}/wiki/{slug}wiki_pageA wiki page by slug: title, slug, format (markdown, rdoc, asciidoc or org) and raw content. Slugs are case-sensitive and use hyphens for spaces
gitlab://project/{project_id}/label/{label_id}labelOne project label by numeric ID or name: ID, name, color and description. No usage count, since GitLab sends a label’s counts only with a label list: the project.label_list action returns them when called with with_counts: true
gitlab://project/{project_id}/milestone/{milestone_iid}milestoneOne project milestone by IID: ID, IID, title, description, state, due date and web URL
gitlab://project/{project_id}/board/{board_id}boardOne issue board by numeric ID: ID and name
gitlab://project/{project_id}/deployment/{deployment_id}deploymentOne deployment by numeric ID: ID, IID, ref, SHA, status and environment name
gitlab://project/{project_id}/environment/{environment_id}environmentOne environment by numeric ID: ID, name, slug, state and tier
gitlab://project/{project_id}/job/{job_id}jobOne CI/CD job by numeric ID: ID, name, stage, status, ref, duration and web URL
gitlab://project/{project_id}/feature_flag/{name}feature_flagOne feature flag by name: name, description, active flag and version
gitlab://project/{project_id}/deploy_key/{deploy_key_id}deploy_keyOne project deploy key by numeric ID: ID, title, key and fingerprint
gitlab://project/{project_id}/snippet/{snippet_id}project_snippetOne project snippet by numeric ID: ID, title, file name, description, visibility and web URL
ResourceNameDescription
gitlab://project/{project_id}/issue/{issue_iid}issueOne issue by its IID (project-scoped ID): title, state, labels, assignees, author, web URL and creation date
gitlab://project/{project_id}/mr/{merge_request_iid}merge_requestOne merge request by its IID: title, state, source and target branches, author, merge status and web URL
gitlab://project/{project_id}/mr/{merge_request_iid}/notesmerge_request_notesNotes (comments) on a merge request, up to one page of 100 in the order GitLab returns them: ID, author username, body, system flag, resolvable and resolved flags, timestamps
gitlab://project/{project_id}/mr/{merge_request_iid}/discussionsmerge_request_discussionsDiscussion threads on a merge request, up to one page of 100: ID, individual_note flag, and the notes of each (ID, author, body, system, resolved and resolvable, creation time)
ResourceNameDescription
gitlab://project/{project_id}/pipelines/latestlatest_pipelineThe most recent pipeline of the project’s default branch: ID, status (running, pending, success, failed, canceled), ref, SHA, source and web URL
gitlab://project/{project_id}/pipeline/{pipeline_id}pipelineOne pipeline by its numeric ID: status, ref, SHA, source and web URL
gitlab://project/{project_id}/pipeline/{pipeline_id}/jobspipeline_jobsA pipeline’s jobs, up to one page (100): each job’s name, stage, status, duration, failure reason (when it failed) and web URL
ResourceNameDescription
gitlab://group/{group_id}groupGroup details, by numeric ID or URL-encoded path: name, full path, description, visibility and web URL
gitlab://group/{group_id}/membersgroup_membersGroup members, up to one page (100), with access levels (10=guest, 20=reporter, 30=developer, 40=maintainer, 50=owner), inherited members included
gitlab://group/{group_id}/projectsgroup_projectsProjects in the group, up to one page (100): ID, name, namespace path, visibility, web URL, description and default branch
gitlab://group/{group_id}/label/{label_id}group_labelOne group label by numeric ID or name: ID, name, color and description. No usage count, since GitLab sends a label’s counts only with a label list: the group.group_label_list action returns them when called with with_counts: true
gitlab://group/{group_id}/milestone/{milestone_iid}group_milestoneOne group milestone by IID: ID, IID, title, description, state, due date and web URL
ResourceNameDescription
gitlab://snippet/{snippet_id}snippetOne personal (user-scoped) snippet by numeric ID: ID, title, file name, description, visibility and web URL

Static best-practice guides for AI assistants, written into the server: reading one makes no GitLab request, and each declares its size in bytes in the listing, so a client can budget context for it before reading. A guide names a call by its canonical action ID (pipeline.get), which reads the same whatever surface is served.

ResourceNameTitleDescription
gitlab://guides/git-workflowgit_workflowGit Workflow GuideBest practices for Git branching strategies with GitLab (feature branches, trunk-based, GitLab Flow)
gitlab://guides/merge-request-hygienemerge_request_hygieneMerge Request Hygiene GuideGuidelines for creating and reviewing high-quality merge requests
gitlab://guides/conventional-commitsconventional_commitsConventional Commits GuideConventional commit message format and examples for consistent Git history
gitlab://guides/code-reviewcode_reviewCode Review GuideCode review checklist and best practices for GitLab merge request reviews
gitlab://guides/pipeline-troubleshootingpipeline_troubleshootingPipeline Troubleshooting GuideCommon GitLab CI/CD pipeline issues and how to diagnose and fix them

resources/read has no continuation. MCP scopes pagination to the list methods (resources/list, resources/templates/list, tools/list, prompts/list) and defines neither a cursor nor a partial-result shape for a read, so a collection resource cannot hand back a page token and a client cannot ask for the next page.

The 13 collection resources (gitlab://groups and every template above whose description says “up to one page”) therefore ask GitLab for one page of 100, GitLab’s maximum, and state their own completeness in _meta, under the vendor-namespaced key io.github.jmrplens/pageInfo:

{
"_meta": {
"io.github.jmrplens/pageInfo": { "returned": 100, "total": 137, "complete": false }
},
"contents": [{ "mimeType": "application/json", "text": "[…]" }]
}

returned is how many items the body holds. total is how many exist, and is omitted when GitLab sends no total, which is the case on keyset-paginated endpoints. complete is the field to branch on: it is false whenever GitLab reports a next page. When it is false, read the same data through the tool surface, whose list actions paginate and return total_items, next_page and has_more.

This also bounds what a watch can see: a subscription to one of the three subscribable lists is notified about changes inside the page it reads, and not about changes past it (ADR-0015, NEG-005).

26 templates accept a subscription: every single-object GitLab template above except the commit, which never changes, plus the three lists that belong to one parent (a pipeline’s jobs, a merge request’s notes and its discussions). The static resources, the other collections, the two tool manifest resources and the guides do not.

Each subscribable template says so in resources/templates/list, twice. Its description ends with the sentence Subscribable: subscriptions/listen (protocol 2026-07-28). Resources/subscribe on stateful sessions., which a model reads, and its _meta carries "io.github.jmrplens/subscribable": true, which a generic client can filter on without knowing this server. The machine-readable list is published in two more places, both only on the full capability surface:

  • the subscriptions section of gitlab://tools: supported, subscribable_uri_templates and the notification a change sends;
  • the subscriptions block of the enumerating server card that HTTP mode serves at /.well-known/mcp/server-card.json, beside a capabilities object copied from the handshake. It also says which method this deployment answers (subscriptions/listen on the default stateless transport, resources/subscribe with --stateless=false) and lists the reasons a watch can end. The SEP-2127 card at /server-card carries identity and connection details only, none of this.

Resource subscriptions covers polling cadence, cost and lifetime.

Resource URIs with {project_id}, {group_id} and the other variables are resource templates: the client substitutes the actual value when requesting the resource.

ParameterTypeDescription
project_idstringNumeric project ID or URL-encoded path (group%2Fproject)
group_idstringNumeric group ID or URL-encoded path
pipeline_idintegerNumeric pipeline ID
merge_request_iidintegerMerge request IID (project-scoped number, shown as !N in GitLab)
issue_iidintegerIssue IID (project-scoped number, shown as #N in GitLab)
milestone_iidintegerMilestone IID within the project or group
board_id, deployment_id, environment_id, job_id, deploy_key_id, snippet_idintegerNumeric ID of the object
shastringCommit SHA
refstringBranch name, tag name or commit SHA (feature%2Flogin for feature/login)
branchstringBranch name (feature%2Flogin for feature/login)
tag_namestringTag name (v1.0.0%2Bbuild for v1.0.0+build)
label_idstringNumeric label ID or label name (priority%3A%3Ahigh for priority::high)
pathstringRepository file path; may contain slashes (RFC 6570 reserved expansion, {+path})
slugstringWiki page slug (case-sensitive, hyphens for spaces)
namestringFeature flag name
idstringAn entry ID from gitlab://tools, or a canonical action ID

Every variable except {+path} is an RFC 6570 simple expansion, and each one fills exactly one path segment. A value carrying any character outside A-Z a-z 0-9 - . _ ~ is therefore percent-encoded once before it goes into the URI: group/project is written group%2Fproject, the branch feature/login is feature%2Flogin, and the scoped label priority::high is priority%3A%3Ahigh. The server decodes each variable exactly once before it asks GitLab, so the value GitLab receives is the one you encoded. A raw slash in such a variable either matches no template, and the read answers resource-not-found, or is read as a separator, as the file template’s {ref} is before {+path}, so a different object is asked for. Encode it. The resource blocks that tool results embed are already spelled this way, so their URIs can be handed to resources/read unchanged.

{+path} is a reserved expansion: its slashes stay as they are, and every segment is decoded once like any other variable. Reserved expansion passes an existing percent-escape through, so a file whose name literally contains one (a%20b.txt) must have its % encoded as %25 (a%2520b.txt), or it is read as a b.txt. The same holds for a name sent unencoded that happens to contain a valid escape, such as a branch fix-%41: it is decoded, and names fix-A.

Through completion/complete, the server suggests project_id and group_id values as they are typed, and merge_request_iid and issue_iid from the project’s open merge requests and issues once project_id is filled in the same request. No other URI parameter gets suggestions, and neither does one whose data an operator excluded with GITLAB_MCP_EXCLUDE_TOOLS. Completions describes the mechanism.

MCP clients can request resources at any time using the resources/read method:

{
"method": "resources/read",
"params": {
"uri": "gitlab://user/current"
}
}

The server returns the resource content as JSON, or as Markdown for a workflow guide; a collection adds its page information in _meta.

To inspect accepted call shapes, read the surface-aware tool manifest first and then the action schema:

{
"method": "resources/read",
"params": {
"uri": "gitlab://tools"
}
}
{
"method": "resources/read",
"params": {
"uri": "gitlab://tools/merge_request.create"
}
}

With GITLAB_MCP_TOOL_SURFACE=meta the entry is gitlab://tools/gitlab_merge_request.create, and with GITLAB_MCP_TOOL_SURFACE=individual it is the tool name, gitlab://tools/gitlab_mr_create: use whatever ID gitlab://tools listed for the active surface.

MCP prompts are reusable templates that guide AI assistants through common workflows. When a client requests a prompt, the server collects the relevant data from GitLab and returns structured context that the LLM uses to produce a high-quality output — a code review, a release-notes draft, or a team report — without the user re-explaining the task each time.

The server provides 37 prompt templates organized into categories. Each table lists a prompt’s arguments, read from the server’s own registration: an argument marked * is required, and every other one may be left out, with the defaults given under Common arguments. Every prompt argument is a string, as MCP defines them. A prompt reads one page of each paginated list it gathers, so on a busy project or group its report covers part of the data; the matching list actions on the tool surface paginate. The page holds 100 items, GitLab’s maximum, for every list a prompt reads but one: mr_discussion_health reads 20 open merge requests, since it asks for the discussions of each. Each prompt’s description states the bound it reads to, as “up to 100”, so review_mr, summarize_mr_changes, mr_risk_assessment and mr_description_quality read up to 100 changed files of a merge request, and a report built from a list that has more counts the first 100.

Merge request analysis, project overview, and personal productivity.

PromptArgumentsDescription
summarize_mr_changesproject_id*, merge_request_iid*The changed files and key modifications in a merge request, each file with its change type (new, modified, deleted, renamed)
review_mrproject_id*, merge_request_iid*A structured code review: files grouped by risk (high-risk, business logic, tests, documentation) with per-file metrics, branch context and a review plan; each file’s full diff, not truncated
suggest_mr_reviewersproject_id*, merge_request_iid*Reviewers suggested from the changed files and the active project members, excluding the author: the prompt lists both and asks the model to suggest the most suitable reviewers and say why
mr_risk_assessmentproject_id*, merge_request_iid*Risk level (LOW, MEDIUM, HIGH, CRITICAL) from size (lines added and removed), changed files, new and deleted files, sensitive file patterns (env, auth, migration, CI, security) and conflict status
PromptArgumentsDescription
summarize_pipeline_statusproject_id*The jobs of the default branch’s latest pipeline grouped by outcome (failed, passed, other), with failure reasons for debugging
summarize_open_mrsproject_id*Open merge requests with title, author, branches, age in days and merge status, highlighting stale ones (over 7 days) and blockers; for one target branch, use branch_mr_summary
project_health_checkproject_id*Health assessment combining the default branch’s latest pipeline, open merge requests and branch hygiene (merged and stale branch counts), with recommendations for maintenance
generate_release_notesproject_id*, from*, toRelease notes from the commits, merge requests and file changes between two refs (tags, branches or SHAs): commits, the MRs merged around the commits’ dates with their labels, contributors and statistics
compare_branchesproject_id*, from*, to*Commit and file differences between two refs, for release branch preparation, divergence analysis, or deciding whether a merge or backport needs a deeper review
PromptArgumentsDescription
daily_standupproject_id*, usernameA standup summary for a user: contribution events from the last 24 hours, plus the user’s open MRs in the project (authored, assigned and reviewing) and open issues (assigned and created), with done, planned and blockers sections
team_member_workloadproject_id*, username*, daysOne team member’s workload over a period: contribution events, authored and assigned MRs, MRs under review, authored and assigned issues; for team management and capacity planning
user_statsproject_id*, username, daysUser statistics: contribution events across all projects with their daily trends and a Mermaid activity chart, and the project’s MR stats (authored, assigned and reviewed, by state) and issue stats (authored and assigned, by state)

Personal dashboards that take no project or group argument.

PromptArgumentsDescription
my_open_mrsusernameOpen merge requests across all projects where you are author or assignee, grouped by project: a personal MR dashboard without naming a project
my_pending_reviewsusernameOpen merge requests across all projects where you are assigned as reviewer, grouped by project, to track which are waiting for your review
my_issuesusername, stateIssues assigned to you across all projects, grouped by project, with overdue detection
my_activity_summaryusername, daysPersonal activity over a period, aggregated across all projects: contribution events by action, the count of MRs authored that were created in the period and merged, the count of MRs under review that were updated in it, and a daily activity chart

Group-level team management prompts.

PromptArgumentsDescription
user_activity_reportusername*, daysAn activity report for one user (contribution events, the MRs they authored that were created in the period and merged, open MRs under their review, daily activity chart), designed for managers reviewing a team member’s productivity
team_overviewgroup_id*, daysA team dashboard of the group’s direct members, each with the counts of their open MRs, of the open MRs they review and of their MRs created in the period and merged, and a workload distribution pie chart
group_mr_dashboardgroup_id*, state, target_branchMerge requests across a group, filtered by state and target branch, grouped by project with blocker and readiness statistics
reviewer_workloadgroup_id*Review distribution across the group’s direct members: how many open MRs each is reviewing, and where the load is uneven

Project-level analysis and reporting.

PromptArgumentsDescription
branch_mr_summaryproject_id*, target_branch*, stateMerge requests targeting one branch, with a readiness summary of draft and conflict counts; suited to release branch reviews
project_activity_reportproject_id*, daysRecent events, the MRs created in the period and merged, open MRs and open issues, with a daily activity chart and a contributor breakdown
mr_discussion_healthproject_id*Unresolved discussion threads across open MRs, for review follow-up and merge-readiness cleanup, not approval-rule status
unassigned_itemsproject_id*Open MRs and issues with no assignee, to find ownership gaps and items needing attention
stale_items_reportproject_id*, stale_daysMRs and issues not updated for a number of days (14 unless stale_days says otherwise), to find forgotten or blocked items

Velocity and release analytics.

PromptArgumentsDescription
merge_velocityproject_id*, daysMR throughput from the MRs created in the period and since merged: merge rate, average and median time to merge and a daily merged-count chart
release_readinessproject_id*, branchReadiness of a release branch: open MRs targeting it, draft and conflict counts, and unresolved discussion threads
release_cadenceproject_id*, daysRelease frequency: time between releases, average cadence and a release history table
weekly_team_recapgroup_id*, daysA weekly recap for a team: the MRs created in the period and since merged, by project, open MR and open issue counts, and open MR health (drafts and conflicts), all as tables

Milestone tracking and label analysis.

PromptArgumentsDescription
milestone_progressproject_id*, milestoneMilestone progress: issue and MR completion, a progress bar and due-date risk; without milestone, every active milestone
label_distributionproject_id*Label usage per label (open and closed issues, open MRs), read from one label listing that asks GitLab for the counts, ranked by total use with a chart of open issues by label; a label nobody uses is left out of the table
group_milestone_progressgroup_id*Milestone progress across the group’s projects: issue and MR completion per milestone, with progress bars
project_contributorsproject_id*Contributors ranked by commits, additions and deletions, from the repository contributors API

Commit history and MR authoring quality.

PromptArgumentsDescription
audit_commit_hygieneproject_id*, from*, toCommit message quality between two refs: Conventional Commit usage, merge commits, breaking-change markers, body quality and linked work references, for release and contribution readiness
mr_description_qualityproject_id*, merge_request_iid*A score of an MR description’s reviewer readiness: context, linked work, test evidence, rollout and risk notes, checklists, and whether the changed files suggest missing screenshots or migration notes

Project configuration audit prompts.

PromptArgumentsDescription
audit_project_workflowproject_id*Workflow configuration: labels (names, colors, descriptions, and the open issues and MRs using each), milestones (open or closed, due dates) and issue and MR templates, naming gaps such as labels without descriptions, milestones without due dates or missing templates
audit_project_fullproject_id*One report opening with a quick scorecard and auditing settings, branch protection, access management, labels, active milestones, templates, webhooks and push rules, with actionable recommendations
ArgumentWhat it isWhen omitted
project_idNumeric project ID or path as written (my-group/my-project), not URL-encodedRequired wherever a prompt takes it
merge_request_iidMerge request IID (project-scoped number, shown as !N in GitLab)Required wherever a prompt takes it
group_idNumeric group ID or path as written (my-group, parent/child), not URL-encodedRequired wherever a prompt takes it
usernameA GitLab usernameThe authenticated user; required in team_member_workload and user_activity_report
daysDays to look back, a positive integer7, 30 or 90 depending on the prompt (below)
from, toGit refs: a tag name, a branch name or a commit SHAto is HEAD in generate_release_notes and audit_commit_hygiene; both are required in compare_branches
branchThe release branch release_readiness checksmain
target_branchThe branch the listed merge requests targetRequired in branch_mr_summary; in group_mr_dashboard, no branch filter
stateopened, closed, merged or all for merge requests; opened, closed or all for issues (my_issues)opened
milestoneA milestone title, looked up among the active milestonesEvery active milestone, up to 100
stale_daysDays without an update after which an item counts as stale14

days defaults to 7 in team_member_workload, my_activity_summary, user_activity_report, team_overview, project_activity_report and weekly_team_recap; to 30 in user_stats and merge_velocity; and to 90 in release_cadence. A days or stale_days value that is not a positive integer is refused with JSON-RPC error -32602 (Invalid params) by every prompt, before it asks GitLab anything, and so is a missing required argument. The project_id and group_id of a prompt are passed to GitLab as given and escaped once on the way, so a URL-encoded path such as my-group%2Fmy-project would be escaped twice and name no project; a resource URI is the other way round, since there the path is part of the URI and has to be encoded.

GoalPrompt
Review code changes in depthreview_mr
Check whether an MR description is ready for reviewersmr_description_quality
Find suitable reviewerssuggest_mr_reviewers
Follow up unresolved review threadsmr_discussion_health
Summarize a project’s open MRssummarize_open_mrs
Summarize the MRs that target one branchbranch_mr_summary
Review MR status across a groupgroup_mr_dashboard
Draft release notesgenerate_release_notes
Check commit messages and history before a releaseaudit_commit_hygiene
Audit a project’s governance as a wholeaudit_project_full
Audit labels, milestones and templates onlyaudit_project_workflow

Through completion/complete, the server suggests project_id, group_id and username values as they are typed. merge_request_iid (from the project’s open merge requests), from and to (branch and tag names), branch and target_branch (branch names) and milestone (milestone titles) are suggested once project_id is filled in the same request. days, stale_days and state get no suggestions. A completion naming a prompt this server does not serve is refused with -32602. Completions describes the mechanism.

Prompts are requested via the prompts/get MCP method:

{
"method": "prompts/get",
"params": {
"name": "review_mr",
"arguments": {
"project_id": "my-group/my-project",
"merge_request_iid": "42"
}
}
}

The server returns a structured prompt with context-aware content that the LLM uses to guide its workflow.

VariableDefaultDescription
GITLAB_MCP_CAPABILITY_SURFACEfullfull registers resources, workflow guides, prompts, and gitlab://tools; minimal keeps gitlab://tools

GITLAB_MCP_EXCLUDE_TOOLS narrows this page’s surfaces as well as the tools: a resource that returns the same GitLab data as an excluded action is not registered, nor is a prompt that reads such data, and completions backed by it answer nothing. See Configuration.

Frequently asked questions

What is the difference between resources, prompts, and tools?

GitLab MCP Server exposes three MCP primitives. Tools perform actions, such as creating an issue or merging a request. Resources provide read-only context data — a project's metadata or members, for example — that a client can request at any time without invoking a tool, and 26 resource kinds (single objects plus three single-parent lists) can also be watched for changes. Prompts are reusable templates that collect GitLab data and return structured context to guide a workflow. In short, resources and prompts add context, while tools change state.

What is the difference between a static resource and a resource template?

A static resource is a fixed URI that always points to the same thing, such as gitlab://user/current. A resource template contains placeholders like {project_id} or {group_id} that the client fills in at request time to read a specific project, group, issue, or merge request. MCP lists fixed resources through resources/list and templates through resources/templates/list, so of the 45 resources a client that inspects only resources/list sees the 8 fixed URIs, and finds the other 37, the templates, only through resources/templates/list.

Can I disable resources and prompts?

Yes. The GITLAB_MCP_CAPABILITY_SURFACE setting controls which capabilities are registered. The default full registers resources, workflow guides, prompts, and the surface-aware gitlab://tools manifest. Setting GITLAB_MCP_CAPABILITY_SURFACE=minimal keeps only the gitlab://tools manifest — useful when a client does not consume resources or prompts and you want a smaller capability surface.

How many resources and prompts are available?

The server exposes 45 resources (8 fixed URIs plus 37 URI templates) and 37 prompt templates organized into categories such as core MR analysis, cross-project dashboards, team reports, analytics, and audits. The exact counts are generated from the server's live capability registration, so this page stays in sync with the running server.

How do I read an MCP resource from GitLab MCP Server?

A client reads a resource with the MCP resources/read method, passing the resource URI in the params. For a static resource the URI is used as-is, for example gitlab://user/current. For a template, the client substitutes the actual identifier or URL-encoded path first, for example gitlab://project/my-group%2Fmy-project/issues. The server returns the content as JSON, or as Markdown for the five workflow guides.