Skip to main content
Glama
igordev96
by igordev96

gitlab-readonly-mcp

CI

A small, read-only, git-backed MCP server for a self-managed GitLab.

It lets an AI agent read files from any branch, tag, or commit — including branches that are not checked out locally — without ever touching your working tree. Content comes from a local bare mirror the server keeps in a cache directory, or from a clone of your own when you register one.

Why git instead of the GitLab REST API?

Reading a file at a ref, comparing branches, history, blame and code search are git's strengths and, on a self-managed free tier, the REST API's weaknesses. How it works has the longer answer.

Related MCP server: GitLab MCP Server

Requirements

  • Node.js 24+ (developed on Node 24.21)

  • git on PATH

  • A GitLab token with the read_repository scope (a personal or project access token). Never use api or write_repository.

Install

Install the tarball attached to the latest release. No checkout, no build, no npm account:

npm install -g https://github.com/igordev96/gitlab-readonly-mcp/releases/download/v0.10.1/gitlab-readonly-mcp-0.10.1.tgz

Each release carries SHA256SUMS beside the tarball if you want to check the download before installing it. The package is not on npm (private: true), and the Source code archives GitHub attaches to a release are repository snapshots without dist/ — they install nothing.

To work on the server instead, build the tarball from your checkout:

npm install
npm pack --pack-destination .          # gitlab-readonly-mcp-0.10.1.tgz
npm install -g .\gitlab-readonly-mcp-0.10.1.tgz

Either way, gitlab-readonly-mcp lands on PATH and speaks MCP on stdio from any directory. To upgrade, install the newer release's tarball. To uninstall, npm rm -g gitlab-readonly-mcp.

Under nvm, global packages live inside the active Node version, so switching versions hides the command until you reinstall it.

Configuration

All configuration is via environment variables.

Variable

Required

Description

GITLAB_HOST

yes

Base URL of the instance, e.g. https://gitlab.example.com (no trailing slash).

GITLAB_TOKEN

yes

Read-only token (read_repository). Injected per git call via http.extraheader; never written to .git/config.

GITLAB_DEFAULT_PROJECT

no

Project path used when a tool call omits project, e.g. group/subgroup/repo.

GITLAB_MCP_CACHE

no

Cache root for mirrors. Defaults to %LOCALAPPDATA%\gitlab-readonly-mcp (or ~/.cache/... elsewhere).

GITLAB_CA_INFO

no

Path to a CA bundle, if the server uses a private CA.

GITLAB_GIT_BIN

no

Git executable. Defaults to git.

GITLAB_FETCH_MODE

no

Default freshness policy for every project: ttl (default) fetches only when a mirror is older than the TTL, always fetches before every read, manual never fetches by itself. A project can override it in repos.json.

GITLAB_FETCH_TTL_SECONDS

no

Age in seconds after which a mirror counts as stale. Default 600 (10 minutes). 0 behaves like always.

These are the defaults; a project can override its freshness policy in repos.json (see Repositories and policy).

Wire into OpenCode

opencode mcp add gitlab --global `
  --env GITLAB_HOST=https://gitlab.example.com `
  --env 'GITLAB_TOKEN={env:GITLAB_TOKEN}' `
  --env GITLAB_DEFAULT_PROJECT=group/subgroup/repo `
  -- gitlab-readonly-mcp

Or add it to configuration by hand (mcp.servers):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "servers": {
      "gitlab": {
        "type": "local",
        "command": ["gitlab-readonly-mcp"],
        "environment": {
          "GITLAB_HOST": "https://gitlab.example.com",
          "GITLAB_TOKEN": "{env:GITLAB_TOKEN}",
          "GITLAB_DEFAULT_PROJECT": "group/subgroup/repo"
        }
      }
    }
  }
}

The command is the installed binary, so the entry point no longer depends on where the checkout lives — a global MCP server's working directory is the workspace it is launched from, not this project. If the bare name does not resolve on your machine, npm prefix -g gives the prefix; <prefix>\gitlab-readonly-mcp.cmd is the same package by absolute path.

The tools appear as gitlab_<tool> — gitlab_get_file, gitlab_log, and so on. All sixteen are listed below.

Wire into Cursor

Cursor reads MCP servers from a mcpServers object, in .cursor/mcp.json for one project or ~/.cursor/mcp.json for every project (%USERPROFILE%\.cursor\mcp.json on Windows). It starts the command from Install, so that has to be on PATH first.

{
  "mcpServers": {
    "gitlab": {
      "command": "cmd",
      "args": ["/c", "gitlab-readonly-mcp"],
      "env": {
        "GITLAB_HOST": "https://gitlab.example.com",
        "GITLAB_TOKEN": "${env:GITLAB_TOKEN}",
        "GITLAB_DEFAULT_PROJECT": "group/subgroup/repo"
      }
    }
  }
}

On Windows the cmd /c wrapper is not optional. The installed package is a .cmd shim, and Cursor starts the command itself rather than through a shell: "command": "gitlab-readonly-mcp" fails with ENOENT and the server never appears in the list. On macOS and Linux the bare name is correct:

"command": "gitlab-readonly-mcp",

Quit Cursor completely and reopen it; a window reload is not always enough. The server then shows under Settings → MCP, and anything it printed on the way up is in Output → MCP Logs — the first place to look when the entry exists but its tools do not.

Two traps, both silent:

  • The interpolation syntax is not OpenCode's. Cursor resolves ${env:NAME}; OpenCode resolves {env:NAME}. Copy a config from one to the other unchanged and the literal string is passed as the token, which GitLab rejects.

  • ${env:GITLAB_TOKEN} reads Cursor's own environment, not your shell's history: a variable set only in the current terminal is invisible to an app started from the taskbar. Use the OS-level variable, or point envFile at a file: "envFile": "${workspaceFolder}/.env". A token pasted literally works too, but then .cursor/mcp.json must stay out of git.

What it can do

Tool

What it answers

Files and trees

get_file

One file at a ref — the whole file or a line range. Accepts a blob, raw or blame link.

list_tree

A directory at a ref, one level deep or recursive. Accepts a tree link.

Refs

list_refs

Branches and tags, with the commit each points at.

resolve_ref

What a branch, tag or sha resolves to, with close matches when the name is wrong.

Search

search

Grep a ref's tree, grouped by file — matched lines, file paths, or per-file counts.

pickaxe

The commits whose diff changed how often a text appears.

History and diffs

log

A ref's history, optionally for one path. Accepts a history link.

get_commit

One commit: message, parents, author, files, line counts, and the patch on request. Accepts a commit link.

blame

Who last touched each line, grouped by commit. Accepts a blame link.

compare

What changed on one ref since it split from another, as a capped file summary.

diff_file

One file's patch between two refs.

Links

parse_gitlab_url

What a GitLab link names — project, target, ref, path and line range — without reading anything.

Repository policy

list_repos

Every project in use: its source, its policy and its true age.

sync_repo

Fetch now, ignoring the TTL.

add_repo

Read a project from a clone of your own instead of a mirror.

remove_repo

