Skip to main content
Glama
README.md
# code-repo-mcp

An MCP server that exposes `glob`, `grep` and `list_repos` tools over a folder
containing multiple git repositories. Point it at a directory where you mount
(or check out) several repos side by side, and any MCP client can search
across them by name — without needing local filesystem/shell access itself.

Runs as a single npm bin and serves the [MCP Streamable HTTP
transport](https://modelcontextprotocol.io/) (stateless mode), so it works
equally well as a personal local tool or as a small shared service.

## Install & run

```bash
npm install -g code-repo-mcp
code-repo-mcp --root /path/to/repos
```

Or without installing globally:

```bash
npx code-repo-mcp --root /path/to/repos
```

### Options

| Flag/env var                | Default     | Description                                   |
| ---------------------------- | ----------- | ---------------------------------------------- |
| `--root` / `CODE_REPO_ROOT`   | *(required)* | Folder containing git repos as subdirectories |
| `--port` / `PORT`             | `3900`      | Port to listen on                             |
| `--host` / `HOST`             | `127.0.0.1` | Host to bind to                               |

The server exposes a single MCP endpoint at `http://<host>:<port>/mcp`, plus
`GET /healthz` for a basic liveness check.

## Repo layout

`--root` should point at a folder whose immediate subdirectories are git
repositories (i.e. each contains a `.git` directory or file), e.g.:

```
/path/to/repos/
├── service-a/   (git repo)
├── service-b/   (git repo)
└── shared-lib/  (git repo)
```

Only these first-level subdirectories are considered repos; other files or
non-git directories under `--root` are ignored by `list_repos` and rejected
by `glob`/`grep`.

## Tools

- **`list_repos`** — no arguments. Returns the names of all git repos found
  directly under `--root`. Use these names as the `repo` argument for the
  other tools.
- **`glob`** — `{ repo, pattern, ignore?, dot?, limit? }`. Runs a
  [fast-glob](https://github.com/mrmlnc/fast-glob) pattern scoped to that
  repo and returns matching relative file paths.
- **`grep`** — `{ repo, pattern, glob?, caseInsensitive?, fixedStrings?, contextLines?, maxMatches? }`.
  Runs [ripgrep](https://github.com/BurntSushi/ripgrep) (bundled via
  `@vscode/ripgrep`, no system install required) scoped to that repo and
  returns `{ file, line, text }` matches.

All repo access is confined to the resolved repo directory: repo names must
be a single path segment (no `/`, `..`), and results that would resolve
outside the repo are filtered out as defense in depth.

## Connecting a client

Point any MCP-over-HTTP client at `http://127.0.0.1:3900/mcp`. For example,
in Claude Code's MCP config:

```json
{
  "mcpServers": {
    "code-repo-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:3900/mcp"
    }
  }
}
```

## Docker

Prebuilt images are published to GitHub Container Registry on every push to
`main` and on version tags (see
[.github/workflows/docker-publish.yml](.github/workflows/docker-publish.yml)):

```bash
docker pull ghcr.io/janstuemmel/code-repo-mcp:latest
```

Or build it yourself:

```bash
docker build -t code-repo-mcp .
docker run -d --name code-repo-mcp \
  -p 3900:3900 \
  -v /path/to/repos:/repos:ro \
  code-repo-mcp
```

The image mounts the repo folder at `/repos` by default (override with
`--root`/`CODE_REPO_ROOT` if you need a different path inside the container).
Mounting it `:ro` is recommended — the server only ever reads. It binds to
`0.0.0.0:3900` inside the container so `-p <host-port>:3900` is all you need;
override `HOST`/`PORT` env vars if you need something else.

Note: the image is based on `node:22-slim` (glibc), not Alpine — the bundled
ripgrep binary is a glibc build and won't run under musl.

## Development

```bash
npm install
npm run dev -- --root /path/to/repos   # run from source via tsx
npm run build                          # compile to dist/
npm start -- --root /path/to/repos     # run the compiled build
```