{"id":33665702,"url":"https://github.com/yaniv-golan/mcp-bash-framework","last_synced_at":"2026-04-05T10:04:09.186Z","repository":{"id":326018190,"uuid":"1078318974","full_name":"yaniv-golan/mcp-bash-framework","owner":"yaniv-golan","description":"Portable Bash-only framework for building stdio Model Context Protocol (MCP) servers with zero dependencies.","archived":false,"fork":false,"pushed_at":"2026-04-03T14:14:53.000Z","size":11598,"stargazers_count":5,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-03T15:53:19.362Z","etag":null,"topics":["agents","automation","bash","cli","cross-platform","devtools","framework","linux","llm-integration","llm-tools","macos","mcp","mcpb","model-context-protocol","portable","sdk","shell","stdio"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yaniv-golan.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-17T14:42:55.000Z","updated_at":"2026-04-03T14:14:59.000Z","dependencies_parsed_at":"2026-01-05T12:03:31.245Z","dependency_job_id":null,"html_url":"https://github.com/yaniv-golan/mcp-bash-framework","commit_stats":null,"previous_names":["yaniv-golan/mcp-bash-framework"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/yaniv-golan/mcp-bash-framework","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaniv-golan%2Fmcp-bash-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaniv-golan%2Fmcp-bash-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaniv-golan%2Fmcp-bash-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaniv-golan%2Fmcp-bash-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yaniv-golan","download_url":"https://codeload.github.com/yaniv-golan/mcp-bash-framework/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yaniv-golan%2Fmcp-bash-framework/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31431454,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-05T08:13:15.228Z","status":"ssl_error","status_checked_at":"2026-04-05T08:13:11.839Z","response_time":75,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","automation","bash","cli","cross-platform","devtools","framework","linux","llm-integration","llm-tools","macos","mcp","mcpb","model-context-protocol","portable","sdk","shell","stdio"],"created_at":"2025-12-03T02:00:20.210Z","updated_at":"2026-04-05T10:04:09.173Z","avatar_url":"https://github.com/yaniv-golan.png","language":"Shell","funding_links":[],"categories":["SDKs"],"sub_categories":["Bash"],"readme":"\u003c!--\nNOTE: README.md is generated from README.md.in.\nEdit README.md.in and run: bash scripts/render-readme.sh\n--\u003e\n\n# mcp-bash\n\n[![mcp-bash framework banner](assets/mcp-bash-framework.png)](assets/mcp-bash-framework.png)\n\n[![CI](https://img.shields.io/github/actions/workflow/status/yaniv-golan/mcp-bash-framework/ci.yml?branch=main\u0026label=CI)](https://github.com/yaniv-golan/mcp-bash-framework/actions)\n[![License](https://img.shields.io/github/license/yaniv-golan/mcp-bash-framework)](LICENSE)\n[![Bash](https://img.shields.io/badge/bash-%3E%3D3.2-green.svg)](https://www.gnu.org/software/bash/)\n[![MCP Protocol](https://img.shields.io/badge/MCP-2025--11--25-blue)](https://modelcontextprotocol.io/specification)\n[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey)](#runtime-requirements)\n\n\u003e **Repository:** [`mcp-bash-framework`](https://github.com/yaniv-golan/mcp-bash-framework) \u0026nbsp;•\u0026nbsp; **CLI/Binary:** `mcp-bash`\n\n\u003e **For AI agents:** Read [`llms.txt`](llms.txt) (compact) or [`llms-full.txt`](llms-full.txt) (detailed) for agent-optimized context — includes a step-by-step Quick Start, critical allowlist requirement, and CLI wrapper patterns.\n\n## Contents\n\n- [MCP Spec Coverage](#mcp-spec-coverage)\n- [Why Bash?](#why-bash)\n- [Quick Start](#quick-start)\n- [Security Model (60 seconds)](#security-model-60-seconds)\n- [Configure Your MCP Client](#configure-your-mcp-client)\n- [MCPB Bundles](#mcpb-bundles)\n- [Vendoring the Runtime](#vendoring-the-runtime)\n- [Project Structure](#project-structure)\n- [Configuration](#configuration)\n- [Learn by Example](#learn-by-example)\n- [Documentation](#documentation)\n- [Built with mcp-bash](#built-with-mcp-bash)\n- [FAQ](#faq)\n\n\u003e **The most complete MCP implementation in pure Bash.** Tools, resources, prompts, elicitation, roots, progress, cancellation—the full spec, no runtimes beyond your shell.\n\u003e\n\u003e - Runs on Bash 3.2+ (macOS/Linux stock). No Node, no Python, no containers.\n\u003e - Handles concurrency, timeouts, and cancellation the way production systems need.\n\u003e - You write the tools. The framework stays out of your way.\n\n## TL;DR\n\n**Turn any Bash script into an MCP tool in minutes.** No Node, no Python, no containers.\n\n```bash\nmcp-bash new my-server \u0026\u0026 cd my-server\nmcp-bash scaffold tool my-tool   # edit tools/my-tool/tool.sh\nmcp-bash config --client cursor  # paste into your MCP client\nmcp-bash bundle                  # create distributable package\n```\n\n## What you’ll build\n\n```mermaid\nflowchart TD\n  Client[\"MCP client\u003cbr/\u003e(Claude Desktop / Cursor / Windsurf)\"]\n  Transport[\"stdio (JSON-RPC)\"]\n  Framework[\"mcp-bash framework\u003cbr/\u003e(registry + runtime + policy)\"]\n  Project[\"Your project\u003cbr/\u003etools/ resources/ prompts/ server.d/\"]\n\n  Client --\u003e Transport --\u003e Framework --\u003e Project\n```\n\n## Design Principles\n\n- Tools shouldn’t need another runtime to talk to AI.\n- Everything must be inspectable. No magic.\n- If it’s not needed in production, it isn’t in the framework.\n- Your project stays yours. The framework upgrades cleanly.\n\n## MCP Spec Coverage\n\nmcp-bash targets the **2025-11-25** MCP specification with negotiated downgrades to older versions.\n\n| Category | Coverage | Notes |\n|----------|----------|-------|\n| Core Protocol | ✅ Full | Lifecycle, ping, capabilities, downgrades |\n| Tools | ✅ Full | list, call, icons, errors, listChanged, annotations |\n| Resources | ✅ Full | list, read, subscriptions, templates, binary, annotations |\n| Prompts | ✅ Full | list, get, arguments, icons |\n| Utilities | ✅ Full | Progress, cancellation, logging, completion |\n| Elicitation | ✅ Full | Form, URL, enum, multi-choice modes |\n| Roots | ✅ Full | Server→client request, listChanged |\n| MCP Apps (UI) | ⚠️ Partial | `ui://` resources, templates; interactivity blocked by [host bug](https://github.com/modelcontextprotocol/ext-apps/issues/386) |\n\n**Not yet implemented:** Audio content, sampling. Tasks (async job/poll) and server-identity discovery are HTTP-oriented and not applicable to stdio.\n\nTransport is stdio-only by design. See [Remote Connectivity](docs/REMOTE.md) for HTTP/SSE proxy options, including the shared-secret guard (`MCPBASH_REMOTE_TOKEN`) and readiness probe (`mcp-bash --health`).\n\n→ [Full compliance matrix](SPEC-COMPLIANCE.md)\n\nFor a complete feature-by-feature breakdown across all MCP versions, see the [Feature Support Matrix](SPEC-COMPLIANCE.md#feature-support-matrix) in `SPEC-COMPLIANCE.md`.\n\n## Why Bash?\n\n| | mcp-bash | TypeScript SDK | Python SDK |\n|---|----------|----------------|------------|\n| Runtime | Bash 3.2+ (pre-installed) | Node.js 18+ | Python 3.10+ |\n| Install | `brew install` or `curl \\| bash` | `npm install` | `pip install` |\n| Startup | No VM warmup | Node.js startup | Python startup |\n| Dependencies | jq or gojq | npm packages | pip packages |\n| Best for | Shell automation, existing scripts, air-gapped/minimal environments | Node.js applications | Python applications |\n\nIf your tools are already shell scripts, wrapping them in Node or Python adds complexity for no benefit. mcp-bash lets you expose them directly.\n\n## Quick Start\n\nWhen you run `mcp-bash` from inside a project (a directory containing `server.d/server.meta.json`), it auto-detects the project root. Running `mcp-bash` outside any project starts a temporary getting-started helper tool. For MCP clients, set `MCPBASH_PROJECT_ROOT` so the server can find your project regardless of working directory.\n\n### 0. Requirements (10 seconds)\n\n```bash\n# Preflight: Bash 3.2+ and jq/gojq for full functionality (tools/resources/prompts).\nbash --version | head -1\ncommand -v jq \u003e/dev/null 2\u003e\u00261 || command -v gojq \u003e/dev/null 2\u003e\u00261 || printf '%s\\n' '⚠ jq/gojq missing: minimal mode only (tools/resources/prompts disabled)'\n```\n\n### 1. Install the Framework\n\n**Homebrew** (macOS and Linux — recommended):\n\n```bash\nbrew install yaniv-golan/mcp-bash/mcp-bash\n```\n\nUpdate later with `brew upgrade mcp-bash`.\n\n**curl installer** (CI, Docker, Windows/Git Bash, or environments without Homebrew):\n\n```bash\ncurl -fsSL \"https://raw.githubusercontent.com/yaniv-golan/mcp-bash-framework/v1.2.1/install.sh\" | bash -s -- --yes --version \"v1.2.1\"\n```\n\nVerified install (recommended for production / security-sensitive environments):\n\n```bash\nversion=\"v1.2.1\"\nfile=\"mcp-bash-${version}.tar.gz\"\ncurl -fsSLO \"https://github.com/yaniv-golan/mcp-bash-framework/releases/download/${version}/${file}\"\ncurl -fsSLO \"https://github.com/yaniv-golan/mcp-bash-framework/releases/download/${version}/SHA256SUMS\"\n\n# Verify (macOS):\ngrep -E \"([[:space:]]|\\\\*)${file}$\" SHA256SUMS | shasum -a 256 -c -\n# Verify (Linux):\ngrep -E \"([[:space:]]|\\\\*)${file}$\" SHA256SUMS | sha256sum -c -\n\ncurl -fsSLO \"https://raw.githubusercontent.com/yaniv-golan/mcp-bash-framework/${version}/install.sh\"\nbash install.sh --archive \"${file}\" --version \"${version}\"\n```\n\nWhy this is “verified”: you download the release tarball + `SHA256SUMS`, verify the checksum locally, then run the installer against the verified archive.\n\nFor tagged releases (`vX.Y.Z`), the installer also attempts to verify the archive against `SHA256SUMS` automatically when it’s available.\n\nManual/offline install (for policy-driven or air-gapped environments):\n\n```bash\ngit clone https://github.com/yaniv-golan/mcp-bash-framework.git ~/.local/share/mcp-bash\nmkdir -p ~/.local/bin \u0026\u0026 ln -sf ~/.local/share/mcp-bash/bin/mcp-bash ~/.local/bin/mcp-bash\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' \u003e\u003e ~/.bashrc  # or ~/.zshrc (if not already in PATH)\n```\n\nPin a release with the installer (auto-prefixes `v` for bare versions):\n\n```bash\nbash install.sh --verify \u003csha256-from-SHA256SUMS\u003e --version 1.2.1\n```\n\n### 1.5 Verify It Works (30 seconds)\n\nSecurity defaults: hooks are disabled unless `MCPBASH_ALLOW_PROJECT_HOOKS=true`, and tools require an explicit allowlist (`MCPBASH_TOOL_ALLOWLIST=*` to allow all in trusted projects).\n\n```bash\nmcp-bash doctor\n# Expected output includes lines like:\n#   ✓ Bash version: 5.x.x (\u003e= 3.2 required)\n#   ✓ jq installed: /usr/bin/jq\n#   All checks passed! Ready to build MCP servers.\n\n# Preview and apply managed-install repairs (shim + optional upgrade when --min-version is set):\nmcp-bash doctor --dry-run\nmcp-bash doctor --fix\n\n# Quick end-to-end test (optional):\nmcp-bash new demo-server\ncd demo-server\nmcp-bash run-tool hello --allow-self --args '{\"name\":\"World\"}'\n# Expected output includes: \"Hello, World!\"\n\n# Cleanup (the demo-server directory persists until you remove it):\ncd .. \u0026\u0026 rm -rf demo-server\n```\n\n### 1.6 Uninstall (if needed)\n\nTo completely remove mcp-bash from your system:\n\n```bash\n# 1. Remove the framework installation\nrm -rf ~/.local/share/mcp-bash\n\n# 2. Remove the symlink\nrm -f ~/.local/bin/mcp-bash\n\n# 3. Remove any generated wrapper scripts (in each project)\nrm -f /path/to/your/project/*.sh  # e.g., my-server.sh, my-server-env.sh\n\n# 4. (Optional) Remove PATH addition from your shell config\n#    Edit ~/.bashrc or ~/.zshrc and remove the line:\n#    export PATH=\"$HOME/.local/bin:$PATH\"\n```\n\n**Notes:**\n- Your project directories (`tools/`, `resources/`, `prompts/`) are untouched—they live in your own repos.\n- Wrapper scripts are only created if you ran `mcp-bash config --wrapper` or `--wrapper-env`.\n- After uninstalling, you can reinstall anytime with the Quick Install command above.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eSomething not working?\u003c/strong\u003e (click to expand)\u003c/summary\u003e\n\n| Symptom | Likely cause | Fix |\n|---------|--------------|-----|\n| `mcp-bash: command not found` | PATH not configured | `export PATH=\"$HOME/.local/bin:$PATH\"` then open a new shell |\n| “Operating in minimal mode…” / tools missing | `jq`/`gojq` missing | `brew install jq` or `apt install jq` |\n| “blocked by policy” | Default-deny tool policy | CLI: re-run with `--allow-self`. MCP clients: set `MCPBASH_TOOL_ALLOWLIST` in client config |\n| Claude Desktop starts but shows no tools | GUI non-login env / PATH | Use `mcp-bash config --wrapper-env` and point the client at the wrapper |\n| macOS `Operation not permitted` / quarantine | Gatekeeper quarantine | `scripts/macos-dequarantine.sh ~/.local/share/mcp-bash` (trusted paths only), restart client |\n| Windows Git Bash path weirdness | MSYS path conversion | `MSYS2_ARG_CONV_EXCL=\"*\"` (and prefer `jq` on Windows CI) |\n\nStill stuck? Run `mcp-bash doctor` (or `mcp-bash doctor --json`) and include output when opening an issue.\n\n\u003c/details\u003e\n\n### 2. Create Your Project\n\nYour server code lives in a separate project directory:\n\n```bash\nmcp-bash new my-mcp-server\ncd my-mcp-server\n```\n\nAlready in a directory you created yourself? Run `mcp-bash init --name my-mcp-server [--no-hello]` instead.\n\n### 3. Scaffold Your First Tool\n\n```bash\nmcp-bash scaffold tool check-disk\n```\n\nThis scaffolds `tools/check-disk/tool.sh` and `tools/check-disk/tool.meta.json` in your project. You write the logic.\nEach scaffolded tool also includes `tools/check-disk/smoke.sh`—run it after edits to ensure your tool’s stdout is valid JSON (update the sample args in the script if you change `tool.meta.json`).\n\n### 3.5 (Optional) Add a Test Harness\n\nCreate a lightweight runner for tool smoke tests:\n\n```bash\nmcp-bash scaffold test\n./test/run.sh --verbose  # add run_test calls inside test/run.sh\n```\n\nThe harness wraps `mcp-bash run-tool`, validates your project before running, and refuses to overwrite existing `test/run.sh` or `test/README.md`.\n\n## Security Model (60 seconds)\n\nmcp-bash is **secure by default**. Here's what that means:\n\n| Layer | Default | What it does |\n|-------|---------|--------------|\n| **Tool allowlist** | Deny all | Tools won't run unless explicitly listed in `MCPBASH_TOOL_ALLOWLIST` |\n| **Hooks** | Disabled | Project hooks (`server.d/*.sh`) are ignored unless `MCPBASH_ALLOW_PROJECT_HOOKS=true` |\n| **Tool environment** | Minimal | Tools inherit only essential vars (`PATH`, `HOME`, `TERM`). Use `MCPBASH_TOOL_ENV_MODE` to change |\n\n### Quick reference\n\n```bash\n# Allow a single tool (CLI)\nmcp-bash run-tool my-tool --allow-self --args '{}'\n\n# Allow specific tools (MCP client config)\nMCPBASH_TOOL_ALLOWLIST=\"tool1,tool2\"\n\n# Allow all tools (trusted projects only)\nMCPBASH_TOOL_ALLOWLIST=\"*\"\n\n# Enable project hooks (server.d/*.sh)\nMCPBASH_ALLOW_PROJECT_HOOKS=true\n\n# Tool environment modes\nMCPBASH_TOOL_ENV_MODE=minimal    # default: PATH, HOME, TERM only\nMCPBASH_TOOL_ENV_MODE=inherit    # pass through parent environment\nMCPBASH_TOOL_ENV_MODE=allowlist  # minimal + MCPBASH_TOOL_ENV_ALLOWLIST vars\n```\n\n**Demo tip:** For local testing, use `--allow-self` (CLI) or `MCPBASH_TOOL_ALLOWLIST=*` (MCP clients). For production, allowlist only the tools you need.\n\n→ [Full security guide](docs/SECURITY.md) · [Environment reference](docs/ENV_REFERENCE.md)\n\n## Configure Your MCP Client\n\nEvery client works the same way: point it at the framework and tell it where your project lives:\n\n1. Set `MCPBASH_PROJECT_ROOT=/path/to/your/project`.\n2. Point it at the `mcp-bash` binary (installed to `~/.local/bin/mcp-bash` by the installer).\n   - If you generated a wrapper via `mcp-bash config --wrapper` or `--wrapper-env`, you can point clients at `\u003cproject-root\u003e/\u003cserver-name\u003e.sh`; the wrapper already wires `MCPBASH_PROJECT_ROOT` for you.\n\n### Generate Config (CLI)\n\n```bash\nmcp-bash config --show\nmcp-bash config --json           # machine-readable descriptor (name/command/env)\nmcp-bash config --client cursor  # client-specific snippet\nmcp-bash config --inspector      # ready-to-run Inspector command (stdio)\nmcp-bash config --wrapper-env    # wrapper that sources your shell profile first (macOS-safe)\nmcp-bash config --wrapper        # TTY: creates ./\u003cserver-name\u003e.sh; piped/redirected: stdout\n```\n\n`config --show` prints one labeled snippet per supported client (headings like `# Claude Desktop`, `# Cursor`, etc.) so you can see which block to copy; use `--client \u003cname\u003e` or `--json` when you only want a single paste-ready block.\n\nCopy the snippet for your client (Claude Desktop/CLI/Code, Cursor, Windsurf, LibreChat, etc.) and paste it into the appropriate config file. This sets `MCPBASH_PROJECT_ROOT` and the `mcp-bash` command path for you. When run in a terminal (stdout is a TTY), `config --wrapper` writes `\u003cproject-root\u003e/\u003cserver-name\u003e.sh`, marks it executable, and prints the path to stderr; piping or redirecting prints the wrapper script to stdout.\nPicking a wrapper:\n- Use `--wrapper` when your PATH/env is already correct in non-login shells (e.g., Linux, or macOS with absolute paths).\n- Use `--wrapper-env` when you need your login shell to set PATH/version managers/vars before starting the server (common on macOS Claude Desktop).\n- Distributing a server? Ship the env wrapper by default for GUI launches (macOS/Windows clients), and include a non-login wrapper or absolute runtime path for CI/WSL/Linux users who want fast, side-effect-free startups.\n\n### Per-Client Snippets\n\n- **Claude Desktop**: Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\\Claude\\claude_desktop_config.json` (Windows) and add:\n  ```jsonc\n  \"mcpServers\": {\n    \"mcp-bash\": {\n      \"command\": \"/Users/you/.local/bin/mcp-bash\",\n      \"env\": {\n        \"MCPBASH_PROJECT_ROOT\": \"/Users/you/my-mcp-server\",\n        \"MCPBASH_TOOL_ALLOWLIST\": \"*\"\n      }\n    }\n  }\n  ```\n  - macOS runtime note: Claude Desktop launches servers from a minimal, non-login shell, so your PATH, version managers (nvm/pyenv/uv/rbenv), and env vars from `.zshrc`/`.bash_profile` are skipped. Use absolute paths to runtimes (e.g., `/opt/homebrew/bin/node`) and set missing vars in the `env` block, or generate a login-aware wrapper:\n    ```bash\n    mcp-bash config --project-root /Users/you/my-mcp-server --wrapper-env \u003e /Users/you/my-mcp-server/mcp-bash.sh\n    chmod +x /Users/you/my-mcp-server/mcp-bash.sh\n    ```\n    Then point Claude Desktop at `/Users/you/my-mcp-server/mcp-bash.sh` as the `command`.\n  - macOS quarantine: Gatekeeper can block quarantined downloads (typically from browsers/DMGs/AirDrop) even when paths are correct. CLI downloads (curl/wget/git) often skip quarantine. If you see `ENOENT`, `transport closed unexpectedly`, or `Operation not permitted` despite correct paths, clear quarantine and restart Claude Desktop:\n    ```bash\n    xattr -r -d com.apple.quarantine ~/.local/share/mcp-bash\n    xattr -r -d com.apple.quarantine /Users/you/my-mcp-server\n    ```\n    Helper: `scripts/macos-dequarantine.sh [path]` will clear quarantine for the repo (or a specific path). `xattr -cr` clears all extended attributes; only use it on trusted paths.\n  - macOS folder permissions: Desktop/Documents/Downloads are TCC-protected and Downloads is often quarantined. Move servers to a neutral folder (e.g., `~/mcp-servers`) or grant Claude “Full Disk Access” and “Files and Folders” in System Settings.\n- **Claude CLI/Claude Code**: Run once:\n  ```bash\n  claude mcp add --transport stdio mcp-bash \\\n    --env MCPBASH_PROJECT_ROOT=\"$HOME/my-mcp-server\" \\\n    --env MCPBASH_TOOL_ALLOWLIST=\"*\" \\\n    -- \"$HOME/.local/bin/mcp-bash\"\n  ```\n- **Cursor**: Create `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project) with the same `mcpServers` JSON as above.\n- **Windsurf (Cascade)**: Edit `~/.codeium/windsurf/mcp_config.json` via Settings → Advanced → Cascade, and add the same `mcpServers` entry.\n- **LibreChat**: In `librechat.yaml` add:\n  ```yaml\n  mcpServers:\n    mcp-bash:\n      type: stdio\n      command: /Users/you/.local/bin/mcp-bash\n      env:\n        MCPBASH_PROJECT_ROOT: /Users/you/my-mcp-server\n        MCPBASH_TOOL_ALLOWLIST: \"*\"\n  ```\n- **OpenAI Agents SDK (Python)**: Use `MCPServerStdio(params=...)`; the constructor does not take a `name` kwarg.\n  ```python\n  import os\n  from agents.mcp import MCPServerStdio\n\n  os.environ[\"MCPBASH_PROJECT_ROOT\"] = \"/Users/you/my-mcp-server\"\n  os.environ[\"MCPBASH_TOOL_ALLOWLIST\"] = \"*\"\n  async with MCPServerStdio(\n      params={\n          \"command\": \"/Users/you/.local/bin/mcp-bash\",\n          # optionally add args/env/cwd if your server needs them\n      }\n  ) as server:\n      ...\n  ```\n- **Clawdbot**: Clawdbot uses [mcporter](https://github.com/steipete/mcporter) for MCP. Add to `~/.mcporter/mcporter.json`:\n  ```json\n  {\n    \"servers\": {\n      \"mcp-bash\": {\n        \"type\": \"stdio\",\n        \"command\": \"/Users/you/.local/bin/mcp-bash\",\n        \"env\": {\n          \"MCPBASH_PROJECT_ROOT\": \"/Users/you/my-mcp-server\",\n          \"MCPBASH_TOOL_ALLOWLIST\": \"*\"\n        }\n      }\n    }\n  }\n  ```\n  Verify with `npx mcporter list mcp-bash`. Clawdbot agents call tools via the bundled `mcporter` skill.\n- **Highlight AI**: Go to Highlight → Settings → Connections → Add → Custom command:\n  - **Connection name**: `mcp-bash`\n  - **Command**: `/Users/you/.local/bin/mcp-bash`\n  - **Environment variables**: `MCPBASH_PROJECT_ROOT=/Users/you/my-mcp-server MCPBASH_TOOL_ALLOWLIST=*`\n- **Windows note**: Git Bash (CI-tested) or WSL both work. Git Bash ships with Git for Windows; WSL behaves like Linux. See [Windows Support](docs/WINDOWS.md) for details.\n\n\u003e **Security note:** `MCPBASH_TOOL_ALLOWLIST=\"*\"` allows all registered tools. For production deployments, replace `*` with a comma-separated list of specific tool names (e.g., `\"search-notes,get-note\"`).\n\n### Compatibility Notes\n\n| Client | Status | Known issues / notes |\n|--------|--------|----------------------|\n| Claude Desktop | Tested (macOS, Windows) | macOS: non-login shell PATH/env (use `config --wrapper-env`); macOS quarantine/TCC can block execution; restart required after config changes |\n| Claude CLI / Claude Code | Tested | Generally straightforward; ensure `MCPBASH_PROJECT_ROOT` points at your project |\n| Clawdbot | Config documented | Uses mcporter for MCP; config in `~/.mcporter/mcporter.json` |\n| Highlight AI | Tested | UI-based config: Settings → Connections → Add → Custom command |\n| Cursor | Config documented | Config file location differs by install; use `mcp-bash config --client cursor` |\n| Windsurf (Cascade) | Config documented | Use the app's MCP config UI/file; see snippet in README |\n| LibreChat | Config documented | YAML config format; see snippet in README |\n| OpenAI Agents SDK | Example provided | Python example only; verify SDK version and stdio wiring |\n\n**Tested** = maintainers have manually verified end-to-end. **Config documented** = configuration instructions provided but not regularly tested.\n\n**CI-tested platforms:** Ubuntu, macOS, Windows (Git Bash). CI validates the MCP protocol layer via integration tests, not specific client applications.\n\nUsing a different client? Any MCP-compliant stdio client should work. [Open an issue](https://github.com/yaniv-golan/mcp-bash-framework/issues) if you hit compatibility problems.\n\n## MCPB Bundles\n\nPackage your server for one-click installation in Claude Desktop:\n\n```bash\nmcp-bash bundle\n# Creates: my-server-1.0.0.mcpb\n```\n\nDouble-click the `.mcpb` file to install, or drag it to Claude Desktop.\n\n### Quick Configuration\n\nCreate `mcpb.conf` in your project root to customize the bundle:\n\n```bash\nMCPB_NAME=\"my-server\"\nMCPB_AUTHOR_NAME=\"Your Name\"\nMCPB_AUTHOR_EMAIL=\"you@example.com\"\nMCPB_REPOSITORY=\"https://github.com/you/my-server\"\n```\n\nWithout a config file, metadata is auto-resolved from `server.meta.json`, `VERSION`, and git config.\n\n### Bundle Options\n\n```bash\nmcp-bash bundle --validate          # Check without creating\nmcp-bash bundle --output ./dist     # Output to specific directory\nmcp-bash bundle --verbose           # Show detailed progress\n```\n\nThe bundle includes your tools, resources, prompts, and an embedded copy of the mcp-bash framework—fully self-contained for distribution.\n\n\u003e [Full bundling guide](docs/MCPB.md)\n\n## Vendoring the Runtime\n\nEmbed the mcp-bash runtime directly into your project repository so that no system install is needed at runtime. Useful for dev teams, CI, and MCP clients that don't support MCPB bundles:\n\n```bash\nmcp-bash vendor          # embed .mcp-bash/ into project root\ngit add .mcp-bash/       # commit it\nmcp-bash vendor --verify # verify integrity at any time\n```\n\n\u003e [Full vendoring guide](docs/VENDORING.md)\n\n## Project Structure\n\n```\nFramework (Install Once)               Your Project (Version Control This)\n~/.local/share/mcp-bash/               ~/my-mcp-server/\n├── bin/mcp-bash                       ├── tools/\n├── lib/                               │   └── check-disk/\n├── handlers/                          │       ├── tool.sh\n└── ...                                │       └── tool.meta.json\n                                       ├── prompts/\n~/.local/bin/                          ├── resources/\n└── mcp-bash → ../share/mcp-bash/...   ├── server.d/\n                                       │   └── server.meta.json (optional)\n                                       └── .registry/ (auto-generated)\n```\n\n## Direct Tool Execution (run-tool)\n\nUse `run-tool` to invoke a single tool without starting the full MCP server. This wires the same environment as the server (SDK path, args, metadata, roots). Tool names must match `^[a-zA-Z0-9_-]{1,64}$`; some clients, including Claude Desktop, enforce this and reject dotted names, so prefer hyphens/underscores for namespaces.\n\n```bash\n# Basic invocation (project inferred from CWD or MCPBASH_PROJECT_ROOT)\nmcp-bash run-tool my-tool --args '{\"value\":\"hello\"}'\n\n# Simulate roots (comma-separated), stream stderr, override timeout, or print env\nmcp-bash run-tool my-tool --args '{\"value\":\"hi\"}' --roots /tmp/project,/data/shared --verbose --timeout 15\n# Inspect wiring without executing\nmcp-bash run-tool my-tool --print-env --dry-run\n\n# Dry-run validates metadata/args without executing the tool\nmcp-bash run-tool my-tool --dry-run\n```\n\nFlags: `--args` (JSON object), `--roots` (comma-separated paths), `--dry-run`, `--timeout \u003csecs\u003e`, `--verbose` (stream tool stderr), `--no-refresh` (reuse cached registry), `--minimal` (force degraded mode), `--project-root \u003cdir\u003e`, `--print-env` (dump wiring without executing). Elicitation is not supported in CLI mode.\n\nThe scaffolder and examples use per-tool directories (e.g., `tools/check-disk/tool.sh`); automatic discovery requires tools to live under subdirectories of `tools/` (root-level scripts are not discovered).\n\nSee [**Project Structure Guide**](docs/PROJECT-STRUCTURE.md) for detailed layouts, Docker deployment, and multi-environment setups.\n\n## Diagnostics \u0026 Validation\n\n- Readiness/health probe: `mcp-bash --health [--project-root DIR] [--timeout SECS]` (`0`=ready, `1`=unhealthy, `2`=misconfigured)\n- Project checks: `mcp-bash validate [--project-root DIR] [--fix] [--json] [--explain-defaults] [--strict] [--inspector]`\n- Environment check: `mcp-bash doctor [--json] [--dry-run|--fix]`\n- Registry cache introspection: `mcp-bash registry status [--project-root DIR]`\n- Client config: `mcp-bash config --json` (machine-readable), `--client \u003cname\u003e` (pasteable JSON), `--wrapper` (generate auto-install wrapper)\n\n## SDK Discovery\n\nEvery tool sources shared helpers from `sdk/tool-sdk.sh`. When `mcp-bash` launches a tool it exports `MCP_SDK=/path/to/framework/sdk`, so tool scripts can run:\n\n```bash\nsource \"${MCP_SDK}/tool-sdk.sh\"\n```\n\nIf you copy a tool out of this repository (or build your own project layout) and run it directly, set `MCP_SDK` before executing the script:\n\n```bash\nexport MCP_SDK=~/.local/share/mcp-bash/sdk\n./tools/check-disk/tool.sh\n```\n\nIf the SDK can’t be resolved, the script exits with a clear error.\n\n## Roots (scoping filesystem access)\n- If the client supports MCP Roots, mcp-bash requests them after `initialized` and exposes them to tools via env (`MCP_ROOTS_JSON`, `MCP_ROOTS_PATHS`, `MCP_ROOTS_COUNT`) and SDK helpers (`mcp_roots_list`, `mcp_roots_count`, `mcp_roots_contains`).\n- If the client does not provide roots or times out, you can supply them via `MCPBASH_ROOTS=\"/path/one:/path/two\"` or an optional `config/roots.json` in your project. Paths are normalized and enforced consistently.\n\n## Completions\n\nCompletions are manually registered (they are not auto-discovered). Prefer declarative registration via `server.d/register.json`:\n\n```json\n{\n  \"version\": 1,\n  \"completions\": [\n    {\"name\":\"example.completion\",\"path\":\"completions/example.sh\",\"timeoutSecs\":5}\n  ]\n}\n```\n\nPaths are resolved relative to `MCPBASH_PROJECT_ROOT`, and registry refreshes pick them up automatically.\n\n## Tool Policy Hook (optional)\n\nProjects can gate tool execution centrally by adding `server.d/policy.sh` with `mcp_tools_policy_check()`. The framework calls this before every tool run (default: allow all).\n\n```bash\n# server.d/policy.sh\nmcp_tools_policy_check() {\n\tlocal tool_name=\"$1\"\n\tif [ \"${MYPROJECT_READ_ONLY:-0}\" = \"1\" ] \u0026\u0026 [[ \"${tool_name}\" != myProj.get* ]]; then\n\t\tmcp_tools_error -32602 \"Read-only mode: ${tool_name} disabled\"\n\t\treturn 1\n\tfi\n\treturn 0\n}\n```\n\nUse `-32602` for policy/invalid-params blocks, `-32600` for capability/auth failures. Keep logic lightweight; the hook runs on every invocation.\n\n## Learn by Example\n\nThe [`examples/`](examples/) directory shows common patterns end-to-end:\n\n| Example | Concepts Covered |\n|---------|------------------|\n| [**00-hello-tool**](examples/00-hello-tool/) | Basic \"Hello World\" tool structure and metadata. |\n| [**01-args-and-validation**](examples/01-args-and-validation/) | Handling JSON arguments and input validation. |\n| [**02-logging-and-levels**](examples/02-logging-and-levels/) | Sending logs to the client and managing verbosity. |\n| [**03-progress-and-cancellation**](examples/03-progress-and-cancellation/) | Long-running tasks, reporting progress, and handling user cancellation. |\n| [**04-roots-basics**](examples/04-roots-basics/) | MCP roots scoping for tools; allows/denies file reads based on configured roots. |\n| [**05-resources-basics**](examples/05-resources-basics/) | Listing and reading resources via the built-in file provider. |\n| [**06-embedded-resources**](examples/06-embedded-resources/) | Embedding file content directly in tool responses. |\n| [**07-prompts-basics**](examples/07-prompts-basics/) | Discovering and rendering prompt templates. |\n| [**08-elicitation**](examples/08-elicitation/) | Client-driven elicitation prompts that gate tool execution. |\n| [**09-registry-overrides**](examples/09-registry-overrides/) | Declarative registry overrides, live progress streaming, and a custom resource provider. |\n| [**10-completions**](examples/10-completions/) | Completion registration, query filtering, and pagination/hasMore. |\n| [**11-resource-templates**](examples/11-resource-templates/) | Resource template discovery, manual overrides, and client-side expansion. |\n| [**Advanced: ffmpeg-studio**](examples/advanced/ffmpeg-studio/) | Real-world application: video processing pipeline with media inspection (optional, heavy deps). |\n\n## Features at a Glance\n\n- **Auto-Discovery**: Place scripts in your project's `tools/`, `resources/`, or `prompts/` directories—the framework finds them automatically.\n- **Scaffolding**: Generate compliant tool, resource, prompt templates, and a test harness (`mcp-bash scaffold \u003ctype\u003e \u003cname\u003e`, `mcp-bash scaffold test`).\n- **Stdio Transport**: Standard input/output. No custom daemons or sidecars.\n- **Framework/Project Separation**: Install the framework once, create unlimited projects.\n- **Graceful Degradation**: Automatically detects available JSON tools (`gojq`, `jq`) or falls back to minimal mode if none are present.\n- **Progress Streaming**: Emits progress and log notifications; set `MCPBASH_ENABLE_LIVE_PROGRESS=true` to stream them during execution (uses a lightweight background flusher).\n- **Debug Mode**: Run `mcp-bash debug` to capture all JSON-RPC messages for analysis. See [docs/DEBUGGING.md](docs/DEBUGGING.md).\n\n## Configuration\n\n### Required Configuration\n\n| Variable | Description |\n|----------|-------------|\n| `MCPBASH_PROJECT_ROOT` | **Required for MCP clients.** Path to your project directory containing `tools/`, `prompts/`, `resources/`. CLI commands (`mcp-bash scaffold`, `mcp-bash validate`, etc.) auto-detect the project root from the current directory. |\n\n### Optional Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MCPBASH_TOOLS_DIR` / `MCPBASH_RESOURCES_DIR` / `MCPBASH_PROMPTS_DIR` / `MCPBASH_SERVER_DIR` | Derived from `MCPBASH_PROJECT_ROOT` | Override content and server hook locations. |\n| `MCPBASH_REGISTRY_DIR` | `$MCPBASH_PROJECT_ROOT/.registry` | Registry cache location. |\n| `MCPBASH_MAX_CONCURRENT_REQUESTS` | `16` | Cap concurrent worker slots. |\n| `MCPBASH_MAX_TOOL_OUTPUT_SIZE` | `10485760` | Tool stdout limit; stderr/resources inherit when unset. |\n| `MCPBASH_LOG_LEVEL` | `info` | Log level; use `debug` for discovery traces. |\n| `MCPBASH_DEBUG_ERRORS` | `false` | Include tool diagnostics in outputSchema validation errors (exit code, stderr tail, trace line). |\n| `MCPBASH_DEBUG_LOG` | (unset) | Override per-tool debug log path; SDK `mcp_debug` appends to it. |\n| `MCPBASH_ENABLE_LIVE_PROGRESS` | `false` | Stream progress/log notifications during execution (starts a background flusher). |\n| `MCPBASH_ENV_PAYLOAD_THRESHOLD` | `65536` | Spill args/metadata to temp files above this size. |\n| `MCPBASH_TOOL_ENV_MODE` | `minimal` | Tool env isolation: `minimal`, `inherit`, or `allowlist`. |\n| `MCPBASH_TOOL_ENV_INHERIT_ALLOW` | `false` | Must be `true` to allow `MCPBASH_TOOL_ENV_MODE=inherit`. |\n| `MCPBASH_DEFAULT_TOOL_TIMEOUT` | `30` | Default tool timeout (seconds). |\n| `MCPBASH_REMOTE_TOKEN` | (unset) | Shared secret for proxied deployments (minimum 32 chars; failures throttled). |\n| `MCPBASH_HTTPS_ALLOW_HOSTS` / `MCPBASH_HTTPS_DENY_HOSTS` | (unset) | HTTPS provider host allow/deny lists; private/loopback always blocked. Allow list is required unless `MCPBASH_HTTPS_ALLOW_ALL=true`. |\n| `MCPBASH_HTTPS_ALLOW_ALL` | `false` | Explicitly allow all public HTTPS hosts (unsafe; prefer `MCPBASH_HTTPS_ALLOW_HOSTS`). |\n| `MCPBASH_CI_MODE` | (unset) | CI defaults: safe tmp/log dirs, keep-logs, timestamped logs, failure summary (`failure-summary.jsonl`), env snapshot (`env-snapshot.json`); `MCPBASH_CI_VERBOSE=true` starts at debug; GH annotations when tracing provides file/line. |\n\nFull list and defaults: see [docs/ENV_REFERENCE.md](docs/ENV_REFERENCE.md).\n\n### Server Metadata\n\nServer identity is configured via `server.d/server.meta.json`. All fields are optional—smart defaults are applied when omitted:\n\n| Field | Default | Description |\n|-------|---------|-------------|\n| `name` | Project directory name | Server identifier (e.g., `my-server`) |\n| `title` | Titlecase of name | Human-readable display name (e.g., `My Server`) |\n| `version` | `VERSION` file, `package.json`, or `0.0.0` | Server version |\n| `description` | (omitted) | Brief description of the server |\n| `websiteUrl` | (omitted) | URL to server homepage or documentation |\n| `icons` | (omitted) | Array of icon objects for visual identification |\n\nExample `server.d/server.meta.json`:\n```json\n{\n  \"name\": \"weather-api\",\n  \"title\": \"Weather API Server\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Provides weather data for any location\",\n  \"websiteUrl\": \"https://example.com/weather-api\",\n  \"icons\": [\n    {\"src\": \"https://example.com/icon.svg\", \"sizes\": [\"any\"], \"mimeType\": \"image/svg+xml\"}\n  ]\n}\n```\n\nIf no `server.meta.json` exists, the server uses smart defaults based on your project directory name.\n\nOptional initialize guidance can be defined in `server.d/server.instructions.md`.\nWhen present and non-empty, its contents are returned in `initialize.result.instructions`\nfor protocol versions `2025-03-26` and newer (omitted for `2024-11-05`).\n\n### Resource Annotations\n\nResources can carry optional `annotations` metadata (audience hints, priority, etc.) that clients may use for filtering or display.\nAnnotations are supported through all discovery paths:\n\n- **`*.meta.json`**: include an `annotations` object in the metadata file.\n- **Inline `# mcp:` header**: add `annotations` to the JSON payload.\n- **Manual registration** (`register.sh`): pass `annotations` in the `mcp_register_resource` JSON.\n\nExample `resources/report.meta.json` with annotations:\n```json\n{\n  \"name\": \"monthly-report\",\n  \"description\": \"Monthly analytics report\",\n  \"uri\": \"file:///data/report.csv\",\n  \"mimeType\": \"text/csv\",\n  \"annotations\": {\n    \"audience\": [\"user\"],\n    \"priority\": 0.8\n  }\n}\n```\n\nWhen annotations are absent, the field is omitted from `resources/list` responses (not emitted as `null`).\n\n### Tool SDK environment\n- `MCPBASH_JSON_TOOL` and `MCPBASH_JSON_TOOL_BIN` point to the detected JSON processor (`gojq`/`jq`) and are injected into tool processes when available.\n- `MCPBASH_MODE` is `full` when JSON tooling is present and `minimal` otherwise; SDK helpers warn and downgrade behaviour when running in minimal mode.\n- `MCPBASH_DEBUG_LOG` points to a per-invocation debug log file (when available); use `mcp_debug` inside tools to append file-based checkpoints.\n- `MCPBASH_TOOL_ENV_MODE` controls isolation for tool processes (`minimal`, `inherit`, or `allowlist`), but MCPBASH/MCP-prefixed variables (including JSON tool hints) are always propagated. Example allowlist for minimal exposure: `MCPBASH_TOOL_ENV_MODE=allowlist MCPBASH_TOOL_ENV_ALLOWLIST=HOME,PATH`.\n\n### Capability Modes\n\n| Mode | Supported surface | Limitations / when it applies |\n|------|-------------------|--------------------------------|\n| Full | Lifecycle, ping, logging/setLevel, tools/resources/prompts (list, call/read/subscribe), completion, pagination, `listChanged` notifications | Requires `jq`/`gojq` available; default mode. |\n| Minimal | Lifecycle, ping, logging/setLevel | Tools/resources/prompts/completion are disabled and registry notifications are suppressed. Activated when no JSON tool is found or `MCPBASH_FORCE_MINIMAL=true`. |\n\n### Registry Maintenance\n- Auto-refresh: registries re-scan on TTL expiry (default 5s) and use lightweight file-list hashing to skip rebuilds when nothing changed.\n- Manual refresh: `bin/mcp-bash registry refresh [--project-root DIR] [--no-notify] [--quiet] [--filter PATH]` rebuilds `.registry/*.json` and returns a status JSON. In minimal mode the command is skipped gracefully.\n\n## Troubleshooting (quick hits)\n- `PATH` issues (mcp-bash not found): ensure `~/.local/bin` is on PATH; rerun `source ~/.bashrc` or `~/.zshrc`.\n- Missing JSON tooling (`jq`/`gojq`): install one; otherwise the server enters minimal mode (tools/resources/prompts disabled).\n- macOS quarantine blocks execution: run `xattr -d com.apple.quarantine ~/.local/share/mcp-bash/bin/mcp-bash` (and your project path if needed).\n- Git Bash/MSYS exec-limit quirks: set `MCPBASH_JSON_TOOL=jq` and `MSYS2_ARG_CONV_EXCL=\"*\"` before running `mcp-bash`.\n\n## Requirements\n\n### Runtime Requirements\n*   **Bash**: version 3.2 or higher (standard on macOS, Linux, WSL, and Git Bash on Windows).\n*   **JSON Processor**: `gojq` (recommended) or `jq`.\n    *   *Note*: If no JSON tool is found, the server runs in \"Minimal Mode\" (Lifecycle \u0026 Ping only).\n\n### Development Requirements\nIf you plan to contribute to the core framework, see [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions (linting, tests, etc).\n\n### Testing (quick start)\nFrom the repo root:\n```bash\n./test/lint.sh\n./test/unit/run.sh\n./test/integration/run.sh\n# Optional:\n# ./test/compatibility/run.sh\n# ./test/stress/run.sh\n```\n\n### Windows Notes\n- Signals from the client may not reliably terminate subprocesses on Git Bash; prefer explicit `shutdown`/`exit` and short tool timeouts.\n- Paths are normalized to `/c/...` style; avoid mixing Windows- and POSIX-style roots in the same project.\n- Large payloads can be slower under MSYS; keep registry TTLs reasonable.\nSee [docs/WINDOWS.md](docs/WINDOWS.md) for full guidance and workarounds.\n\n---\n\n## Documentation\n\n### Getting Started\n- [**Project Structure Guide**](docs/PROJECT-STRUCTURE.md) - Layouts, Docker deployment, multi-environment setups.\n- [**Examples**](examples/) - Learn by example: hello-world, args, logging, progress, real-world video processing.\n\n### Feature Guides\n- [**MCPB Bundles**](docs/MCPB.md) - One-click distribution via Claude Desktop and MCP Registry.\n- [**Vendoring**](docs/VENDORING.md) - Embed the runtime in your git repo for CI and non-MCPB clients.\n- [**Elicitation**](docs/ELICITATION.md) - Form and URL modes, SDK helpers, and client capability checks.\n- [**Roots**](docs/ROOTS.md) - Roots/list flow, env wiring, validation, and fallbacks.\n- [**Completions**](docs/COMPLETION.md) - Manual registration, provider types, pagination, and script contracts.\n- [**Registry**](docs/REGISTRY.md) - Registry envelopes, TTL, manual registration, and cache formats.\n- [**Resource Templates**](docs/RESOURCE-TEMPLATES.md) - Auto/manual discovery, pagination, collisions, and client-side expansion.\n- [**Limits \u0026 Performance**](docs/LIMITS.md) - Concurrency, payload ceilings, throttling.\n- [**Errors**](docs/ERRORS.md) - Protocol errors vs tool execution errors (SEP-1303).\n- [**Best Practices**](docs/BEST-PRACTICES.md) - Development, testing, operations guidance.\n\n### Deep Dive\n- [**Architecture Guide**](docs/ARCHITECTURE.md) - Internal architecture, lifecycle loop, concurrency model.\n- [**Protocol Compliance**](SPEC-COMPLIANCE.md) - Detailed MCP protocol support breakdown.\n- [**Performance Guide**](docs/PERFORMANCE.md) - Tuning concurrency, timeouts, and registry scans.\n- [**Security Policy**](docs/SECURITY.md) - Input validation and execution safety.\n- [**Minimal Mode**](docs/MINIMAL-MODE.md) - Behavior when jq/gojq is missing or minimal mode is forced.\n- [**Changelog**](CHANGELOG.md) - Notable changes between releases.\n- [**Windows Support**](docs/WINDOWS.md) - Running on Git Bash/WSL.\n- [**Remote Connectivity**](docs/REMOTE.md) - Exposing mcp-bash over HTTP/SSE via external gateways.\n\n### Scope and Goals\n- Bash-only Model Context Protocol server verified on macOS Bash 3.2, Linux Bash ≥3.2, and Windows (Git Bash is CI-tested; WSL behaves like Linux).\n- Targets MCP protocol version `2025-11-25` while supporting negotiated downgrades.\n- Transport support is limited to stdio; HTTP/SSE/OAuth transports remain out of scope (see [Remote Connectivity](docs/REMOTE.md) for gateway options).\n\n## Embedded resources in tool output\n\nTools can attach files directly to the MCP response as `type:\"resource\"` content parts; binary files are auto-base64-encoded into the `blob` field, text stays in `text`.\n\nUse `mcp_result_text_with_resource` to embed files with your tool result:\n\n```bash\npayload_path=\"${MCPBASH_PROJECT_ROOT}/resources/report.txt\"\nprintf 'Report content' \u003e\"${payload_path}\"\nmcp_result_text_with_resource \\\n  \"$(mcp_json_obj message \"See embedded report\")\" \\\n  --path \"${payload_path}\" --mime text/plain\n```\n\nSee the dedicated example at `examples/06-embedded-resources/` and [BEST-PRACTICES.md](docs/BEST-PRACTICES.md#embedding-resources-in-tool-responses) for full documentation.\n\n## Built with mcp-bash\n\n| Project | Description |\n|---------|-------------|\n| [affinity-sdk](https://github.com/yaniv-golan/affinity-sdk) | Affinity CRM SDK with MCP server support |\n| [claude-familiar](https://github.com/yaniv-golan/claude-familiar) | Companion personality and MCP tools for Claude Code |\n| [git-hex](https://github.com/yaniv-golan/git-hex) | Safe, powerful git refactoring tools for AI assistants |\n\nIf you've built an MCP server using this framework, show it off! Add this badge to your project's README:\n\n[![MCP Bash Framework](https://img.shields.io/badge/MCP-MCP_Bash_Framework-green?logo=modelcontextprotocol)](https://github.com/yaniv-golan/mcp-bash-framework)\n\n```markdown\n[![MCP Bash Framework](https://img.shields.io/badge/MCP-MCP_Bash_Framework-green?logo=modelcontextprotocol)](https://github.com/yaniv-golan/mcp-bash-framework)\n```\n\nWe'd love to see what you build—consider [opening a discussion](https://github.com/yaniv-golan/mcp-bash-framework/discussions) to share your project with the community.\n\n## FAQ\n\n### Why is the repository named `mcp-bash-framework` but the CLI is `mcp-bash`?\n\nThe repository name `mcp-bash-framework` reflects what this project is: a framework you install once and use to create multiple MCP server projects. The CLI/binary is named `mcp-bash` because that's what you invoke—short and memorable. The name `mcp-bash` was already taken on GitHub, so we chose `mcp-bash-framework` to accurately describe the architecture while avoiding namespace conflicts.\n\n---\n\nmcp-bash is intentionally small. It gives you control, clarity, and a predictable surface for AI systems. **Build tools, not infrastructure.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaniv-golan%2Fmcp-bash-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyaniv-golan%2Fmcp-bash-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyaniv-golan%2Fmcp-bash-framework/lists"}