## Project Overview

This is an MCP (Model Context Protocol) server that provides structural code search and transformation using ast-grep. The project is a **direct wrapper with zero abstractions** - it passes commands directly to ast-grep CLI for maximum performance and perfect CLI compatibility.

**Key Philosophy:** No abstractions layer, no custom DSL - just direct ast-grep command execution with validation and workspace security.

## Core Architecture

### Entry Point: `src/index.ts`
- MCP server initialization and tool registration
- CLI argument parsing for installation options
- Request routing to three main tools: `ast_search`, `ast_replace`, `ast_run_rule`
- Error handling with typed exceptions (ValidationError, BinaryError, ExecutionError)

### Binary Management: `src/core/binary-manager.ts`
Handles ast-grep binary resolution with priority:
1. Custom binary path (via `AST_GREP_BINARY_PATH` env var)
2. System binary (default - requires ast-grep installed on system)

**Important:** Users must install ast-grep on their system using official methods (npm, cargo, homebrew, scoop). The manager validates binaries with `--version` test before use.

### Workspace Management: `src/core/workspace-manager.ts`
Detects project boundaries and enforces security constraints:
- **Workspace detection hierarchy:**
  - Primary: `.git`, `package.json`, `Cargo.toml`, `go.mod`, `pom.xml`
  - Secondary: `pyproject.toml`, `composer.json`, `build.gradle`, `tsconfig.json`
  - Tertiary: `Makefile`, `README.md`, `.vscode`, `.idea`, `Gemfile`
- **Security:** Blocks system directories (`/etc`, `/bin`, `C:\Windows`, `.ssh`, `.aws`)
- **Path validation:** All paths normalized to forward slashes for ast-grep compatibility
- **Max depth:** 10 levels to prevent excessive traversal

### Tool Implementation: `src/tools/`
Three tools implement direct ast-grep command construction:

**SearchTool (`search.ts`):**
- Executes `ast-grep run --pattern <pattern>`
- Uses `--json=stream` for structured output
- Supports inline code via stdin or file paths via command args

**ReplaceTool (`replace.ts`):**
- Executes `ast-grep run --pattern <pattern> --rewrite <replacement>`
- Defaults to dry-run mode (`dryRun: true`)
- Validates metavariable consistency between pattern and replacement

**ScanTool (`scan.ts`):**
- Generates YAML rule files dynamically
- Executes `ast-grep scan --rule <temp-rule-file>`
- Supports constraints (`where` clauses) and fix suggestions
- Cleans up temp files after execution

### Validation: `src/utils/validation.ts`
Centralized validation for:
- **Pattern syntax:** Validates metavariables (`$VAR`, `$$$NAME`, `$_`)
- **Parameter ranges:** Context (0-100), maxMatches (1-10000), timeout (1000-300000ms)
- **YAML rules:** Rule ID format (kebab-case), severity levels
- **Path safety:** Windows path detection, normalization to forward slashes

## Development Commands

```bash
# Build
bun run build              # TypeScript compilation
bun run build:bun          # Bun-specific build with declarations

# Development
bun run dev                # Run with tsx (Node-based)
bun run dev:bun            # Run with bun --watch (hot reload)

# Testing
bun test                   # Run all tests
bun run test:unit          # Unit tests only (validation.test.ts, binary-manager.test.ts)
bun run test:integration   # Integration tests only (integration.test.ts, cli-flag-mapping.test.ts)
bun run test:cli-mapping   # CLI flag mapping tests only
bun run test:binary-manager # Binary manager tests only

# Clean
bun run clean              # Remove build directory
```

## Testing Strategy

**Critical rules:**
- Use real services only - **no mocking** (except for CLI flag mapping tests)
- Complete each test fully before proceeding
- Write verbose tests for debugging
- Check existing test patterns before adding new tests

### Test File Structure

1. **`tests/validation.test.ts`** - Unit tests for validation logic
2. **`tests/binary-manager.test.ts`** - Binary management tests (≥95% coverage)
3. **`tests/cli-flag-mapping.test.ts`** - CLI flag mapping verification tests
   - Mocks `executeAstGrep` to capture CLI arguments
   - Verifies MCP parameters map to correct ast-grep CLI flags
   - Tests language normalization, path handling, YAML generation
   - References AST_GREP_ALL_DOCUMENTS.md for CLI documentation
4. **`tests/integration.test.ts`** - End-to-end MCP tool execution tests (87 tests)
   - Uses real ast-grep binary
   - Tests search-then-replace workflows
   - Tests timeout handling, stdin/file modes, context parameters
   - Tests dry-run vs update-all behavior
   - Tests JSON stream format verification
5. **`tests/setup.ts`** - Global test configuration (preloaded via bunfig.toml)
6. **`tests/fixtures/`** - Test code samples for file-based tests
7. **`tests/helpers/stderr-capture.ts`** - Test utilities and CLI assertion helpers

### CLI Flag Mapping Tests

CLI flag mapping tests verify that MCP parameters correctly translate to ast-grep CLI flags:

