Skip to main content
Glama

mcp-repo-tools

An MCP server that gives AI agents safe, structured access to a local git repository. It is built for code review: read files at any commit, search, diff a branch the way a pull request does, and (only if you opt in) run allowlisted test commands.

It's the foundation of a three-part series on production AI engineering in the code-review domain:

Repo

What it does

mcp-repo-tools (this)

MCP server: the agent's only window onto the repo

pr-review-agent

LangGraph.js agent that uses these tools to review a PR, with checkpointing and human approval

gameable-tests-bench

Tasks with deliberately weak tests, plus a grader that catches agents gaming them (hardcoding, over-mocking, etc.)

read_file · search_code · list_changed_files · get_diff · run_tests (opt-in)

Tools

Every tool validates its input with Zod and returns structuredContent that matches a published output schema, plus a compact text rendering for chat clients. Refs are resolved to full SHAs and echoed back, so a caller always knows exactly which commit it saw.

Tool

Purpose

Key inputs

read_file

Read a text file (or a line range) from the working tree or at any commit

path, ref?, startLine?, endLine?

search_code

git grep over tracked files: literal by default, optional regex, globs, context lines

query, regex?, caseSensitive?, pathGlobs?, ref?, contextLines?

list_changed_files

Cheap index of a change: status, renames, +/- counts, isBinary, isTest

base, head?, mode?, paths?

get_diff

Unified diff split per file, filled up to a byte budget; each omitted patch says why

base, head?, mode?, paths?, contextLines?, maxBytes?

run_tests

Run a pre-configured test target; returns exit code, timing and the tail of stdout/stderr

target, args?

mode defaults to merge-base (what a PR shows, i.e. base...head); direct compares the two commits as-is (base..head).

Errors come back as MCP tool errors (isError: true) with text CODE: message, where CODE is one of INVALID_INPUT, PATH_DENIED, NOT_FOUND, TOO_LARGE, INVALID_REF, TOOL_DISABLED, TIMEOUT, GIT_ERROR or INTERNAL. Inputs that fail the JSON schema itself are rejected by the SDK before reaching a tool, with an Input validation error message.

Related MCP server: Git Code Review MCP

Architecture

flowchart LR
  subgraph Clients
    CC[Claude Code / Desktop]
    AG[pr-review-agent]
  end

  CC -- stdio --> T1[StdioServerTransport]
  AG -- Streamable HTTP --> T2["HTTP /mcp<br/>Host/Origin check · bearer token"]

  T1 --> S[McpServer<br/>Zod in/out schemas]
  T2 --> S

  S --> RF[read_file]
  S --> SC[search_code]
  S --> LC[list_changed_files]
  S --> GD[get_diff]
  S -. "--allow-run-tests" .-> RT[run_tests]

  subgraph Policy["Policy layer (src/lib)"]
    P[RepoPaths<br/>containment · allow/deny globs]
    G[Git<br/>hardened · refs → SHAs]
    X[runProcess<br/>no shell · timeout · output caps · scrubbed env]
  end

  RF --> P
  RF --> G
  SC --> G
  SC --> P
  LC --> G
  GD --> G
  GD --> P
  RT --> X
  G --> X

  X --> R[(git repository)]
  P --> R

Tools are plain definitions (inputSchema, outputSchema, run, render) in src/tools/, so they're unit-tested without a server. All enforcement lives in src/lib/: every filesystem read goes through RepoPaths, every subprocess through runProcess.

Quick start

Requires Node ≥ 22.12, git ≥ 2.44 and pnpm. Linux or macOS.

git clone https://github.com/pshashanka/mcp-repo-tools && cd mcp-repo-tools
pnpm install && pnpm build
node dist/index.js --repo /path/to/your/repo   # speaks MCP on stdio

Claude Code

claude mcp add repo-tools -- node /abs/path/to/mcp-repo-tools/dist/index.js --repo /abs/path/to/repo

Or add a project-scoped .mcp.json to the repo you want reviewed (use absolute paths):

{
  "mcpServers": {
    "repo-tools": {
      "command": "node",
      "args": ["/abs/path/to/mcp-repo-tools/dist/index.js", "--repo", "/abs/path/to/repo"]
    }
  }
}

