mcp-proxy-bridge
by xiaolaifeng
README.md
# mcp-proxy-bridge
> An MCP server + Claude Code hook that makes a target host (e.g. **github.com**) reachable through your **local proxy** — launching the proxy client if needed and configuring your tools to route through it.
[](LICENSE)
[](https://nodejs.org)
[](#)
If you're behind a network where GitHub (or another host) only works through a local proxy like **Clash / Clash Verge / v2rayN / sing-box**, this bridge makes it *just work* for your AI coding assistant:
- **MCP server** — tools to check reachability, start/stop the proxy, and orchestrate the whole flow.
- **PreToolUse hook** — fires automatically on Bash commands that touch a configured host, brings the proxy up, and points git at it.
Zero dependencies (Node stdlib only) — deliberately, because a tool that fixes network problems must not need a network install.
---
## How it works
Most local proxies run with **system proxy and TUN off**, so simply starting the proxy client doesn't route your traffic. The bridge:
1. Probes whether the target is reachable directly.
2. If not, checks the local proxy port; if closed, launches your proxy client and waits for the port.
3. Verifies the target through the proxy (HTTP CONNECT or SOCKS5 → TLS HEAD).
4. Sets a **URL-scoped** git proxy so only the configured host routes through the proxy — every other repo host is untouched. Idempotent and reversible.
> Note: this is a **local** tool. It launches *your* proxy client and configures *your* machine. Each user runs their own copy next to their own proxy — it is **not** a shared hosted service.
## Install
### Use without installing (npx)
```bash
# MCP server (spawned once by your client at startup — npx is fine here)
claude mcp add proxy-bridge -- npx -y mcp-proxy-bridge
```
### Install globally (recommended for the hook, which runs on every Bash call)
```bash
npm install -g mcp-proxy-bridge
```
### From source / GitHub
```bash
git clone https://github.com/xiaolaifeng/mcp-proxy-bridge.git
cd mcp-proxy-bridge
node src/server.mjs --print-config # sanity check
```
## Quick start (Claude Code)
1. **Create a config** (edit the result to match your proxy client):
```bash
mcp-proxy-bridge --init # writes ~/.mcp-proxy-bridge.json
$EDITOR ~/.mcp-proxy-bridge.json # set launch.command, ports, process.names
mcp-proxy-bridge --print-config # verify
```
See [`examples/`](examples) for Clash Verge, v2rayN, sing-box, and SOCKS5.
2. **Register the MCP server** (user scope = all projects):
```bash
claude mcp add proxy-bridge --scope user -- npx -y mcp-proxy-bridge
# or, if installed globally:
claude mcp add proxy-bridge --scope user -- mcp-proxy-bridge
```
3. **Register the hook** in `~/.claude/settings.json`:
```jsonc
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "mcp-proxy-bridge-hook" }
]
}
]
}
}
```
(Use `npx -y mcp-proxy-bridge-hook` instead if not installed globally, but global install is faster for a per-command hook.)
4. Restart Claude Code. Run a `git pull` that touches GitHub — the proxy comes up automatically.
## Configuration
Config is layered, later wins: **defaults < JSON file < environment variables**.
- **File**: `~/.mcp-proxy-bridge.json` (override path with `PROXY_BRIDGE_CONFIG`).
- **Env**: see table below.
- **CLI**: `--print-config`, `--init [path]`.
```jsonc
{
"targets": ["github.com", "api.github.com", "raw.githubusercontent.com"],
"checkPort": 443,
"proxy": { "host": "127.0.0.1", "port": 7897, "scheme": "http" },
"launch": { "command": "clash-verge", "args": [], "cwd": null, "waitPortMs": 40000 },
"process": { "names": ["clash-verge", "verge-mihomo", "mihomo"] },
"gitProxy": { "enable": true, "scope": null },
"hook": { "matchTargets": true, "extraPatterns": ["\\bgit\\s+[^|;&\\n]*\\b(clone|fetch|pull|push|ls-remote|submodule)\\b"] }
}
```
| Field | Meaning |
|-------|---------|
| `targets` | Hosts to verify. |
| `checkPort` | Port probed on each target (443 = HTTPS). |
| `proxy.host` / `proxy.port` | Your local proxy address. |
| `proxy.scheme` | `http` (HTTP CONNECT) or `socks5`. |
| `launch.command` / `launch.args` | Command to start your proxy client. `null` = you start it manually. |
| `launch.waitPortMs` | How long to wait for the port after launching. |
| `process.names` | Best-effort process names for `status` / `stop` (Windows auto-appends `.exe`). |
| `gitProxy.enable` | Hook sets URL-scoped git proxy for the targets. |
| `gitProxy.scope` | Override git URL prefixes (defaults to `https://<target>/` per target). |
| `hook.matchTargets` | Hook fires when a command mentions any target host. |
| `hook.extraPatterns` | Extra regexes that trigger the hook (default: git network verbs). |
### Environment variables
| Var | Maps to |
|-----|---------|
| `PROXY_BRIDGE_CONFIG` | Config file path. |
| `PROXY_BRIDGE_TARGETS` | Comma-separated targets. |
| `PROXY_BRIDGE_CHECK_PORT` | Target port. |
| `PROXY_BRIDGE_PROXY_HOST` / `PROXY_BRIDGE_PROXY_PORT` / `PROXY_BRIDGE_PROXY_SCHEME` | Proxy endpoint. |
| `PROXY_BRIDGE_LAUNCH_CMD` / `PROXY_BRIDGE_LAUNCH_ARGS` | Launch command (args: JSON array or space-split). |
| `PROXY_BRIDGE_PROCESS_NAMES` | Comma-separated process names. |
| `PROXY_BRIDGE_SET_GIT_PROXY` | `0` disables git proxy. |
| `PROXY_BRIDGE_GIT_SCOPE` | Comma-separated git URL prefixes. |
| `PROXY_BRIDGE_HOOK_EXTRA` | Comma-separated extra trigger regexes. |
## MCP tools
| Tool | Description |
|------|-------------|
| `ensure_access` | Check direct; if down, start proxy, wait for port, verify via proxy. |
| `check` | `useProxy` true/false reachability of a target. |
| `status` | Proxy process running? Port open? Targets? |
| `start_proxy` / `stop_proxy` | Launch / best-effort kill. |
| `proxy_info` | Proxy URL + env/git-config hints (and unset). |
| `set_git_proxy` | Apply the URL-scoped git proxy. |
| `show_config` | Resolved config + config path. |
## Platform notes
- **Windows**: process detection via `tasklist`, stop via `taskkill`. Append `.exe` automatically.
- **macOS / Linux**: process detection via `pgrep`, stop via `pkill`. Set `launch.command` to the app binary or `open -a "Clash Verge"` on macOS.
- Port readiness is the primary "proxy is up" signal on all platforms.
## Other MCP clients
Works with any MCP-capable client that speaks stdio (Claude Desktop, etc.). Point the client at:
```
npx -y mcp-proxy-bridge
```
The hook is Claude-Code-specific (PreToolUse). For other clients, call the `ensure_access` tool before GitHub operations, or use the git-proxy hint from `proxy_info`.
## Troubleshooting
- **`status` shows `proxyPortOpen: false`**: your proxy client isn't running or the port differs — check `proxy.port` and `launch.command`.
- **Proxy up but target still unreachable**: the selected node/subscription in your proxy client can't reach the target — switch nodes, then retry.
- **`processRunning: false` even when running**: add the right `process.names` (this field is best-effort; the port probe is authoritative).
- **Don't want the persistent git proxy**: run `git config --global --unset http.<scope>.proxy`, or set `PROXY_BRIDGE_SET_GIT_PROXY=0`.
- If you enable **TUN** or **system proxy** in your client, the explicit git proxy becomes unnecessary but stays harmless.
## Manual testing
```bash
mcp-proxy-bridge --print-config
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'$'\n''{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | node src/server.mjs
echo '{"tool_input":{"command":"git pull origin main"}}' | node src/hook.mjs # should emit context
echo '{"tool_input":{"command":"docker ps"}}' | node src/hook.mjs # should be silent
```
## Security & notes
- The bridge only ever talks to `127.0.0.1` (your proxy) and the configured target hosts over TLS. No telemetry, no remote calls.
- `set_git_proxy` / the hook modify **global git config** (`http.<scope>.proxy`) — reversible via the `--unset` commands in `proxy_info`.
- MIT licensed.
---
## For maintainers — publishing
**npm:**
```bash
npm version patch # or minor / major
npm pack # inspect the tarball contents
npm publish # publishes the files listed in package.json "files"
```
Before publishing, fill in `package.json` `author`, `repository`, `homepage`, `bugs` (already set: author Robin Lee, repo xiaolaifeng/mcp-proxy-bridge).
**GitHub:** push the repo, then users can `npx github:xiaolaifeng/mcp-proxy-bridge`.
**MCP directories** (for discovery): submit to [mcp.so](https://mcp.so), [Glama](https://glama.ai/mcp/servers), [Smithery](https://smithery.ai), and the [Anthropic MCP server list](https://github.com/modelcontextprotocol/servers).
## License
[MIT](LICENSE)
TDQS
A3.7/5.0
Scored across 8 tools
Disambiguation4/5
Most tools have distinct purposes, but 'check' and 'ensure_access' both test reachability; 'ensure_access' is a higher-level operation that may also launch the proxy, causing slight ambiguity.
Naming Consistency3/5
Tool names use a mix of conventions: some are verbs only ('check'), some are verb_noun ('start_proxy'), and some are noun_only ('status') or noun_info ('proxy_info'), lacking a consistent pattern.
Tool Count5/5
With 8 tools, the set is well-scoped for managing a proxy bridge, covering essential operations without unnecessary bloat.
Completeness4/5
The tool set covers core proxy lifecycle (start/stop/status), reachability testing, configuration access, and git proxy setup. Missing direct tool for managing proxy targets, but config editing may be external.
Maintenance
ActivityInactive
ResponsivenessNo issues