Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,6 @@ native/macos/MCPProxy/.build/
.wrangler/

.run

# demo pipeline: playwright node_modules symlink (recreated at capture time)
scripts/demo/node_modules
40 changes: 26 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
# MCPProxy – Smart Proxy for AI Agents
# 🛡️ MCPProxy — Supercharge AI Agents, Safely

**MCPProxy** is an open-source desktop application that super-charges AI agents with intelligent tool discovery, massive token savings, and built-in security quarantine against malicious MCP servers.
> One safe endpoint in front of every MCP server.

### **📚 [Read the Documentation](https://docs.mcpproxy.app/)**
[![Release](https://img.shields.io/github/v/release/smart-mcp-proxy/mcpproxy-go?sort=semver)](https://github.com/smart-mcp-proxy/mcpproxy-go/releases)
[![Build](https://github.com/smart-mcp-proxy/mcpproxy-go/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/smart-mcp-proxy/mcpproxy-go/actions/workflows/unit-tests.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/smart-mcp-proxy/mcpproxy-go)](https://goreportcard.com/report/github.com/smart-mcp-proxy/mcpproxy-go)
[![Go Reference](https://pkg.go.dev/badge/github.com/smart-mcp-proxy/mcpproxy-go.svg)](https://pkg.go.dev/github.com/smart-mcp-proxy/mcpproxy-go)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/smart-mcp-proxy/mcpproxy-go?style=social)](https://github.com/smart-mcp-proxy/mcpproxy-go/stargazers)

<!-- Old video: https://youtu.be/l4hh6WOuSFM -->
[![MCPProxy Demo](https://img.youtube.com/vi/2aKrgJnbbcw/0.jpg)](https://youtu.be/2aKrgJnbbcw)
<a href="https://mcpproxy.app" target="_blank" rel="noopener">
<img src="docs/social.png" alt="MCPProxy — Supercharge AI Agents, Safely" width="100%" />
</a>

<a href="https://mcpproxy.app" target="_blank" rel="noopener">🌐 Visit mcpproxy.app</a>
<p align="center">
<img src="docs/demo.gif" alt="MCPProxy web UI demo: server dashboard, tool discovery, activity log, and security quarantine" width="900" />
</p>

<p align="center">
<strong>📺 <a href="https://youtu.be/2aKrgJnbbcw">Watch the full walkthrough</a></strong> &nbsp;·&nbsp;
<strong>📚 <a href="https://docs.mcpproxy.app/">Read the docs</a></strong> &nbsp;·&nbsp;
<strong>🌐 <a href="https://mcpproxy.app">mcpproxy.app</a></strong>
</p>

> The demo above shows the **embedded web UI**. The MCPProxy **core is a single binary for macOS, Linux, and Windows** — the web UI ships inside it, with no extra service to run. On **macOS**, an optional **menu‑bar app** adds one‑click convenience (start/stop, server health, quarantine, logs).

<div align="center">
<a href="https://mcpproxy.app/images/menu_upstream_servers.png" target="_blank">
<img src="https://mcpproxy.app/images/menu_upstream_servers.png" alt="System Tray - Upstream Servers" width="250" />
</a>
<img src="docs/screenshot-macos-tray.png" height="300" alt="MCPProxy macOS menu-bar app" />
&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://mcpproxy.app/images/menu_security_quarantine.png" target="_blank">
<img src="https://mcpproxy.app/images/menu_security_quarantine.png" alt="System Tray - Quarantine Management" width="250" />
</a>
<img src="docs/screenshot-macos-activity.png" height="300" alt="MCPProxy macOS app — Activity log with sensitive-data detection" />
<br />
<em>System Tray - Upstream Servers &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System Tray - Quarantine Management</em>
<em>macOS menu‑bar app &nbsp;&nbsp;·&nbsp;&nbsp; Activity log &amp; audit in the macOS app</em>
</div>


Expand All @@ -27,7 +39,7 @@
- **Scale beyond API limits** – Federate hundreds of MCP servers while bypassing Cursor's 40-tool limit and OpenAI's 128-function cap.
- **Save tokens & accelerate responses** – Agents load just one `retrieve_tools` function instead of hundreds of schemas. Research shows ~99 % token reduction with **43 % accuracy improvement**.
- **Advanced security protection** – Automatic quarantine blocks Tool Poisoning Attacks until you manually approve new servers.
- **Works offline & cross-platform** – Native binaries for macOS (Intel & Apple Silicon), Windows (x64 & ARM64), and Linux (x64 & ARM64) with system-tray UI.
- **Works offline & cross-platform** – A single core binary for macOS (Intel & Apple Silicon), Windows (x64 & ARM64), and Linux (x64 & ARM64), with the **web UI embedded**. macOS additionally ships an optional menu-bar app.

---

Expand Down
Binary file added docs/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions docs/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshot-macos-activity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshot-macos-tray.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions docs/social.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
* { margin:0; padding:0; box-sizing:border-box; }
html,body { width:1280px; height:640px; overflow:hidden; }
body {
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
background:#0f172a; position:relative; color:#fff;
display:flex; flex-direction:column; align-items:center; justify-content:center;
}
.blob { position:absolute; border-radius:50%; filter:blur(90px); opacity:.55; }
.b1 { width:520px; height:520px; left:-80px; top:-120px; background:#3b82f6; }
.b2 { width:560px; height:560px; right:-120px; bottom:-160px; background:#006644; opacity:.6; }
.b3 { width:360px; height:360px; left:60%; top:-140px; background:#60a5fa; opacity:.4; }
.grid {
position:absolute; inset:0;
background-image:radial-gradient(rgba(255,255,255,.08) 1px, transparent 1px);
background-size:26px 26px;
-webkit-mask:radial-gradient(circle at 50% 45%, #000 0%, transparent 72%);
mask:radial-gradient(circle at 50% 45%, #000 0%, transparent 72%);
}
.stack { position:relative; text-align:center; z-index:2; }
.brandrow { display:flex; align-items:center; justify-content:center; gap:18px; margin-bottom:14px; }
.logo { width:66px; height:66px; display:block; }
.name { font-size:30px; font-weight:800; letter-spacing:.5px; }
h1 { font-size:64px; font-weight:800; line-height:1.05; letter-spacing:-1px;
background:linear-gradient(90deg,#93c5fd 0%,#ffffff 45%,#86efac 100%);
-webkit-background-clip:text; background-clip:text; color:transparent; }
.sub { font-size:22px; color:#94a3b8; margin-top:16px; }
.tiles { display:flex; gap:16px; justify-content:center; margin-top:40px; }
.tile { font-size:20px; color:#e2e8f0; padding:14px 22px; border-radius:14px;
background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.12);
-webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); }
.url { position:absolute; bottom:34px; font-size:18px; color:#64748b; z-index:2; }
</style>
</head>
<body>
<div class="blob b1"></div><div class="blob b2"></div><div class="blob b3"></div>
<div class="grid"></div>
<div class="stack">
<div class="brandrow"><img class="logo" src="logo.svg" alt="MCPProxy logo" /><div class="name">MCPProxy</div></div>
<h1>Supercharge AI Agents, Safely</h1>
<div class="sub">One safe endpoint in front of every MCP server.</div>
<div class="tiles">
<div class="tile">🔍 Discover</div>
<div class="tile">🛡️ Quarantine</div>
<div class="tile">🔗 Federate</div>
<div class="tile">⚡ −99% tokens</div>
</div>
</div>
<div class="url">mcpproxy.app</div>
</body>
</html>
Binary file added docs/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions scripts/demo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Demo asset pipeline

Regenerates the README hero banner and the (web-UI-only) demo GIF. Run from repo root.

1. `scripts/demo/render-banner.sh` # docs/social.html (+ docs/logo.svg) -> docs/social.png
2. Boot a demo mcpproxy and capture the web UI:
```
cd scripts/demo
ln -sfn ../../e2e/playwright/node_modules ./node_modules
MCPPROXY_BASE_URL=http://127.0.0.1:18082 MCPPROXY_API_KEY=<key> \
./node_modules/.bin/playwright test --config=playwright.config.ts
```
# produces /tmp/demo-webui/<test>/video.webm for the 4 beats
3. `scripts/demo/build-demo.sh` # stitches the 4 web beats -> docs/demo.gif + docs/demo.webp

The macOS tray menu and native app are shown as **static screenshots** in the README
(`docs/screenshot-macos-tray.png`, `docs/screenshot-macos-activity.png`), not in the GIF.

All outputs are committed under docs/. social.png is also uploaded manually to
GitHub Settings -> Social preview (one-time, cannot be scripted).
52 changes: 52 additions & 0 deletions scripts/demo/build-demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Stitch the demo GIF from four web-UI video segments (web-UI-only; the macOS tray
# is shown as a static screenshot in the README instead).
#
# Inputs (produced by capture-webui.spec.ts):
# /tmp/demo-webui/*1-servers*/video.webm server cards / federation
# /tmp/demo-webui/*2-tools*/video.webm tools / discovery
# /tmp/demo-webui/*3-activity*/video.webm activity log / audit (detail drawer)
# /tmp/demo-webui/*4-security*/video.webm quarantine close-up
# Outputs: docs/demo.gif + docs/demo.webp
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
WEB=/tmp/demo-webui
WORK=$(mktemp -d)
W=860; H=538; FPS=15; BG="#0f172a"; WEBSPEED=1.8 # speed up web segments to fit size budget

# Ordered web segments (the leading number in the test name fixes the order).
# Portable array fill (avoid mapfile — macOS ships bash 3.2).
WEBS=()
for pat in 1-servers 2-tools 3-activity 4-security; do
f=$(find "$WEB" -name '*.webm' -path "*$pat*" | head -1)
[ -n "$f" ] && WEBS+=("$f")
done
[ "${#WEBS[@]}" -eq 4 ] || { echo "expected 4 web videos in $WEB, got ${#WEBS[@]} (run capture-webui.spec.ts)"; exit 1; }

# Segments 0..3 — web videos, scaled to canvas, sped up, no audio
i=0
for v in "${WEBS[@]}"; do
ffmpeg -y -i "$v" -an \
-vf "setpts=PTS/${WEBSPEED},scale=${W}:${H}:force_original_aspect_ratio=decrease,pad=${W}:${H}:(ow-iw)/2:(oh-ih)/2:color=${BG},fps=${FPS},format=yuv420p" \
-c:v libx264 -pix_fmt yuv420p "$WORK/seg${i}.mp4"
i=$((i+1))
done

# Concat with the concat FILTER (re-encodes — normalizes SAR/timebase; the concat
# demuxer with -c copy silently drops mismatched segments).
ffmpeg -y -i "$WORK/seg0.mp4" -i "$WORK/seg1.mp4" -i "$WORK/seg2.mp4" -i "$WORK/seg3.mp4" \
-filter_complex "[0:v]setsar=1,fps=${FPS}[a];[1:v]setsar=1,fps=${FPS}[b];[2:v]setsar=1,fps=${FPS}[c];[3:v]setsar=1,fps=${FPS}[d];[a][b][c][d]concat=n=4:v=1:a=0[v]" \
-map "[v]" -c:v libx264 -pix_fmt yuv420p "$WORK/full.mp4"

# Palette-optimized GIF (-threads 1 dodges an ffmpeg 8.0 paletteuse threading bug)
ffmpeg -y -threads 1 -i "$WORK/full.mp4" -vf "fps=${FPS},scale=${W}:-2:flags=lanczos,palettegen=stats_mode=diff" "$WORK/pal.png"
ffmpeg -y -threads 1 -i "$WORK/full.mp4" -i "$WORK/pal.png" \
-lavfi "fps=${FPS},scale=${W}:-2:flags=lanczos,paletteuse=dither=bayer:bayer_scale=3" "$ROOT/docs/demo.gif"

# WebP (smaller; also autoplays in README). Non-fatal — the GIF is the README embed.
ffmpeg -y -threads 1 -i "$WORK/full.mp4" -vcodec libwebp -filter:v "fps=${FPS},scale=${W}:-2" \
-lossless 0 -compression_level 6 -q:v 55 -loop 0 -an "$ROOT/docs/demo.webp" || \
{ echo "WARN: webp encode failed (non-fatal); removing partial"; rm -f "$ROOT/docs/demo.webp"; }

echo "Wrote docs/demo.gif ($(du -h "$ROOT/docs/demo.gif" | cut -f1)) and docs/demo.webp ($(du -h "$ROOT/docs/demo.webp" | cut -f1))"
rm -rf "$WORK"
18 changes: 18 additions & 0 deletions scripts/demo/capture-tray.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Tray capture shot-list (mcpproxy-ui-test MCP)

Goal: ~12 still frames of the macOS tray menu showing upstream servers + health,
to be assembled into a ~5s montage (beat 1 of the demo GIF).

Prereq: MCPProxy tray .app running with 3-4 healthy demo servers configured;
`mcpproxy-ui-test` MCP connected (bundle id com.smartmcpproxy.mcpproxy.dev).

Capture into /tmp/demo-tray/ as frame-01.png, frame-02.png, ... in this order:

1. frame-01..03: `screenshot_status_bar_menu` — closed → menu opening (3 shots)
2. frame-04..06: `list_menu_items` then `screenshot_status_bar_menu` with the
"Upstream Servers" submenu expanded (servers + green health dots)
3. frame-07..09: hover/select a single server submenu (its tools count, status)
4. frame-10..12: `screenshot_status_bar_menu` returning to the top menu (close)

Naming MUST be zero-padded frame-NN.png so ffmpeg globbing is ordered.
mkdir -p /tmp/demo-tray before capturing.
Loading
Loading