{"_id":"4q-tokenz","_rev":"8-4f2458eb7fb34a20cec46d8f52b65269","name":"4q-tokenz","dist-tags":{"latest":"1.21.2"},"versions":{"1.14.1":{"name":"4q-tokenz","version":"1.14.1","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","arvore"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.14.1","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokens#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokens/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"d654e6ae364dd368fff69bb39e075bbcf0260853","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.14.1.tgz","fileCount":86,"integrity":"sha512-1MY5zZrrh7TQ4Y4QveMDENxna6h0Ew8AFMmFHmvCrX2MdN48jcwRJ2ATdxq9ZMU4jcqx0YmZhKapqOv0ecTo0Q==","signatures":[{"sig":"MEYCIQDYd2axXaC4SOiM56KrFNTEiYtTuMfnY7JFAAB1pLFXrAIhAMEQLE4ZjndM7h4AEUPKJ3OHEPUkkNztQw5mIM5SKvJj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":319655},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","gitHead":"c8eded5fda6af86450aa1975c413de66e9770c0f","scripts":{"dev":"tsx src/index.ts","lint":"eslint src/**/*.ts","test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","lint:fix":"eslint src/**/*.ts --fix","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokens.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search and mcp_call","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@xenova/transformers":"^2.17.2","@modelcontextprotocol/sdk":"~1.22.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.14.1_1778233525504_0.9559138331809391","host":"s3://npm-registry-packages-npm-production"}},"1.15.0":{"name":"4q-tokenz","version":"1.15.0","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","arvore"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.15.0","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokens#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokens/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"878debd0fabe15d5538cda3a8c860f7f9ed18041","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.15.0.tgz","fileCount":86,"integrity":"sha512-8JHQnw9nqfobZaKwR33ehJRfJn3DuhzeP4OyTOk1nPk4bcVNHSPRV/WoODPOgkLcvxDhOeAx22a8XSW0C7kvUQ==","signatures":[{"sig":"MEYCIQCwvzBeqzFe2abvBJxyGnDjWAxEZr7VZOZiANDWlGYpggIhANMIa8OXnKGMzGy1s+oRGeq+LaDjFbKd7sKUzy36JWMJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":320214},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","gitHead":"9e0a758001ac693bda856a3c2ebd210423dab2fb","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"dev":"tsx src/index.ts","lint":"eslint src/**/*.ts","test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","lint:fix":"eslint src/**/*.ts --fix","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokens.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search and mcp_call","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@xenova/transformers":"^2.17.2","@modelcontextprotocol/sdk":"~1.22.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.15.0_1778235491567_0.9956520089769305","host":"s3://npm-registry-packages-npm-production"}},"1.16.0":{"name":"4q-tokenz","version":"1.16.0","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","arvore"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.16.0","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokens#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokens/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"4cbee645e7643c15780062d0ef19dc641221b89f","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.16.0.tgz","fileCount":86,"integrity":"sha512-tXZdUgXUbqHftAuv8s9nKDzMLe4aAERUdBEfIULEJExFAvn8bDexEa4mopDKvR0LKX4sRLuOA6H9lmUeOyyCXg==","signatures":[{"sig":"MEUCIQCIjZWIUtUE5xxe49HDS3tZpx/QEt/bWJYy1SsIfp99CgIgET1M7ngEGiXAZoKN0aESTOY5lVf5SlNQWgrg/cbJT+o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":320310},"main":"dist/index.js","pnpm":{"overrides":{"qs":">=6.15.2","protobufjs":">=7.5.8"}},"type":"module","types":"./dist/index.d.ts","gitHead":"53170990d12df75d00567dc364389dba5b6d543a","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"dev":"tsx src/index.ts","lint":"eslint src/**/*.ts","test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","lint:fix":"eslint src/**/*.ts --fix","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokens.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search and mcp_call","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@xenova/transformers":"^2.17.2","@modelcontextprotocol/sdk":"^1.26.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.16.0_1779497839436_0.9538984627684168","host":"s3://npm-registry-packages-npm-production"}},"1.18.0":{"name":"4q-tokenz","version":"1.18.0","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","arvore"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.18.0","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokens#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokens/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"f20accd3aa900fc183343b79070914cdd9da15fe","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.18.0.tgz","fileCount":80,"integrity":"sha512-NFJ48YO+E5f3kCt+s5lWR5HaPM3z4BQbTk2Uxa3lOmsZPr4M0E38eg9fjtBQvR13JjrYhG9VjrY3V7x2TCvGxA==","signatures":[{"sig":"MEYCIQDJV0BI+AA6TG8LHd274KRwwvKPvlaFKvmpqZkx2y8Y1AIhAKr7T5dyOGwqDJhpGD2V5i1AmCVO4GQgb/bjyt2XgxZQ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":304835},"main":"dist/index.js","pnpm":{"overrides":{"qs":">=6.15.2"}},"type":"module","types":"./dist/index.d.ts","gitHead":"66f461f4f72548796892005c399a2300ec37ecf0","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"dev":"tsx src/index.ts","lint":"eslint src/**/*.ts","test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","lint:fix":"eslint src/**/*.ts --fix","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokens.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search and mcp_call","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@modelcontextprotocol/sdk":"^1.26.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.18.0_1779503153264_0.6852645577107668","host":"s3://npm-registry-packages-npm-production"}},"1.19.0":{"name":"4q-tokenz","version":"1.19.0","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","claude","context-window"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.19.0","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokenz#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokenz/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"9fcf655b756a35ee6838b84f6c64449c23474c16","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.19.0.tgz","fileCount":77,"integrity":"sha512-6HiCfpSx+G/2kWeTIzYTNE/GRd++nBbxaIFCoJt/X3+TtB/qH5cZJluvWta0NgqX9B0UwwSIu9RNW7KmD6d4zQ==","signatures":[{"sig":"MEUCIQCV02gSULs9mqwW5UpGaDFmdEUflj/mN3QFQZN792BXRgIgKE9jXRtuiQmjt0nQYf6yvk+XZCIizFjqWX9MQcTaqfU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":301526},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","gitHead":"c0e79319ff48d7b082166883d97085f36f0b9cee","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokenz.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search, mcp_call, and mcp_schema","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@modelcontextprotocol/sdk":"^1.26.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.19.0_1779522872653_0.4524780991270365","host":"s3://npm-registry-packages-npm-production"}},"1.21.0":{"name":"4q-tokenz","version":"1.21.0","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","claude","context-window"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.21.0","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokenz#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokenz/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"342443f4625f2d284395546493a9dd424c58430e","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.21.0.tgz","fileCount":77,"integrity":"sha512-nAAGYNipKVwFYhpseit/NCkMSBuqP8pjZSacEEBUI+cFACNtGa7piurqpfH904J4sin4QA5eezyv/3114FB1Dg==","signatures":[{"sig":"MEUCIQCvoTS3y436lHFFJc9gkcjWepI0QvMZ3jyF3lYlBZgnEwIgPT2KueDU/RFx7lfARwuR7GB/NNsMyqwpFp7lGy0yF3o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":314134},"main":"dist/index.js","type":"module","types":"./dist/index.d.ts","gitHead":"85a78beb6a2812faad8aa32f84c4d70def38cdff","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"test":"echo 'No tests configured'","build":"tsc","start":"node dist/index.js","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokenz.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search, mcp_call, and mcp_schema","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@modelcontextprotocol/sdk":"^1.26.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.21.0_1781768538170_0.5797941995447065","host":"s3://npm-registry-packages-npm-production"}},"1.21.1":{"name":"4q-tokenz","version":"1.21.1","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","claude","context-window"],"author":{"url":"fork of @arvoretech/mcp-proxy by Árvore Educação","name":"Steve Weltman"},"license":"MIT","_id":"4q-tokenz@1.21.1","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"homepage":"https://github.com/steveweltman/4q-tokenz#readme","bugs":{"url":"https://github.com/steveweltman/4q-tokenz/issues"},"bin":{"mcp-proxy":"dist/index.js"},"dist":{"shasum":"ab0e1c8c709c410e76ce842a30b8a470e5dc8829","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.21.1.tgz","fileCount":77,"integrity":"sha512-769sqg8UJZcfY0ZWC3XsfguR9/ZEH8B/yeBWSfmGR5bjo8cRXfjm0QTf/oTVGsNcXULoxoQUKzf/vITbtgMlCg==","signatures":[{"sig":"MEUCIQCRsBqMJKEelgFWrovm0mX2da5hCmCJ3v1tImanJkpsQwIgAROXkn+Zlf/6lbBpb8H3OQvAaZfkTjr8e1lv3FvXGRI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":314377},"main":"dist/index.js","pnpm":{"overrides":{"hono":">=4.12.25"}},"type":"module","types":"./dist/index.d.ts","gitHead":"519a312fce61f6bb1a1b719b3004d9db198ca26a","mcpName":"io.github.steveweltman/4q-tokenz","scripts":{"test":"echo 'No tests configured'","audit":"pnpm audit --audit-level=moderate","build":"tsc","start":"node dist/index.js","test:cov":"echo 'No tests configured'"},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"repository":{"url":"git+https://github.com/steveweltman/4q-tokenz.git","type":"git"},"_npmVersion":"10.9.7","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search, mcp_call, and mcp_schema","directories":{},"_nodeVersion":"22.22.2","dependencies":{"zod":"^3.22.4","@modelcontextprotocol/sdk":"^1.26.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^6.0.3","@types/node":"^25.6.0"},"_npmOperationalInternal":{"tmp":"tmp/4q-tokenz_1.21.1_1784239751140_0.9696383207558059","host":"s3://npm-registry-packages-npm-production"}},"1.21.2":{"name":"4q-tokenz","mcpName":"io.github.steveweltman/4q-tokenz","version":"1.21.2","description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search, mcp_call, and mcp_schema","main":"dist/index.js","type":"module","bin":{"mcp-proxy":"dist/index.js"},"scripts":{"build":"tsc","start":"node dist/index.js","test":"echo 'No tests configured'","test:cov":"echo 'No tests configured'","audit":"pnpm audit --audit-level=moderate"},"pnpm":{"overrides":{"hono":">=4.12.34","@hono/node-server":">=1.19.15","fast-uri":">=3.1.5","ip-address":">=10.3.1","body-parser":">=2.3.0"}},"keywords":["mcp","proxy","gateway","token-reduction","llm","ai","claude","context-window"],"author":{"name":"Steve Weltman","url":"fork of @arvoretech/mcp-proxy by Árvore Educação"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/steveweltman/4q-tokenz.git"},"dependencies":{"@modelcontextprotocol/sdk":"^1.30.0","zod":"^3.22.4"},"devDependencies":{"@types/node":"^25.6.0","typescript":"^6.0.3"},"gitHead":"e206de3ba4acacb1cbd7914db74f8e7ac370d67d","types":"./dist/index.d.ts","_id":"4q-tokenz@1.21.2","bugs":{"url":"https://github.com/steveweltman/4q-tokenz/issues"},"homepage":"https://github.com/steveweltman/4q-tokenz#readme","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-q/NUXJpQKJd7qj5Nrq3PKRnDDsrLDV/l15g0gtG8xZnkPKsy/X7AVTCsZTNxb8SfeaT3ogh8GG6Fb9s4qbCcaA==","shasum":"c5f0c5bc97f357c987e48792b297a32bce5b7f2f","tarball":"https://registry.npmjs.org/4q-tokenz/-/4q-tokenz-1.21.2.tgz","fileCount":77,"unpackedSize":315463,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIHZYVKWOHdEabaH8ayE9jf9mG5j3SnVwL+eV4X+eTVr1AiEA3IBcs7ZeTjZc8oloSH5fN30H3I8JIySq4Mg3b8UKhIU="}]},"_npmUser":{"name":"asc-steve","email":"steve@steveweltman.com"},"directories":{},"maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/4q-tokenz_1.21.2_1787570684219_0.8062244824449165"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-08T09:45:25.503Z","modified":"2026-08-24T11:24:44.532Z","1.14.1":"2026-05-08T09:45:25.644Z","1.15.0":"2026-05-08T10:18:11.761Z","1.16.0":"2026-05-23T00:57:19.576Z","1.18.0":"2026-05-23T02:25:53.436Z","1.19.0":"2026-05-23T07:54:32.809Z","1.21.0":"2026-06-18T07:42:18.295Z","1.21.1":"2026-07-16T22:09:11.289Z","1.21.2":"2026-08-24T11:24:44.372Z"},"bugs":{"url":"https://github.com/steveweltman/4q-tokenz/issues"},"author":{"name":"Steve Weltman","url":"fork of @arvoretech/mcp-proxy by Árvore Educação"},"license":"MIT","homepage":"https://github.com/steveweltman/4q-tokenz#readme","keywords":["mcp","proxy","gateway","token-reduction","llm","ai","claude","context-window"],"repository":{"type":"git","url":"git+https://github.com/steveweltman/4q-tokenz.git"},"description":"MCP Proxy Gateway - Intelligent proxy that reduces token usage by exposing only mcp_search, mcp_call, and mcp_schema","maintainers":[{"name":"asc-steve","email":"steve@steveweltman.com"}],"readme":"# MCP Proxy Gateway\n\nA context-aware MCP proxy that reduces token usage by exposing only 3 tools (`mcp_search`, `mcp_call`, `mcp_schema`) to LLMs instead of the full catalog.\n\n## Why This Exists\n\nWhen 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.\n\nMCP Proxy Gateway sits between your LLM and your MCP servers, offering:\n\n- **JIT tool loading** — tools from upstream servers are discovered once at startup, then tools are called on-demand. Clients never see the full catalog.\n- **Intelligent search** — fast lexical (BM25) search to find the right tool for a query. Tool tokens are pre-computed at startup for zero-overhead per-query scoring.\n- **Token savings** — LLMs only see 3 tool schemas (search, call, schema) instead of 50+. Typical savings: 20-40% per turn for tool-heavy workflows.\n- **Zero native dependencies** — pure JavaScript, no native modules, no model downloads, no supply chain risk from ML packages.\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                         Your LLM                                │\n│   (sees only: mcp_search, mcp_call, mcp_schema)                │\n└────────────────────┬────────────────────────────────────────────┘\n                     │\n         ┌───────────▼──────────────┐\n         │   MCP Proxy Gateway      │\n         │ ┌──────────────────────┐ │\n         │ │ Tool Registry        │ │\n         │ │ (BM25 lexical)       │ │\n         │ └──────────────────────┘ │\n         │ ┌──────────────────────┐ │\n         │ │ Connector Manager    │ │\n         │ │ (Idle timeout reap)  │ │\n         │ └──────────────────────┘ │\n         └────────────┬─────────────┘\n                      │\n        ┌─────────────┼─────────────┐\n        │             │             │\n        ▼             ▼             ▼\n   ┌─────────┐  ┌─────────┐  ┌─────────┐\n   │Google   │  │MailerLite│ │Your Svc │\n   │Gmail    │  │ Campaigns│ │ Custom  │\n   │Calendar │  │          │ │ Tools   │\n   │Drive    │  │          │ │         │\n   └─────────┘  └─────────┘  └─────────┘\n```\n\n## Prerequisites\n\n- Node.js 18+ with npm or pnpm\n- One or more MCP servers to proxy (stdio or HTTP)\n\n## Installation\n\n### From Source\n\n```bash\ngit clone https://github.com/steveweltman/4q-tokenz.git\ncd 4q-tokenz\n\npnpm install\npnpm build\n\n# Install to ~/.local/bin and configure\n./install.sh\n```\n\n### As a Dependency\n\n```bash\nnpm install -g 4q-tokenz\n```\n\n## Getting Started: Google Workspace Example\n\nHere's a concrete walkthrough to connect Google Workspace (Gmail, Calendar, Drive) to your LLM through the proxy:\n\n### Step 1: Choose or Build an MCP Server for Google\n\nYou need an MCP server that wraps Google APIs. Options:\n\n- **@antidrift/mcp-google** (recommended) — A collection of MCP server implementations for Google Workspace (Gmail, Calendar, Drive, Docs, Sheets). Works out of the box with this proxy.\n  ```bash\n  npm install @antidrift/mcp-google\n  # or\n  npx @antidrift/mcp-google --help\n  ```\n\n- **@modelcontextprotocol/server-gmail** — Gmail-only, official MCP server\n- **Build your own** — See the [MCP spec](https://modelcontextprotocol.io/) to wrap your own APIs\n\n### Step 2: Set Up Google OAuth\n\n1. Go to [Google Cloud Console](https://console.cloud.google.com/)\n2. Create a new project or select an existing one\n3. Enable these APIs:\n   - Gmail API\n   - Google Calendar API\n   - Google Drive API\n4. Create an OAuth 2.0 credential (type: Desktop application)\n5. Download the credential JSON\n6. Run the Google MCP server once to generate `token.json`:\n   ```bash\n   GOOGLE_CREDENTIAL_FILE=~/Downloads/credentials.json \\\n   npx @antidrift/mcp-google\n   ```\n   This opens a browser for you to authorize. Once done, it saves `token.json` locally.\n\n### Step 3: Configure the Proxy\n\nCreate `~/.config/4q-tokens/config.json`:\n\n```json\n{\n  \"upstreams\": [\n    {\n      \"name\": \"google-workspace\",\n      \"transport\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"@antidrift/mcp-google\"],\n      \"env\": {\n        \"GOOGLE_TOKEN_FILE\": \"~/.local/share/google-mcp/token.json\",\n        \"GOOGLE_CONNECTORS\": \"gmail,calendar,drive\"\n      }\n    }\n  ],\n  \"searchLimit\": 5,\n  \"callItemLimit\": 30,\n  \"maxTextLength\": 800,\n  \"maxOutputTokens\": 10000,\n  \"idleTimeoutMs\": 600000\n}\n```\n\n### Step 4: Start the Proxy\n\n```bash\nmcp-proxy\n# Or via systemd if installed:\nsystemctl --user start mcp-proxy\n```\n\n### Step 5: Connect Your LLM\n\nConfigure your LLM to use `http://127.0.0.1:9200/mcp` as its MCP server. It will see:\n- `mcp_search` — find tools by natural language\n- `mcp_call` — invoke a tool\n- `mcp_schema` — see tool details\n\nExample query:\n```\nmcp_search(\"send an email\")\n# Returns: google_send_email (Gmail)\n\nmcp_call(ref=\"google_send_email\", args={\"to\": \"user@example.com\", \"subject\": \"Hello\", \"body\": \"Test\"})\n```\n\n## Configuration\n\n### Quick Start with Environment Variables\n\n```bash\nexport MCP_PROXY_UPSTREAMS='[\n  {\n    \"name\": \"google\",\n    \"transport\": \"stdio\",\n    \"command\": \"node\",\n    \"args\": [\"/path/to/google/server.mjs\"],\n    \"env\": {\n      \"GOOGLE_TOKEN_FILE\": \"token.json\"\n    }\n  }\n]'\n\nexport MCP_PROXY_SINGLETON_PORT=9200\nexport MCP_PROXY_DASHBOARD_PORT=9100\n\nnode dist/index.js\n```\n\n### Config File (Recommended)\n\nCreate `~/.config/4q-tokens/config.json`:\n\n```json\n{\n  \"upstreams\": [\n    {\n      \"name\": \"google-workspace\",\n      \"transport\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\"@antidrift/mcp-google\"],\n      \"env\": {\n        \"GOOGLE_TOKEN_FILE\": \"token.json\",\n        \"GOOGLE_CONNECTORS\": \"gmail,calendar,drive\"\n      }\n    },\n    {\n      \"name\": \"external-api\",\n      \"transport\": \"http\",\n      \"url\": \"https://mcp.example.com/\",\n      \"auth\": {\n        \"apiKey\": \"MY_API_KEY_ENV_VAR\"\n      }\n    }\n  ],\n  \"searchLimit\": 3,\n  \"callItemLimit\": 20,\n  \"maxTextLength\": 500,\n  \"maxOutputTokens\": 8000,\n  \"idleTimeoutMs\": 300000\n}\n```\n\nThen run:\n\n```bash\nnode dist/index.js\n```\n\nThe proxy will load the config from `~/.config/4q-tokens/config.json` if it exists, otherwise fall back to the `MCP_PROXY_UPSTREAMS` environment variable.\n\n### Configuration Reference\n\n#### Upstream Server Config\n\n```json\n{\n  \"name\": \"unique-id\",\n  \"transport\": \"stdio\" | \"http\",\n  \n  // For stdio transport:\n  \"command\": \"node\",\n  \"args\": [\"path/to/server.mjs\"],\n  \"cwd\": \"/working/dir\",  // optional\n  \"env\": { \"KEY\": \"value\" },  // optional\n  \n  // For http transport:\n  \"url\": \"https://example.com/mcp\",\n  \"auth\": {\n    \"apiKey\": \"ENV_VAR_NAME\"  // reads from process.env[ENV_VAR_NAME]\n  }\n}\n```\n\n#### Proxy Options\n\n| Option | Default | Description |\n|--------|---------|-------------|\n| `searchLimit` | 3 | Max tools returned by mcp_search |\n| `callItemLimit` | 20 | Max items in mcp_call response |\n| `maxTextLength` | 500 | Truncate text fields to N chars (detail=false: 500, detail=true: 1500) |\n| `maxOutputTokens` | 8000 | Hard cap on response size |\n| `idleTimeoutMs` | 300000 | Disconnect upstream servers after N ms of inactivity (0 = disabled) |\n\nEnvironment variable overrides:\n\n```bash\nexport MCP_PROXY_SEARCH_LIMIT=5\nexport MCP_PROXY_CALL_ITEM_LIMIT=30\nexport MCP_PROXY_MAX_TEXT_LENGTH=800\nexport MCP_PROXY_MAX_OUTPUT_TOKENS=10000\nexport MCP_PROXY_IDLE_TIMEOUT_MS=600000\n```\n\n## Running\n\n### Standalone (Stdio Transport)\n\n```bash\nnode dist/index.js\n```\n\nThe proxy connects via stdio to your LLM. Use it with Claude or other MCP clients.\n\n### As a Systemd User Service\n\nThe install script can set this up for you (see below), or manually:\n\n1. Create `~/.config/systemd/user/mcp-proxy.service`:\n\n```ini\n[Unit]\nDescription=MCP Proxy Gateway\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=%h/.local/bin/mcp-proxy\nRestart=on-failure\nRestartSec=5s\nEnvironment=\"PATH=%h/.local/bin:/usr/local/bin:/usr/bin\"\n\n[Install]\nWantedBy=default.target\n```\n\n2. Enable and start:\n\n```bash\nsystemctl --user daemon-reload\nsystemctl --user enable mcp-proxy\nsystemctl --user start mcp-proxy\n```\n\n3. View logs:\n\n```bash\njournalctl --user -u mcp-proxy -f\n```\n\n### Prometheus Metrics (Port 9100)\n\nThe dashboard exposes a Prometheus-compatible `/metrics` endpoint:\n\n```bash\ncurl http://localhost:9100/metrics\n```\n\nMetrics exposed:\n| Metric | Type | Description |\n|--------|------|-------------|\n| `mcp_proxy_uptime_seconds` | gauge | Seconds since process started |\n| `mcp_proxy_registered_tools` | gauge | Tools in the registry |\n| `mcp_proxy_upstream_up` | gauge | 1 if upstream is connected/idle, 0 if error |\n| `mcp_proxy_upstream_tools` | gauge | Tools discovered per upstream |\n| `mcp_proxy_calls_total` | counter | Calls by tool, provider, status |\n| `mcp_proxy_call_duration_ms_total` | counter | Cumulative call duration (ms) |\n| `mcp_proxy_output_bytes_total` | counter | Cumulative output bytes |\n\nAdd a scrape job in your Prometheus/Alloy config:\n\n```yaml\nscrape_configs:\n  - job_name: mcp-proxy\n    static_configs:\n      - targets: ['localhost:9100']\n    metrics_path: /metrics\n```\n\n### HTTP Server (Port 9200)\n\nThe proxy always starts an HTTP transport on port 9200 by default. Set `MCP_PROXY_SINGLETON_PORT` to use a different port. This allows multiple clients to connect to a single proxy instance.\n\n```bash\nexport MCP_PROXY_SINGLETON_PORT=9200\nnode dist/index.js &\n\n# From another process:\ncurl -X POST http://127.0.0.1:9200/mcp -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\": \"2.0\", \"method\": \"tools/call\", \"params\": {...}}'\n```\n\n## Troubleshooting\n\n### Upstream MCP Server Won't Connect\n\nCheck the server logs in the dashboard (port 9100 by default) or daemon logs:\n\n```bash\njournalctl --user -u mcp-proxy -e\n```\n\nThe proxy logs:\n- Tool discovery on startup\n- Connection failures with error messages\n- Upstream stderr (piped from stdio servers)\n\n### Proxy Crashes or Freezes\n\nThe proxy has comprehensive error handling to gracefully degrade on upstream failures:\n\n- If an upstream tool call fails, the error is logged and returned to the client\n- If all upstreams fail at discovery, startup fails with `NO_UPSTREAMS`\n\nFor unhandled errors, check:\n\n```bash\njournalctl --user -u mcp-proxy -n 50  # Last 50 lines\n```\n\n### Tool Returns No Data\n\nWhen a tool returns `null` or malformed data, the output shaper handles it gracefully:\n\n- Null results return `[]`\n- Strings are wrapped as `{value: string}`\n- CSV is auto-parsed if it looks like tabular data\n- Raw binary content (images, files) is preserved via `_rawContent`\n\nIf a tool response looks truncated, retry with `detail=true` in mcp_call to disable output shaping:\n\n```\nmcp_call(ref=\"google_send_email\", args={...}, detail=true)\n```\n\n## Security & Networking\n\nThe proxy binds to **`127.0.0.1` only** for security — it's not accessible from the network by default. To access remotely:\n\n- **Same machine**: Connect locally on `127.0.0.1:9200`\n- **Remote access**: Use Tailscale, SSH forwarding, or a VPN tunnel\n  ```bash\n  ssh -L 9200:127.0.0.1:9200 user@remote-host\n  ```\n- **Systemd service**: Access is local by default; no firewall rule needed\n\n## Known Limitations\n\n- **No automated tests** — this is production-quality code used daily, but test suite is not included\n\n## Changelog\n\n### v1.21.2\n- Fix incomplete v1.21.1 patch: the `hono` pnpm override (`>=4.12.25`) still resolved to a vulnerable 4.12.x release; tightened to `>=4.12.34`\n- Add pnpm overrides for `@hono/node-server >=1.19.15`, `fast-uri >=3.1.5`, `ip-address >=10.3.1`, `body-parser >=2.3.0` — all transitive via `@modelcontextprotocol/sdk`, resolves 3 high and 6 medium/low CVEs (DoS, ReDoS, SSRF-adjacent parsing bugs)\n- Bump `@modelcontextprotocol/sdk` from `^1.26.0` to `^1.30.0`\n- Verified clean against `pnpm audit` and OSV.dev for all resolved dependency versions\n\n### v1.21.1\n- Attempted hono dependency patch (`pnpm override: hono >=4.12.25`) — override was too loose and did not actually clear the vulnerable range; fully resolved in v1.21.2 above\n\n### v1.21.0\n- `detail=true` no longer truncates text fields in tool output\n\n### v1.20.0\n- Per-agent lane isolation: URL routing at `/mcp/{agentId}`, filtered tool registry views, `MCP_PROXY_AGENTS` config\n\n### v1.19.0\n- Add Prometheus `/metrics` endpoint on the dashboard port (9100 by default)\n- Exposes: `mcp_proxy_uptime_seconds`, `mcp_proxy_registered_tools`, `mcp_proxy_upstream_up`, `mcp_proxy_upstream_tools`, `mcp_proxy_calls_total`, `mcp_proxy_call_duration_ms_total`, `mcp_proxy_output_bytes_total`\n- Counters persist for the lifetime of the process; scrape with Prometheus/Alloy and visualize in Grafana\n\n### v1.18.0\n- Drop `@xenova/transformers` entirely — eliminates the protobufjs/ONNX runtime supply chain\n- Switch to pure lexical (BM25) search; tool tokens pre-computed at startup, zero per-query overhead\n- No change to mcp_search quality for English-language tool catalogs\n- Removes ~90MB model download on first run and all native module requirements\n\n### v1.17.1\n- Pre-compute tool token sets at registry build time; lexical scoring now reads the cache instead of re-tokenizing on every query\n- Add LRU cache for query embeddings (embeddings removed entirely in v1.18.0)\n\n### v1.17.0\n- Switch to lighter English-optimized embedding model, reducing cold-start download by ~380MB (embeddings removed entirely in v1.18.0)\n\n### v1.16.0\n- Update `@modelcontextprotocol/sdk` from `~1.22.0` to `^1.26.0` — resolves 3 high-severity CVEs: ReDoS, cross-client data leak, DNS rebinding\n- Add pnpm override: `protobufjs >=7.5.8` — resolves critical arbitrary code execution and multiple high CVEs in `@xenova/transformers` transitive dependency chain\n- Add pnpm override: `qs >=6.15.2` — resolves moderate DoS vulnerability in `express` transitive dependency\n\n## Attribution\n\nMCP Proxy Gateway is a fork of [@arvoretech/mcp-proxy](https://github.com/arvoreeducacao/arvore-mcp-servers), originally created by **João Augusto** and **Árvore Educação**.\n\nForked and extended with:\n- Singleton mode for HTTP bridge\n- Idle server reaping\n- Comprehensive error handling\n- Config file support\n- Systemd integration\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n","readmeFilename":"README.md"}