Forget a project. Never deletes your clone.

Quickstart

Examples use group/sub/repo; set GITLAB_DEFAULT_PROJECT to leave project= out. Every result says which commit answered and how fresh it is — see What the odd bits mean.

Read a file from a branch you have not checked out. No clone of your own, no checkout, no change to your working tree:

gitlab_get_file(project="group/sub/repo", ref="fix/PROJ-7608", path="src/index.tsx")
<file project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" path="src/index.tsx" synced_at="2026-10-18T09:12:44.318Z">
…file contents…
</file>

Browse a tree before reading. Files carry their size, so a small config is easy to tell from a bundle. recursive=true walks the whole subtree:

gitlab_list_tree(project="group/sub/repo", ref="fix/PROJ-7608", path="src")
<tree project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" path="src" count="3" synced_at="…">
blob	3047	src/App.tsx
tree	-	src/components
blob	412	src/theme.css
</tree>

Find and confirm a branch. list_refs searches names; resolve_ref turns one into a commit, and suggests close matches when the name is wrong:

gitlab_list_refs(project="group/sub/repo", kind="branches", search="PROJ")
<refs project="group/sub/repo" kind="branches" default_branch="develop" count="1" synced_at="…">
branch	abc123def456	fix/PROJ-7608	PROJ-7608: adjust the header
</refs>

Find where something is used — no clone, no knowledge of the file:

gitlab_search(project="group/sub/repo", ref="fix/PROJ-7608", query="orderTotals")
<search project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" query="orderTotals" count="2" files="1" synced_at="…">
src/reports/OrderTotals.tsx
  22: export const OrderTotalsReport = () => {
  64:   title={translations.reporting.seeOrderTotalsPage}
</search>

output="count" answers "how many, in which files" without listing every match; context=2 adds the lines around each hit. pickaxe(query=…) answers the follow-up: when did this text appear?

Read a pasted link, including the lines it names. A #L118-126 anchor becomes the range:

gitlab_get_file(url="https://gitlab.example.com/group/sub/repo/-/blob/fix/PROJ-7608/src/index.tsx#L118-126")
<file project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" path="src/index.tsx" lines="118-126" file_lines="373" synced_at="…">
118: …
</file>

Each link kind has one reader: blob, raw and blame links go to get_file (or blame), tree links to list_tree, /-/commit/ to get_commit, /-/commits/ to log. A link handed to another tool is refused by name and says which tool wants it. parse_gitlab_url(url) reports what a link names without reading anything, and resolve=false does it offline.

See the history, and who last touched a line. path is optional and is a git pathspec, so globs work:

gitlab_log(project="group/sub/repo", ref="fix/PROJ-7608", path="src/index.tsx")
<log project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" path="src/index.tsx" count="2" synced_at="…">
abc123def4	2026-10-15T12:32:33+01:00	A. Author	PROJ-7608: adjust the header
def456abc7	2026-10-14T09:15:02+01:00	B. Author	Merge branch 'develop' into fix/PROJ-7608	(merge)
</log>
gitlab_blame(project="group/sub/repo", ref="fix/PROJ-7608", path="src/index.tsx", lines="118-126")
<blame project="group/sub/repo" ref="fix/PROJ-7608" commit="abc123…" path="src/index.tsx" lines="118-126" file_lines="373" groups="2" count="9" max_lines="500" synced_at="…">
def456abc789	B. Author	2026-04-23T10:11:50+02:00	118-121
  118: …
abc123def456	A. Author	2026-10-15T12:32:33+01:00	122-126
  122: …
</blame>

get_commit(rev=…) reads one commit — message, files, line counts, and the patch with patch=true.

Compare two branches. compare prints the merge base it used, so which diff ran is never hidden:

gitlab_compare(project="group/sub/repo", from="develop", to="fix/PROJ-7608")
<compare project="group/sub/repo" from="develop" to="fix/PROJ-7608" from_commit="…" to_commit="…" merge_base="def456abc789…" files="1" total_files="1" additions="32" deletions="11" max_files="100" synced_at="…">
M	src/index.tsx	+32 -11
</compare>

diff_file(from=…, to=…, path=…) is one file's patch; pass the merge_base it printed as from for the branch's own view of the file.

Gotchas

  • search and pickaxe match literally and case-insensitively: foo|bar looks for that text. Pass regex=true for alternation, case_sensitive=true for exact case.

  • A plain pathspec's ** needs a directory level — src/**/*.tsx misses src/index.tsx. Use :(glob)src/**/*.tsx for zero or more.

  • Omit ref to read the default branch, which is what a fresh clone shows you.

  • #L12 and #L12-20 anchors are 1-based and inclusive.

  • compare is three-dot by default; merge_base=false asks for the raw two-dot diff.

  • Binary files are refused where the answer would be meaningless (a read, a blame); a diff gives git's Binary files … differ line instead of a patch.

  • Caps are always reported: truncated="true", total=… and [cut: …] say when an answer was shortened, rather than quietly returning less.

What the odd bits mean

You see

It means

synced_at="…"

When the source that answered last fetched successfully. unknown means no successful fetch has ever stamped it.

refresh_failed="true"

A refresh was due and failed, so the answer came from the cache; a [refresh failed: …] note says why.

truncated="true" / total=…

The answer was capped. Where the tool can count it, total is the real number before the cap.

ref_confirmed="false"

parse_gitlab_url could not match the link's ref against the project's refs — it is offline, or the link names a sha. commit="…" is the resolved revision when the link names one.

merge_base="none"

The two refs share no history, so compare ran the raw two-dot diff and said so.

(no matches)

Nothing matched. That is an answer, not an error.

Repositories and policy

A project registers itself the first time it is used — its mirror is cloned on demand — or explicitly with add_repo. The registry is a small repos.json in the cache directory:

<repos count="2">
group/sub/repo	source=mirror	freshness=ttl	ttl=600s	present=true	synced_at="2026-10-18T21:44:25.655Z"
group/sub/other	source=local	freshness=ttl	ttl=600s	present=true	local_path=C:\work\other	synced_at="unknown"
</repos>

synced_at is when that source last fetched successfully, or unknown when no fetch has ever stamped it; present=false means the project is registered but its data is not on disk — a mirror never cloned, or a clone since moved. A project's policy can be overridden by hand (absent fields mean the configured default):

{
  "version": 1,
  "repos": {
    "group/sub/repo": {
      "source": "mirror",          // "mirror" | "local"
      "localPath": null,           // set when source == "local"
      "cloneStrategy": "full",
      "freshnessMode": "manual",   // "ttl" | "always" | "manual"
      "freshnessTtlSeconds": 3600
    }
  }
}

add_repo merges into what is already recorded, so re-pointing a project cannot reset a freshnessMode you set by hand. sync_repo(project) fetches immediately and follows the project's source (a mirror, or the clone's own remote) — that is what makes manual usable, and what to call when you want a fresh answer now. Unlike a read, sync_repo reports a failure as an error rather than answering from the cache.

Reading from a clone of your own

gitlab_add_repo(project="group/sub/repo", local_path="C:\\work\\repo")