Then ask, for example: "Review the changes on this branch against main. Start with list_changed_files."

Claude Desktop

Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json, then restart Claude Desktop:

{
  "mcpServers": {
    "repo-tools": {
      "command": "node",
      "args": ["/abs/path/to/mcp-repo-tools/dist/index.js", "--repo", "/abs/path/to/repo"]
    }
  }
}

Over HTTP (for agents and services)

MCP_REPO_TOOLS_TOKEN=$(openssl rand -hex 32) \
  node dist/index.js --repo /path/to/repo --transport http --port 3333
# → serving /path/to/repo at http://127.0.0.1:3333/mcp

claude mcp add --transport http repo-tools http://127.0.0.1:3333/mcp \
  --header "Authorization: Bearer $MCP_REPO_TOOLS_TOKEN"

Binding beyond loopback (e.g. --host 0.0.0.0) requires MCP_REPO_TOOLS_TOKEN and at least one --allowed-host <name> for every hostname clients will send in their Host header.

Enabling run_tests

run_tests needs both the --allow-run-tests flag and targets in a config file you control:

node dist/index.js --repo /path/to/repo --config ./mcp-repo-tools.example.json --allow-run-tests

See mcp-repo-tools.example.json for the config format. Every key is optional.

CLI reference

--repo <path>        Repository to serve: the work tree root (default: current directory)
--config <file>      JSON config file (path policy, limits, test targets)
--allow-run-tests    Register the run_tests tool (needs targets in --config)
--transport <kind>   stdio (default) or http
--host <host>        HTTP bind address (default: 127.0.0.1)
--port <port>        HTTP port (default: 3333)
--allowed-host <name> Extra hostname accepted in Host/Origin (repeatable)
MCP_REPO_TOOLS_TOKEN If set, HTTP requests must send "Authorization: Bearer <token>"

Security model

The threat model has two untrusted parties: the repository (it may be a stranger's pull request) and the model (it reads that repository, so it can be prompt-injected by it). The server enforces its policy whatever the model asks for. Full details are in SECURITY.md; in summary:

  • Read-only by default. Four of the five tools only read. run_tests isn't even registered unless the operator passes --allow-run-tests and configures targets.

  • Path containment. Paths must be repo-relative; .., absolute paths and NUL bytes are rejected. Symlinks are followed and the real target is checked again, so a link can't reach outside the repo or reach a denied file.

  • Deny list. .git/ (including nested .git directories), .env*, private keys, .npmrc/.netrc, .envrc, .git-credentials, .aws/ and the like are never readable or searchable, in the working tree or at any commit. Matching is case-insensitive. Config can add to the deny list but can't remove the defaults. An optional allow list narrows things further.

  • Hardened git. No shell, ever: arguments are passed as an array. Refs that look like options are rejected and refs are resolved to SHAs once. Pathspecs are literal unless a glob is explicitly wanted. System/global git config is ignored; fsmonitor, hooks, external diff and textconv are disabled (a hostile .git/config can name programs for git to run). No optional locks, no lazy network fetches.

  • Bounded everything. Per-tool byte limits that a request can lower but never raise; git calls are killed once their output passes the cap; timeouts on every subprocess.

  • run_tests runs configured commands, not requested ones. The client chooses a target name from an enum; extra args must fully match an operator-supplied regex. The process gets a scrubbed environment (no tokens or cloud credentials), its own process group (a timeout kills grandchildren too) and a hard timeout. It is not a container: it runs the repository's code with your user's permissions. For untrusted code, run the server inside a container or VM.

  • HTTP. Binds to loopback; refuses other addresses without a token; constant-time token comparison; Host/Origin validation against DNS rebinding.

  • Config never comes from the served repo, so a PR can't widen its own permissions.

Design decisions

git is the source of truth. search_code is git grep and read_file --ref is git cat-file. That means no ripgrep dependency, .gitignore is respected without extra work, and every tool works at any commit, which matters when an agent needs the old version of a file to judge a change.

Refs in, SHAs out. A ref is validated and resolved once, and only SHAs reach later git commands. Outputs echo the resolved SHAs (base, head, mergeBase, ref), so pr-review-agent can checkpoint and resume against exactly the commits it reviewed even if the branch moves.

Pull-request semantics by default. get_diff and list_changed_files diff from the merge base, because a reviewer wants "what this branch changed", not "how it differs from main today".

A cheap index, then content. list_changed_files (with isTest and line counts) lets an agent plan before it spends tokens on patches. It's also how a test-coverage check asks "did tests change alongside the source?" without parsing diffs.

Budgets degrade per file, not mid-hunk. get_diff runs git once per file (bounded concurrency), which maps patches to files exactly even for odd filenames. It fills a byte budget with whole patches. Files that don't fit, are binary, or are denied stay in the list with patchOmitted set to the reason, so the agent can ask for them specifically. A half-truncated hunk is worse than none.

Names are metadata; contents are policy. A changed .env still appears in list_changed_files, because "this PR touches secrets" is exactly what a reviewer should flag. Its contents are never returned.

Structured output and readable text. Agents consume structuredContent; chat clients see a grep-style or unified-diff rendering rather than escaped JSON. Error codes go in the text (CODE: message) and not in structuredContent, because MCP clients validate structuredContent against the success schema even on errors.

A failing test run is a result, not an error. run_tests returns passed: false with the output. Only "couldn't run" is an error. Output keeps the tail, where failure summaries are. gameable-tests-bench relies on this stable shape to score runs.

One repo per server, stateless HTTP. There's no repo parameter, which keeps the containment model trivial; run one server per repo. HTTP creates a fresh server per request (the SDK's stateless pattern), so there is no session state to leak between callers.

