AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Harshal Mcp Proxy

mcp-harshalrathore-harshal-mcp-proxy · by HarshalRathore

Shared MCP gateway with schema deferral, response shielding, and HTTP daemon mode. Replaces 12+ MCP servers with 6 tools — saves ~99% context tokens and ~2.7GB RAM. npm: harshal-mcp-proxy

No reviews yet
0 installs
38 views
0.0% view→install

Install

$ agentstack add mcp-harshalrathore-harshal-mcp-proxy

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-harshalrathore-harshal-mcp-proxy)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Harshal Mcp Proxy? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

harshal-mcp-proxy

Custom MCP gateway that slashes costs: load 6 gateway tools (~375 tokens) instead of 40-70K tokens of upstream MCP server schemas — a ~99.3% reduction — and run one shared daemon instead of a server farm per agent session, saving ~2.7 GB RAM. Combines schema deferral (from mcp-gateway) with response shielding (from tldr) in a single TypeScript server.

What it does

Instead of your AI client loading 40-70K tokens of tool schemas from 12+ MCP servers at startup, it loads 6 tool definitions from this proxy (~375 tokens). The proxy then:

  1. Schema deferral — Tools are discovered via BM25 search (gateway.search), full

schemas loaded on demand (gateway.describe), and executed through the proxy (gateway.invoke). The model never sees schemas it doesn't need.

  1. Response shielding — Every tool response passes through a truncation engine before

reaching the model context:

  • Arrays >50 items → capped at 50, remainder stored for pagination
  • Strings >8192 chars → truncated with marker
  • Heavy fields in array-of-objects → stripped (avg >256 bytes), signal fields preserved
  • Total response >64KB → iteratively shrunk to fit
  • Full untruncated responses stored in a ring buffer (last 100), accessible via

gateway.get_result with pagination, field projection, and text search

  1. Shared process elimination — In daemon mode, ONE proxy instance serves ALL your AI

clients (pi, VS Code, etc.), eliminating duplicate MCP server processes.

  1. On-demand lazy loading — MCP server processes are no longer started at boot.

Instead, tool schemas are loaded from disk-based catalog snapshots at startup. The actual server process is spawned only when you first invoke a tool on that server. After 5 minutes of inactivity, the idle monitor auto-disconnects it — freeing RAM and CPU without losing searchability.


Why the Shared Daemon?

Every AI coding agent (pi session, VS Code MCP extension) traditionally spawns its own complete set of MCP server processes. With 12+ MCP servers in your config, this means:

┌──────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  pi session 1│────►│  harshal-mcp-    │────►│  12 MCP servers  │
│              │     │  proxy (stdio)   │     │  (1.3 GB)        │
├──────────────┤     └──────────────────┘     └──────────────────┘
│  pi session 2│────►┌──────────────────┐     ┌──────────────────┐
│              │     │  harshal-mcp-    │────►│  12 MCP servers  │
├──────────────┤     │  proxy (stdio)   │     │  (1.3 GB)        │
│  VS Code     │────►└──────────────────┘     └──────────────────┘
└──────────────┘                               ┌──────────────────┐
                                               │  12 MCP servers  │
                                               │  (1.3 GB)        │
                                               └──────────────────┘

3 sets × 12 servers = 36 processes, ~4 GB wasted RAM.

With the shared daemon:

┌──────────────┐     ┌────────────────────────┐     ┌──────────────────┐
│  pi session 1│────►│                        │     │                  │
├──────────────┤     │  harshal-mcp-proxy     │────►│  12 MCP servers  │
│  pi session 2│────►│  daemon (HTTP port     │     │  (1.3 GB)        │
├──────────────┤     │  8765)                 │     │     ONE SET      │
│  VS Code     │────►│                        │     │                  │
└──────────────┘     └────────────────────────┘     └──────────────────┘

3 clients × 1 daemon = ~10 MCP processes, saves ~2.7 GB RAM.


Two Modes

Mode 1: Stdio (original, single-client)