The path is checked there and then — it must exist and be a git repository, working clone or bare — so a typo fails at the call that records it. From then on every read runs against that clone: nothing is cloned, and nothing is written to your working tree, so uncommitted work is untouched. A branch that is not the checked-out one is still found through its remote-tracking ref, because that is where git clone keeps every other branch. A clone with no remote still reads everything it holds; a miss says so plainly instead of pretending the ref does not exist.

gitlab_add_repo(project="group/sub/repo")             # back to a mirror
gitlab_remove_repo(project="group/sub/repo")          # forget it entirely
gitlab_remove_repo(project="group/sub/repo", delete_mirror=True)

remove_repo never deletes a clone: that repository is yours, and the server only ever deletes inside its own mirrors/ directory. Forgetting a mirror-backed project does not stick, because the next read registers it again; forgetting a local registration does, and is how a project goes back to being read from a mirror.

Troubleshooting

A failed read explains itself: the cause, a hint when the failure is one we recognise, and git's own output as evidence (git said: …). No extra logging is needed to find out what happened.

What you see

What it means

GitLab rejected the credentials

GITLAB_TOKEN is missing, expired, or lacks read_repository access to the project. GitLab reports a project you cannot see as a 401 too, so a typo in the project path looks identical.

GitLab could not find this project

Check the project path (group/subgroup/repo) and the token's access to it.

TLS verification failed

The server uses a private CA; point GITLAB_CA_INFO at the CA bundle.

Could not reach GitLab

Network or VPN.

[refresh failed: …] in a result

The source could not be refreshed, so the answer came from the cache as of synced_at. The note says why; the causes are the same as for a failed read.

The registered clone at … is not a usable git repository

The path recorded by add_repo has been moved, deleted or emptied. Run add_repo again with the current path, or remove_repo to go back to a mirror.

The registered clone at … has no remote to fetch from

The clone has no remote configured, so a ref it does not already hold cannot be fetched. Everything it does hold still reads.

search finds nothing, although you can see the text

Matching is literal and one argument: foo|bar means that text, not foo or bar — pass regex=true for alternation. A plain pathspec's ** needs a directory level (src/**/*.tsx misses src/index.tsx; use :(glob)src/**/*.tsx).

pickaxe lists no commits for text you can see

It reports commits whose diff changed how many times the text appears (git log -S), so text unchanged since the root commit, or brought in by a merge git does not diff, has no commit to list. Matching is literal and case-insensitive; case_sensitive=true follows the case exactly.

A link is refused: URL host "…" does not match GITLAB_HOST ("…")

The link belongs to another GitLab instance. Use a link from the instance GITLAB_HOST names; the server will not read a same-named project from elsewhere.

A link is refused: is a file link; use get_file for it (or directory, commit, history)

The link went to a tool that does not read it. Each kind has one reader: blob/raw/blame → get_file (or blame), tree → list_tree, /-/commit/ → get_commit, /-/commits/ → log. parse_gitlab_url says what a link names if it is unclear.

A link is refused: is a merge request link

Merge requests, issues and other non-code links name no version-control object, so they are refused by name. Take the ref and path from the page and call the tool directly.

A context call is refused

It needs output="matches"; files and count have no matched line to put context around.

list_repos prints clone_strategy=blobless(unsupported)

A repos.json entry asks for a clone strategy this server does not implement, so every read of that project fails with the value named. Set "cloneStrategy": "full" if the data on disk is a full clone, or remove_repo it with deleteMirror=true and use the project again, which clones it in full.

The credential case is worth one extra note: a running MCP server keeps the token it started with. Editing GITLAB_TOKEN does nothing to a server that is already running, which makes a valid token look broken. Restart the client (for OpenCode, opencode service restart) after changing it.

The first read of a project also clones it, so it is slow exactly once.

Security

  • The token is only ever passed as -c http.extraheader=… on the git command line, so it never lands in .git/config.

  • The token is redacted from error output before it reaches a tool result.

  • credential.helper= is cleared and GIT_TERMINAL_PROMPT=0 is set, so a bad token fails fast instead of prompting or hanging.

  • Refs and paths beginning with - are rejected to prevent argument injection.

  • Git is invoked with an argument array and shell: false.

Read more

  • How it works — where content comes from, freshness, and the read-only guarantee.

  • Development — build, test, releasing and the source layout.

  • Plan — the design decisions and what is next.

  • History — milestones, findings, and the evidence from live checks.

Available Tools

16 tools
add_repoRegister a repositoryA

Register a project with this server. With local_path, reads use that existing clone instead of a server-side mirror; the path is checked to be a git repository here, so a wrong path is refused now rather than at read time. Without it, the project is registered as mirror-backed, which also makes it appear in list_repos before it has ever been read. Nothing is cloned or fetched: use sync_repo for that, or simply read the project. A project already registered is updated; its freshness policy is kept.

ParametersJSON Schema
NameRequiredDescriptionDefault
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
local_pathNoPath to an existing clone (or bare repository) to read from instead of a mirror.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only give readOnlyHint=false and openWorldHint=false; the description goes well beyond that, disclosing that the path is validated as a git repo at registration time, that nothing is cloned or fetched, that mirror-backed projects surface in list_repos before first read, and that re-registration preserves the existing freshness policy. These are exactly the behavioral traits an agent needs before calling.

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

Conciseness5/5

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

The core action is front-loaded, followed by conditional behavior, side-effect exclusions, and re-registration semantics in four tight sentences. No filler and no repetition of schema or annotation content.

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

Completeness5/5

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

For a zero-required-param, two-parameter registration tool with no output schema, the description covers validation timing, side effects (no clone/fetch), visibility effects, idempotence, and alternative tools. An agent has everything needed to invoke it correctly and to route elsewhere when cloning is actually wanted.

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?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema: it explains what selecting local_path changes (reads use that clone rather than a mirror) and that the path is validated here, while the schema only says 'Path to an existing clone'. The project parameter's default behavior is left to the schema, which already covers it.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Register a project with this server') and immediately differentiates the two registration modes: local_path clone-backed vs. mirror-backed. The distinction from siblings (sync_repo, list_repos) is made explicit in the body, so an agent can place this tool without opening any schema.

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

Usage Guidelines5/5

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

States precisely when to supply local_path (read from an existing clone instead of a server-side mirror) and what happens without it (mirror-backed registration). It names the alternative for fetching ('use sync_repo for that, or simply read the project') and the update semantics for an already-registered project, leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

blameBlame a file at a refA
Read-only