Tools are data. defineTool({ inputSchema, outputSchema, run, render }) keeps the MCP wiring in one small file (src/server.ts), and every tool is tested by calling run directly against a real fixture repo. The fixture is built by a script at test time, so this repo contains no nested .git.

Known limitations

  • POSIX only (process groups, /dev/null for git config).

  • run_tests runs in the current working tree. Running at an arbitrary ref (in a temporary git worktree) is a planned opt-in.

  • search_code covers tracked files only, and its regexes are POSIX ERE, not PCRE.

  • TypeScript is pinned to 6.0 until typescript-eslint supports the 7.x native compiler.

Development

pnpm install
pnpm test        # Vitest: unit tests per tool and lib + MCP client integration tests
pnpm lint        # typescript-eslint, strict type-checked
pnpm typecheck
pnpm build
src/
  index.ts            CLI: flags → config → transport
  server.ts           createServer(config): registers tools on an McpServer
  config.ts           Zod config schema and defaults
  tools/              one file per tool, plus the defineTool type
  lib/                paths, git, exec, changes, truncate, errors: all the enforcement
  transports/         stdio, http
test/
  fixtures/           builds a PR-shaped git repo in a temp dir
  unit/               per tool and per lib module
  integration/        SDK Client ↔ server over in-memory, stdio and HTTP

CI (GitHub Actions) runs lint, format check, typecheck, tests and build on Node 22 and 24.

License

MIT

Available Tools

4 tools
get_diffGet diffA
Read-onlyIdempotent

Get the unified diff between two commits, split per file. Defaults to pull-request semantics (changes on head since it branched from base). Output is capped: files that don't fit have patchOmitted: "size_limit"; fetch them separately with paths.

ParametersJSON Schema
NameRequiredDescriptionDefault
baseYesBase ref, e.g. `main` or a SHA.
headNoHead ref. Defaults to HEAD.HEAD
modeNo`merge-base` diffs from where head branched off base (what a pull request shows, like `base...head`). `direct` diffs the two commits as they are (`base..head`).merge-base
pathsNoOnly include these files or directories (literal paths, not globs).
maxBytesNoTotal patch budget in bytes. Can't exceed the server's limit.
contextLinesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
baseYes
headYes
filesYes
mergeBaseYes
truncatedYesTrue if any patch was omitted for size.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds genuinely new behavior: output is size-capped, omitted files are flagged with `patchOmitted: "size_limit"`, and they can be retrieved with `paths`. That is real disclosure beyond the structured fields, though server-side limit details remain implicit.

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?

