io.github.steveweltman/4q-tokenz
Intelligent MCP proxy that reduces token usage by exposing only mcp_search and mcp_call.
Ask AI about io.github.steveweltman/4q-tokenz
Powered by Claude Β· Grounded in docs
I know everything about io.github.steveweltman/4q-tokenz. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
MCP Proxy Gateway
A context-aware MCP proxy that reduces token usage by exposing only 2 tools (mcp_search, mcp_call) to LLMs instead of the full catalog.
Why This Exists
When you connect multiple MCP servers to an LLM, every tool from every server is listed in the LLM's context window. For a typical workspace with 50-100 tools across multiple MCP servers, that's thousands of tokens of schema documentation on every request.
MCP Proxy Gateway sits between your LLM and your MCP servers, offering:
- JIT tool loading β tools from upstream servers are discovered once at startup, then tools are called on-demand. Clients never see the full catalog.
- Intelligent search β hybrid lexical + semantic search (BM25 + embeddings) to find the right tool for a query, ranked by relevance.
- Token savings β LLMs only see 3 tool schemas (search, call, schema) instead of 50+. Typical savings: 20-40% per turn for tool-heavy workflows.
- Graceful degradation β when embeddings fail (e.g., sharp module missing), falls back to lexical search automatically.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your LLM β
β (sees only: mcp_search, mcp_call, mcp_schema) β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββΌβββββββββββββββ
β MCP Proxy Gateway β
β ββββββββββββββββββββββββ β
β β Tool Registry β β
β β (BM25 + Embeddings) β β
β ββββββββββββββββββββββββ β
β ββββββββββββββββββββββββ β
β β Connector Manager β β
β β (Idle timeout reap) β β
β ββββββββββββββββββββββββ β
ββββββββββββββ¬ββββββββββββββ
β
βββββββββββββββΌββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββ βββββββββββ βββββββββββ
βGoogle β βMailerLiteβ βYour Svc β
βGmail β β Campaignsβ β Custom β
βCalendar β β β β Tools β
βDrive β β β β β
βββββββββββ βββββββββββ βββββββββββ
Prerequisites
- Node.js 18+ with npm or pnpm
- One or more MCP servers to proxy (stdio or HTTP)
- Optional: for semantic search, the
@xenova/transformerslibrary is pre-installed, but requires thesharpmodule for best performance
Installation
From Source
git clone https://github.com/steveweltman/4q-tokens.git
cd 4q-tokens
pnpm install
pnpm build
# Install to ~/.local/bin and configure
./install.sh
As a Dependency
npm install @arvoretech/mcp-proxy
Getting Started: Google Workspace Example
Here's a concrete walkthrough to connect Google Workspace (Gmail, Calendar, Drive) to your LLM through the proxy:
Step 1: Choose or Build an MCP Server for Google
You need an MCP server that wraps Google APIs. Options:
-
@antidrift/mcp-google (recommended) β Supports Gmail, Calendar, Drive, Docs, Sheets
npm install @antidrift/mcp-google # or npx @antidrift/mcp-google --help -
@modelcontextprotocol/server-gmail β Gmail-only, official MCP server
-
Build your own β See the MCP spec to wrap your own APIs
Step 2: Set Up Google OAuth
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable these APIs:
- Gmail API
- Google Calendar API
- Google Drive API
- Create an OAuth 2.0 credential (type: Desktop application)
- Download the credential JSON
- Run the Google MCP server once to generate
token.json:
This opens a browser for you to authorize. Once done, it savesGOOGLE_CREDENTIAL_FILE=~/Downloads/credentials.json \ npx @antidrift/mcp-googletoken.jsonlocally.
Step 3: Configure the Proxy
Create ~/.config/4q-tokens/config.json:
{
"upstreams": [
{
"name": "google-workspace",
"transport": "stdio",
"command": "npx",
"args": ["@antidrift/mcp-google"],
"env": {
"GOOGLE_TOKEN_FILE": "~/.local/share/google-mcp/token.json",
"GOOGLE_CONNECTORS": "gmail,calendar,drive"
}
}
],
"searchLimit": 5,
"callItemLimit": 30,
"maxTextLength": 800,
"maxOutputTokens": 10000,
"idleTimeoutMs": 600000
}
Step 4: Start the Proxy
mcp-proxy
# Or via systemd if installed:
systemctl --user start mcp-proxy
Step 5: Connect Your LLM
Configure your LLM to use http://127.0.0.1:9200/mcp as its MCP server. It will see:
mcp_searchβ find tools by natural languagemcp_callβ invoke a toolmcp_schemaβ see tool details
Example query:
mcp_search("send an email")
# Returns: google_send_email (Gmail)
mcp_call(ref="google_send_email", args={"to": "user@example.com", "subject": "Hello", "body": "Test"})
Configuration
Quick Start with Environment Variables
export MCP_PROXY_UPSTREAMS='[
{
"name": "google",
"transport": "stdio",
"command": "node",
"args": ["/path/to/google/server.mjs"],
"env": {
"GOOGLE_TOKEN_FILE": "token.json"
}
}
]'
export MCP_PROXY_SINGLETON_PORT=9200
export MCP_PROXY_DASHBOARD_PORT=9100
node dist/index.js
Config File (Recommended)
Create ~/.config/4q-tokens/config.json:
{
"upstreams": [
{
"name": "google-workspace",
"transport": "stdio",
"command": "node",
"args": ["/home/user/.antidrift/tools/google/server.mjs"],
"env": {
"GOOGLE_TOKEN_FILE": "token.json",
"GOOGLE_CONNECTORS": "gmail,calendar,drive"
}
},
{
"name": "mailerlite",
"transport": "stdio",
"command": "node",
"args": ["/home/user/.antidrift/tools/mailerlite/server.mjs"],
"env": {
"MAILERLITE_API_KEY": "your-api-key-here"
}
},
{
"name": "external-api",
"transport": "http",
"url": "https://mcp.example.com/",
"auth": {
"apiKey": "API_KEY_ENV_VAR"
}
}
],
"searchLimit": 3,
"callItemLimit": 20,
"maxTextLength": 500,
"maxOutputTokens": 8000,
"idleTimeoutMs": 300000
}
Then run:
node dist/index.js
The proxy will load the config from ~/.config/4q-tokens/config.json if it exists, otherwise fall back to the MCP_PROXY_UPSTREAMS environment variable.
Configuration Reference
Upstream Server Config
{
"name": "unique-id",
"transport": "stdio" | "http",
// For stdio transport:
"command": "node",
"args": ["path/to/server.mjs"],
"cwd": "/working/dir", // optional
"env": { "KEY": "value" }, // optional
// For http transport:
"url": "https://example.com/mcp",
"auth": {
"apiKey": "ENV_VAR_NAME" // reads from process.env[ENV_VAR_NAME]
}
}
Proxy Options
| Option | Default | Description |
|---|---|---|
searchLimit | 3 | Max tools returned by mcp_search |
callItemLimit | 20 | Max items in mcp_call response |
maxTextLength | 500 | Truncate text fields to N chars (detail=false: 500, detail=true: 1500) |
maxOutputTokens | 8000 | Hard cap on response size |
idleTimeoutMs | 300000 | Disconnect upstream servers after N ms of inactivity (0 = disabled) |
Environment variable overrides:
export MCP_PROXY_SEARCH_LIMIT=5
export MCP_PROXY_CALL_ITEM_LIMIT=30
export MCP_PROXY_MAX_TEXT_LENGTH=800
export MCP_PROXY_MAX_OUTPUT_TOKENS=10000
export MCP_PROXY_IDLE_TIMEOUT_MS=600000
Running
Standalone (Stdio Transport)
node dist/index.js
The proxy connects via stdio to your LLM. Use it with Claude or other MCP clients.
As a Systemd User Service
The install script can set this up for you (see below), or manually:
- Create
~/.config/systemd/user/mcp-proxy.service:
[Unit]
Description=MCP Proxy Gateway
After=network.target
[Service]
Type=simple
ExecStart=%h/.local/bin/mcp-proxy
Restart=on-failure
RestartSec=5s
Environment="PATH=%h/.local/bin:/usr/local/bin:/usr/bin"
[Install]
WantedBy=default.target
- Enable and start:
systemctl --user daemon-reload
systemctl --user enable mcp-proxy
systemctl --user start mcp-proxy
- View logs:
journalctl --user -u mcp-proxy -f
HTTP Server (Port 9200)
When MCP_PROXY_SINGLETON_PORT is set, the proxy starts an HTTP transport on that port. This allows multiple clients to connect to a single proxy instance.
export MCP_PROXY_SINGLETON_PORT=9200
node dist/index.js &
# From another process:
curl -X POST http://127.0.0.1:9200/mcp -H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools/call", "params": {...}}'
Troubleshooting
Semantic Search Not Working
If embeddings fail with "Cannot find module 'sharp'", the proxy automatically falls back to lexical (keyword) search.
To enable semantic search, install the optional sharp module:
npm install sharp
If installation still fails (common on M1/M2 Macs or unusual architectures), the fallback is already in place. See error logs for details.
Upstream MCP Server Won't Connect
Check the server logs in the dashboard (port 9100 by default) or daemon logs:
journalctl --user -u mcp-proxy -e
The proxy logs:
- Tool discovery on startup
- Connection failures with error messages
- Upstream stderr (piped from stdio servers)
Proxy Crashes or Freezes
The proxy has comprehensive error handling to gracefully degrade on upstream failures:
- If an upstream tool call fails, the error is logged and returned to the client
- If embeddings init fails, lexical search takes over
- If all upstreams fail at discovery, startup fails with
NO_UPSTREAMS
For unhandled errors, check:
journalctl --user -u mcp-proxy -n 50 # Last 50 lines
Tool Returns No Data
When a tool returns null or malformed data, the output shaper handles it gracefully:
- Null results return
[] - Strings are wrapped as
{value: string} - CSV is auto-parsed if it looks like tabular data
- Raw binary content (images, files) is preserved via
_rawContent
If a tool response looks truncated, retry with detail=true in mcp_call to disable output shaping:
mcp_call(ref="google_send_email", args={...}, detail=true)
Security & Networking
The proxy binds to 127.0.0.1 only for security β it's not accessible from the network by default. To access remotely:
- Same machine: Connect locally on
127.0.0.1:9200 - Remote access: Use Tailscale, SSH forwarding, or a VPN tunnel
ssh -L 9200:127.0.0.1:9200 user@remote-host - Systemd service: Access is local by default; no firewall rule needed
Known Limitations
- No automated tests β this is production-quality code used daily, but test suite is not included
- Embeddings module: The
sharpmodule may fail to build on some systems. The proxy falls back to lexical (BM25) search automatically with no performance loss
Attribution
MCP Proxy Gateway is a fork of @arvoretech/mcp-proxy, originally created by JoΓ£o Augusto and Γrvore EducaΓ§Γ£o.
Forked for single-player use with enhancements:
- Singleton mode for HTTP bridge
- Idle server reaping
- Comprehensive error handling
- Config file support
- Systemd integration
License
MIT. See LICENSE.
