PR Guardian MCP
by maiv3n
README.md
# PR Guardian MCP
Servidor [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) open-source que analisa diffs de Pull Requests do GitHub com foco em **segurança** e **vazamento de dados**.
A arquitetura prioriza **economia de tokens**: a maioria dos PRs (docs, CSS, formatação) é aprovada por lógica nativa TypeScript, sem chamar a LLM. Apenas mudanças em arquivos de lógica disparam análise via LangGraph + Claude 3.5 Haiku.
## Arquitetura
```mermaid
flowchart TD
A[MCP Tool: analyze_pr_diff] --> B[LangGraph: classify]
B --> C{Filtro Determinístico}
C -->|docs / css / formatação| D[auto_approve]
C -->|.ts / .tsx / outros riscos| E[ai_analyze]
E --> F[Claude 3.5 Haiku]
F --> G[Zod Validation]
D --> G
G --> H[Resposta MCP estruturada]
subgraph Observabilidade
F -.->|trace| LS[LangSmith]
end
```
### 1. Filtro Determinístico (custo zero)
Antes de qualquer chamada à API da Anthropic, o nó `classify` executa regras nativas em TypeScript:
| Condição | Ação |
|---|---|
| Apenas `.md`, `.mdx`, `.css`, `.scss` etc. | Aprovação automática |
| Diff altera somente whitespace (formatação) | Aprovação automática |
| Presença de `.ts`, `.tsx`, `.js`, `.jsx` | Encaminha para IA |
| Outros arquivos fora do escopo seguro | Encaminha para IA |
**Por que isso importa?** Em repositórios reais, uma parcela significativa dos PRs altera apenas documentação, estilos ou formatação. Enviar esses diffs para uma LLM gera:
- **Custo desnecessário** — tokens de entrada/saída cobrados sem valor de segurança
- **Latência** — 1–3s adicionais por PR trivial
- **Ruído** — falsos positivos em conteúdo que não executa código
O filtro determinístico responde em **microssegundos**, com custo **$0.00**.
### 2. Filtro de IA (LangGraph)
Quando arquivos de lógica são detectados, o grafo aciona o nó `ai_analyze`:
- Modelo: **Claude 3.5 Haiku** (`claude-3-5-haiku-20241022`)
- Escopo: **apenas** riscos de segurança e vazamento de dados
- Saída: JSON estruturado via `withStructuredOutput`
Categorias analisadas: `secret_leak`, `injection`, `auth_bypass`, `data_exposure`, `dependency_risk`.
### 3. Validação (Zod)
Toda resposta — determinística ou da LLM — passa pelo nó `validate_result` e é parseada com `PrAnalysisResultSchema` antes de retornar ao cliente MCP. Respostas malformadas da LLM são rejeitadas com erro explícito.
### 4. Observabilidade (LangSmith)
Chamadas LLM são rastreadas automaticamente quando:
```env
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=lsv2_...
LANGCHAIN_PROJECT=pr-guardian-mcp
```
No dashboard do LangSmith você visualiza **latência**, **tokens consumidos** e **custo estimado** por execução do grafo.
## Estrutura do Projeto
```
pr-guardian-mcp/
├── src/
│ ├── index.ts # Servidor MCP (stdio)
│ ├── graph.ts # LangGraph: classify → auto_approve | ai_analyze → validate
│ ├── schema.ts # Schemas Zod (input, output, LLM)
│ ├── deterministic-filter.ts # Lógica de filtro nativo (custo zero)
│ └── langsmith.ts # Configuração de observabilidade
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── package.json
└── tsconfig.json
```
## Pré-requisitos
- Node.js ≥ 20
- Chave da API Anthropic (apenas para PRs com arquivos de lógica)
- Chave do LangSmith (opcional, recomendado)
## Instalação
```bash
git clone https://github.com/seu-usuario/pr-guardian-mcp.git
cd pr-guardian-mcp
npm install
cp .env.example .env
# Edite .env com suas chaves
```
## Uso Local
```bash
# Desenvolvimento
npm run dev
# Build + produção
npm run build
npm start
```
### Configuração no Cursor / Claude Desktop
Adicione ao arquivo de configuração MCP:
```json
{
"mcpServers": {
"pr-guardian-mcp": {
"command": "node",
"args": ["/caminho/absoluto/pr-guardian-mcp/dist/index.js"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"LANGCHAIN_TRACING_V2": "true",
"LANGCHAIN_API_KEY": "lsv2_...",
"LANGCHAIN_PROJECT": "pr-guardian-mcp"
}
}
}
}
```
### Ferramenta MCP
**`analyze_pr_diff`**
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| `diff` | `string` | Sim | Diff unified do PR (formato git) |
| `prTitle` | `string` | Não | Título do PR para contexto |
| `prNumber` | `number` | Não | Número do PR |
**Exemplo de resposta:**
```json
{
"approved": true,
"path": "deterministic",
"reason": "Alterações exclusivas em documentação (.md) ou estilos (.css) — aprovado sem chamada à LLM.",
"findings": [],
"metadata": {
"analyzedAt": "2026-07-15T18:00:00.000Z",
"filesChanged": ["README.md", "docs/guide.md"],
"tokenCostSaved": true
}
}
```
## Docker
### Build e execução
```bash
docker build -t pr-guardian-mcp .
docker run -i --rm \
-e ANTHROPIC_API_KEY=sk-ant-... \
-e LANGCHAIN_TRACING_V2=true \
-e LANGCHAIN_API_KEY=lsv2_... \
-e LANGCHAIN_PROJECT=pr-guardian-mcp \
pr-guardian-mcp
```
### Docker Compose
```bash
cp .env.example .env
docker compose up --build
```
O container expõe o servidor via **stdio** (`-i`), compatível com clientes MCP que lançam processos filhos.
## Stack
| Pacote | Papel |
|---|---|
| `@modelcontextprotocol/sdk` | Servidor MCP |
| `@langchain/langgraph` | Orquestração do fluxo Determinístico vs IA |
| `@langchain/anthropic` | Integração Claude 3.5 Haiku |
| `zod` | Validação estrita de input/output |
| `langsmith` | Tracing de custo e latência |
## Licença
MIT
TDQS
A3.8/5.0
Scored across 1 tool
Disambiguation5/5
Only one tool exists, so there is no ambiguity in tool selection.
Naming Consistency5/5
With a single tool, naming consistency is perfect as there is no pattern to compare.
Tool Count3/5
The server has only one tool, which is on the low end for typical MCP servers. However, the narrow focus on PR diff analysis justifies the minimal count.
Completeness4/5
The single tool fully covers its stated purpose of analyzing PR diffs for security risks, but the server lacks additional tools for follow-up actions like reporting or issue creation.
Maintenance
ActivityStale
ResponsivenessNo issues