Skip to main content
Glama
Stokesy-dev

MCP Codebase Context Server

by Stokesy-dev
README.md
# MCP Codebase Context Server

A self-hosted MCP (Model Context Protocol) server that gives LLMs intelligent, semantic access to your codebase — instead of dumping raw files, it lets agents *query* code the way a senior engineer would.

[![CI](https://github.com/your-username/mcp-codebase-server/actions/workflows/ci.yml/badge.svg)](https://github.com/your-username/mcp-codebase-server/actions/workflows/ci.yml)

---

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                        MCP Client (Claude Code)                 │
└───────────────────────────┬─────────────────────────────────────┘
                            │ HTTP/SSE (MCP protocol)
                            ▼
┌─────────────────────────────────────────────────────────────────┐
│                    Caddy (TLS + reverse proxy)                  │
│     /mcp → mcp-server:8000   /agent → langgraph-agent:8001     │
└───────────┬─────────────────────────────┬───────────────────────┘
            │                             │
            ▼                             ▼
┌───────────────────┐         ┌───────────────────────────────────┐
│   MCP Server      │         │   LangGraph Agent Service         │
│   (port 8000)     │         │   (port 8001)                     │
│                   │         │                                   │
│ Tools:            │         │  POST /invoke                     │
│  search_codebase  │◄────────│  ┌─────────────────────────────┐ │
│  get_recent_changes         │  │ router_node (ChatGroq)       │ │
│  explain_function │         │  │      ↓ (conditional)        │ │
└─────────┬─────────┘         │  │ tool_executor_node          │ │
          │                   │  │      ↓ (loop back)          │ │
          ▼                   │  │ synthesizer_node            │ │
┌─────────────────────────────┤  └─────────────────────────────┘ │
│         Retrieval Pipeline  │                                   │
│                             └───────────────────────────────────┘
│  PythonChunker (ast)
│      ↓
│  Embedder (unixcoder-base)
│      ↓
│  RepoIndex (FAISS IndexFlatIP) ──── persisted to data/
│      ↓
│  HybridRanker
│    • w1 × semantic_score
│    • w2 × recency_score  (exp(-λ × days_since_commit))
│    • w3 × file_relevance (1 / (1 + import_graph_distance))
│      ↓
│  ImportGraph (networkx DiGraph)
│  GitIntegration (GitPython)
└─────────────────────────────────────────────────────────────────
```

**Free stack**: Oracle Cloud Always Free (Ampere A1, 4 OCPU / 24GB), Groq free API tier (llama-3.3-70b-versatile), no paid dependencies.

---

## Prerequisites

- Python 3.11+
- [uv](https://docs.astral.sh/uv/) (install: `curl -LsSf https://astral.sh/uv/install.sh | sh`)
- Git
- Docker + Docker Compose (for deployment)
- A [Groq API key](https://console.groq.com) (free, no credit card required)

---

## Quick Start (Local)

### 1. Clone and install

```bash
git clone https://github.com/your-username/mcp-codebase-server.git
cd mcp-codebase-server
uv sync --all-extras --dev
```

### 2. Configure

```bash
cp .env.example .env
# Edit .env — set GROQ_API_KEY and MCP_API_KEY
```

Edit `repos.yaml` to point at your local repositories:

```yaml
repos:
  - name: "my-project"
    path: "/absolute/path/to/your/repo"
    branch: "main"
```

Optionally tune `config.yaml` (ranking weights, model, etc.).

### 3. Run the MCP server

```bash
uv run uvicorn src.server.app:app --port 8000 --reload
```

### 4. Run the LangGraph agent

```bash
uv run uvicorn src.orchestration.agent_app:app --port 8001 --reload
```

### 5. Run tests

```bash
uv run pytest --cov=src -v
```

---

## Connecting Claude Code

Add to your Claude Code MCP config (`~/.claude/claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "codebase": {
      "url": "http://localhost:8000/mcp",
      "headers": {
        "X-API-Key": "your-mcp-api-key"
      }
    }
  }
}
```

---

## Docker (Local or Cloud)

```bash
# Build and start all services
docker compose up --build -d

# Check health
curl http://localhost:8000/health
curl http://localhost:8001/health

# Tail logs
docker compose logs -f
```

---

## Example Queries

### Via MCP tools (Claude Code)

```
search_codebase("JWT authentication token validation")
get_recent_changes("src/auth/", "my-project", limit=5)
explain_function("process_payment", "src/payments/processor.py", "my-project")
```

### Via LangGraph agent (HTTP)

```bash
curl -X POST http://localhost:8001/invoke \
  -H "Content-Type: application/json" \
  -d '{
    "query": "How does the authentication flow work and what changed recently?",
    "repo_names": ["my-project"],
    "anchor_files": ["src/auth/middleware.py"]
  }'
```

The agent will autonomously call `search_codebase`, then `get_recent_changes`, then synthesize a final answer.

---

## Configuration Reference

### `repos.yaml`

| Field | Required | Description |
|---|---|---|
| `name` | ✅ | Unique identifier for the repo |
| `path` | ✅ | Absolute path to the repo root |
| `branch` | ❌ | Branch to index (default: current HEAD) |

### `config.yaml`

| Field | Default | Description |
|---|---|---|
| `retrieval.w1_semantic` | `0.6` | Weight for semantic similarity |
| `retrieval.w2_recency` | `0.2` | Weight for commit recency |
| `retrieval.w3_file_relevance` | `0.2` | Weight for import graph proximity |
| `retrieval.recency_lambda` | `0.05` | Decay constant λ (days) |
| `retrieval.default_k` | `10` | Default search result count |
| `retrieval.embedding_model` | `microsoft/unixcoder-base` | Sentence-transformers model |
| `retrieval.data_dir` | `data` | Directory for persisted indexes |
| `orchestration.max_iterations` | `5` | Max LangGraph tool-call iterations |
| `orchestration.groq_model` | `llama-3.3-70b-versatile` | Groq model for routing/synthesis |

### `.env`

| Variable | Description |
|---|---|
| `MCP_API_KEY` | API key required in `X-API-Key` header |
| `GROQ_API_KEY` | Groq API key for LangGraph LLM |
| `LOG_LEVEL` | `DEBUG`, `INFO`, `WARNING`, `ERROR` |

---

## Design Decisions

| Decision | Rationale |
|---|---|
| AST chunking over line-based | Function/class boundaries are the natural unit engineers reason about |
| Three ranking signals | Semantic alone misses temporal relevance; recency + file proximity approximate how a senior engineer prioritises |
| Groq over Ollama | Oracle free VM has 24GB RAM; offloading LLM compute to Groq keeps the VM dedicated to embedding/retrieval |
| `unixcoder-base` embeddings | Pre-trained on CodeSearchNet — meaningfully represents identifiers and API names |
| Import graph file relevance | Static AST import parsing; neutral score (0.5) for unresolvable imports |

---

## Deployment

See [`docs/deployment.md`](docs/deployment.md) for the full Oracle Cloud setup guide.

---

## License

MIT