Skip to content

A tech lead MCP server intended to offer LLM agents guidance and guardrails for proper implementations.

License

Notifications You must be signed in to change notification settings

jayehmke/techlead

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tech Lead

An AI supervisor for Claude Code. The tech lead reviews implementation plans before they reach you, catching over-engineering, scope creep, and unnecessary complexity.

The Problem

Claude Code is capable but eager. Ask it to "add logging" and you might get a 6-file logging framework with interfaces, formatters, handlers, and configuration systems. By the time you see the plan, you're already parsing complexity.

The Solution

The tech lead sits between Claude Code (the implementer) and you. Every plan gets reviewed before you see it:

┌─────────────────────────────────────────────────────────────────┐
│ You: "Add request logging"                                      │
│                                                                 │
│ Implementer drafts plan → Tech Lead reviews                     │
│                                                                 │
│ Tech Lead: "Reject. 6 files for logging is over-engineering.    │
│            Use slog directly. 2 files max."                     │
│                                                                 │
│ Implementer revises → Tech Lead reviews                         │
│                                                                 │
│ Tech Lead: "Approve. Clean, minimal, uses stdlib."              │
│                                                                 │
│ You see: "I'll add request logging with slog. One file:         │
│          internal/middleware/logging.go"                        │
└─────────────────────────────────────────────────────────────────┘

You only see vetted plans. The messy iterations happen before they reach you.

Features

  • Plan Review — Evaluates scope, complexity, and adherence to project standards
  • Code Review — Post-implementation review catches bugs, anti-patterns, and missing tests
  • Knowledge Storage — Learns from past decisions and reviews using vector embeddings
  • Semantic Search — Finds similar past reviews even with different terminology
  • Project Standards — Configurable thresholds for files, tests, and strictness
  • MCP Integration — Works as an MCP server for Claude Code
  • Hook Enforcement — Optional Claude hooks to enforce the workflow

Requirements

  • Go 1.21+
  • Docker (for Ollama)
  • Claude Code CLI

Quick Install

git clone https://github.com/jasonehmke/techlead.git
cd techlead
./scripts/install.sh

This script:

  • Builds and installs the techlead binary to ~/.local/bin
  • Starts Ollama in Docker and pulls the embedding model
  • Configures the MCP server globally for all Claude Code projects

After installation, the consult_tech_lead tool is available in every Claude Code session.

Manual Installation

If you prefer to set things up manually:

# Clone and build
git clone https://github.com/jasonehmke/techlead.git
cd techlead
make build

# Install to PATH
cp bin/techlead ~/.local/bin/

# Add MCP server globally
claude mcp add techlead ~/.local/bin/techlead mcp -s user

Set Up Ollama

The tech lead uses Ollama for generating embeddings. This enables semantic search across past decisions and reviews.

# Install Ollama (macOS)
brew install ollama

# Pull the embedding model
ollama pull nomic-embed-text

# Start Ollama (runs in background)
ollama serve

Quick Start

1. Initialize a Project

cd your-project
techlead init

This creates:

.techlead/
├── config.yaml      # Project standards
└── knowledge.db     # Vector database (created on first run)

2. Start the Tech Lead Server

techlead

The server starts on http://localhost:8080 by default. Set PORT environment variable to change.

3. Configure Claude Code

If you used the install script, the MCP server is already configured globally. Skip to step 4.

Global install (all projects):

claude mcp add techlead ~/.local/bin/techlead mcp -s user

Project-only install:

Add to your project's .mcp.json:

{
  "mcpServers": {
    "techlead": {
      "command": "/path/to/techlead",
      "args": ["mcp"]
    }
  }
}

HTTP mode (for development/testing):

{
  "mcpServers": {
    "techlead": {
      "type": "http",
      "url": "http://localhost:8080"
    }
  }
}

4. Add Implementer Instructions

Copy context/implementer.md to your project's CLAUDE.md or append it to existing instructions. This tells Claude Code to consult the tech lead before showing you plans.

Configuration

Edit .techlead/config.yaml:

standards:
  require_linting: true
  require_tests: true
  max_files_per_task: 10

review:
  # How hard to push: minimal, standard, strict, pedantic
  strictness: standard

knowledge:
  embeddings:
    endpoint: http://localhost:11434
    model: nomic-embed-text

Strictness Levels

Level Behavior
minimal Only catch egregious issues
standard Clear issues + obvious improvements (default)
strict Standard + questionable decisions
pedantic Maximum scrutiny, question everything

API Reference

HTTP Endpoints

Review a Plan

