# MCPProxy collapses a fleet of MCP tool schemas into one retrieve_tools call

> MCPProxy is a Go binary that sits between an AI agent and many Model Context Protocol servers: new servers sit in quarantine until a person approves them, pluggable scanners normalize findings to SARIF, and the agent loads a single tool instead of a catalog. Six install routes exist and they ship different pieces of the product.

**smart-mcp-proxy/mcpproxy-go** — Supercharge AI Agents, Safely

- Repository: https://github.com/smart-mcp-proxy/mcpproxy-go
- Website: https://mcpproxy.app
- Stars: 381 · Forks: 57
- Language: Go
- License: MIT
- Published: 2026-09-17 · Updated: 2026-09-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/smart-mcp-proxy-mcpproxy-go

## One retrieve_tools call stands in for Cursor's 40-tool ceiling

MCPProxy's central trade is schema count. An agent that loads tool definitions for every server it can reach runs into a wall: Cursor caps tools at 40, and OpenAI caps functions at 128. The project's answer is to sit between the agent and the server fleet, load one retrieve_tools function, and let the model ask for what it needs at the moment it needs it. Federating hundreds of MCP servers is the stated goal, and the numbers attached to the idea are about 99 percent token reduction together with a 43 percent accuracy improvement, both attributed to research that the project does not cite, so treat the pair as a claim to check rather than a measurement. What is concrete is the shape of the request: one function definition travels instead of several hundred schemas. The Go module list backs that plumbing with pkoukk/tiktoken-go for token counting, toon-format/toon-go for compact serialization, and bleve/v2 for indexing so a large server catalog stays searchable.

## Quarantine gates every new server until a person approves it

Adding a server does not make it callable. New servers land in quarantine, and automatic quarantine is described as blocking Tool Poisoning Attacks until a person manually approves the server. Approval is therefore the security boundary, and there is a second layer around it in the form of pluggable scanners: Snyk, Semgrep, Trivy, Cisco, and other Docker-based scanners can be run against a quarantined server before approval, with findings normalized to SARIF and a composite risk score, so output from different tools lands in one comparable format. Those scanners are containers, which means the approval step depends on Docker being present and on image pulls succeeding, and none of that is a reason to skip the gate. Secret handling is delegated rather than reinvented: zalando/go-keyring stores credentials in the operating system keychain, golang-jwt/jwt/v5 handles tokens, and the macOS menu-bar app surfaces quarantine state and logs so a pending decision does not get lost in a terminal. The price is that every new server needs a deliberate click before it can do anything.

## Six install routes, and each one ships a different subset

The core is a single binary with the web UI embedded, so there is no second service to run. Around that core sit several routes with different contents. The macOS DMG and the Windows installer are the GUI paths, and the Windows installer is the more automated of the two: it places both mcpproxy.exe for the core server and mcpproxy-tray.exe for the system tray app into Program Files, adds the binary to the system PATH for command line access, creates Start Menu shortcuts, and accepts a silent switch.

Homebrew splits the same platform in two. The cask installs the menu-bar app and bundles the CLI with it, while the formula installs the CLI binary only:

```bash
brew install --cask smart-mcp-proxy/mcpproxy/mcpproxy
brew install smart-mcp-proxy/mcpproxy/mcpproxy
```

Both update through brew upgrade. Anywhere with Go 1.26 or newer is one command away, and it is the only route that compiles from source rather than downloading a build:

```bash
go install github.com/smart-mcp-proxy/mcpproxy-go/cmd/mcpproxy@latest
```

Starting it is one line:

```bash
mcpproxy serve
```

That command starts the HTTP server on port 8080 and shows the tray.

## The apt and dnf repositories start the service for you

Linux package routes behave differently from the binary downloads because they own the service lifecycle. Debian and Ubuntu get an apt repository with a pinned signing key, and the packages ship a hardened systemd unit that starts the service automatically and updates through apt upgrade:

```bash
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://apt.mcpproxy.app/mcpproxy.gpg \
  | sudo tee /etc/apt/keyrings/mcpproxy.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/mcpproxy.gpg] https://apt.mcpproxy.app stable main" \
  | sudo tee /etc/apt/sources.list.d/mcpproxy.list > /dev/null
sudo apt update && sudo apt install mcpproxy
```

