{"_id":"@aemrezorlu/sidecar-mcp","_rev":"2-bcf90cba20d1e88d9ea1eb31915dc3e9","name":"@aemrezorlu/sidecar-mcp","dist-tags":{"latest":"0.2.1"},"versions":{"0.2.0":{"name":"@aemrezorlu/sidecar-mcp","version":"0.2.0","license":"MIT","_id":"@aemrezorlu/sidecar-mcp@0.2.0","maintainers":[{"name":"aemrezorlu","email":"ahmetemrezorlu@gmail.com"}],"bin":{"sidecar-mcp":"dist/index.js"},"dist":{"shasum":"47720dd4da223c29a64e83ed61caed162bde031a","tarball":"https://registry.npmjs.org/@aemrezorlu/sidecar-mcp/-/sidecar-mcp-0.2.0.tgz","fileCount":16,"integrity":"sha512-RH+HYtlGjXJP/KUU4e3Z9Gsur+dk83qo2X4DWVL6kMXaZLsSrSjGV6OLJpgmprZwb6KHFSE6IfUuxJM1GUnRlg==","signatures":[{"sig":"MEUCICIj4u2j0AVaUdhSnQRf/7iM0UtLeEbdhkUKszv9Zat7AiEAzkEa5r0FFegFIPLDF3dpBgwPECr7+AkH0dYjZ8TE2J8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38099},"type":"module","engines":{"node":">=24"},"scripts":{"dev":"tsx watch src/index.ts","demo":"tsx demo/bulk-read.demo.ts","test":"vitest run","build":"tsc -p tsconfig.build.json && chmod +x dist/index.js","test:watch":"vitest"},"_npmUser":{"name":"aemrezorlu","email":"ahmetemrezorlu@gmail.com"},"repository":{"url":"https://github.com/dEMonaRE/sidecar-mcp.git","type":"git"},"description":"MCP server that delegates bulk file reading to a cheap worker LLM, so the main agent's context stays small.","directories":{},"_nodeVersion":"26.0.0","dependencies":{"zod":"^3.23.0","@modelcontextprotocol/sdk":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^24.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sidecar-mcp_0.2.0_1789053589831_0.023596680342823584","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"_id":"@aemrezorlu/sidecar-mcp@0.2.1","bin":{"sidecar-mcp":"dist/index.js"},"dist":{"shasum":"cffd92908cfd1df835e49acf3ce8b373f559fe76","tarball":"https://registry.npmjs.org/@aemrezorlu/sidecar-mcp/-/sidecar-mcp-0.2.1.tgz","fileCount":16,"integrity":"sha512-sccR78Yg3eDAHncFlZsK1yApqp0elSIXxnp9bbk+bnyYOOmhji7OEfBL6RAPmjNVRd0r/n7gAnpT9ma+76/22w==","signatures":[{"sig":"MEUCIG5WNVaHYvEr7AVI4j1UIoG68YZWQD1wubMGlfcYJlTnAiEA2ekZSEcBTDLda0glDaeUPs6vj9iYrCg9B6Sq9AonOPI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHrh+9+9wURNzYbvlF+d8Y/q0qwmuKcpMno9yDu7qEEAAiBvTTSh1kCNgFMwFMy+dgEsw3kiO2SUMFKfeeU5B5X6Dg=="}],"unpackedSize":37945},"name":"@aemrezorlu/sidecar-mcp","type":"module","engines":{"node":">=24"},"license":"MIT","scripts":{"dev":"tsx watch src/index.ts","demo":"tsx demo/bulk-read.demo.ts","test":"vitest run","build":"tsc -p tsconfig.build.json && chmod +x dist/index.js","test:watch":"vitest"},"version":"0.2.1","_npmUser":{"name":"aemrezorlu","email":"ahmetemrezorlu@gmail.com"},"repository":{"url":"https://github.com/dEMonaRE/sidecar-mcp.git","type":"git"},"description":"MCP server that delegates bulk file reading to a cheap worker LLM, so the main agent's context stays small.","directories":{},"maintainers":[{"name":"aemrezorlu","email":"ahmetemrezorlu@gmail.com"}],"_nodeVersion":"26.0.0","dependencies":{"zod":"^3.23.0","@modelcontextprotocol/sdk":"^1.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.20.0","vitest":"^2.1.0","typescript":"^5.7.0","@types/node":"^24.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sidecar-mcp_0.2.1_1789076682425_0.8386302804832517"}}},"time":{"created":"2026-09-10T15:19:49.722Z","modified":"2026-09-10T21:44:42.672Z","0.2.0":"2026-09-10T15:19:49.997Z","0.2.1":"2026-09-10T21:44:42.502Z"},"license":"MIT","repository":{"url":"https://github.com/dEMonaRE/sidecar-mcp.git","type":"git"},"description":"MCP server that delegates bulk file reading to a cheap worker LLM, so the main agent's context stays small.","maintainers":[{"name":"aemrezorlu","email":"ahmetemrezorlu@gmail.com"}],"readme":"# sidecar-mcp\n\nAn MCP server that delegates bulk file reading to a cheap worker LLM, so the main agent's context stays small.\n\nWhen the main agent needs to understand 2+ files or any file over ~100 lines, it calls `bulk_read`. The full file content never enters the main agent's context — only the worker's summary does.\n\n## Install\n\nsidecar-mcp is a small stdio subprocess that sits next to your coding agent. Reads happen out-of-band to a cheap worker LLM, so the main agent's context stays small. Two install paths — both wired in under a minute.\n\n### Any MCP client (canonical)\n\nThe MCP primitive is the same everywhere — a subprocess with a command and some env vars. Every client wraps it in its own config syntax. Pick your worker backend, set `SIDECAR_BACKEND` (and any keys), then plug this into your client's MCP config:\n\n```json\n{\n  \"command\": \"npx -y @aemrezorlu/sidecar-mcp\",\n  \"env\": { \"SIDECAR_BACKEND\": \"ollama\" }\n}\n```\n\nFor a from-source install, swap `npx -y @aemrezorlu/sidecar-mcp` for `node /absolute/path/to/sidecar-mcp/dist/index.js`. See **Wire into any MCP client** below for client-specific config locations.\n\n### A. Claude Code CLI (once the package is on the npm registry)\n\nIf you're on Claude Code, `claude mcp add` is the shortest path — it writes the same config for you. The `SIDECAR_BACKEND=*` env vars are independent of the client; `claude` here is just the CLI that registers the MCP server.\n\n```bash\n# Ollama — local, free, no API key:\nclaude mcp add sidecar -e SIDECAR_BACKEND=ollama -- npx -y @aemrezorlu/sidecar-mcp\n\n# OpenAI:\nclaude mcp add sidecar -e SIDECAR_BACKEND=openai -e SIDECAR_OPENAI_KEY=\"$OPENAI_API_KEY\" -- npx -y @aemrezorlu/sidecar-mcp\n\n# Anthropic (or any Anthropic-compatible provider):\nclaude mcp add sidecar -e SIDECAR_BACKEND=anthropic -e SIDECAR_ANTHROPIC_KEY=\"$ANTHROPIC_API_KEY\" -- npx -y @aemrezorlu/sidecar-mcp\n# Add -e SIDECAR_ANTHROPIC_URL=https://your-host for Anthropic-compatible proxies.\n```\n\n`npx -y @aemrezorlu/sidecar-mcp` downloads and runs the published package on first call. No clone, no build, no `node_modules` to manage.\n\n### B. From source (works today, no publish needed)\n\n```bash\ngit clone https://github.com/dEMonaRE/sidecar-mcp.git\ncd sidecar-mcp\npnpm install --frozen-lockfile\npnpm build\nclaude mcp add sidecar -e SIDECAR_BACKEND=ollama -- node \"$PWD/dist/index.js\"\n```\n\n### Pick a backend\n\n| Backend | Cost | Needs |\n|---|---|---|\n| `ollama` | free, local | `ollama serve` + `ollama pull llama3.1:8b` |\n| `openai` | $$ | `SIDECAR_OPENAI_KEY` |\n| `anthropic` | $$ | `SIDECAR_ANTHROPIC_KEY` (works with Anthropic-compatible providers via `SIDECAR_ANTHROPIC_URL`) |\n\n### Verify\n\nIn your MCP client (Claude Code shown), ask: *\"Use bulk_read to summarize README.md.\"* You should see `bulk_read` fire and return a tight summary. Every reply ends with a usage footer (`tokens: <prompt> in / <completion> out`):\n\n```\n---\nsidecar: model=llama3.1:8b, backend=ollama, tokens=412 in / 87 out\n```\n\nIf `bulk_read` doesn't show up:\n- **Claude Code**: `claude mcp list` should show `sidecar` as connected.\n- **VS Code Copilot**: Command Palette → \"MCP: List Servers\".\n- **Codex CLI**: `codex mcp list`.\n- **Cursor / Zed**: check the MCP panel in settings.\n\n## Configuration\n\n`sidecar-mcp` reads everything from env vars. No config file. No CLI flags (MCP stdio can't pass them).\n\n| Var | Default | Notes |\n|---|---|---|\n| `SIDECAR_BACKEND` | `ollama` | `ollama` \\| `openai` \\| `anthropic` \\| `fake` |\n| `SIDECAR_MODEL` | per-backend default | see below |\n| `SIDECAR_OLLAMA_URL` | `http://127.0.0.1:11434` | |\n| `SIDECAR_OPENAI_URL` | `https://api.openai.com` | any OpenAI-compatible endpoint |\n| `SIDECAR_OPENAI_KEY` | _required for openai_ | |\n| `SIDECAR_ANTHROPIC_URL` | `https://api.anthropic.com` | any Anthropic-compatible endpoint |\n| `SIDECAR_ANTHROPIC_KEY` | _required for anthropic_ | also accepts Anthropic-compatible providers |\n| `SIDECAR_FILE_MAX_BYTES` | `524288` (512 KB) | files larger are skipped + reported |\n| `SIDECAR_TOTAL_MAX_BYTES` | `5242880` (5 MB) | bulk_read errors if total bytes across all readable files exceeds cap |\n| `SIDECAR_ALLOW_ROOTS` | cwd (with stderr warning) | comma-separated absolute paths; see **Security** |\n| `SIDECAR_REQUEST_TIMEOUT_MS` | `120000` | |\n| `SIDECAR_LOG_LEVEL` | `info` | `error` \\| `info` \\| `debug` |\n\n**Default models:**\n- ollama → `llama3.1:8b`\n- openai → `gpt-4o-mini`\n- anthropic → `claude-3-5-haiku-latest`\n\n### Per-backend quick config\n\n**Ollama (local, free, no API key)**\n```bash\nollama serve &\nollama pull llama3.1:8b\nexport SIDECAR_BACKEND=ollama\n```\n\n**OpenAI**\n```bash\nexport SIDECAR_BACKEND=openai\nexport SIDECAR_OPENAI_KEY=sk-...\n```\n\n**Anthropic (or any Anthropic-compatible provider)**\n```bash\nexport SIDECAR_BACKEND=anthropic\nexport SIDECAR_ANTHROPIC_KEY=sk-ant-...\n# Optional — point at a proxy that speaks the Anthropic Messages API:\n# export SIDECAR_ANTHROPIC_URL=https://your-anthropic-compatible-host\n```\n\n## Wire into any MCP client\n\nThe MCP spec is the same everywhere — `sidecar-mcp` is a subprocess with a command and some env vars. Every MCP client wraps that primitive in its own config syntax, but the primitive itself doesn't change.\n\n**Canonical shape** (the only thing you actually need to know):\n\n```json\n{\n  \"command\": \"npx -y @aemrezorlu/sidecar-mcp\",\n  \"env\": { \"SIDECAR_BACKEND\": \"ollama\" }\n}\n```\n\nFor a from-source install, swap `npx -y @aemrezorlu/sidecar-mcp` for `node /absolute/path/to/sidecar-mcp/dist/index.js`.\n\n**Where each client stores it:**\n\n| Client | Config location | Key |\n|---|---|---|\n| Claude Code | `~/.claude.json` or `.mcp.json` (or `claude mcp add …`) | `mcpServers` |\n| VS Code Copilot | `.vscode/settings.json` | `github.copilot.chat.mcp.servers` |\n| Codex CLI | `~/.codex/config.toml` | `[mcp_servers.X]` |\n| Cursor | `~/.cursor/mcp.json` | `mcpServers` |\n| Zed | `~/.config/zed/settings.json` | `context_servers` |\n| any other MCP client | see [modelcontextprotocol.io/clients](https://modelcontextprotocol.io/clients) | — |\n\n**Example — VS Code Copilot** (`.vscode/settings.json`):\n\n```json\n{\n  \"github.copilot.chat.mcp.servers\": {\n    \"sidecar\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@aemrezorlu/sidecar-mcp\"],\n      \"env\": { \"SIDECAR_BACKEND\": \"ollama\" }\n    }\n  }\n}\n```\n\n**Example — Codex CLI** (`~/.codex/config.toml`):\n\n```toml\n[mcp_servers.sidecar]\ncommand = \"npx\"\nargs = [\"-y\", \"@aemrezorlu/sidecar-mcp\"]\n\n[mcp_servers.sidecar.env]\nSIDECAR_BACKEND = \"ollama\"\n```\n\nThe `command`/`args` split varies by client (some take a single string, some take an array); the primitive above is what every client is configuring.\n\n## Tool reference\n\n### `bulk_read`\n\n| Field | Type | Required | Notes |\n|---|---|---|---|\n| `paths` | string[] | yes | 1–50 paths. Relative or absolute. |\n| `question` | string | yes | what to ask the worker |\n| `model` | string | no | override configured default for this call |\n\n**Returns:** the worker's text summary. The full file content never appears in the caller's context.\n\n**Response footer:** every `bulk_read` reply ends with a one-line footer for cost spot-checks:\n\n```\n---\nsidecar: model=<model>, backend=<backend>, tokens=<in> in / <out> out\n```\n\n(or `tokens: n/a` if the backend didn't report usage). Footer is included automatically; no flag to disable in MVP.\n\n**Example call:**\n```json\n{\n  \"paths\": [\"src/Service.java\", \"src/Handler.java\"],\n  \"question\": \"What does this service do and what are its key methods?\"\n}\n```\n\n**Worker prompt shape** (for debugging):\n```\n<files>\n<file path=\"src/Service.java\">…</file>\n<file path=\"src/Handler.java\">…</file>\n<!-- unreadable: path/to/binary.bin — binary file -->\n</files>\n\n<question>\nWhat does this service do?\n</question>\n```\n\n## How it works\n\n```\nmain agent (whatever MCP client you wired it into)\n   │\n   │  MCP stdio JSON-RPC:\n   │  {\"method\":\"tools/call\",\"params\":{\"name\":\"bulk_read\", ...}}\n   ▼\nsidecar-mcp subprocess\n   │\n   │  reads files, wraps in XML, POSTs to:\n   ▼\nworker model (any configured backend — Ollama / OpenAI / Anthropic / proxy — cheap)\n   │\n   │  returns ~600 token summary\n   ▼\nback to main agent as tool result\n```\n\nThe full file content stays between `sidecar-mcp` and the worker. The main agent only ever sees the summary.\n\n## Security\n\n`bulk_read` reads files from the local filesystem and ships their content to the worker LLM. Two layers scope what the worker can see:\n\n- **`SIDECAR_ALLOW_ROOTS`** is a comma-separated allowlist of absolute paths. Anything outside is skipped with `path outside allowed roots`. If unset, sidecar-mcp defaults to the current working directory and prints a one-line warning to stderr at boot. Set it explicitly for any non-dev use.\n- **Symlink escape is blocked.** Every file is checked both lexically (path prefix) and via `realpath` (canonical target). A symlink inside `allowRoots` that points outside is rejected with `path resolves outside allowed roots (symlink escape)`. `allowRoots` are also realpath'd, so `/var` vs `/private/var` style mounts collapse consistently.\n\nPer-file safety: `SIDECAR_FILE_MAX_BYTES` (default 512 KB) skips oversize files, NUL-byte sniff skips binaries, and the worker's reply is the only thing that returns to the MCP client — the main agent's context never holds raw file content.\n\n**Cwd default is a footgun.** Launching from `$HOME` exposes `~/.ssh`, `~/.aws`, `.env` to the worker. For any deployment, set `SIDECAR_ALLOW_ROOTS` to a tight scope (e.g. the project root) instead of relying on the default.\n\n## Limitations\n\n- **Non-streaming.** Worker replies are returned as one text blob.\n- **No `code_write`.** Bulk boilerplate generation is out of scope for MVP. If you need it, build a separate tool.\n- **Claude Code hook layer is opt-in.** Auto-redirect of large `Read`/`Bash cat|head|tail` calls to `bulk_read` lives in `extras/claude-hooks/` and is **not** installed by default. See `extras/claude-hooks/README.md` to wire it into `~/.claude/settings.json`.\n- **`SIDECAR_ALLOW_ROOTS` defaults to cwd.** Files outside are skipped with a warning. Set explicitly for stricter scoping.\n\n## Development\n\n```bash\ngit clone https://github.com/dEMonaRE/sidecar-mcp.git\ncd sidecar-mcp\npnpm install\npnpm dev          # run with tsx watch\npnpm test         # vitest\npnpm demo         # offline self-check (fake backend, prints prompt + reply)\npnpm build        # tsc → dist/\npnpm pack         # build a tarball to verify before publishing\n```\n\n**Manual smoke test with real Ollama:**\n```bash\nollama serve &\nollama pull llama3.1:8b\nSIDECAR_BACKEND=ollama sidecar-mcp &   # in one terminal\n# Wire into your MCP client (Claude Code, Copilot, Codex) and call bulk_read.\n```\n\n## License\n\nMIT — see [LICENSE](./LICENSE).\n","readmeFilename":""}