POST /consult
curl -X POST http://localhost:8080/consult \
  -H "Content-Type: application/json" \
  -d '{
    "task": "Add request logging",
    "plan_summary": "Create middleware that logs requests using slog",
    "files": ["internal/middleware/logging.go", "internal/middleware/logging_test.go"],
    "rationale": "Simple middleware with tests"
  }'

Response:

{
  "decision": "approve",
  "reason": "Clean, minimal approach. Uses stdlib slog, includes tests.",
  "guidance": ""
}

Search Knowledge

POST /knowledge/search
curl -X POST http://localhost:8080/knowledge/search \
  -H "Content-Type: application/json" \
  -d '{"query": "logging and observability", "limit": 5}'

Returns semantically similar decisions, learnings, and past reviews.

Record a Decision

POST /knowledge/decision
curl -X POST http://localhost:8080/knowledge/decision \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Use slog for all logging",
    "context": "Stdlib is sufficient, no external dependencies needed"
  }'

Record a Learning

POST /knowledge/learning
curl -X POST http://localhost:8080/knowledge/learning \
  -H "Content-Type: application/json" \
  -d '{
    "pattern": "Implementer proposes 6+ files for simple task",
    "response": "Reject. Scope to 2 files maximum.",
    "severity": "high"
  }'

List All Decisions

GET /knowledge/decisions

List All Learnings

GET /knowledge/learnings

Review Code

POST /review
curl -X POST http://localhost:8080/review \
  -H "Content-Type: application/json" \
  -d '{
    "task": "Add user authentication",
    "files": {
      "internal/auth/handler.go": "package auth\n\nfunc Login(w http.ResponseWriter, r *http.Request) {\n    // handler code\n}"
    },
    "description": "Login endpoint with JWT tokens"
  }'

Response:

{
  "approved": true,
  "summary": "Clean implementation with proper error handling",
  "issues": [],
  "praise": "Good use of stdlib http patterns"
}

If issues are found:

{
  "approved": false,
  "summary": "Several issues need attention",
  "issues": [
    "SQL injection vulnerability in query construction",
    "Error from db.Query is ignored",
    "Missing nil check on user result"
  ],
  "praise": ""
}

Health Check

GET /health

How It Works

Plan Review Flow

  1. Implementer (Claude Code) drafts a plan
  2. Implementer calls consult_tech_lead tool with the plan
  3. Tech lead searches knowledge base for similar past reviews
  4. Tech lead evaluates plan against standards and historical context
  5. Tech lead returns: approve, modify, or reject
  6. If not approved, implementer revises and tries again
  7. Approved plan is shown to user

Knowledge System

The tech lead learns from experience using vector embeddings:

"Add logging framework" → [0.12, -0.45, 0.78, ...]  (768 numbers)
"Create observability system" → [0.11, -0.44, 0.76, ...]  (similar meaning = similar numbers)

When a new plan comes in:

  1. Embed the plan summary
  2. Search for similar past reviews
  3. Include relevant context in the evaluation
  4. Store the new review for future reference

This means rejecting a "logging framework" informs future reviews of "monitoring systems"—they're semantically related even without shared words.

Code Review Flow

After implementation is complete:

  1. Implementer calls review_code tool with the code
  2. Tech lead reviews for bugs, anti-patterns, and quality issues
  3. Returns approval status with any issues found
  4. If issues exist, implementer fixes and re-reviews
  5. Clean code is presented to the user

Code review is lighter than plan review—it approves "good enough" code and only flags real issues.

Hook Enforcement (Optional)

By default, the tech lead relies on instructions in CLAUDE.md to guide Claude Code. For stricter enforcement, you can add Claude hooks that block code changes until the tech lead approves.

How It Works

  1. PreToolUse hook blocks Write, Edit, and MultiEdit until consult_tech_lead returns approval
  2. PostToolUse hook tracks approval status and reminds about code review after implementation

Setup

Create the enforcement hook at ~/.claude/hooks/techlead-enforce.sh:

#!/bin/bash
# Blocks code changes until tech lead approval

set -e

input=$(cat)
session_id=$(echo "$input" | jq -r '.session_id')
tool_name=$(echo "$input" | jq -r '.tool_name')

STATE_DIR="/tmp/claude-techlead"
mkdir -p "$STATE_DIR"
APPROVAL_FILE="$STATE_DIR/approved-$session_id"

# Only enforce in projects with .techlead/ directory
check_techlead_project() {
    local dir=$(echo "$input" | jq -r '.cwd // "."')
    [[ -d "$dir/.techlead" ]]
}