Show who last touched each line of a file at a branch, tag, or commit — git blame --porcelain — without a working tree. Lines are grouped into runs from the same commit: a row is commit, author, date, line range, then the lines themselves, numbered. lines narrows the blame to a range ("118-126", or "118"), and a range past the end is clamped and reported rather than treated as an error. max_lines caps how many lines come back. The ref defaults to the repository's default branch, and the result states the commit it blamed and synced_at. A binary file is refused: git blames one, but its lines carry NUL bytes. Give either url — a GitLab /-/blame/<ref>/<path> link, whose #L12-20 anchor narrows the blame — or ref and path; the link's host must be GITLAB_HOST.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit to blame at, e.g. 'fix/PROJ-7608'. Defaults to the default branch.
urlNoA GitLab file link to blame, e.g. 'https://gitlab.example.com/group/repo/-/blame/develop/src/index.tsx#L12-20'. Replaces ref, path and lines; the host must be GITLAB_HOST.
pathNoFile path from the repository root, e.g. 'src/index.tsx'. Required unless `url` is given.
linesNoRestrict the blame to a line range: '118' or '118-126' (an `L` prefix is accepted, as in a `#L118-126` link). A `url` with an anchor wins over this.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
max_linesNoMaximum blamed lines to return (default 500). A capped answer says so.

TDQS

A4.6/5.0
Behavior5/5

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

With annotations only covering read-only/open-world hints, the description carries real behavioral weight: binary files are refused, out-of-range lines are clamped and reported rather than erroring, `max_lines` caps output, and the result reports the blamed `commit` and `synced_at`. This is exactly the extra context annotations don't provide.

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 core purpose and output row shape are front-loaded, and each subsequent sentence (clamping, max_lines, binary refusal, input modes) earns its place. It is dense and runs long, but no sentence is filler.

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

Completeness5/5

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

With no output schema, the description steps up to describe the return shape (commit, author, date, line range, then numbered lines) plus the reported `commit`/`synced_at`. Combined with the documented input modes and edge-case behavior, an agent has everything needed to call it correctly.

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?

Schema coverage is 100%, so the baseline is 3, but the description adds genuine meaning beyond the schema: the clamping/reporting behavior for `lines`, the precedence of a URL anchor over `lines`, and the interaction where `url` replaces ref/path/lines. It stops short of 5 only because the schema already documents formats.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource — showing per-line last-touch authorship of a file at a ref — and pins it to `git blame --porcelain`. It is clearly distinguishable from siblings like `log`, `diff_file`, and `get_file` by its line-level authorship semantics and 'without a working tree' framing.

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

Usage Guidelines4/5

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

It gives clear invocation context: default ref is the default branch, and you supply either `url` (with `#L12-20` anchor narrowing) or `ref`+`path`. However, it never explicitly contrasts when to choose this over `log`, `pickaxe`, or `diff_file`, so it stops short of full alternative routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compareCompare two refsA
Read-only

Summarise what changed on to since it split from from — git diff <merge-base> <to> — as one row per file: git's status letter (A, M, D, R091 old -> new) and ± counts, or binary. The merge_base is printed, so which diff ran is never hidden; merge_base: false asks for the raw two-dot diff instead, and when the two refs share no history the two-dot diff runs with merge_base="none". This never returns a patch — a branch diff is unbounded — so the file list is capped by max_files and a capped answer says so. Use diff_file for one file's patch, passing a printed merge_base as from for the branch view of it. path is a git pathspec, and it narrows rename detection with it: a rename can then appear as a delete and an add. Both refs are resolved before the diff and both commits are stated in the result, with synced_at.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesThe ref to compare to — whose changes are summarised, e.g. 'fix/PROJ-7608'.
fromYesThe ref to compare from — what the split is measured from, e.g. 'develop' or a commit sha.
pathNoA git pathspec to narrow the comparison, e.g. 'src/'. Note that it narrows rename detection too.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
max_filesNoMaximum changed files to list (default 100). Totals still cover every file; a capped answer says so.
merge_baseNoDiff from the merge base of the two refs (default true). Set false for the raw two-dot diff — 'what would applying this do'.

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, so safety is covered; the description adds non-obvious behaviour instead: it never returns a patch because branch diffs are unbounded, the file list is capped by `max_files` and a capped answer is labelled as such, the `merge_base` used is printed, and both resolved commits plus `synced_at` appear in the result. These are real operational traits an agent cannot get from the 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?

Front-loaded with the core operation and output format before the caveats, and essentially every sentence carries information. It is a dense single paragraph with several interleaved concerns (capping, rename narrowing, no-history case), which costs some scannability but no obvious filler.

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

Completeness5/5

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

There is no output schema, so the description must carry the return contract — and it does: per-file status letters (`A`/`M`/`D`/`R091 old -> new`), ± counts, `binary`, printed `merge_base`, resolved commits and `synced_at`. Combined with the cap semantics and sibling routing, an agent has everything needed to call and interpret this tool.

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?

Schema coverage is 100%, so the baseline is 3; the description earns an extra point by explaining consequences the schema only hints at — that narrowing with `path` can turn a rename into a delete plus an add, and that a `merge_base="none"` result signals unrelated histories. The `merge_base` toggle is largely restated from the schema, keeping this short of a 5.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource — summarise what changed on `to` since it split from `from` — and pins down the exact git operation (`git diff <merge-base> <to>`) and output shape (one row per file with status letter and ± counts). It also differentiates itself from the sibling `diff_file`, so an agent can pick between them without opening either schema.

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

Usage Guidelines5/5

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

Explicitly routes the agent: use `diff_file` for a single file's patch, and pass a printed `merge_base` as `from` to get the branch view of it. It also states the conditions that change behaviour (`merge_base: false` for the raw two-dot diff, no shared history ⇒ two-dot with `merge_base="none"`), leaving nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diff_fileDiff one file between two refsA
Read-only

The unified diff of one file between two refs — git diff -M <from> <to> -- <path> — without a working tree. The caller names the file and the diff is scoped before git runs, so nothing is found by parsing a patch header. context sets the lines shown around each hunk (default 3, 0-10) and max_bytes caps the diff. Scoping by path narrows rename detection, so a renamed file is read as an added (or deleted) file. The two refs are a raw two-dot diff: pass a merge_base printed by compare as from for the branch view of one file. A file that is unchanged between the refs yields no diff, and one absent from both is reported as not found. A binary file is refused: git has only a "Binary files … differ" line for it, which is not a patch.

ParametersJSON Schema
NameRequiredDescriptionDefault
toYesThe ref to diff to, e.g. 'fix/PROJ-7608'.
fromYesThe ref to diff from, e.g. 'develop' or a commit sha.
pathYesFile path from the repository root, e.g. 'src/index.tsx'.
contextNoLines of context on each side of a hunk (default 3, at most 10). Use 0 for the fewest lines.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
max_bytesNoByte cap for the patch (default 200000). A cut patch is marked in the result.

TDQS

A4.6/5.0
Behavior5/5

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

With annotations only covering readOnly/openWorld, the description adds substantial behavioral detail: path scoping is applied before git runs, rename detection is narrowed so renames read as add/delete, unchanged files yield no diff, absent files are reported not found, and binary files are refused because git emits no patch. These are exactly the edge cases an agent must anticipate.

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?

Front-loaded first sentence gives purpose and command form, and the remaining sentences each carry an edge case rather than filler. It is dense but slightly long, with some detail (e.g. restating context default) that the schema already supplies.

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

Completeness5/5

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