**Requirements:**
- Mock `AstGrepBinaryManager.executeAstGrep` to capture arguments
- Assert exact CLI flag names, values, and order
- Reference AST_GREP_ALL_DOCUMENTS.md line numbers in test comments
- Verify all flags documented in AST_GREP_ALL_DOCUMENTS.md lines 355-814

**Test patterns:**
```typescript
// Verify flag presence and value
assertCliFlag(capturedArgs, "--pattern", "console.log($ARG)");
assertCliFlag(capturedArgs, "--lang", "js");
assertCliFlag(capturedArgs, "--json=stream", null); // Boolean flag

// Verify flag absence
assertCliFlagAbsent(capturedArgs, "--update-all");

// Verify command and positional args
assertCliCommand(capturedArgs, "run");
assertPositionalArgs(capturedArgs, ["src/", "tests/"]);
```

**Coverage areas:**
- SearchTool: `--pattern`, `--lang`, `--json=stream`, `--context`, `--stdin`, paths
- ReplaceTool: `--pattern`, `--rewrite`, `--lang`, `--update-all`, `--stdin`, paths
- ScanTool: `--rule`, `--json=stream`, temp file paths, YAML generation
- Language normalization (javascript→js, typescript→ts, python→py, etc.)
- Path handling and validation
- Temp file lifecycle (creation, cleanup)

## Code Quality Standards (from AGENTS.md)

**Non-negotiable:**
- No partial implementations or TODO comments
- No code duplication - reuse existing functions
- No dead code - delete entirely
- No emojis in code
- Complete functions only - ask if requirements unclear
- All docstrings follow Google style conventions

**Path handling:**
- Never assume `process.cwd()` equals project root
- Always use `WorkspaceManager` for path validation
- Never hardcode paths - use configuration
- Always normalize Windows paths to forward slashes for ast-grep

**CLI compliance:**
- All CLI flags must match ast-grep documentation exactly
- Reference AST_GREP_ALL_DOCUMENTS.md line numbers when adding/modifying CLI flags
- Add CLI flag mapping tests for new parameters
- Verify flag order matches tool implementation

## Publishing

Version bumps use standard npm versioning:
```bash
npm version patch          # 1.0.0 → 1.0.1
npm version minor          # 1.0.0 → 1.1.0
npm version major          # 1.0.0 → 2.0.0
git push origin develop --tags
```

GitHub Actions handles automated publishing to npm when tags are pushed. See `.github/PUBLISHING.md` for details.

## Important ast-grep References

Always consult ast-grep documentation for pattern syntax and best practices:
- https://ast-grep.github.io/
- https://ast-grep.github.io/guide/introduction.html

## Common Patterns

### Adding a new tool parameter
1. Add validation in `src/utils/validation.ts` (e.g., `ParameterValidator.validateNewParam()`)
2. Update tool schema in tool class (e.g., `SearchTool.getSchema()`)
3. Add parameter to command args construction in tool's `execute()` method
4. Add CLI flag mapping test in `tests/cli-flag-mapping.test.ts` to verify correct flag usage
5. Add integration test in `tests/integration.test.ts` for end-to-end functionality
6. Reference AST_GREP_ALL_DOCUMENTS.md line numbers in test comments

### Handling new programming languages
Languages are normalized via language alias maps in each tool (e.g., `javascript` → `js`, `typescript` → `ts`). The map is defined in tool execute methods.

### Error handling flow
1. Validation errors → throw `ValidationError` with actionable messages
2. Binary errors → throw `BinaryError` (not recoverable)
3. Execution errors → throw `ExecutionError` (recoverable)
4. MCP server catches all and returns structured error responses

### CLI flag mapping test pattern
When adding new CLI flags or modifying existing ones:

```typescript
// 1. Mock executeAstGrep in beforeAll
spyOn(binaryManager, "executeAstGrep").mockImplementation(async (args, options) => {
  capturedArgs = [...args];
  capturedOptions = { ...options };
  return { stdout: "", stderr: "" };
});

// 2. Execute tool with new parameter
await tool.execute({ newParameter: "value" });

// 3. Assert CLI flag presence and value
assertCliFlag(capturedArgs, "--new-flag", "value");

// 4. Document AST_GREP_ALL_DOCUMENTS.md reference
// Reference: AST_GREP_ALL_DOCUMENTS.md line 123
```

### YAML generation test pattern
When adding fields to YAML rule generation:

```typescript
// 1. Execute ScanTool with new parameter
const result = await scanTool.execute({
  id: "test-rule",
  language: "javascript",
  pattern: "$PATTERN",
  newField: "value",
});

// 2. Parse and validate YAML
const yaml = parseYamlSafe(result.yaml);
assertYamlField(yaml, "newField", "value");
assertYamlStructure(yaml, ["id", "language", "rule", "newField"]);

// 3. Verify YAML escaping for special characters
```

## Runtime Environment

- Node.js >= 18.0.0 or Bun >= 1.0.0
- Uses native `fetch` for downloads (Node 18+ built-in)
- TypeScript with strict mode enabled
- ESM modules only (`"type": "module"`)
