A testing MCP server featuring persistence, Git, and other essential tools for everyday project management, writing, and coding.
The mcp-server offloads heavy tool outputs (large file reads, git diffs/show, fetched URLs, command output) into a persistent, content-addressed SQLite store. Each captured payload is identified by a SHA-256 content hash and is reachable from the client via the records://{hash} MCP resource. Project decisions (when enabled) are cross-linked to the snapshots that were captured at the moment they were recorded, so the rationale and the code state stay tied together.
Key features:
- Content-Addressed Records: All captured payloads live in a SQLite-backed scratchpad keyed by SHA-256 hash.
- Automatic Snapshotting: Write tools (
write_files,update_file) automatically snapshot the affected files and, when project tracking is enabled, attach those hashes to a recorded decision viasnapshot_id. - Smart Caching: Tool results are persistently memoized (mtime, size, hash-aware) so repeated queries hit cache instead of disk/git.
- Parallel Processing: Worker threads offload heavy I/O, git, and SQLite operations so the MCP request loop stays responsive.
Requires:
{
"mcpServers": {
"cabrera-mcp": {
"command": "npx",
"args": ["-y", "@cdcabrera/cabrera-mcp@latest"],
"description": "Persistence, Git, and other essential tools for everyday project management, writing, and coding."
}
}
}Requires:
Important
When running in a container, you must mount the host directory you want the server to access to the /data volume inside the container.
To activate optional features (like ALLOW_WRITE, ENABLE_NODE, etc.) or configure limits (like MCP_MAX_BUFFER) when running in a container, pass them as environment variables using the -e flag:
{
"mcpServers": {
"cabrera-mcp": {
"command": "podman",
"env": {
"PODMAN_USERNS": "keep-id"
},
"args": [
"run",
"--rm",
"-i",
"-v", "/path/to/your/project:/data:z",
"-e", "ALLOW_WRITE=true",
"-e", "ENABLE_NODE=true",
"-e", "MCP_MAX_BUFFER=52428800",
"--security-opt=no-new-privileges",
"--cap-drop=ALL",
"localhost/cabrera-mcp:latest",
"--log-stderr"
],
"description": "Persistence, Git, and other essential tools for everyday project management, writing, and coding."
}
}
}| Variable | Description | Default |
|---|---|---|
ROOT_DIRECTORY |
Root path for all filesystem operations. Access outside this path is denied. May also be passed as the first CLI argument. | Current working directory |
ALLOW_WRITE |
Set to "true" to enable the write_files and update_file tools. |
"false" |
ENABLE_NODE |
Set to "true" to enable the node and npm execution tools. |
"false" |
ENABLE_PODMAN |
Set to "true" to enable the podman and podman-compose execution tools. |
"false" |
ENABLE_PROJECT |
Set to "true" to enable the project decision tracking tools and automatic snapshot capture on file writes. |
"false" |
SCRATCHPAD_DB_PATH |
Path to the SQLite scratchpad database. Use ":memory:" for volatile storage. |
":memory:" |
SCRATCHPAD_DB_SIZE_LIMIT |
Maximum size of the persistent store in bytes. | 1073741824 (1 GiB) |
SCRATCHPAD_DB_PROJECT_ID |
Stable project identifier. Required when using persistent storage (i.e., when SCRATCHPAD_DB_PATH is a file). |
"" |
MCP_MAX_BUFFER |
Maximum buffer size for process execution in bytes. | 52428800 (50 MiB) |
Unless noted, every tool is always registered. Tools gated by an environment variable are explicitly marked.
list_directory: List directory contents with details. Supports recursive listing, tree-style output, and name-pattern filtering.get_file_info: Detailed file metadata and type information viastatandfile.read_file: Read a file. Supportssummary(metadata + peek) andfulldetail levels; supportsjq/yqfiltering for JSON/YAML when those binaries are available.search_files: Recursive grep-style search across a directory for strings and content.grep:grepinvocation with arbitrary flags (useful for context lines, case-insensitive matching, etc.).diff: Compare two files or directories using the systemdifftool. Only registered whendiffis available onPATH.write_files(requiresALLOW_WRITE=true): Write multiple files asynchronously.update_file(requiresALLOW_WRITE=true): Update a single file: full overwrite or surgical search-and-replace.
When ENABLE_PROJECT=true, write_files and update_file additionally trigger an automatic capture of the affected files into the scratchpad and record a decision row whose snapshot_id references the captured content hashes.
git_log: Commit log. Supportssummary(one-line) andfulldetail levels.git_show: Show a commit.summaryreturns metadata + file list;fullreturns the patch. Large outputs are also captured into the scratchpad in the background.git_diff: Show diff.summaryreturns--stat;fullreturns the patch. Large outputs are also captured into the scratchpad in the background.git_query: Execute a read-only git subcommand (status,blame,branch,tag,ls-files,ls-tree,config,remote,rev-parse,describe,stash,grep,log,show,diff) with allow-listed flags. Destructive flags are rejected.
fetch_url: Fetch content from one or more URLs in parallel. Supportssummaryandfulldetail levels.
get_system_info(registered only whenps,lsof, ornetstatare available): System information such as active processes, open ports, and network status. The supportedtypevalues depend on which binaries are present.
node: Run a localnodecommand.npm: Run a localnpmcommand.
podman: Run a localpodmancommand.podman_compose: Run a localpodman-composecommand. Only registered whenpodman-compose(orpodman compose) is available onPATH.
run_async_command: Run a command in the background and return a job ID immediately. Useful for long-running tasks.get_async_job_status: Get the status, stdout, stderr, and exit code of a background job.stop_async_job: Forcefully stop a running background job using itsjobId.list_async_jobs: List all active and completed background jobs with their respectivejobIds and execution statuses.
record_decision: Explicitly record a significant architecture/project decision or plan. Parameters:title,description,category(architectural|refactor|feature|manual, defaultmanual). The server does not accept a diff parameter — file snapshots are linked automatically by the filesystem write tools viasnapshot_id.search_decisions: Search historical decisions byquery,file_path,start_date/end_date,category, withlimit/offset. Uses a Project ID → Project Root → Orphans fallback so history survives project renames.get_decision_log: Chronological list of recent decisions. Supportscategory,limit,offset.get_decision_entry: Retrieve a single decision and its linked record content. Accepts eitherid(decision row id; appends content for every linkedsnapshot_idhash) orhash(returns the raw record body directly). Useful for clients that do not natively support MCP resources.
record: Provides a template for recording decisions. Takesdirections(e.g., "the plan we just went over") and instructs the model to userecord_decisionto document it, inferring the title, rationale, and category from the conversation context.
Three resource templates are registered to retrieve scratchpad records and runtime configuration details:
records://{hash}: Resolves to the decoded body of a specific scratchpad record by its content hash.records://{id}: Resolves to the decoded body of a specific scratchpad record by its metadata ID.records://context(Registered asproject-context): Yields general information, limits, and runtime environment settings of the running MCP server.
results://{jobId}: Resolves to the current status and captured output (stdout/stderr) of a specific background job.jobs://list(Registered asasync-jobs-list): Resolves to a structured text listing of all active and recently executed background jobs.
Records are produced automatically by:
- Filesystem writes (
write_files,update_file) capturing the touched files. - Background ingestion in
git_show/git_diffwhen theirsummaryform is requested. - Any tool path that calls into the scratchpad (
loadFromFile,loadFromCommand, etc.).
When ENABLE_PROJECT=true, the comma-separated hashes captured during a write are stored in project_decisions.snapshot_id and can be replayed through get_decision_entry or directly through the records:// resource.
The @modelcontextprotocol/inspector is the recommended way to visualize the server's interface.
- Build the MCP:
npm install npm run build
- Start the Inspector:
npx -y @modelcontextprotocol/inspector node dist/index.js
- Interact: The inspector opens a web interface (typically at
http://localhost:5173) where you can list tools, resources, and prompts, then execute and view their responses.
- Path isolation: Every filesystem and git operation is resolved against
ROOT_DIRECTORY; any path that escapes the root is rejected. - Injection protection: Prepared statements for all SQLite access;
execFile(never shell) with allow-listed arguments for child processes;git_queryrejects destructive flags. - Non-blocking architecture: Heavy I/O, git, and SQLite work runs in worker threads so MCP requests stay responsive.