No output schema exists, yet the description explains the meaningful result states (patch, empty diff, not-found, binary refusal) and the safety profile is covered by annotations. An agent has everything needed to call it correctly across the 6-param surface.

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?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning to `from`/`to` (raw two-dot diff; merge_base from `compare`) and to how `context` and `max_bytes` shape the patch. The context default/range restates the schema, but the ref semantics elevate it above the baseline.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('The unified diff of one file between two refs') plus the exact underlying command, and distinguishes the scope from siblings like compare and get_file. An agent can tell it produces a patch for a single named path rather than a ref comparison or file read.

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

Usage Guidelines4/5

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

Gives clear operative guidance: pass a `merge_base` printed by `compare` as `from` for a per-file branch view, and explains the consequences of path scoping (narrowed rename detection). It references the `compare` sibling but does not explicitly say when to prefer this over `compare`/`get_file` for other tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_commitRead one commitA
Read-only

Read one commit — its sha, parents, author and committer with dates, and full message — then the files it changed with git's status letter (A, M, D, R091 old -> new) and their line counts, or binary. rev accepts a full or abbreviated sha, or a branch or tag. patch: true appends the unified diff, capped by max_bytes. A merge commit reports merge="true" and no file list, because git shows no diff for a merge by default: compare a parent with the commit to see what it brought in. The result states the commit it resolved rev to and synced_at. Give either url — a GitLab /-/commit/<sha> link — or rev; the link's host must be GITLAB_HOST.

ParametersJSON Schema
NameRequiredDescriptionDefault
revNoThe commit to read: a full or abbreviated sha, or a branch or tag name that resolves to one. Required unless `url` is given.
urlNoA GitLab commit link, e.g. 'https://gitlab.example.com/group/repo/-/commit/8297d0da'. Replaces rev; the host must be GITLAB_HOST.
patchNoAppend the commit's unified diff. Default false: metadata and the file list only.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
max_bytesNoByte cap for the patch when `patch` is set (default 200000). A cut patch is marked in the result.

TDQS

A4.3/5.0
Behavior4/5

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

Annotations only declare readOnlyHint and openWorldHint, so the description adds real behavioral context: merge commits report merge="true" with no file list, patches are capped and marked when cut, and the result states the resolved commit and synced_at. No contradictions with the read-only annotation.

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?

Dense but front-loaded, leading with what the commit read returns before the parameter guidance and merge caveat. Every sentence carries information, though the run-on style packs several distinct ideas into long clauses.

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?

With no output schema, the description correctly carries the burden of describing the return shape (commit metadata, file list with status letters, merge marker, synced_at). It is nearly complete for the tool's complexity, with only minor gaps such as pagination or error behavior.

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?

Schema coverage is 100% so the baseline is 3, but the description still adds meaning beyond the schema: rev accepts full/abbreviated sha or branch/tag, url must have a GITLAB_HOST host, and patch appends a unified diff capped by max_bytes with cut patches flagged.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (read) and resource (one commit) and enumerates exactly what is returned: sha, parents, author/committer with dates, message, and changed files with status letters and line counts. This clearly differentiates it from list-oriented siblings like log and list_tree.

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

Usage Guidelines4/5

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

Explains the url-vs-rev choice ("Give either `url` ... or `rev`") and points to the alternative for merges ("compare a parent with the commit to see what it brought in"). It names the sibling compare implicitly but does not spell out general when-not-to-use cases beyond merges.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_fileRead a file at a specific refA
Read-only

Return the contents of a file at a given branch, tag, or commit WITHOUT checking it out. Use this to inspect files on a branch other than the one currently checked out. Give either url — a GitLab web link, whose #L12-20 line anchor is honoured — or both ref and path. The repository is mirrored locally on first use and refreshed when it goes stale, or, for a project registered with add_repo, read from your own clone. The result reports the resolved commit and the last sync time. If the copy cannot be refreshed, the cached copy answers and the result says the refresh failed.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit SHA, e.g. 'develop' or 'fix/PROJ-7608'. Required unless `url` is given.
urlNoA GitLab web link, e.g. 'https://gitlab.example.com/group/repo/-/blob/develop/src/index.tsx#L12-20'. Replaces ref, path and (usually) project; the host must be GITLAB_HOST.
pathNoFile path inside the repository, forward slashes, e.g. 'src/index.tsx'. Required unless `url` is given.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT, or to the URL's project.
max_bytesNoMaximum bytes of content to return (default 200000). Ignored when a line range is asked for, which needs the whole file.

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only carry readOnlyHint=true and openWorldHint=false; the description goes well beyond that by disclosing the mirror-on-first-use / refresh-when-stale model, the add_repo clone path, the stale-cache fallback when refresh fails, and that the result reports the resolved commit and sync time. This is exactly the extra behavioral context the annotations cannot supply, and it is consistent with openWorldHint=false.

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 scope constraint is front-loaded, and each subsequent sentence carries distinct information (addressing modes, the mirror lifecycle, the failure fallback). A few sentences are dense and could be split, but there is no filler or repetition.

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 no output schema, the description usefully sketches the return payload (resolved commit, last sync time) and the degraded-refresh case, and it covers all five parameters' roles. A fully 5 definition might specify the content/encoding shape or the error behaviour when neither url nor ref+path is supplied, but the critical calling information is present.

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?

Schema coverage is 100%, so baseline is 3, but the description adds genuine semantics: the `url` alternative to `ref`+`path`, that a `#L12-20` line anchor is honoured, that the URL usually overrides project, and that project falls back to GITLAB_DEFAULT_PROJECT or the URL's project. It does not explain max_bytes interaction beyond what the schema already says.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource ('Return the contents of a file at a given branch, tag, or commit') and adds the differentiator 'WITHOUT checking it out', which separates it from diff_file, list_tree, and get_commit. An agent can pick this tool out of the sibling list without opening a schema.

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

Usage Guidelines4/5

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

Gives a clear operative condition: 'Use this to inspect files on a branch other than the one currently checked out.' It also explains how to address the file (url vs ref+path) and when the local mirror versus your own registered clone is used. It does not name a sibling alternative or state when NOT to use it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_refsList branches and tagsA
Read-only

List branch and/or tag names in a repository, without cloning it into a working tree. Each row is kind, short commit, name, and the tip commit's subject. The list reflects the local copy as of synced_at (by default at most 10 minutes old); a ref created since that moment may be missing, because a stale list cannot be detected. Use resolve_ref to check one specific ref, which does refresh on a miss. If the copy cannot be refreshed, the cached copy answers and the result says the refresh failed.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindNoWhich refs to list: 'branches' (default), 'tags', or 'all'.
searchNoCase-insensitive substring filter on the ref name, e.g. 'PROJ' or 'fix/'.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
max_refsNoMaximum refs to return (default 200).

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only declare readOnlyHint/openWorldHint; the description adds substantial non-obvious behavior: results reflect a local copy as of `synced_at` (default ≤10 min old), newly created refs may be missing, staleness is undetectable, and on refresh failure the cached copy answers and the result flags the failure. That is exactly the kind of operational context structured fields cannot carry.

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?

