GhostLink
A security-hardened MCP server that gives AI coding agents safe, deterministic access to local repositories.
What is GhostLink?
GhostLink is a local-first Model Context Protocol 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 |
| 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) |
Every tool returns a ToolEnvelope:
{
"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.
Quick Start
Prerequisites
- Node.js 18+
- ripgrep (
brew install ripgrep)
- A git repository to expose
Install and Build
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:
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.
npm Package
npm install @bgorzelic/ghostlink
Client Configuration
GhostLink works with any MCP client that supports STDIO transport.
Claude Code
Create .mcp.json in the target repo root:
{
"mcpServers": {
"ghostlink": {
"command": "node",
"args": ["/absolute/path/to/ghostlink/dist/index.js"],
"env": {
"GHOSTLINK_REPO_ROOT": "/path/to/target/repo"
}
}
}
}
Then run claude in that directory. GhostLink tools appear as available MCP tools.
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ghostlink": {
"command": "node",
"args": ["/absolute/path/to/ghostlink/dist/index.js"],
"env": {
"GHOSTLINK_REPO_ROOT": "/path/to/target/repo"
}
}
}
}
Restart Claude Desktop. GhostLink tools appear in the tool picker.
Cursor, Windsurf, Cline, and Other MCP Clients
Add to your client's MCP server configuration:
{
"ghostlink": {
"command": "node",
"args": ["/absolute/path/to/ghostlink/dist/index.js"],
"env": {
"GHOSTLINK_REPO_ROOT": "/path/to/target/repo"
}
}
}
Consult your client's documentation for the exact config file location. The transport is always STDIO.
Prompt Templates
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.
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.
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:
GHOSTLINK_LOG=file GHOSTLINK_REPO_ROOT=/path/to/repo node dist/index.js
Development
npm install
npm test
npm run lint
npm run typecheck
npm run build
npm run dev
Full verification after edits:
npm test && npm run lint && npm run typecheck && npm run build
Documentation
Architecture
GhostLink is a three-layer stack designed for extensibility without core changes:
Transport (src/index.ts) STDIO now, HTTP/SSE in Phase 2
|
Server Factory (src/server.ts) Transport-agnostic tool registration via MCP SDK + Zod schemas
|
Tools (src/core/tools/*) Six tools, each returning ToolEnvelope<T> through shared policy
|
Policy (src/core/policy/*) Sandbox enforcement, audit logging, output caps
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.
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