Skip to main content
Glama

gitlore

CI Python License: MIT

Read-only, structured access to a Git repository's history — as an MCP server and as a CLI.

An agent reading your codebase sees only the current state. It cannot tell a deliberate workaround from an accident, a hot spot from a stable file, or who to ask about a subsystem. All of that is in the Git history; gitlore exposes it as seven typed tools instead of handing the model a shell.

Tools

Tool

Answers

search_commits

When was this introduced, or removed?

file_history

How has this file evolved? (follows renames)

blame

Which commit put this line here, and why?

churn

Which files change most — where does risk concentrate?

contributors

Who knows this code? What is the bus factor?

commit_detail

What exactly did this commit do?

what_changed_between

What is different between these two refs?

Related MCP server: mcp-git

Install

pip install gitlore

Use it as a CLI

Every MCP tool is also a subcommand, so you can try the whole thing without an MCP client:

gitlore who                              # contributors and bus factor
gitlore churn --since "6 months ago"     # where the change concentrates
gitlore history src/app/auth.py          # a file's evolution, through renames
gitlore blame src/app/auth.py -s 40 -e 60
gitlore search -q "rate limit" --author alice
gitlore between v1.2.0 v1.3.0
gitlore show 9f2c1ab

Add --json to any command for machine-readable output, and --repo/-r to point at a repository other than the working directory.

Use it as an MCP server

gitlore serve --repo /path/to/repo

For Claude Code:

claude mcp add gitlore -- gitlore serve --repo /path/to/repo

Or, in a client that reads a JSON config:

{
  "mcpServers": {
    "gitlore": {
      "command": "gitlore",
      "args": ["serve", "--repo", "/path/to/repo"]
    }
  }
}

All seven tools are annotated readOnlyHint: true and openWorldHint: false, so a host can auto-approve them without prompting a human on every call.

Security

gitlore is driven by a language model whose context contains text written by strangers — commit messages, branch names, paths in a repository someone else authored. Every argument is treated as hostile.

No shell. subprocess.run([...], shell=False) with an argument list. There is no string interpolation into a command line anywhere in the codebase.

Allowlisted subcommands. Only read-only git subcommands run; anything else raises before a process is spawned. A denylist would be the wrong shape — git has well over a hundred subcommands and gains more each release.

Option-injection defence. A path or ref beginning with - is rejected. This is the check that gets left out: a "filename" of --output=/home/user/.ssh/authorized_keys is not a filename, and --upload-pack=… is a remote-code-execution primitive. Because arguments are passed in an argv list, quoting does not help — only refusing does. Paths also go after a -- separator so git cannot reinterpret them as revisions.

Path confinement. Every path is resolved and checked to be inside the repository root, so .. cannot walk out.

Hostile-repository hardening. Git runs commands out of a repository's own config — core.fsmonitor, core.hooksPath, core.pager, diff.external. Pointing a naive tool at a repository someone else wrote is enough to execute their code. Every invocation neutralises those with -c overrides and runs in a scrubbed environment: inherited GIT_* variables are dropped, system and global config are disabled, and terminal prompting is off so git can never block on a credential prompt.

Bounded output. Timeouts on every invocation, byte caps at the subprocess boundary, and record caps at the tool boundary. An unbounded git log would exhaust the agent's context window — a denial of service against the thing gitlore exists to help.

Pinned repository. The repository is fixed when the server starts and no tool takes a repository argument, so a model cannot be talked into reading somewhere else. There is no parameter through which to ask.

tests/test_security.py is adversarial and asserts all of the above.

Development

uv venv && uv pip install -e ".[dev]"
pytest              # fixtures build real git repos; nothing about git is mocked
ruff check .
mypy

Tests build real repositories with git init and real commits at controlled timestamps, then assert against real git output. Mocking git would only prove the mock matches the code's assumptions, which is the thing in doubt.

docs/design.md covers the architecture and the reasoning.

License

MIT — see LICENSE.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables Git repository interaction and automation via LLMs, providing tools to read, search, and manipulate Git repositories.
    15
    162
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables analysis of local Git repositories via standard git commands, providing insights like line authorship, commit frequency, code churn, and co-changed files.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/narek-keshishyan/gitlore'

If you have feedback or need assistance with the MCP directory API, please join our Discord server