Front-loaded with purpose and output shape, then caveats in decreasing priority. Dense but almost every clause carries real information; the staleness/failure explanation is slightly verbose but justified given no output schema.

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

Completeness5/5

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

With no output schema, the description compensates by specifying the returned row fields (kind, short commit, name, tip subject) and the freshness/failure semantics. An agent has everything needed to call it and interpret results.

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

Parameters3/5

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

Schema description coverage is 100%, so all four parameters (kind, search, project, max_refs) are already documented in the schema. The description adds no syntax or default detail beyond it, so the baseline 3 applies.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List branch and/or tag names in a repository') plus the defining scope qualifier 'without cloning it into a working tree', which distinguishes it from file/tree siblings like list_tree and get_file. It even describes the row shape, so an agent knows exactly what comes back.

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

Usage Guidelines5/5

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

Explicitly routes the agent to the sibling alternative: 'Use `resolve_ref` to check one specific ref, which does refresh on a miss.' This gives a clear when-to-prefer-the-other-tool condition rather than leaving the choice to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_reposList known repositoriesA
Read-only

List the repositories this server knows about, with the freshness policy applied to each and when it last synced successfully. Each row is the project path followed by source (mirror or local), freshness (ttl, always or manual), ttl, clone_strategy=<value>(unsupported) when the registration names a strategy this server does not implement (only full is; such a project refuses to be read until it is re-cloned), present (whether the data is on disk), local_path for a local clone, and synced_at, or unknown when it has never synced. A mirror-backed project is registered the first time it is used; add_repo registers one before that, and is also how a project is pointed at an existing local clone. freshness=manual means nothing refreshes it by itself: use sync_repo.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

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

With annotations already declaring readOnlyHint and openWorldHint=false, the description adds substantial operational context: freshness semantics (ttl/always/manual), the fact that manual entries never self-refresh, that unsupported clone_strategy makes a project refuse to be read until re-cloned, and that synced_at may be 'unknown'. This is behavior an agent cannot infer from the 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 output-column enumeration is dense but front-loaded with purpose, and each column row earns its place given there is no output schema. Slightly long, but no clearly redundant sentences.

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

Completeness5/5

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

There is no output schema, so the description compensates by documenting the full row layout (path, source, freshness, ttl, clone_strategy, present, local_path, synced_at). Combined with the freshness and re-clone caveats, it is complete enough for an agent to call and interpret the result correctly.

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?

The tool takes zero parameters, so the schema carries no semantic burden; the baseline for a 0-param tool is 4. The description instead spends its budget on return-shape semantics, which is appropriate but not a parameter concern.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('List the repositories this server knows about') and immediately scopes it with the freshness policy and sync state, which no sibling does. It also contrasts with add_repo and sync_repo, letting an agent place it among the siblings without opening a schema.

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

Usage Guidelines4/5

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

Gives clear routing context: add_repo registers a mirror-backed project before first use or points at an existing clone, and freshness=manual cases should be refreshed via sync_repo. There is no explicit 'use list_repos when X vs Y' statement, so it stops short of full when/when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_treeList a directory at a refA
Read-only

List the files and subdirectories at a given ref, one level deep by default; set recursive to walk the whole subtree. Files carry their size in bytes, so you can tell a small config from a bundle before reading it. Names are full paths relative to the repository root. Give either url — a GitLab tree link — or ref (and optionally path). Everything comes from git, so no file is fetched to answer this. If the copy cannot be refreshed, the cached copy answers and the result says the refresh failed.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit SHA, e.g. 'develop' or 'fix/PROJ-7608'. Required unless `url` is given.
urlNoA GitLab tree link, e.g. 'https://gitlab.example.com/group/repo/-/tree/develop/src'. Replaces ref, path and (usually) project; the host must be GITLAB_HOST.
pathNoDirectory inside the repository, forward slashes, e.g. 'src'. Defaults to the repository root.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT, or to the URL's project.
recursiveNoList every file in the subtree instead of just the immediate children (files only).
max_entriesNoMaximum entries to return (default 200).

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnlyHint and openWorldHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: everything is answered from git with no file fetched, and a stale-cache fallback where the result flags a failed refresh. This is genuinely useful operational detail.

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?

Front-loaded with the core action and default depth, then parameter selection, then behavior. Every sentence carries information; the length is justified by the six parameters and caching nuance, though it is denser than strictly necessary.

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?

With no output schema, the description carries the return-value burden, and it does explain that results carry sizes and repo-root-relative full paths. Ordering and pagination behavior beyond the max_entries default are not covered, leaving a minor gap for a listing tool.

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?

Schema coverage is 100%, so the baseline is 3. The description goes further by clarifying relationships the schema does not: url replaces ref/path/project, names are full paths relative to repo root, and size is in bytes. That adds meaning beyond the per-field descriptions.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb (list) on a specific resource (files and subdirectories at a ref) and states scope precisely: 'one level deep by default; set recursive to walk the whole subtree.' This clearly separates it from read-oriented siblings like get_file and log without needing to name them.

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

Usage Guidelines4/5

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

It gives concrete selection guidance: use url OR ref (plus optional path), and use recursive only when you want the whole subtree. The remark that sizes let you 'tell a small config from a bundle before reading it' implies using this before get_file. It stops short of explicit when-not or naming alternative siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

logList commits at a refA
Read-only

List commits on a branch, tag, or commit — git log — newest first, without cloning it into a working tree. Each row is commit, date, author, subject, and a merge commit carries (merge). The ref defaults to the repository's default branch, is resolved before the walk, and the result states the commit it walked and synced_at. path is a git pathspec, so globs work — and history stops at a rename, because git's --follow accepts only one path and walks renames backwards; pass the new name or use get_commit when you need to see the rename itself. limit bounds the answer; when it hides older commits the result says so rather than inventing a total. Use get_commit on a row's full sha to see what it changed. Give either url — a GitLab /-/commits/<ref>[/<path>] link, e.g. 'https://gitlab.example.com/group/repo/-/commits/fix/PROJ-7608/src/index.tsx' — or ref and path; the link's host must be GITLAB_HOST.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit whose history to walk, e.g. 'fix/PROJ-7608'. Defaults to the default branch.
urlNoA GitLab history link, e.g. 'https://gitlab.example.com/group/repo/-/commits/develop'. Replaces ref and path; the host must be GITLAB_HOST.
pathNoA git pathspec to limit the walk, e.g. 'src/components/*.tsx'. History stops at a rename: a file's earlier names are not followed.
limitNoMaximum commits to return (default 20). A capped answer says so.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.

TDQS

A4.8/5.0
Behavior5/5

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

With readOnlyHint/openWorldHint already covering the safety profile, the description adds real behavioral context: no working-tree clone, ref resolution before the walk, the result reporting the walked commit and `synced_at`, truncation being disclosed rather than a fabricated total, and the rename termination behavior of `path`.

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?

Front-loaded with the core action and return shape, and every sentence carries information; the caustic details (rename stop, limit honesty) earn their place. It is dense, with several clauses packed per sentence, which slightly taxes readability but adds no filler.

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