Three dense sentences, front-loaded with the core action, then the default semantics, then the truncation escape hatch. 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?

An output schema exists, so return values need not be re-explained; nonetheless the description covers the partial-output edge case that matters most for correct invocation. Nothing an agent needs to call this 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 83%, so baseline is 3. The description adds cross-parameter meaning the schema doesn't: the `base`/`head` pair defaults to PR-style comparison, and `paths` is framed as the recovery mechanism for omitted files rather than just a filter.

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 ('Get the unified diff between two commits, split per file') and immediately clarifies scope with the pull-request default. This is clearly distinguishable from read_file, search_code, and list_changed_files.

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 default mode (PR semantics) and tells the agent what to do when output is truncated (fetch omitted files via `paths`). It stops short of naming sibling alternatives or stating when-not to use this tool, but the situational context is clear.

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

list_changed_filesList changed filesA
Read-onlyIdempotent

List files changed between two commits, with status, line counts, and whether each file is a test (by the server's test globs). Cheap; call this before get_diff to decide what to read. Paths of changed files are always listed, even ones whose contents the path policy hides.

ParametersJSON Schema
NameRequiredDescriptionDefault
baseYesBase ref, e.g. `main` or a SHA.
headNoHead ref. Defaults to HEAD.HEAD
modeNo`merge-base` diffs from where head branched off base (what a pull request shows, like `base...head`). `direct` diffs the two commits as they are (`base..head`).merge-base
pathsNoOnly include these files or directories (literal paths, not globs).

Output Schema

ParametersJSON Schema
NameRequiredDescription
baseYesResolved base SHA.
headYesResolved head SHA.
filesYes
mergeBaseYesMerge-base SHA in `merge-base` mode, else null.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive, closed-world behavior, so the bar is lower; the description still adds real value by disclosing the path-policy interaction ('Paths ... are always listed, even ones whose contents the path policy hides') and the cost profile. It does not mention pagination or limits on large change sets, which is the remaining gap.

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?

Three short sentences, front-loaded with the core purpose, then the activation cue, then the policy caveat. Every sentence carries distinct information with no repetition of the schema or annotations.

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?

An output schema exists, so return values need not be spelled out, yet the description still summarizes them plus a caveat the schema cannot express. For a read-only four-parameter listing tool, an agent has everything needed to invoke and interpret it correctly.

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 base, head, mode, and paths are already fully documented in the schema. The description only implies the two-commit comparison and does not expand on the merge-base vs direct mode distinction or path filtering, so 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 files changed between two commits') and enumerates the returned fields (status, line counts, test flag), so the agent knows exactly what it gets. It also names the sibling get_diff, distinguishing this cheap listing tool from the content-reading one.

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 an explicit sequencing rule: 'call this before get_diff to decide what to read', which routes the agent between the two siblings on a clear condition. The cost note ('Cheap') supplies the rationale for preferring this over fetching diffs outright.

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

read_fileRead fileA
Read-onlyIdempotent

Read a text file from the repository, optionally a line range, either from the working tree or at a specific commit (ref). Use ref to compare a file before and after a change. Output is capped; if truncated is true, request a later startLine.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoCommit, branch or tag to read from. Omit to read the working tree.
pathYesRepo-relative path, e.g. `src/index.ts`.
endLineNoLast line to return (inclusive).
startLineNoFirst line to return (1-based).

Output Schema

ParametersJSON Schema
NameRequiredDescription
refYesResolved commit SHA, or null for the working tree.
pathYes
contentYes
endLineYesLast line actually returned.
isBinaryYes
startLineYes
truncatedYes
totalLinesYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent and non-destructive, so safety is covered. The description adds real behavioral context the annotations lack: output is capped, a `truncated` flag is returned, and the caller should re-request with a later `startLine`. It omits error behavior (missing path, binary files), which keeps it below a 5.

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?

Two sentences, zero filler, and the most important scoping fact (working tree vs. ref) is front-loaded. Every clause carries information the caller needs.

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?

An output schema exists so return values need not be spelled out, and the description covers the one non-obvious runtime behavior (capping and the `truncated` recovery path). Nothing required to call 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 description coverage is 100%, so the baseline is 3. The description adds semantics beyond the schema by explaining what `ref` is for (comparing a file before and after a change) and by tying `startLine` to the truncation-recovery loop, which the schema's bare 'First line to return' does not convey.

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?

States a specific verb+resource ('Read a text file from the repository') plus the two axes of scope: working tree vs. a specific commit, and an optional line range. It implicitly separates itself from search_code and get_diff by framing ref as a way to see a file's state rather than a change set, though it never names a sibling explicitly.

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?

'Use `ref` to compare a file before and after a change' gives a concrete usage condition, and the truncation sentence tells the agent how to recover. It lacks explicit exclusions or named alternatives (e.g., 'use search_code to find a file'), 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.

search_codeSearch codeA
Read-onlyIdempotent

Search tracked files for a string or regex (git grep). Searches the working tree by default, or a specific commit with ref. Binary files and files hidden by the server's path policy are skipped. Prefer a literal query; set regex for POSIX extended regular expressions.

ParametersJSON Schema
NameRequiredDescriptionDefault
refNoCommit, branch or tag to search. Omit for the working tree.
queryYes
regexNoTreat `query` as a POSIX extended regex.
pathGlobsNoOnly search matching paths, e.g. `src/**/*.ts`. `*` does not cross `/`.
maxResultsNo
contextLinesNo
caseSensitiveNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
refYesResolved commit SHA, or null for the working tree.
matchesYes
truncatedYesTrue if there were more matches than were returned.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations cover safety (read-only, idempotent, non-destructive). The description adds useful behavioral context: binary files are skipped, and files hidden by the server's path policy are skipped. It omits result limits/pagination behavior, but the output schema likely covers returns.

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?

Three tight sentences, front-loaded with purpose and scope, then edge-case behavior, then usage advice. No filler.

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 7-parameter search tool with an output schema, the description covers purpose, default scope, filtering skips, and regex guidance. It could do more on pathGlobs/maxResults/contextLines, but the schema and output schema shoulder much of that burden.

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 coverage is 43%, but the description adds meaning for `ref` and `regex` and establishes the default search target. Other parameters (pathGlobs, maxResults, contextLines, caseSensitive) are not explained in the description, leaving gaps relative to the low coverage.

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 (search tracked files) with the underlying mechanism (git grep) and scope (working tree vs. commit). This clearly distinguishes it from siblings like read_file, list_changed_files, and get_diff, which do not perform content search.

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?

Clarifies default behavior (working tree) vs. using `ref`, and gives a preference rule (literal query, set regex for POSIX ERE). It does not explicitly name alternative sibling tools or state when-not-to-use, 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.

Tool Schema Changelog

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

  1. 4 tool updatesv0.1.0
    • First observedget_diff
    • First observedlist_changed_files
    • First observedread_file
    • First observedsearch_code

TDQS

A4.2/5.0

Scored across 4 tools

Disambiguation4/5

Each tool has a fairly distinct role: read_file (single file contents), search_code (grep across tracked files), list_changed_files (cheap change summary), and get_diff (full unified diff). The only mild overlap is between list_changed_files and get_diff, but the descriptions explicitly position them as a cheap-then-expensive pair, so an agent can tell them apart.

Naming Consistency5/5

All four tools follow a clean verb_noun snake_case pattern: read_file, search_code, list_changed_files, get_diff. Verb style is consistent and the convention is predictable across the set.

Tool Count4/5

Four tools is a reasonable, tightly-scoped set for read-only repository inspection. It is on the lean side but each tool earns its place with no redundancy, so it is not thin enough to penalize heavily.

Completeness3/5

The read/find/diff lifecycle is covered, but there is no way to enumerate the directory tree, list commits/branches, or view history/blame, which limits discovery of what to inspect. An agent can partly work around file discovery via search_code, but the lack of commit enumeration is a notable gap for a git-oriented surface.

Related MCP Connectors

Related MCP Servers