Fedora, RHEL, Rocky, and AlmaLinux take the dnf equivalent, with a separate line for Fedora 41 and later where dnf5 is in play:

```bash
sudo dnf config-manager --add-repo https://rpm.mcpproxy.app/mcpproxy.repo
sudo dnf install -y mcpproxy
```

Arch users install the mcpproxy-bin AUR package, either through yay or by cloning the packaging repository and running makepkg -si. The project publishes the repository signing key fingerprint so a package can be checked by hand. For machines with no outbound network, one-off .deb and .rpm files are downloadable from the latest release, and prerelease builds come from the next branch through GitHub Actions artifacts named dmg-darwin-arm64, dmg-darwin-amd64, versioned-linux-amd64, and versioned-windows-amd64. Those prerelease artifacts are signed and notarized for macOS but are flagged by the project as possibly unstable.

## go.mod asks for 1.26 while the Dockerfile builds on 1.27

There is a version skew worth settling before anyone builds from source. go.mod declares go 1.26.0, the install instructions ask for Go 1.26 or newer, and the container build stage uses golang:1.27-alpine. Nothing in the repository explains the gap, so a contributor with a pinned toolchain has to choose which line to follow and accept the consequences. The rest of the container build is careful about portability: the builder is pinned to the build platform and cross-compiled for the target architecture, so a multi-arch build never needs QEMU emulation, and CGO_ENABLED=0 keeps the binary static. The frontend is built with npm ci and npm run build inside frontend/, its dist output is copied into web/frontend/, and ./cmd/mcpproxy is then compiled with the server build tag. Version, commit, and build date are injected at link time through ldflags, and the update check channel is stamped to docker, which is how the binary knows it is running in a container. The runtime image is gcr.io/distroless/static-debian12 with one binary at /usr/local/bin/mcpproxy, which is what makes a CGO-free build necessary rather than merely tidy. Desktop self-update comes from inconshreveable/go-update, pinned to a 2016 revision.

## The container binds every interface where the sample config does not

The listen address differs by how the proxy is started, and that difference is the entire network boundary for a process that forwards tool calls on your behalf. The container entrypoint is:

```dockerfile
ENTRYPOINT ["mcpproxy", "serve", "--listen", "0.0.0.0:8080"]
```

That binds all interfaces, and the image exposes 8080. The sample configuration file shown for local use sets listen to 127.0.0.1:8080 instead, which is loopback only. A local run is therefore unreachable from another machine, while a container run is reachable from wherever the container is reachable, and anyone deploying the image on a shared host has to bind it back to loopback or place something authenticating in front of it. The port itself is fixed by convention rather than negotiated, so two proxies on one host collide by default.

The HTTP surface is treated as a real API rather than an internal detail. The Makefile generates an OpenAPI specification into the oas directory from cmd/mcpproxy/main.go, and a second target regenerates it and fails when the checked-in artifacts come out dirty, which is the mechanism that keeps the published spec in step with the handlers. A wix directory at the root holds the Windows installer sources, and server.json provides the manifest that editors and clients read for discovery.

## The public version numbers are still in the zero series

The recent tags are v0.67.0, v0.68.0, and v0.69.0, all published inside a single week in September 2026, which is a quick cadence for a project whose newest public number sits below 1.0. Nothing at the repository root states a stability promise for the 0.x line, and there is no compatibility policy file to soften that, so consumers are better off pinning a tag than tracking a moving branch. The cadence comes with matching paperwork in the tree: CHANGELOG.md, cliff.toml for generating it, AUTOUPDATE.md for the update path, ROADMAP.md with roadmap.yaml and roadmap.archive.yaml beside it, a specs directory alongside a .specify directory, and AGENTS.md and CLAUDE.md carrying in-repo agent instructions. There is also a bench directory, separate test and tests directories, an e2e directory, a native directory, and a contrib directory, which describes a codebase with several delivery shapes rather than one. Thirty-nine open issues against 381 stars and 57 forks is an active ratio, consistent with a pre-1.0 project absorbing feature requests faster than it closes them.

## The Makefile carries a TODO and the module list cuts off mid-block