Completeness5/5

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

There is no output schema, so the description supplies the return shape itself (commit, date, author, subject, `(merge)` marker) plus the `synced_at`/walked-commit metadata. Combined with 100% parameter coverage, an agent has everything needed to invoke and interpret this tool.

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?

Schema coverage is 100%, so the baseline is 3, but the description goes further: it gives the concrete `/-/commits/<ref>[/<path>]` link shape with a full example for `url`, notes `url` replaces `ref` and `path`, and explains the glob/rename semantics of `path` and the capping behavior of `limit`.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource ('List commits on a branch, tag, or commit'), names the git equivalent, and specifies ordering ('newest first') and the no-clone execution model. It is clearly distinguishable from siblings get_commit (what a single commit changed) and blame/list_tree.

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

Usage Guidelines5/5

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

Explicitly routes to alternatives: 'Use `get_commit` on a row's full sha to see what it changed' and 'use `get_commit` when you need to see the rename itself.' It also states the two mutually exclusive input forms (either `url`, or `ref` and `path`) and their constraints.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

parse_gitlab_urlParse a GitLab web URLA
Read-only

Turn a GitLab web link into the project, ref, path and line range a read needs — including a ref that contains slashes, which is resolved against the project's own refs. Accepts /-/blob/, /-/raw/, /-/tree/ and /-/blame/ links, which name a file or a directory, and /-/commit/ and /-/commits/[/], which name a commit and a history; merge request and other links are refused by name rather than guessed at. The link's host must be GITLAB_HOST. Resolving may mirror the project on first use; set resolve: false to parse offline without touching it. get_file, list_tree, log, get_commit and blame accept a url directly, so this tool is for inspecting a link, not for reading.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesThe GitLab web link, e.g. 'https://gitlab.example.com/group/repo/-/blob/fix/PROJ-7608/src/index.tsx#L12-20'.
resolveNoMatch the link's ref against the project's refs and resolve it to a commit (default true). Set false to split the ref at the first segment without touching the project.

TDQS

A4.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered structurally. The description nonetheless adds real behavioral context: the host must be GITLAB_HOST, resolving may mirror the project on first use, and `resolve: false` avoids touching it. It does not describe the shape of the returned object (project/ref/path/line range are only implied), so it adds value but stops short of full behavioral disclosure.

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?

Front-loaded with the core transformation in the first clause, and every sentence carries non-redundant information (link types, refusals, host constraint, mirroring, plus the sibling hand-off). Sentences are long and clause-heavy, which costs some scannability but not correctness.

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

Completeness5/5

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

No output schema exists, and the description compensates by naming what is extracted (project, ref, path, line range) and what happens on rejection. With the host/mirroring constraints and offline option covered, an agent has enough to call it correctly.

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?

Schema coverage is 100%, so the baseline is 3; the description adds meaning beyond the schema by explaining that refs containing slashes are resolved against the project's own refs, which clarifies the hard case the two schema lines only gesture at. It does not add syntax detail for the base url parameter, so it falls short of 5.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Turn a GitLab web link into the project, ref, path and line range') and enumerates exactly which URL shapes it handles. It distinguishes itself from siblings by naming get_file, list_tree, log, get_commit and blame and clarifying they accept a url directly, so an agent can route without opening schemas.

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

Usage Guidelines5/5

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

Gives explicit when-to-use ('for inspecting a link, not for reading') and when-not-to-use, plus an inbound filter: which GitLab link types are accepted versus refused ('merge request and other links are refused by name rather than guessed at'). It also states the host precondition and the offline escape hatch.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pickaxeFind commits that changed a stringA
Read-only

Find the commits whose diff changed how often a piece of text appears — git log -S — so you can answer "when was this introduced, and by whom?". Each row is commit, date, author, subject, most recent first. The text is matched literally and case-insensitively, as search matches it, so a pickaxe never reports "nothing changed" about text the caller can see. Unlike search this walks the history of the ref and is therefore slower; pair it with search to go from "where is it" to "when did it appear". The ref defaults to the repository's default branch, and path is a git pathspec.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoBranch, tag, or commit whose history to walk. Defaults to the default branch.
pathNoA git pathspec to limit the search, e.g. 'src/components'.
limitNoMaximum commits to return (default 20).
queryYesExact text to follow through history, e.g. 'orderTotals'.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
case_sensitiveNoFollow the text case-sensitively. Default false: history is followed by case too.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations cover the safety profile (readOnlyHint=true, openWorldHint=false), and the description adds matching semantics (literal, case-insensitive, consistent with `search`), the ref default (repository default branch), result ordering (most recent first), and the relative cost versus `search`. These are concrete behavioral traits beyond the structured fields.

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

Conciseness5/5

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

Front-loads the core behavior in the first clause, then layers return shape, matching semantics, cost/comparison to sibling, and argument defaults. Every sentence carries distinct information despite the length.

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

Completeness5/5

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

With no output schema, the description still specifies the row shape (`commit`, `date`, `author`, subject) and ordering, so an agent knows what comes back. Combined with the annotations and full schema coverage, nothing needed to invoke it correctly is missing.

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?

Schema coverage is 100%, so the baseline is 3; the description adds value by clarifying that matching is literal and case-insensitive consistent with `search`, which explains `case_sensitive`'s default behavior, and by restating ref/path semantics in workflow terms. It does not document `limit` or `project` beyond the schema, so it is not fully additive.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb+resource: finding commits whose diff changed the occurrence count of a piece of text, with the git analogue (`git log -S`) and the user-facing question it answers. It explicitly distinguishes itself from the `search` sibling, so an agent can select between them without opening either schema.

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

Usage Guidelines5/5

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

Gives explicit when-to-use and the routing rule: use `search` to find where text is, use this to find when it appeared, and pair them. It also warns that this walks history and is slower, which is exactly the exclusion criterion an agent needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

remove_repoForget a repositoryA
Destructive

Forget a project's registration. With delete_mirror, the server-side mirror is deleted as well — but only a mirror: a registered local clone is never touched, and the request is reported as ignored. Forgetting a mirror-backed project is not permanent, since the next read registers it again and clones it again if the mirror was deleted. Forgetting a local registration is how a project goes back to being read from a mirror.

ParametersJSON Schema
NameRequiredDescriptionDefault
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.
delete_mirrorNoAlso delete the cached mirror for this project. Never deletes a local clone. Defaults to false, which forgets the project and leaves the data on disk.

TDQS

A4.2/5.0
Behavior5/5

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

Beyond the annotations' destructiveHint=true, it discloses exactly what is destroyed (server-side mirror only; local clone never touched), that the request may be silently 'reported as ignored', and that mirror-backed forgetting is not permanent because the next read re-registers and re-clones. This is rich operational detail an agent cannot get from the 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 core action is front-loaded in the first sentence, and every following clause carries a distinct behavioral fact (mirror scope, ignored request, re-registration, local→mirror revert). The dense em-dash constructions make it slightly heavier than necessary, but nothing is padding.

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?

