Every Claude Code session that involves more than one repo starts with the same monologue: “we have a payment service that calls user-service via REST, which publishes events that notification-service consumes, and oh by the way the platform team owns auth-service…” By the time I’ve finished the briefing, I’ve burned tokens and patience.

cartographer-mcp is my attempt at fixing that. It crawls your GitLab organization, builds a service catalog with a dependency graph, and exposes it as MCP tools so Claude Code already knows the shape of your architecture.

What it does

Point it at one or more GitLab group paths. It walks every project, scrapes metadata (name, description, README, latest version, lifecycle), and builds a graph. If a project has a .cartographer.yaml file at its root, that file enriches the auto-discovered data with human-curated facts — service type, owner, declared dependencies, declared outputs.

You ask Claude Code things like “what depends on user-service?” or “which services emit events?” and it answers from the cache instantly, no GitLab API calls during the query.

The tools available:

  • list_services — filter by type, lifecycle, or tag
  • get_service — full details for a service
  • get_dependencies — what this service depends on
  • get_dependents — what depends on this service
  • search_services — keyword search across names, descriptions, tags, outputs
  • refresh_cache — re-crawl from GitLab

The “what depends on X” answer alone has paid for the project several times over.

Install

Build it from source for now:

go build -o cartographer ./cmd/cartographer/

Configure with environment variables:

export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"
# Optional for self-hosted instances
export GITLAB_URI="https://gitlab.example.com/"
# Comma-separated list of group paths to crawl
export CARTOGRAPHER_GROUPS="myorg/platform,myorg/product"

Or drop a config file at $HOME/.config/cartographer/config.yaml:

groups:
  - "myorg/platform"
  - "myorg/product"

Wire it into Claude Code:

claude mcp add cartographer -s user -- /path/to/cartographer

Or via .mcp.json:

{
  "mcpServers": {
    "cartographer": {
      "command": "/path/to/cartographer",
      "env": {
        "GITLAB_TOKEN": "glpat-xxxxxxxxxxxx"
      }
    }
  }
}

First thing to do in a new session: Refresh the cartographer cache. Then ask away.

The .cartographer.yaml file

Auto-discovery gets you the basics. The richer answers come when teams drop a .cartographer.yaml at the root of each repo:

schema_version: 1
service:
  name: "payment-service"
  type: "api"
  lifecycle: "production"
  owner: "payments-team"
  tags:
    - "payments"
    - "stripe"
dependencies:
  - service: "user-service"
    type: "api"
  - service: "notification-service"
    type: "events"
outputs:
  - name: "payment-events"
    type: "events"
    description: "Payment lifecycle events"
  - name: "payments-api"
    type: "api"
    description: "REST API for payment operations"

Projects without the file are still in the catalog — they just have less depth. The point is that you can roll this out incrementally, one repo at a time, without forcing every team to fill out a form.

What this looks like in practice

Once Claude Code has the catalog loaded, queries that used to take a paragraph of context become single sentences:

What services do we have?
Tell me about the payment service.
What depends on the user service?
Which services send emails?

The impact-analysis question — “what would break if I change this service?” — is the one that converted me. Reverse dependencies in plain English, computed offline, no GitLab API calls during the conversation.

A few practical notes

  • All queries hit the local cache. The crawl is the only network-bound operation.
  • The crawler retries with exponential backoff on GitLab rate limits, so pointing it at a large org overnight doesn’t blow up.
  • read_api scope is enough for the token. No write access needed.

Where to find it

If your GitLab org has more than a handful of repos and you’re using Claude Code daily, it’s worth the half-hour of setup. The first time Claude correctly answers “what depends on this?” without you typing a word of context, you’ll see why.