The build file is candid about where its edges are. Its help text lists targets for the complete build, the OpenAPI step, frontend production and development builds, a backend build with a dev flag, unit tests, coverage, end to end tests, an OAuth end to end run with Playwright, linting, and dependency setup, and then the server edition targets for a tagged binary, a Docker image, and a .deb package. The .deb line ends with the word TODO, even though an apt repository and downloadable .deb files are already part of the distribution story, so a contributor reading the Makefile would reasonably assume a gap that the release page does not show. Two other targets are unusually specific for a build file: one is a unit test for the process-tree walk used by the end to end cleanup trap, and another is an integration test asserting that the cleanup trap reaps only its own processes. That is a project that has been bitten by orphaned test processes before.

Reading go.mod is the fastest way to see what the thing actually does. spf13/cobra, pflag, and viper build the command line and layered configuration; mark3labs/mcp-go v1.0.0 is the Model Context Protocol implementation; fyne.io/systray, gen2brain/beeep, and an indirect toast package cover the desktop shell; charmbracelet/bubbletea and lipgloss cover a terminal interface; dop251/goja and evanw/esbuild handle JavaScript execution and bundling for the embedded web UI; bleve/v2 indexes the server catalog; go.etcd.io/bbolt is the embedded store; go.uber.org/zap and lumberjack handle logging and rotation; prometheus/client_golang and the OpenTelemetry packages cover metrics and traces; santhosh-tekuri/jsonschema/v6 validates input; pgregory.net/rapid does property-based testing. That file stops partway into its indirect block, and the configuration walkthrough stops mid-line at a remote server entry, showing "url": "ht and nothing after it, so the fields those entries accept are not readable from the repository root and the oas directory is where the schema lives.

## Conclusion

MCPProxy fits a team that has outgrown a 40-tool ceiling and wants one process in front of its MCP servers, with a quarantine gate that forces a human decision before a new server can act on their behalf. It does not fit a single-server setup, where the indirection buys nothing, and it needs care if you run the container as shipped, because 0.0.0.0:8080 is a wider door than 127.0.0.1:8080. Before adopting it, verify three things yourself: the scanner path, since it depends on Docker images you may not be able to pull; the config schema, since the configuration walkthrough in the repository stops in the middle of an entry; and the version you pin, since the public tags are still in the 0.x series with three releases inside a single week.

## FAQ

### What does a MCP proxy do?

MCPProxy sits between an AI agent and many Model Context Protocol servers. Instead of sending every tool schema to the model, the agent loads a single retrieve_tools function and asks for tools when it needs them, which works around Cursor's 40-tool limit and OpenAI's 128-function cap.

### How to install MCP proxy?

Pick the route for your platform: a DMG on macOS, an installer on Windows, the Homebrew cask or formula, the apt or dnf repository on Linux, the mcpproxy-bin AUR package on Arch, or go install with Go 1.26 or newer. Then run mcpproxy serve to start the HTTP server on port 8080.

### Does MCPProxy let an unapproved MCP server run?

No. New servers land in quarantine, and automatic quarantine blocks Tool Poisoning Attacks until you manually approve the server. Before approval you can point Snyk, Semgrep, Trivy, Cisco, or another Docker-based scanner at it, with findings normalized to SARIF and a composite risk score.

### Where does MCPProxy keep its configuration?

In ~/.mcpproxy/mcp_config.json. The sample sets listen to 127.0.0.1:8080, and each entry in mcpServers carries a name, with a stdio entry adding command, args, protocol, and enabled, and a remote entry using url.

### What does the MCPProxy container expose?

The runtime image is gcr.io/distroless/static-debian12, it exposes port 8080, and its entrypoint runs mcpproxy serve --listen 0.0.0.0:8080, which binds every interface rather than the loopback address the sample config file uses.

## Sources

- [License: MIT](https://github.com/smart-mcp-proxy/mcpproxy-go/blob/main/LICENSE)
- [Project website](https://mcpproxy.app)
- [README](https://github.com/smart-mcp-proxy/mcpproxy-go/blob/main/README.md)
- [Releases](https://github.com/smart-mcp-proxy/mcpproxy-go/releases)
- [smart-mcp-proxy/mcpproxy-go on GitHub](https://github.com/smart-mcp-proxy/mcpproxy-go)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/smart-mcp-proxy-mcpproxy-go