Each client spawns its own proxy instance via stdio. One consumer at a time.

node dist/index.js

Mode 2: HTTP Daemon (recommended, multi-client)

One proxy daemon serves all clients over HTTP. Uses MCP Streamable HTTP transport (JSON-RPC 2.0).

node dist/index.js --daemon
# or with custom port:
node dist/index.js --port 8765

Mode 3: Catalog Discovery (snapshot builder)

Build tool schema snapshots for all servers without keeping them running. Run this once after adding a new server or updating tool schemas.

node dist/index.js --discover
# Connects to ALL servers, fetches tool schemas, saves snapshots to disk, then exits

Catalog snapshots are stored in ~/.cache/harshal-mcp-proxy/catalogs/.


The 6 Gateway Tools

| Tool | Purpose | Token Cost | |------|---------|------------| | gateway.search | BM25 fuzzy search over all upstream tools | Returns IDs + descriptions only | | gateway.describe | Get full inputSchema for one tool | On-demand, only when needed | | gateway.invoke | Execute tool synchronously (with response shielding) | Response auto-truncated | | gateway.invoke_async | Queue tool for async execution | Returns jobId immediately | | gateway.invoke_status | Poll async job status | Minimal response | | gateway.get_result | Paginate through truncated responses | Offset/limit/fields/search |

Model Workflow

1. gateway.search { query: "cypher query", limit: 5 }
   → Returns: [ { id: "neo4j-cypher::run_cypher_query", score: 4.2 }, ... ]

2. gateway.describe { id: "neo4j-cypher::run_cypher_query" }
   → Returns: { inputSchema: { query: "string", params: "object" } }

3. gateway.invoke { id: "neo4j-cypher::run_cypher_query", args: { query: "MATCH (n) RETURN n LIMIT 10" } }
   → Returns: { content: [...], _ref: "r3", _truncated: true }

4. gateway.get_result { ref: "r3", offset: 50, limit: 50, fields: ["name", "id"] }
   → Returns: next page of results with field projection

Quick Start (AI-Powered Setup)

Want an AI agent to set this up for you? Give it the prompt in [SETUP_PROMPT.md](./SETUP_PROMPT.md).

cat SETUP_PROMPT.md | pbcopy  # macOS
cat SETUP_PROMPT.md | xclip   # Linux (or just cat the file and copy it)

The prompt covers: installation, config, systemd service, pi integration, VS Code integration, agent context installation, verification, and troubleshooting — all in one shot.

For existing installations: Teach Your Agent

If you already have harshal-mcp-proxy running but your agent doesn't know how to call the gateway tools, use the [AGENT-CONTEXT.md](./AGENT-CONTEXT.md) file:

# Copy into your agent's config:

# For Pi:
cp AGENT-CONTEXT.md .pi/rules/mcp-proxy-context.md

# For Claude Code / Opencode:
cp AGENT-CONTEXT.md .opencode/rules/mcp-proxy-context.md

# For Cline (VS Code):
cp AGENT-CONTEXT.md .clinerules

# For Cursor:
cp AGENT-CONTEXT.md .cursorrules

Then reference it in your agent's startup config (e.g., .pi/APPEND_SYSTEM.md, AGENTS.md, CLAUDE.md, .cursorrules, etc.) so every session loads it.


Installation

Option 1: Install from npm (recommended)

# Global install — binary available as `harshal-mcp-proxy` in PATH
npm install -g harshal-mcp-proxy

# Or run directly without installing:
npx harshal-mcp-proxy

# Create config from template (EDIT THIS with your values)
mkdir -p ~/.config/harshal-mcp-proxy
cp $(npm root -g)/harshal-mcp-proxy/config.example.json ~/.config/harshal-mcp-proxy/config.json
# ⚠️ Edit ~/.config/harshal-mcp-proxy/config.json with your API keys and paths

# Verify it works (stdio mode)
harshal-mcp-proxy
# Should print: harshal-mcp-proxy starting (stdio)...
# Then: __MCP_GATEWAY_STDIO_READY__
# Ctrl+C to stop