if ! check_techlead_project; then
    exit 0
fi

case "$tool_name" in
    Write|Edit|MultiEdit)
        # Allow config files without approval
        file_path=$(echo "$input" | jq -r '.tool_input.file_path // ""')
        case "$file_path" in
            *.md|*.txt|*.json|*.yaml|*.yml|*.toml|*.env*)
                exit 0
                ;;
        esac

        # Check for approval
        if [[ -f "$APPROVAL_FILE" ]] && [[ "$(cat "$APPROVAL_FILE")" == "approved" ]]; then
            exit 0
        fi

        echo "BLOCKED: Call consult_tech_lead first" >&2
        exit 2
        ;;
esac

exit 0

Create the tracker hook at ~/.claude/hooks/techlead-tracker.sh:

#!/bin/bash
# Tracks tech lead approval status

set -e

input=$(cat)
session_id=$(echo "$input" | jq -r '.session_id')
tool_name=$(echo "$input" | jq -r '.tool_name')

STATE_DIR="/tmp/claude-techlead"
mkdir -p "$STATE_DIR"
APPROVAL_FILE="$STATE_DIR/approved-$session_id"

if [[ "$tool_name" == "mcp__techlead__consult_tech_lead" ]]; then
    tool_output=$(echo "$input" | jq -r '.tool_output // ""')
    if echo "$tool_output" | grep -qi '"decision"[[:space:]]*:[[:space:]]*"approve"'; then
        echo "approved" > "$APPROVAL_FILE"
    fi
fi

exit 0

Make both executable:

chmod +x ~/.claude/hooks/techlead-enforce.sh
chmod +x ~/.claude/hooks/techlead-tracker.sh

Add to ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/.claude/hooks/techlead-enforce.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "mcp__techlead__*|Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/.claude/hooks/techlead-tracker.sh"
          }
        ]
      }
    ]
  }
}

Replace /path/to/ with your actual home directory path.

What the Tech Lead Catches

Pattern Response
Too many files "This should be 2 files, not 8"
Unnecessary abstractions "No interfaces needed here"
Scope creep "Park that for later, finish this task first"
New dependencies "Use stdlib, don't add external deps"
Over-engineering "This is a simple task, keep it simple"
Stdlib reimplementation "Use strings.Contains instead of custom helper"

Running Modes

HTTP Server (Default)

techlead
# or
techlead --port 9090

Good for development and testing. Use curl to interact directly.

MCP Server (stdio)

techlead mcp

Standard MCP protocol over stdin/stdout. This is what Claude Code uses.

Development

Build

make build

Test

make test

Note: Tests that require Ollama will be skipped if Ollama is not running.

Run with Hot Reload

make dev

Requires air.

Project Structure

techlead/
├── cmd/techlead/
│   ├── main.go              # Entry point
│   └── templates/           # Default config templates
├── internal/
│   ├── config/              # Configuration loading
│   ├── knowledge/           # Vector database and embeddings
│   ├── mcp/                 # MCP and HTTP servers
│   ├── plan/                # Plan schema
│   └── techlead/            # Core review logic
├── context/
│   └── implementer.md       # Claude Code instructions
└── .techlead/
    └── config.yaml          # Project configuration

Troubleshooting

"embedder not available: ollama unavailable"

Ollama is not running or the model is not installed.

# Start Ollama
ollama serve

# Pull the model if not installed
ollama pull nomic-embed-text

"sqlite3_auto_extension is deprecated" warning

This is a macOS warning, not an error. Apple deprecated this function in their bundled SQLite, but it still works. The warning can be safely ignored.

Tech lead not being consulted

  1. Check that .mcp.json is configured correctly
  2. Verify the implementer instructions are in your CLAUDE.md
  3. Restart Claude Code after configuration changes
  4. Check that the tech lead server is running

Tech lead only works in one project

The MCP server was likely added with local scope instead of user scope. Fix with:

claude mcp remove techlead -s local
claude mcp add techlead ~/.local/bin/techlead mcp -s user

Plans still seem over-engineered

Increase strictness in .techlead/config.yaml:

review:
  strictness: strict  # or pedantic

Record learnings for patterns you see:

curl -X POST http://localhost:8080/knowledge/learning \
  -H "Content-Type: application/json" \
  -d '{
    "pattern": "Creates interfaces for single implementations",
    "response": "Reject. No interface until there are 2+ implementations.",
    "severity": "high"
  }'

License

MIT

About

A tech lead MCP server intended to offer LLM agents guidance and guardrails for proper implementations.

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages