# GhostLink **A security-hardened MCP server that gives AI coding agents safe, deterministic access to local repositories.** [![CI](https://github.com/bgorzelic/ghostlink/actions/workflows/ci-typescript.yml/badge.svg)](https://github.com/bgorzelic/ghostlink/actions/workflows/ci-typescript.yml) [![npm](https://img.shields.io/npm/v/%40bgorzelic%2Fghostlink?style=flat&logo=npm&logoColor=white&label=npm)](https://www.npmjs.com/package/@bgorzelic/ghostlink) [![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6?style=flat&logo=typescript&logoColor=white)](tsconfig.json) [![Node](https://img.shields.io/badge/Node.js-%E2%89%A518-339933?style=flat&logo=nodedotjs&logoColor=white)](.nvmrc) [![Tests](https://img.shields.io/badge/tests-108%20passing-brightgreen?style=flat&logo=vitest&logoColor=white)](tests/) [![License: ISC](https://img.shields.io/badge/license-ISC-blue?style=flat)](LICENSE) Add it to any MCP client that supports STDIO. For Claude Code, create `.mcp.json` in the target repo root: ```json { "mcpServers": { "ghostlink": { "command": "npx", "args": ["-y", "@bgorzelic/ghostlink"], "env": { "GHOSTLINK_REPO_ROOT": "/path/to/target/repo" } } } } ``` Then run `claude` in that directory — six repo tools appear, all confined to `GHOSTLINK_REPO_ROOT`. Every tool call returns the same deterministic `ToolEnvelope`: ```json { "ok": true, "data": { ... }, "provenance": { "tool": "repo.search", "timestamp": "2026-02-24T...", "duration_ms": 42 } } ``` On error, `"error": { "code": "...", "message": "..." }` replaces `"data"`. Full tool schemas: [docs/TOOLS.md](docs/TOOLS.md). ## Tools | Tool | Description | |---|---| | `repo.search` | Ripgrep-powered regex search with glob filtering, deterministic ordering, and output caps (max 200 results) | | `repo.read_file` | File read with size caps (max 10MB), binary detection, and truncation flags | | `repo.apply_patch` | Unified diff patching with dry-run mode, full sandbox validation, and atomic rollback on failure | | `repo.run` | Curated command execution (test, lint, typecheck, build, smoke) -- no arbitrary shell, allowlisted args only | | `git.status` | Normalized git status with branch info, ahead/behind tracking, and sorted file entries | | `git.diff` | Staged or unstaged diff with path filtering, sandbox validation, and output caps (max 2MB) | ## What is GhostLink? GhostLink is a local-first [Model Context Protocol](https://modelcontextprotocol.io) server that exposes your codebase to AI coding agents through a small set of policy-gated tools. It solves a specific problem: AI agents need to search, read, patch, and verify code, but giving them raw shell access is a liability. GhostLink provides a sandboxed capability plane where every tool call is confined to a single repository root, every output follows a deterministic JSON shape, and every invocation is audit-logged. ## Why GhostLink? | Capability | What it means | |---|---| | Secure local dev plane | Repo-root sandbox, no shell execution, JSONL audit trail on every tool call | | Deterministic output | Same input produces the same JSON envelope shape -- enables golden tests and predictable agent consumption | | Policy enforcement | Command allowlists, output caps, truncation flags, timeout enforcement -- the AI cannot do unbounded damage | | Agent loop foundation | Built for the search, read, patch, verify cycle that autonomous coding agents run in a loop | | Multi-server composition | One GhostLink instance per repo, composable with other MCP servers in the same client session | | Production-ready Phase 2 base | Transport abstraction, schema versioning, and auth hook seams are preserved in the architecture today | ## Architecture GhostLink is a three-layer stack designed for extensibility without core changes: ```mermaid flowchart TD T["Transport -- src/index.ts
STDIO now, HTTP/SSE in Phase 2"] S["Server factory -- src/server.ts
Transport-agnostic tool registration via MCP SDK + Zod schemas"] TL["Tools -- src/core/tools/*
Six tools, each returning ToolEnvelope<T>"] P["Policy -- src/core/policy/*
Sandbox enforcement, audit logging, output caps"] T --> S --> TL --> P ``` The `createServer()` factory knows nothing about transport. Adding HTTP/SSE in Phase 2 means writing a new transport binding and auth middleware -- the server factory and all tool implementations remain unchanged. Phase 3 (agent runtime) adds memory resources and orchestration as consumers of GhostLink, not modifications to it. ## Quick Start ### Prerequisites - Node.js 18+ - ripgrep (`brew install ripgrep`) - A git repository to expose ### Install From npm: ```bash npm install @bgorzelic/ghostlink ``` Or from source: ```bash git clone https://github.com/bgorzelic/ghostlink.git cd ghostlink npm install npm run build ``` ### Smoke Test (Raw STDIO) GhostLink speaks JSON-RPC 2.0 over STDIO. Test it directly: ```bash echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | \ GHOSTLINK_REPO_ROOT=/path/to/target/repo node dist/index.js ``` This returns all 6 tools and their schemas. ## Client Configuration GhostLink works with any MCP client that supports STDIO transport. The `npx` snippet at the top of this page works everywhere; a source checkout uses `node` with the built entry point instead: ```json { "ghostlink": { "command": "node", "args": ["/absolute/path/to/ghostlink/dist/index.js"], "env": { "GHOSTLINK_REPO_ROOT": "/path/to/target/repo" } } } ``` | Client | Where the config goes | |---|---| | Claude Code | `.mcp.json` in the target repo root (`mcpServers` key), then run `claude` there | | Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json` (`mcpServers` key), then restart | | Cursor, Windsurf, Cline, others | Your client's MCP server configuration -- consult its documentation for the file location | The transport is always STDIO. Ready-to-use `.mcp.json` and CLAUDE.md templates for target projects live in [templates/](templates/). ## Security Model GhostLink enforces defense-in-depth at every layer: - **Repo-root sandbox** -- All file operations confined to `GHOSTLINK_REPO_ROOT`. Path traversal, symlink escape, null bytes, and absolute paths outside the root are all rejected before any filesystem access. - **No shell execution** -- `repo.run` uses `spawn` with `shell: false`. Commands are limited to a fixed allowlist (test, lint, typecheck, build, smoke) with per-command argument allowlists. Environment is stripped to six safe variables. - **Output caps** -- Every tool that returns bulk data enforces hard maximums (200 search results, 10MB file reads, 200KB stdout/stderr, 2MB diffs). Truncation is flagged, never silent. - **Atomic patch rollback** -- `repo.apply_patch` validates all paths and computes all patches before writing anything. If any write fails, completed writes are rolled back to their original state. - **Timeout enforcement** -- `repo.run` kills processes at configurable timeouts (default 120s, hard cap 300s) with SIGTERM then SIGKILL. Full threat model and mitigations: [docs/SECURITY.md](docs/SECURITY.md). ## Audit Logging Every tool call produces a JSONL audit entry: `{ts, tool, ok, duration_ms, error_code?, repo_root}`. | `GHOSTLINK_LOG` | Behavior | |---|---| | `stdout` (default) | JSONL audit lines written to stderr | | `file` | JSONL written to `logs/ghostlink.jsonl` (auto-rotates at 10MB) | | `off` | No logging | Set via environment variable: ```bash GHOSTLINK_LOG=file GHOSTLINK_REPO_ROOT=/path/to/repo node dist/index.js ``` ## Prompt Templates [docs/PROMPTS.md](docs/PROMPTS.md) contains ready-to-use prompts for high-autonomy agent operation, including orchestrator prompts, sub-agent role definitions (Protocol Engineer, Toolsmith, Security Reviewer, Test Engineer, Docs Engineer), and multi-instance coordination patterns. ## Development ```bash npm install # Install dependencies npm test # Run test suite (108 tests via Vitest) npm run lint # ESLint npm run typecheck # TypeScript strict mode check npm run build # Compile to dist/ npm run dev # Dev mode with auto-reload (tsx watch) ``` Full verification after edits: ```bash npm test && npm run lint && npm run typecheck && npm run build ``` ## Documentation | Document | Description | |---|---| | [docs/TOOLS.md](docs/TOOLS.md) | Canonical tool schemas (versioned public API) | | [docs/SECURITY.md](docs/SECURITY.md) | Threat model and mitigations | | [docs/QUICKSTART.md](docs/QUICKSTART.md) | Setup, smoke tests, and client configuration walkthrough | | [docs/INSPECTOR.md](docs/INSPECTOR.md) | MCP Inspector manual testing guide | | [docs/PROMPTS.md](docs/PROMPTS.md) | Agent prompts for orchestration and sub-agent roles | | [docs/ROADMAP_DETAILED.md](docs/ROADMAP_DETAILED.md) | Full product roadmap with Phase 2 and Phase 3 deliverables | | [docs/WHY_GHOSTLINK.md](docs/WHY_GHOSTLINK.md) | Strategic value proposition and architecture rationale | | [docs/ENGINEERING_REPORT_v0.1.0.md](docs/ENGINEERING_REPORT_v0.1.0.md) | v0.1.0 ship report with milestone history and decision log | | [templates/](templates/) | Ready-to-use CLAUDE.md and .mcp.json templates for target projects | ## Roadmap ### Phase 1 -- Local STDIO [Shipped, v0.1.0] Deterministic tool surface, repo-root sandbox, curated command execution, 108 tests, JSONL audit logging, npm package published. ### Phase 2 -- Remote Transport [Planned] HTTP/SSE transport, OAuth 2.1 authentication, multi-user tenant separation, per-tenant rate limiting, schema versioning, structured audit logging with correlation IDs. ### Phase 3 -- Agent Runtime [Future] Persistent memory resources exposed via MCP, optional policy-gated memory write tools, orchestration layer (external to GhostLink), evaluation loops, sub-agent coordination framework. ## License ISC