Option 2: Clone from source

# Clone the repo
gh repo clone HarshalRathore/harshal-mcp-proxy
cd harshal-mcp-proxy

# Install dependencies
npm install

# Build
npm run build

# Create config from template (EDIT THIS with your values)
cp config.example.json ~/.config/harshal-mcp-proxy/config.json
# ⚠️ Edit ~/.config/harshal-mcp-proxy/config.json with your API keys and paths

# Verify it works (stdio mode)
node dist/index.js
# Should print: harshal-mcp-proxy starting (stdio)...
# Then: __MCP_GATEWAY_STDIO_READY__
# Ctrl+C to stop

> ⚠️ Security: config.json contains API keys and secrets. It is excluded from > version control via .gitignore. Always use config.example.json as the template > and keep your actual config.json local.

Setup: HTTP Daemon Mode (Systemd User Service)

This is the recommended setup — runs the proxy as a persistent background service that all your AI clients connect to remotely.

Step 1: Install the systemd unit

The .service file ships with the package. Copy it to your user systemd directory:

mkdir -p ~/.config/systemd/user

# If installed from npm:
cp $(npm root -g)/harshal-mcp-proxy/harshal-mcp-proxy.service ~/.config/systemd/user/

# If cloned from source:
# cp harshal-mcp-proxy.service ~/.config/systemd/user/

# Edit the path in the service file to match your setup:
sed -i "s|/home/username/|$HOME/|" ~/.config/systemd/user/harshal-mcp-proxy.service
# If using npm global install, the binary is already in PATH — just uncomment the right line

The service file supports two modes (edit it to choose one):

  • npm global install: ExecStart=harshal-mcp-proxy --daemon (binary in PATH)
  • Source clone: ExecStart=/usr/bin/node /path/to/dist/index.js --daemon

Step 2: Enable and start

systemctl --user daemon-reload
systemctl --user enable harshal-mcp-proxy   # auto-start at boot
systemctl --user start harshal-mcp-proxy    # start now
systemctl --user status harshal-mcp-proxy   # verify

Step 3: Verify

# Health check
curl http://localhost:8765/health

# MCP initialize
curl -X POST http://localhost:8765/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'

# List tools
curl -X POST http://localhost:8765/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

Step 4: Manage the service

systemctl --user stop harshal-mcp-proxy     # stop daemon
systemctl --user restart harshal-mcp-proxy  # restart
systemctl --user disable harshal-mcp-proxy  # disable auto-start
journalctl --user -u harshal-mcp-proxy -f   # follow logs

Client Configuration

For pi (pi-mcp-adapter)

Create or update ~/.pi/agent/mcp.json (global) or /.pi/mcp.json (project-level):

{
  "mcpServers": {
    "harshal-mcp-proxy": {
      "url": "http://localhost:8765/mcp",
      "description": "Shared MCP gateway — search, describe, invoke access to all tools"
    }
  }
}

Then reload pi's MCP config with /mcp reconnect or restart the pi session.

For VS Code

Update /.vscode/mcp.json (project-level) or ~/.config/Code/User/mcp.json (global):

{
  "servers": {
    "harshal-mcp-proxy": {
      "type": "streamableHttp",
      "url": "http://localhost:8765/mcp",
      "description": "Shared MCP gateway — provides search, describe, and invoke access to all tools"
    }
  }
}

Replace all individual MCP server entries (playwright, shadcn, neo4j, etc.) with this single entry. Restart VS Code or reload the MCP extension.

For opencode

Update opencode.json:

{
  "mcp": {
    "harshal-mcp-proxy": {
      "type": "remote",
      "url": "http://localhost:8765/mcp",
      "transport": "streamable_http"
    }
  }
}

Architecture

Stdio Mode (legacy, single-client)