For a mutation tool with no output schema, the description covers the important semantics: what gets deleted, what is immune, idempotency/reversibility. It does not mention permission or authentication requirements, which is the only notable gap.

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?

Schema coverage is 100%, so baseline is 3, but the description adds meaning beyond the schema: delete_mirror's effect is non-permanent (re-created on next read) and applies only to mirrors, while omitting it reverts a local registration to mirror-backed reading.

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 gives a specific verb+resource ('Forget a project's registration') and immediately clarifies the scope of what is and isn't removed, which no sibling tool covers. It doesn't explicitly name add_repo/list_repos as counterparts, so it is clear but not sibling-routed.

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

Usage Guidelines4/5

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

It explains clearly what delete_mirror does and when forgetting is reversible versus how a local registration is switched back to mirror-backed reading, giving real context for choosing the flag. It stops short of an explicit when-to-use-this-instead-of alternative (e.g. add_repo, sync_repo).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resolve_refResolve a ref to a commitA
Read-only

Resolve a branch, tag, or revision to the full commit SHA it points at, and say what it is (branch, tag, or commit for anything else). Use this to confirm a ref exists before reading files from it. If the ref is missing, the error lists similar names, and it says so when the copy could not be refreshed, since then a missing ref proves nothing.

ParametersJSON Schema
NameRequiredDescriptionDefault
refYesBranch, tag, or commit SHA, e.g. 'develop' or 'fix/PROJ-7608'.
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuinely non-derivable behavior: missing refs produce an error that 'lists similar names,' and a stale working copy is flagged so that 'a missing ref proves nothing.' That stale-data caveat is exactly the kind of context that prevents a wrong conclusion, though nothing is said about auth or rate limits.

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?

Two sentences, front-loaded with what the tool returns before the usage advice, and every clause carries information. The final sentence is somewhat dense ('and it says so when the copy could not be refreshed') but still earns its place by qualifying the error semantics.

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?

For a two-parameter read tool with no output schema, the description covers purpose, when to call it, the shape of the return value, and error behavior. With annotations handling the safety profile and the schema handling parameter docs, it is close to complete; only the absence of any mention of alternative ref-listing tools is a minor gap.

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

Parameters3/5

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

Schema description coverage is 100%, with the ref format and an example ('develop', 'fix/PROJ-7608') and the project path fallback to GITLAB_DEFAULT_PROJECT already documented in the schema. The description adds no syntax, format, or default information beyond that, so the baseline 3 applies.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('resolve'), the resource ('a branch, tag, or revision'), and the exact output ('the full commit SHA it points at', plus a type label of branch/tag/commit). That scope clearly separates it from siblings like list_refs (enumerate) or get_commit (fetch metadata), so an agent can route correctly without opening the schema.

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

Usage Guidelines4/5

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

It gives an explicit use case: 'Use this to confirm a ref exists before reading files from it,' which tells the agent when this is the right call. It does not name an alternative or say when not to use it (e.g. vs. list_refs), so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sync_repoFetch a repository nowA

Fetch a project immediately, ignoring its freshness policy — the way to refresh a project whose policy is manual, and to check for new refs without waiting for the TTL. A mirror-backed project is cloned if its mirror is missing; a project registered as a local clone is fetched from that clone's own remote. Unlike a read, a failure is reported as an error rather than answered from the cached copy, because this call exists to fetch.

ParametersJSON Schema
NameRequiredDescriptionDefault
projectNoGitLab project path, e.g. 'group/subgroup/repo'. Defaults to GITLAB_DEFAULT_PROJECT.

TDQS

A4.3/5.0
Behavior5/5

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

Adds rich behavioral detail beyond the annotations: a mirror-backed project is cloned if its mirror is missing, a local clone is fetched from its own remote, and failures surface as errors rather than cached answers. This meaningfully explains the readOnlyHint=false mutating behavior and is exactly the kind of context annotations cannot carry.

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?

Front-loads the core action and keeps to three sentences, each carrying distinct information. Slightly dense and the final clause is somewhat circular ('this call exists to fetch'), but there is no wasted padding.

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?

For a mutation-flagged, open-world single-parameter tool with no output schema, the description covers trigger conditions, cache/failure behavior, and clone vs. mirror handling. It is close to complete; only return-value expectations remain implicit, which is acceptable given the tool's purpose.

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

Parameters3/5

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

Schema description coverage is 100% and the single `project` parameter (including its default) is fully documented in the schema. The description adds behavioral context but no syntax or format detail beyond what the schema already provides, so the baseline 3 applies.

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

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a project immediately, ignoring its freshness policy') and immediately contrasts the behavior with a cached read. An agent can distinguish this from read siblings like get_file or list_refs without opening either schema.

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

Usage Guidelines4/5

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

Explicitly names the conditions that select this tool: refreshing a project whose policy is `manual` and checking for new refs without waiting for the TTL. That is clear when-to-use guidance, though it routes by condition rather than naming a specific sibling alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 16 tool updatesv0.10.1
    • First observedadd_repo
    • First observedblame
    • First observedcompare
    • First observeddiff_file
    • First observedget_commit
    • First observedget_file
    • First observedlist_refs
    • First observedlist_repos
    • First observedlist_tree
    • First observedlog
    • First observedparse_gitlab_url
    • First observedpickaxe
    • First observedremove_repo
    • First observedresolve_ref
    • First observedsearch
    • First observedsync_repo

TDQS

A4.3/5.0

Scored across 16 tools

Disambiguation5/5

Each tool maps to a distinct git or repository-management operation; overlaps like log/get_commit/pickaxe and compare/diff_file are explicitly separated in descriptions. No two tools appear interchangeable.

Naming Consistency4/5

Mostly snake_case with a verb_noun pattern, but several tools are bare git terms (log, blame, compare, search, pickaxe) rather than verb_noun. Casing is consistent and names remain readable, so this is a minor deviation.

Tool Count4/5

16 tools is at the upper end of the ideal 3-15 range, but each adds a distinct capability for git inspection plus mirror administration. Slightly heavy, though still reasonable for the domain.

Completeness4/5

Covers file/tree reading, ref resolution, commit history/detail, blame, diff/compare, search, pickaxe, URL parsing, and mirror registration/sync. Minor gaps: no project discovery on GitLab and no MR/issue support, but the core read-only git surface is complete.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    A
    maintenance
    Enables AI-powered exploration and interaction with GitLab instances through comprehensive search, code browsing, and repository management. Supports both self-hosted and GitLab.com with flexible authentication for read and write operations.
    63
    48 npm
    12
    MIT
  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    Enables AI agents to interact with GitLab repositories, monitor documentation changes, manage issues and merge requests, and search across projects with comprehensive file and commit operations.
    -
  • A
    license
    Not graded
    quality
    F
    maintenance
    Enables AI agents to analyze local Git repositories with commit logs, diffs, blame, statistics, and branch analysis using native git commands without requiring a GitHub API.
    29 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to query and manage GitLab projects, issues, merge requests, and file contents via the GitLab REST API v4.
    8 npm
    MIT