┌──────────────┐     stdio      ┌──────────────────────────┐
│  AI Client   │ ──────────── → │   harshal-mcp-proxy      │
│  (sees 6     │ ← ──────────  │                          │
│   tools)     │                │  ┌──────────────────┐    │
└──────────────┘                │  │  SearchEngine     │    │  ← BM25 index
                                │  │  (MiniSearch)     │    │
                                │  └──────────────────┘    │
                                │  ┌──────────────────┐    │
                                │  │  ResponseShield   │    │  ← Truncation
                                │  │  ResponseStore    │    │  ← Ring buffer
                                │  └──────────────────┘    │
                                │  ┌──────────────────┐    │
                                │  │  ConnectionMgr    │ ───── → Upstream MCP
                                │  └──────────────────┘    │     servers (stdio)
                                └──────────────────────────┘

HTTP Daemon Mode (recommended, multi-client)

┌──────────────┐    HTTP POST    ┌──────────────────────────┐
│  pi #1       │ ──────────────► │                          │
├──────────────┤                 │  harshal-mcp-proxy       │
│  pi #2       │ ──────────────► │  daemon (port 8765)      │
├──────────────┤                 │                          │
│  VS Code     │ ──────────────► │  ┌──────────────────┐    │
├──────────────┤                 │  │  JSON-RPC 2.0    │    │
│  opencode    │ ──────────────► │  │  over HTTP POST  │    │
└──────────────┘                 │  └──────────────────┘    │
                                 │  ┌──────────────────┐    │
                                 │  │  SearchEngine     │    │
                                 │  └──────────────────┘    │
                                 │  ┌──────────────────┐    │
                                 │  │  ResponseShield   │    │
                                 │  │  ResponseStore    │    │
                                 │  └──────────────────┘    │
                                 │  ┌──────────────────┐    │
                                 │  │  ConnectionMgr    │ ───── → ONE set of
                                 │  └──────────────────┘    │     upstream MCP
                                 └──────────────────────────┘     servers

All clients share ONE set of upstream MCP server processes.
No duplicate npm exec, no wasted RAM.

Migration Guide

From stdio to daemon mode

1. Install the service:

# Build the proxy if not already built
cd /path/to/harshal-mcp-proxy && npm run build

# Enable and start the daemon
systemctl --user daemon-reload
systemctl --user enable harshal-mcp-proxy
systemctl --user start harshal-mcp-proxy

2. Update your clients:

| Client | Config file | Change | |--------|-------------|--------| | pi | ~/.pi/agent/mcp.json or /.pi/mcp.json | Set url to http://localhost:8765/mcp | | VS Code | /.vscode/mcp.json | Set type: "streamableHttp" + url | | opencode | opencode.json | Set type: "remote" + url |

3. Remove old local command configs:

Delete entries that used type: "local" with individual command arrays for each MCP server (e.g., playwright, shadcn, neo4j, searxng, etc.). The daemon manages all upstream servers via its own ~/.config/harshal-mcp-proxy/config.json.

4. Reload / restart clients:

  • pi: run /mcp reconnect or restart pi session
  • VS Code: restart the MCP extension or VS Code itself
  • opencode: close and reopen

5. Verify:

Check the daemon health:

curl http://localhost:8765/health
# Expected: {"status":"ok","servers":12,"tools":130,...}

Check that only ONE set of MCP server processes is running:

ps aux | grep "npm exec" | grep -v grep | wc -l
# Before (3 clients): ~35 processes
# After (daemon): ~10 processes

Configuration Hot-Reload

The daemon watches ~/.config/harshal-mcp-proxy/config.json for changes, just like the stdio mode. When you edit it:

  • New servers are connected automatically
  • Removed servers are disconnected
  • Changed configs trigger reconnection
  • "enabled": false disables a server without removing it

No restart needed.


Config File

~/.config/harshal-mcp-proxy/config.json defines all upstream MCP servers.

The lazy field controls on-demand loading per server. When enabled, the server process is NOT started at boot — tool schemas are loaded from a cached snapshot. The process spawns on first use and auto-disconnects after idle timeout.

Minimal config (

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.