From b0ad62a6a16aa70860acdec8d556cd9da736145f Mon Sep 17 00:00:00 2001 From: Algis Dumbris Date: Tue, 15 Sep 2026 06:39:04 +0300 Subject: [PATCH] docs(research): server edition demand research and recommendation (2026-09-14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four-lane deep research (HN/Reddit, GitHub competitors + own issues, web/vendor landscape, code inventory + telemetry) on what teams need from a self-hosted MCP gateway, what the server edition ships today, and which candidate features (Vault, Helm, log exporters, Docker image) are worth building. Recommendation: posture (a) — personal edition first-class in a container — plus a bounded slice of the security wedge: generic OIDC, IdP-group → server allowlist, attributable JSONL audit; freeze the unreachable multiuser router / workspace / token-exchange code until a real user asks. --- .../server-edition-2026-09-14/README.md | 231 +++++++++++++ .../evidence/github.md | 170 +++++++++ .../evidence/hn-reddit.md | 213 ++++++++++++ .../evidence/internal-inventory.md | 325 ++++++++++++++++++ .../evidence/web-vendors.md | 160 +++++++++ 5 files changed, 1099 insertions(+) create mode 100644 docs/research/server-edition-2026-09-14/README.md create mode 100644 docs/research/server-edition-2026-09-14/evidence/github.md create mode 100644 docs/research/server-edition-2026-09-14/evidence/hn-reddit.md create mode 100644 docs/research/server-edition-2026-09-14/evidence/internal-inventory.md create mode 100644 docs/research/server-edition-2026-09-14/evidence/web-vendors.md diff --git a/docs/research/server-edition-2026-09-14/README.md b/docs/research/server-edition-2026-09-14/README.md new file mode 100644 index 000000000..80ba3375b --- /dev/null +++ b/docs/research/server-edition-2026-09-14/README.md @@ -0,0 +1,231 @@ +# MCPProxy Server Edition — Research Report and Recommendation + +Date: 2026-09-14 · Author: planning/design strategist agent · Inputs: four collector files in `evidence/` (`hn-reddit.md`, `github.md`, `web-vendors.md`, `internal-inventory.md`), repo `CLAUDE.md`, `docs/development/server-edition-multiuser-auth.md`, `Dockerfile`, `docs/getting-started/installation.md`, `README.md` (all read-only). Citations are `file:line` into the collector files or URLs. Where the evidence does not reach, the word used is "unknown". + +--- + +## 1. Executive summary + +- **One-line recommendation: adopt posture (a) — "the personal edition, first-class when run headless in a container" — plus a strictly bounded slice of (c): keep the shipped SSO front door, finish only the three server-edition items the demand evidence ranks highest (generic OIDC, IdP-group → server allowlist, attributable JSONL audit), and cut or freeze the rest of the latent multiuser/credential-injection code until a real user asks for it.** +- The real container audience is ~10× the server-edition one: in 90 days **362 personal-edition installs from 86 IPs ran in containers, 113 of them long-lived (≥24 h)**, plus 153 long-lived headless Linux installs, versus **37 server-edition installs from 8 IPs** (`internal-inventory.md:241-261`). All server-edition installs to date were self-built and pre-date the public image (`internal-inventory.md:197`). +- What people ask a team gateway for is boring and consistent across all three external lanes: **SSO/IdP login + group-based access (14 explicit asks), per-call audit with user attribution (13), credentials off the laptop (12), per-tool/per-server policy (10), one central endpoint/catalog (9)** (`hn-reddit.md:152-156`). The canonical demand post says exactly this in one sentence (`hn-reddit.md:78`). +- **SIEM/Splunk/Datadog exporters (1 ask), air-gapped installs (0), quotas as a headline (5, mostly vendor)** are vendor-checklist items, not user demand (`hn-reddit.md:158,166,167`; `github.md:169`). Do not build connectors. +- Vault integration is asked for as *behaviour* ("gateway holds creds, agents get sessions"), not as a HashiCorp SDK; the one concrete OSS ask (obot #6180) was satisfied by syncing Vault into Kubernetes Secrets (`github.md:96`). A `${file:/run/secrets/x}` provider (S effort) covers Vault/ESO/1Password-operator/SOPS at once; MCPProxy has only `${env:}` and a keyring provider that is useless in containers (`internal-inventory.md:95-97`). +- The server edition today is an SSO login + admin REST + agent-token scoping on top of the personal proxy. The multi-user `Router`, `workspace.Manager`, `TokenExchanger` and the whole credential-injection chain (`Client.SetBrokeredAuth`) have **zero production callers**, and `docs/cli/credential-commands.md` claims injection happens (`internal-inventory.md:10,45-52`). The docs overclaim; that is a Phase 0 fix regardless of strategy. +- Competing feature-for-feature is not viable: agentgateway (4.8k★, Linux Foundation), IBM ContextForge (4.5k★), ToolHive (2.2k★, Go, VC-backed enterprise tier) all ship Helm, OIDC, RBAC, rate limits and OTel for free (`github.md:22-24`); ~60 "Show HN: MCP gateway" launches since 2025-08 almost all scored <10 points (`hn-reddit.md:45`); mcpproxy-go has 348★, no organic HN/Reddit mention, and zero external SSO/RBAC/Helm/Vault asks (`hn-reddit.md:63`; `github.md:152`). +- MCPProxy's genuine differentiators are edition-neutral and already shipped: BM25 tool discovery (context bloat is a top-voted ask in *competitor* repos: metamcp #202, docker #187, tbxark #38 — `github.md:39,69,82`), tool-drift/rug-pull detection that InfoQ says gateways lack (`web-vendors.md:46`), quarantine states that map onto the Approved/Review/Blocked model Noma sells (`web-vendors.md:57`), and intent-typed `call_tool_read|write|destructive`. Market these into the container audience instead of adding gateway parity. +- Docker image: keep investing, but make it the **personal edition's** image with a `full` variant (node/uv/git for stdio upstreams — issue #40's actual use case, `github.md:140`), non-root, docker-compose, a minimal Helm chart, and fix the day-1 traps first (`Secure=false` cookie, read-only config, `/root/.mcpproxy`, no `${file:}` secrets — `internal-inventory.md:135-145`). +- Measurement gap to close in Phase 0: telemetry cannot see whether `server_edition` is enabled, which IdP, or how many users — the field does not exist (`internal-inventory.md:129,155`). + +--- + +## 2. Method and evidence base + +| Lane | What was collected | Volume | Known gaps | +|---|---|---|---| +| HN + Reddit (`hn-reddit.md`) | HN Algolia story/comment searches (12 queries, 40 full comment trees); Reddit via Arctic Shift archive (~600 posts, ~450 comments, 22 full threads) | 65 tabulated signals, 17 counter-signals, capability tally (`hn-reddit.md:76-169`) | Reddit rate-limited: the 11×11 subreddit×query matrix was not completed (`hn-reddit.md:49-61`); scores are archive snapshots; Algolia typo-tolerance inflates "sso"/"helm" hits | +| GitHub (`github.md`) | 33 repos' metadata, 41k issue/PR records across 23 dedicated gateway repos, discussions for 20 repos, file-tree greps, mcpproxy-go's own 274 issues + 12 discussions, 58-user stargazer sample | 50 ranked competitor issues, 12 discussions, matrix (`github.md:20-124`) | Keyword regex may miss asks phrased differently; stargazer company rate (34 %) has no competitor baseline (`github.md:162`); Kong/Traefik/Composio lanes were empty (`github.md:126-132`) | +| Web / vendors / guidance (`web-vendors.md`) | 30 WebSearch queries; ~22 vendor product/pricing pages; NSA CSI via a law-firm summary (primary PDF 403); X only via blog embeds | 48 signals, 24-vendor matrix, guidance→control mapping (`web-vendors.md:28-133`) | Lane is vendor/analyst-heavy (V/A dominate); several pricing pages 404 or price-less; Unit 42/Trend Micro not verified; X texts unrecoverable except via embeds (`web-vendors.md:15-22,79`) | +| Internal (`internal-inventory.md`) | Code inventory at HEAD b39800a89 with file:line, D1 telemetry queries with CI filter, release-asset downloads, GHCR tag check | Capability matrix, day-1 operator list, 7 telemetry tables | GHCR pull counts unavailable (403, `internal-inventory.md:296`); server rows have no `machine_id`, containers without volumes churn anonymous IDs (`internal-inventory.md:191-197`); multi-user enablement is unmeasurable (`internal-inventory.md:155`) | + +**Weighting rule used below.** The HN/Reddit and GitHub lanes are demand-side (people describing needs or filing issues); the web lane is mostly supply-side (vendors describing what they sell). Where the lanes disagree, demand-side wins. The one material disagreement: the web collector rated "log/audit exporters (OTel/SIEM)" as the highest-frequency ask (`web-vendors.md:141`), but the demand-side lanes count exactly one SIEM ask (a checklist reply) and no unfulfilled OTel/SIEM issue anywhere (`hn-reddit.md:166`; `github.md:169`). The reconciling read: users want an **attributable audit log with a stable schema**; vendors sell **connectors**. This report treats the former as must-have and the latter as no-demand. + +--- + +## 3. What users need from a server edition (evidence-ranked) + +Explicit asks = people without a product to sell describing the need (`hn-reddit.md:148`). + +| Rank | Capability | Tier | Evidence strength | Representative quote | Sources | +|---|---|---|---|---|---| +| 1 | SSO / corporate IdP login (Okta, Entra, Keycloak) + group-based access | **Must-have** | Strong: 14 asks / 9 built / 8 vendor (`hn-reddit.md:152`); top competitor issue agentgateway #239 👍24 (`github.md:58`); generic-OIDC asks agentic-community #189, mcphub #527 (`github.md:76,84`) | "MCP servers hosted centrally, users authenticate with their corporate identity, access is granted by group membership, and every tool call is logged somewhere I can query." | https://www.reddit.com/r/mcp/comments/1w4oiiv/ (`hn-reddit.md:78`) | +| 2 | Per-call audit with user attribution, stable schema security can approve once | **Must-have** | Strong: 13 asks (`hn-reddit.md:153`); "tipping point from proxy to gateway" (`hn-reddit.md:97`); NSA "what tool was requested, by whom, and what resulted" (`web-vendors.md:121`); MCP roadmap names audit trails first (`web-vendors.md:30`) | "the moment someone asks 'can you show me every time this tool was called and by whom' and you realize you can't." | https://www.reddit.com/r/mcp/comments/1uye015/ ; https://www.reddit.com/r/mcp/comments/1uye015/comment/oy21g3f/ (`hn-reddit.md:99`) | +| 3 | Credentials off the laptop; gateway holds/refreshes upstream creds, agents get a session | **Must-have (behaviour), differentiator (per-user injection)** | Strong: 12 asks (`hn-reddit.md:154`); Composio breach 5,241 keys (`web-vendors.md:51`); Snowflake "inject authorized credentials on the fly" (`web-vendors.md:34`); OSS peers mostly lack per-user upstream creds (agentgateway #239 open; mcpjungle #254; mcp-hub #116 — `github.md:58,77,95`) | "Broker pattern: the client holds one short-lived session token; a server-side broker holds the provider creds, does OAuth refresh, injects per request, scopes per tool call, and writes the audit line." | https://www.reddit.com/r/mcp/comments/1voezx0/comment/p3r541p/ (`hn-reddit.md:104`) | +| 4 | Per-server first, per-tool for mixed-risk servers; deny/HITL for destructive; re-consent on tool drift | **Must-have (per-server) / differentiator (drift)** | Medium-strong: 10 asks, split on granularity (`hn-reddit.md:155,205`); metamcp #103/#179 (`github.md:74,92`); drift re-consent 3 asks (`hn-reddit.md:169`); InfoQ: gateways "do not detect when the tool definitions a team approved last week change" (`web-vendors.md:46`) | "risk-tier the tools, not the servers. Read-only on non-sensitive data = fast lane, self-service. Writes or anything touching personal data = full review." | https://www.reddit.com/r/mcp/comments/1uye015/comment/oy21g3f/ (`hn-reddit.md:99`) | +| 5 | One central endpoint; approved-server list; disable public catalogs | **Must-have** | Medium: 9 asks (`hn-reddit.md:156`); docker #195 "heavily regulated industry", disc #180 "I'd happily pay" (`github.md:83,115`) | "Everyone installs this gateway as their only 'MCP', then at a central location we can add different MCP tools and everyone automatically gains access to them." | https://news.ycombinator.com/item?id=45012257 (`hn-reddit.md:124`) | +| 6 | Self-hosted, open source, runs as a normal service in existing K8s/observability; governance not paywalled | **Must-have (posture)** | Medium: 6 hard-requirement asks (`hn-reddit.md:163`); fin-services eval "hard requirement" (`web-vendors.md:44`) | "Does it run as a normal service you can stick in your existing K8s/observability/CI setup, or does it want to own its own world?" | https://www.reddit.com/r/mcp/comments/1u12f3w/comment/oqzwhhe/ (`hn-reddit.md:93`) | +| 7 | Small context / tool discovery (not a "server" ask, but the top ask inside gateway repos) | **Differentiator (already shipped)** | Medium: metamcp #202 👍6, docker #187, tbxark #38 16💬 (`github.md:39,69,82`); Simon Willison embed (`web-vendors.md:43`) | "50+ tools consume 20,000-25,000 tokens (60-80% of context window)" | https://github.com/metatool-ai/metamcp/issues/202 | +| 8 | Kubernetes deployment / Helm | **Table stakes, not a feature** | Medium-weak as an ask (6 assumed, 3 explicit Helm — `hn-reddit.md:157`); every serious peer ships a chart (`github.md:168`) | one user "3 shot" his own gateway "if you count a second prompt to generate the Helm Chart" | https://news.ycombinator.com/item?id=48885712 (`hn-reddit.md:123`) | +| 9 | PII/DLP redaction of the gateway's own logs and traces | Differentiator (later) | Weak-medium: 5 asks (`hn-reddit.md:159`); redaction is paid at Lasso/MCP Manager (`web-vendors.md:100,104`) | "They are going to be a PII landmine." | https://news.ycombinator.com/item?id=45523623 (`hn-reddit.md:128`) | +| 10 | HITL approval hold for irreversible tools | Differentiator (later) | Weak: 4 asks vs 6 vendor pitches (`hn-reddit.md:161`); IBM #5437 0👍/13💬 (`github.md:102`) | "the Gateway holds the call instead of invoking the downstream tool." | https://www.truefoundry.com/blog/mcp-tool-approval-human-gate-call-path (`web-vendors.md:63`) | +| 11 | Rate limits / per-tenant quotas | No-demand as headline | Weak: 5 asks, LLM-gateway-shaped (`hn-reddit.md:158`; `github.md:169`); mcpproxy #955 from one "shared systemd service" user (`github.md:142`) | — | — | +| 12 | SIEM / Splunk / Datadog export | **No-demand** | 1 checklist ask, 0 built (`hn-reddit.md:166`); Datadog appears only as an upstream target | — | — | +| 13 | Air-gapped install | **No-demand** | 0 asks on HN/Reddit (`hn-reddit.md:167`); one IBM issue, closed (`github.md:94`) | — | — | +| 14 | SCIM, SAML, org-level multi-tenancy | **No-demand** (vendor tiering) | Only in vendor copy (`web-vendors.md:61-62`); multi-tenancy 3 asks (`hn-reddit.md:162`) | — | — | + +Two cross-cutting facts: **the counter-signals never argue against central control** — they argue it should live in IdP scopes, DB roles, oauth2proxy, or 1Password (`hn-reddit.md:196`); and **first-party absorption is coming** — Anthropic's Enterprise-Managed Authorization (XAA/ID-JAG) removes the "OAuth relay" value for Claude clients (`hn-reddit.md:193`). Both narrow what a solo-maintained gateway can durably own to the things that sit *between* IdP and upstream: policy, drift detection, audit, and (if at all) credential brokering. + +--- + +## 4. What we have today + +Condensed from `internal-inventory.md §1`; "half-built" = code exists with no production caller. + +| Area | Shipped | Half-built / unwired | Missing | +|---|---|---|---| +| Identity | Google, GitHub, Microsoft OAuth login; email-domain allowlist; admin role (hot-reloadable, #1169); sessions on BBolt; HS256 JWT; agent tokens with tenant identity, owner gate fail-closed, scope narrowed to entitlement (`internal-inventory.md:25-38`) | — | **Generic OIDC** (registry has exactly 3 keys, `internal-inventory.md:28`); GitHub-org/Workspace-group gating; SAML; any role beyond admin/user | +| Multi-user MCP | Shared-server flag; per-user activity attribution; per-user AES-256-GCM credential store + OAuth "connect" flow; broker audit into the activity log (`internal-inventory.md:44-54`) | **`multiuser.Router`/`ToolFilter`** (`router.go:42-56` "NOT YET WIRED … LATENT"); **`workspace.Manager`** (personal servers are DB rows, never connected); **`TokenExchanger`** RFC 8693/OBO; **`CredentialResolver`/`HeaderInjector` → `Client.SetBrokeredAuth` zero callers** (`internal-inventory.md:45-52`). `docs/cli/credential-commands.md` says injection happens (`internal-inventory.md:10`) | Teams/groups entity; per-tenant token cap (#1177); per-user rate limit (`internal-inventory.md:37,108`) | +| Isolation on `/mcp` today | Rests **only** on agent-token `allowed_servers` (`internal-inventory.md:46`); 17 of 46 server installs run with `require_mcp_auth=0` (`internal-inventory.md:143,225-229`) | — | — | +| Observability | `/healthz` `/readyz` `/livez`; Prometheus 25 series (opt-in); OTLP traces with `user_id` span attr; zap JSON logs + rotation; activity log 90 d in BBolt; `GET /api/v1/activity/export` + pull-based SIEM recipe (`internal-inventory.md:79-88`) | — | OTel metrics/logs; syslog/log shipping; push audit sink; per-user metric labels (by design) | +| Secrets | `${env:}` everywhere; `${keyring:}` (no backend in containers) (`internal-inventory.md:94-95`) | `MCPPROXY_CRED_KEY` from env or plaintext config; store silently disabled if absent (`internal-inventory.md:48,98,140`) | `${file:}`; Vault/AWS/GCP/1Password/SOPS; KMS | +| Limits | Global concurrency + queue (#955), per-server concurrency, graceful shutdown, TLS/mTLS (`internal-inventory.md:106-112`) | Reverse-proxy awareness partial: `Secure` cookie hardcoded false, no `X-Forwarded-For` (`internal-inventory.md:33,113`) | Per-tenant anything; HA (BBolt single writer, exit 3 — `internal-inventory.md:127,136`) | +| Distribution | `ghcr.io/smart-mcp-proxy/mcpproxy-server` (distroless static, multi-arch, root user, tags `latest`/`v0.66.0`/`v0.66.1`); personal-edition `.deb`/`.rpm`/tar.gz with hardened systemd unit (`internal-inventory.md:119-121`) | Server-edition tarball matrix commented out; `docs/configuration.md` has no `server_edition` section (`internal-inventory.md:120,124`) | Helm, compose, K8s docs; README has zero mention of the image/K8s (repo check) | + +**Verdict on the half-built code.** Split it in two: + +- **Credential injection for shared HTTP upstreams** (resolver → `SetBrokeredAuth`): the transport is done and fail-closed; the missing piece is a per-(user, server) client keyed on `Router.BrokeredConnectionKey` (`internal-inventory.md:317`). This targets the single loudest market ask and the one OSS peers leave open (agentgateway #239 is open at 👍24). Worth finishing — **but only once there is a signal that a mcpproxy user needs it** (see Phase 2 trigger). Until then, fix the docs so they stop claiming it. +- **`workspace.Manager` / connected personal servers, `TokenExchanger` (RFC 8693/OBO), and the general-purpose `Router`/`ToolFilter`**: cut. Process-per-user upstreams are what the market calls "too costly" (`hn-reddit.md:101`), token exchange has one competitor RFC with 👍7 (`github.md:67`) and needs an IdP-side setup most shops refuse (DCR wall, `hn-reddit.md:107,120`), and agent-token scoping already provides the per-user view the Router was meant to compute. Delete or move under an `experimental` build tag; keep the REST records only if the Teams UI depends on them. + +--- + +## 5. Competitive landscape (condensed) + +From `github.md:20-50` and `web-vendors.md:87-113`. + +| Capability | Free in OSS peers | Paid / gated somewhere | MCPProxy today | +|---|---|---|---| +| Proxy + OIDC/JWT login | IBM, agentgateway, ToolHive, Obot, agentic-community, metamcp, mcphub | Turnkey Okta/Entra + SCIM group mapping: ToolHive Ent, LiteLLM Ent, Portkey Ent, Composio Ent (`web-vendors.md:157`) | 3 hardcoded IdPs, no generic OIDC | +| RBAC / tool allowlists | IBM (RBAC), agentgateway (CEL), ToolHive (Cedar), LiteLLM per-key/team, Obot ACLs | IdP-group→role mapping: ToolHive Ent (`web-vendors.md:99`) | admin/user + agent-token `allowed_servers`; profiles | +| Helm / K8s | IBM, agentgateway, ToolHive operator, Obot, Unla, agentic-community, Lunar, Agent Router | — | none | +| Secrets backends | IBM `plugins/vault`, ToolHive 1Password, APISIX/LiteLLM Vault | Docker Enterprise call-time injection (`web-vendors.md:89`) | `${env:}` only | +| OTel / Prometheus | IBM, agentgateway, ToolHive, Agent Router, mcpjungle, Lunar | OTel logging: MCP Manager Ent (`web-vendors.md:104`) | Prometheus + OTLP traces (opt-in) | +| Rate limits | IBM, agentgateway, ToolHive, Obot, Agent Router quotas | — | global concurrency queue | +| Audit export | Obot `auditlogexport.go`, ToolHive `audit.go`, Lunar | Retention windows / HIPAA logging: Portkey Ent, MCP Manager Ent | pull `GET /activity/export` | +| **Per-user upstream credentials** | **largely absent** (agentgateway #239 open; mcpjungle #254 open; mcp-hub #116 open) | Docker Enterprise, Obot (OAuth cred mgmt) | store + connect flow shipped; injection unwired | +| **Tool-drift / rug-pull detection** | not found in matrix; InfoQ says gateways lack it (`web-vendors.md:46`) | — | **shipped (Spec 032)** | +| **Token-saving tool discovery** | metamcp/docker/tbxark asks open (`github.md:39,69,82`) | — | **shipped (BM25 retrieve_tools)** | +| HITL approval hold | IBM #5437 open | TrueFoundry native (`web-vendors.md:109`) | intent variants only | +| DLP / redaction | Lasso basic masking, IBM plugins | Lasso paid, MCP Manager Pro+ | detection shipped; no redaction | + +Reading: everything in the first seven rows is free at $0 from at least three well-funded projects. The last five rows are where an OSS gateway can still be *different*, and MCPProxy already owns two of them. + +--- + +## 6. Evaluation of candidate features + +Effort is for a solo Go developer: S ≈ days, M ≈ 2–4 weeks, L ≈ months. + +| Feature | Demand (strength, source) | Effort | Free elsewhere? | Verdict | Why | +|---|---|---|---|---|---| +| **Generic OIDC provider (discovery-based; covers Okta/Keycloak/Authentik/Auth0)** | Strong — 14 asks (`hn-reddit.md:152`); agentic-community #189, mcphub #527 (`github.md:76,84`) | **S** ("~1 file in `oauth_providers.go` plus validator", `internal-inventory.md:316`) | Yes, everywhere | **Build now** | Highest-ranked need, cheapest gap; without it Okta/Keycloak shops are excluded outright (`internal-inventory.md:144`) | +| **IdP-group → server allowlist (config map of `groups` claim → servers; per-server, not per-tool)** | Strong — group-based access is in the canonical ask (`hn-reddit.md:78`); "start with access per server" (`hn-reddit.md:86`); metamcp #103/#179 (`github.md:74,92`) | **S–M** (no Team entity; reuse `entitledServerNames` + agent-token scope; needs `groups` claim from generic OIDC) | Yes (IBM/ToolHive/agentgateway), but IdP-group mapping is paid at ToolHive Ent (`web-vendors.md:99`) | **Cheap partial now** | Delivers the "onboarding is adding someone to a group" story (`hn-reddit.md:83`) without building RBAC; per-tool policy waits for a real ask (`hn-reddit.md:85` warns it "can quietly kill adoption") | +| **Attributable append-only JSONL audit line (stable schema: who/user/token, server, tool, decision, request-id, args-hash, outcome) to file/stdout** | Strong — 13 asks (`hn-reddit.md:153`); NSA (`web-vendors.md:121`); Datadog schema (`web-vendors.md:128`) | **S** (activity records already carry `UserID`; add a sink and a documented schema) | Yes in spirit (Obot/ToolHive) | **Build now** | Turns "we have an activity DB" into "any log forwarder (Loki/Datadog agent/Splunk UF) ships our audit" — satisfies the SIEM checklist without one connector; the "stable audit schema security approves once" ask (`hn-reddit.md:99`) | +| **`${file:/path}` secret provider** | Medium-narrow — obot #6180 (Vault→K8s Secret via VSO), toolhive #1249 (no keyring on K8s), docker #317 (`github.md:68,96,97`) | **S** | Yes | **Build now** | One provider unlocks K8s/Docker secrets, ESO/VSO, 1Password Operator, SOPS-decrypted files; today `${keyring:}` is dead in containers (`internal-inventory.md:95-96`) | +| **Vault / AWS SM / GCP SM / 1Password SDK integration** | Weak as a named integration — "Nobody asked for a specific Vault plugin" (`hn-reddit.md:154`) | **M** each (+ dependency, auth methods, lease renewal) | Yes (IBM, ToolHive, APISIX) | **Don't build** | `${file:}` + the cluster's existing secret operator covers every named store with zero SDKs; revisit only on a direct ask | +| **Docker image: personal edition, `slim` + `full` (node/uv/git), non-root** | Strong for the *personal* edition in containers — 86 IPs / 113 long-lived (`internal-inventory.md:241-259`); #40 wanted stdio upstreams (`github.md:140`) | **S–M** (`full` variant needs a base with node+uv+git and the isolation-image lesson from #1143) | Docker's own gateway is the peer here | **Build now** | See §7 | +| **docker-compose example + K8s manifests + docs** | Table stakes (`github.md:168`) | **S** | Yes | **Build now** | Cheapest way to make the 86-IP audience's day 1 not hit the seven traps in `internal-inventory.md:135-145` | +| **Helm chart (single replica, `Recreate`, PVC, ConfigMap, Secret, probes, Ingress toggle)** | Table stakes; asks are about chart quality (`github.md:168`) | **M** (chart is S; the day-1 fixes it depends on are the M: `Secure` cookie, read-only config, `${file:}`, `MCPPROXY_DATA` bug) | Yes, everywhere | **Build later (Phase 1)** | Shipping a chart before the traps are fixed produces IBM-#1477/agentic-#625-style "upgrade broke" issues (`github.md:101,120`) | +| **Credential injection last mile (per-(user,server) HTTP client → `SetBrokeredAuth`)** | Strongest market ask (`hn-reddit.md:154`; agentgateway #239 👍24 open) — but **0 asks from mcpproxy users** (`github.md:152`) | **M** | Mostly *not* free (open in agentgateway/mcpjungle/mcp-hub; paid at Docker Enterprise) | **Build later, gated** | The one server-edition feature that would be a differentiator rather than parity, and ~80 % exists; but building it for 4–5 deployments who never asked is speculative. Trigger: first external ask, or ≥10 server-edition IPs/week after Phase 1 | +| **Approved-server policy: admin-locked inventory, registry allowlist, user server-adds disabled** | Medium — 9 asks (`hn-reddit.md:156`); docker #195/#180 (`github.md:83,115`) | **S** | Docker: no (the paid Enterprise does it); IBM/ToolHive: yes | **Cheap partial now** | Mostly a config switch over existing quarantine + admin routes; markets directly against "shadow MCP" (`web-vendors.md:53`) | +| **Destructive-tool deny-by-default per server (policy on `call_tool_destructive`)** | Medium — risk-tiering (`hn-reddit.md:99`); NSA human-approval note (`web-vendors.md:125`) | **S** | Partially (CEL/Cedar policies elsewhere) | **Cheap partial now** | Reuses intent variants; gives "read-only fast lane, writes need review" without an approval workflow | +| **HITL approval hold (async, notify, resume)** | Weak-medium; vendor-driven (`hn-reddit.md:161`) | **L** (no MCP approval protocol, client timeouts, notification channel) | No (TrueFoundry paid, IBM open) | **Don't build now** | Cost/evidence ratio is the worst in the table; the deny-by-default partial captures most of the value | +| **Per-tenant token cap (#1177)** | Weak, but a real abuse hole in multi-tenant (`internal-inventory.md:37,109`) | **S** | n/a | **Build now (hygiene)** | One tenant can exhaust the global slot cap; trivial to fix, embarrassing not to | +| **Per-user rate limit / quota** | Weak — 5 asks, LLM-gateway-shaped (`hn-reddit.md:158`; `github.md:169`) | **M** | Yes | **Don't build** | Wait for a second ask like #955 | +| **SIEM/Splunk/Datadog/OTLP-logs push connectors** | **No-demand** — 1 ask (`hn-reddit.md:166`); no unfulfilled competitor issue (`github.md:169`) | **M** each | Yes | **Don't build** | The JSONL audit line + forwarder pattern is what SIEM teams actually deploy | +| **OTel metrics/logs export** | Weak — "OTel appears mostly in vendor copy" (`hn-reddit.md:160`) | **M** | Yes | **Don't build** | Prometheus + OTLP traces already exist | +| **HA / external DB (Postgres/Redis)** | Weak — HA appears in one checklist (`hn-reddit.md:94`) | **L** | Partially (IBM multi-cluster) | **Don't build** | Document the single-replica/`Recreate` contract in the chart instead (`internal-inventory.md:323`) | +| **DLP redaction (both directions) / trace redaction config** | Weak-medium — 5 asks (`hn-reddit.md:159`) | **M** | Paid at Lasso/MCP Manager | **Build later** | Natural extension of shipped detection; do activity-log redaction first (S) if the PII-landmine ask recurs | +| **Air-gapped SKU** | **No-demand** (`hn-reddit.md:167`) | S (docs) | Docker "coming soon" | **Don't build**; document `MCPPROXY_TELEMETRY=false` + `MCPPROXY_DISABLE_AUTO_UPDATE` and whether any other outbound call exists (unknown from the inventory) | — | +| **SAML / SCIM / org-level tenancy / teams entity** | Vendor-only (`web-vendors.md:61-62,157`) | M–L | Paid tiers | **Don't build** | This is precisely the paywalled layer; a solo project should not chase it | +| **Telemetry fields: `server_edition_enabled`, `idp_provider`, `user_count_bucket`, `is_k8s`** | n/a (measurement) | **S** | n/a | **Build now** | Every later gate in this plan depends on it (`internal-inventory.md:325`) | + +--- + +## 7. The Docker image decision + +**Facts.** The only server-edition artifact is `ghcr.io/smart-mcp-proxy/mcpproxy-server` (distroless static, multi-arch, three tags, root user, `ENTRYPOINT ["mcpproxy","serve",…]`, no shell, no `npx`/`uvx`/`docker`) — `internal-inventory.md:119,138`; `Dockerfile:30-36`. The install docs' only container recipe points at that image and warns not to relocate the data dir because `MCPPROXY_DATA` breaks config loading (`docs/getting-started/installation.md:374-395`; `internal-inventory.md:123`). The README does not mention the image, Docker, Helm, or Kubernetes at all (repo grep, 0 hits). GHCR pull counts are not available (`internal-inventory.md:296`). + +**The telemetry twist and what it implies.** 362 personal installs / 86 IPs ran in containers in 90 days, 113 of them ≥24 h uptime (32 IPs); a further 153 personal headless Linux installs are long-lived; Linux tar.gz downloads run 4–6× the .deb and roughly equal the macOS DMG (`internal-inventory.md:241-261,308`). Server edition: 37 installs / 8 IPs, flat at 1–4 IPs/week for four months, all self-built (`internal-inventory.md:197,292`). Both external Docker asks came from Kubernetes people, and #40's concrete use case was fronting a **stdio** HomeAssistant server — impossible in the current distroless image (`github.md:140`; `internal-inventory.md:138`). Caveat: some of the 248 sub-1-hour container installs are agent sandboxes/devcontainers, not ops deployments (`internal-inventory.md:263`); the ≥24 h bucket is the defensible number. + +**Implication:** the audience that runs MCPProxy as a long-lived container wants the *personal* feature set (stdio upstreams via npx/uvx, Docker isolation, registries, quarantine, the Web UI) in a container — not SSO. They are currently building their own images or dropping the tarball into a base image. The published image serves the smaller audience and cannot serve the larger one. + +**Recommendation — keep investing, reposition the image:** + +1. **Publish the personal edition as the primary image** (`ghcr.io/smart-mcp-proxy/mcpproxy`) in two variants: `slim` (current distroless) and **`full`** (node + uv + git, so stdio upstreams and `git+https://` installs work — the `-slim` uv image already bit users, #1143 `github.md:152`). technicalpickles prototyped exactly slim+full on a branch in 2025-09 (`github.md:140`). Keep `mcpproxy-server` as the SSO variant of the same tags. Effort S–M. +2. **Non-root** (`distroless/static-debian12:nonroot`, `USER 65532`, state under `/home/nonroot/.mcpproxy` or better a fixed `/data` via a *working* data-dir flag). This forces the `MCPPROXY_DATA`/`--data-dir` config-loading bug to be fixed rather than documented around (`internal-inventory.md:123,135`). Effort S once the data-dir fix lands. +3. **docker-compose example + `deploy/kubernetes/` manifests** with the seven day-1 traps pre-solved: `MCPPROXY_API_KEY` from a Secret, `${file:}` secrets, `require_mcp_auth: true`, `trusted_hosts`, probes, `terminationGracePeriodSeconds: 45`, single replica. Effort S. +4. **Helm chart** after (2) and the `Secure`-cookie/`X-Forwarded-*` fixes; single-replica `Recreate` contract stated in `values.yaml`. Effort M total (Phase 1). +5. **Docker Hub listing:** low value on its own — GHCR is where the K8s askers already looked (#1171 asked for the *workflow*, not a registry). Do the cheap version: a package README on GHCR and a "Run in Docker / Kubernetes" section in the README (currently zero mentions — this is the discoverability complaint in disc #948, `github.md:154`). Mirror to Docker Hub only if it is a one-time CI change. +6. **Tag hygiene:** publish RC images under `-rc` tags so `latest` does not move on every stable (`internal-inventory.md:145`; memory note on the tag guard). +7. **Measure:** add `is_k8s`/`image_variant` to heartbeats so the next review can count image users instead of inferring from `/.dockerenv` (`internal-inventory.md:156`). + +--- + +## 8. Recommended positioning and phased roadmap + +**Positioning statement.** *MCPProxy is the smart local MCP proxy — smaller context, quarantined servers, drift detection — that also runs unchanged as a headless service in a container. The server edition adds an SSO front door for a small team behind the same proxy: sign in with your IdP, get the servers your group is allowed, every call attributed to you.* It is not a Kubernetes-native enterprise gateway and does not claim to be. + +**Why (a)+bounded (c), not (b) or (d).** + +- (b) *full team gateway* loses on every axis: three well-funded OSS projects give the parity list away free (§5), the supply side is ~60 launches deep (`hn-reddit.md:45`), and 8.6k LOC of server code has produced 4–5 deployments and zero inbound feature asks (`internal-inventory.md:9,13`; `github.md:152`). Pursuing SCIM/HA/HITL/Vault as a solo maintainer is how the project stops improving the thing 2,493 personal installs use (`internal-inventory.md:188`). +- (d) *park it* ignores that the container/headless audience is real and 10× larger than the server one, that the shipped SSO code works for its narrow purpose, and that the market gap ("OSS that self-hosts *with* the enterprise-tier features", `web-vendors.md:158`) is genuinely open for the two items MCPProxy already owns (drift detection, token-saving discovery). Parking without fixing the over-claiming docs would also leave a credibility problem. +- (a) is the posture the demand-side evidence actually describes — "run as a normal service inside existing K8s/observability" (`hn-reddit.md:93`), "adding an MCP server isn't a special case" (`hn-reddit.md:84`) — and it is what the guiding question rewards: every deliverable below improves the personal edition or its container form. +- The bounded (c) slice exists because the three top asks (generic OIDC, group allowlist, attributable audit) are each S-effort on top of shipped code and turn the server edition from "three consumer IdPs" into something a small Okta/Keycloak team can actually deploy. The genuinely differentiating wedge item — per-user credential injection — is gated, not scheduled. + +### Phase 0 — Honesty and hygiene (S, ~1–2 weeks) + +| Deliverable | Evidence | +|---|---| +| Fix docs: `credential-commands.md` no longer claims call-time injection; `server-edition-multiuser-auth.md` marks Router/workspace/token-exchange as unwired or removed; CLAUDE.md editions table stops listing `.deb`/tar.gz for server | `internal-inventory.md:10-11,120` | +| Cut or `experimental`-tag `workspace.Manager`, `multiuser.Router`/`ToolFilter`, `TokenExchanger` | `internal-inventory.md:45-52`; §4 verdict | +| `Secure` session cookie derived from `X-Forwarded-Proto`/TLS; trusted-proxy `X-Forwarded-For` for session IPs | `internal-inventory.md:33,113,141` | +| Fix `MCPPROXY_DATA`/`--data-dir` so config is read from the data dir; then non-root image | `internal-inventory.md:123,135` | +| `${file:}` secret provider | `github.md:96-97`; `internal-inventory.md:96` | +| Fix #1177 per-tenant token cap | `internal-inventory.md:37,109` | +| Telemetry fields: `server_edition_enabled`, `idp_provider`, `user_count_bucket`, `is_k8s`, `image_variant` | `internal-inventory.md:129,155,325` | +| README "Run as a service / in Docker / on Kubernetes" section; GHCR package README | repo grep (0 hits); `github.md:154` | + +### Phase 1 — The container is first-class; the SSO door fits real IdPs (M, ~4–6 weeks) + +| Deliverable | Evidence | +|---|---| +| Personal-edition image `slim` + `full` (node/uv/git); `mcpproxy-server` as the SSO variant; RC tags | `internal-inventory.md:241-259`; `github.md:140,152` | +| docker-compose example; `deploy/kubernetes/` manifests; then a minimal Helm chart (single replica, `Recreate`, probes, Secret/ConfigMap wiring, Ingress toggle) with the single-writer contract stated | `github.md:168`; `internal-inventory.md:127,136,323` | +| Generic OIDC provider (discovery URL, client id/secret, `groups` claim name) | `hn-reddit.md:152`; `github.md:84`; `internal-inventory.md:28,316` | +| IdP-group → server allowlist in `server_edition` config; enforced through the existing entitlement predicate and agent-token scope | `hn-reddit.md:78,83,86`; design doc "entitledServerNames" | +| JSONL audit sink (file/stdout) with a documented, versioned schema; `activity export` gains the same schema | `hn-reddit.md:153,99`; `web-vendors.md:121,128` | +| Admin-locked inventory switch (users cannot add servers; registry allowlist) and per-server "deny `call_tool_destructive`" policy | `hn-reddit.md:156,99`; `github.md:83,115` | +| Server-edition docs: a `server_edition` section in `docs/configuration.md`; a "deploying for a team" guide that is honest about scope (single node, per-server grants, no per-user upstream creds yet) | `internal-inventory.md:124,143` | + +### Phase 2 — Gated wedge (M, only on trigger) + +| Deliverable | Trigger | Evidence | +|---|---|---| +| Per-(user, server) brokered credential injection for HTTP upstreams (wire `CredentialResolver` → `SetBrokeredAuth`; fail-closed; audit line per injection) | First external issue asking for per-user upstream credentials **or** ≥10 distinct server-edition IPs/week for 4 consecutive weeks (vs 1–4 today) | `hn-reddit.md:154`; `github.md:58,166`; `internal-inventory.md:52,317` | +| Activity-log/trace redaction config | A second "PII landmine"/redaction ask against mcpproxy | `hn-reddit.md:128-129` | +| Per-tool allow/deny on top of the group map | A user hits the mixed-risk-server case | `hn-reddit.md:86,155` | + +Marketing note for all phases: lead with the two differentiators competitors' *own* users are asking for — context savings (`github.md:69,82`) and tool-drift re-consent (`web-vendors.md:46`; `hn-reddit.md:169`) — and quote USD alongside tokens when claiming savings (project memory rule). + +--- + +## 9. Kill list + +| Do not build | Why | +|---|---| +| SIEM/Splunk/Datadog/OTLP-logs push connectors | 1 demand-side ask in ~1,050 posts/comments (`hn-reddit.md:166`); JSONL + forwarder is the deployed pattern; every connector is an M with an SDK | +| Vault / AWS SM / GCP SM / 1Password SDK clients | Asked as behaviour, not integration (`hn-reddit.md:154`); `${file:}` + ESO/VSO/1Password-operator covers all of them at S | +| HITL approval hold | L effort, 4 asks vs 6 vendor pitches (`hn-reddit.md:161`); deny-by-default on destructive intents captures most value at S | +| HA / external database | One checklist mention (`hn-reddit.md:94`); BBolt single-writer is fine for a small team if the chart says so (`internal-inventory.md:127`) | +| SAML, SCIM, org/workspace multi-tenancy, Teams entity | Vendor-tier features (`web-vendors.md:61-62,157`); 3 tenancy asks (`hn-reddit.md:162`); this is the paywalled layer a solo project should not chase | +| RFC 8693 / Entra OBO token exchange | Requires IdP-side trust most shops refuse (DCR wall, `hn-reddit.md:107,120`); one competitor RFC at 👍7 (`github.md:67`) | +| Connected per-user personal upstreams (`workspace.Manager`) | Process-per-user is "too costly" (`hn-reddit.md:101`); the demanded per-user thing is credentials on shared servers, not private processes | +| Per-user rate limiting / quotas | 5 LLM-gateway-shaped asks (`hn-reddit.md:158`; `github.md:169`); one mcpproxy ask already served by #955 | +| OTel metrics/logs exporters | "mostly vendor copy" (`hn-reddit.md:160`); Prometheus + OTLP traces exist (`internal-inventory.md:79-81`) | +| Air-gapped SKU | 0 asks (`hn-reddit.md:167`); a doc paragraph on disabling outbound calls suffices | +| Server-edition `.deb`/`.rpm` | The Linux/headless audience arrives via tarball and personal .deb (`internal-inventory.md:308`); the personal package already ships the hardened systemd unit (`internal-inventory.md:121`) | +| Docker Hub as a separate investment | GHCR askers found GHCR; README/GHCR-README is the discoverability fix (`github.md:154`) | + +--- + +## 10. Open questions and measurement gaps + +1. **Multi-user enablement is invisible.** No heartbeat field for `server_edition.enabled`, IdP, or user count (`internal-inventory.md:129,155`). Every Phase 2 gate above is unmeasurable until the Phase 0 telemetry fields ship and ~4 weeks of data accumulate. +2. **Image adoption is invisible.** GHCR pulls need `read:packages` (403 today); containers without volumes churn `anonymous_id` (248 sub-1-hour installs, `internal-inventory.md:259,296`). Decide whether to request the scope for the telemetry PAT or add `image_variant` to heartbeats. +3. **Are the 86 container IPs ops deployments or agent sandboxes?** The ≥24 h bucket (113 installs / 32 IPs) is defensible; the rest is unknown (`internal-inventory.md:263`). A `container_runtime`/cgroup hint would settle it. +4. **Does anything in the personal edition make outbound calls besides telemetry and update checks?** Unknown from the inventory; needed only for the air-gap doc paragraph. +5. **One binary or two?** The `server` build tag keeps the personal edition untouched but hides server routes from `swag`/OAS/CI lint (design doc, last note) and forces a separate image. If the personal-edition image becomes primary, consider whether `server_edition.enabled` could be a runtime block in one binary. Not evidenced either way; flagged for a design decision, not recommended here. +6. **Reddit lane is incomplete, but the ops subreddits are thin.** The subreddit×query matrix was cut short by rate limits (`hn-reddit.md:49-61`); the cells that did complete show "mcp gateway" post counts of 34 (r/selfhosted), 7 (r/devops), 9 (r/kubernetes) and 0 (r/platformengineering) versus ≥100 in r/mcp (`hn-reddit.md:53-59`), and the "mcp kubernetes"/"mcp helm" cells for those subreddits never completed. A follow-up pass could raise the Helm/K8s ask count, but the completed cells point the same way as the tally: platform teams assume K8s rather than ask a gateway for it (`hn-reddit.md:157`). +7. **No competitor stargazer baseline.** The 34 % company-field rate for mcpproxy stargazers has nothing to compare against (`github.md:162`). +8. **The 17 of 46 server installs with `require_mcp_auth=0`** (`internal-inventory.md:143`) suggest the server edition should default that to `true` — a behaviour change for the server tag only; needs a decision. +9. **First-party absorption timing.** Anthropic's Enterprise-Managed Authorization (`hn-reddit.md:193`) may remove the IdP-relay value for Claude clients; unknown when and for which clients. It strengthens the case for owning policy/drift/audit rather than auth plumbing. diff --git a/docs/research/server-edition-2026-09-14/evidence/github.md b/docs/research/server-edition-2026-09-14/evidence/github.md new file mode 100644 index 000000000..93e8d542c --- /dev/null +++ b/docs/research/server-edition-2026-09-14/evidence/github.md @@ -0,0 +1,170 @@ +# GitHub signals: what users ask of server-side / self-hosted / team MCP gateways + +Collected 2026-09-14 by the `collect-github` research agent. Raw dumps (repo metadata, full issue lists, discussions, READMEs, file trees, stargazer sample) are under `scratchpad/gh/`. + +## 1. Method + +- **Repo metadata**: `gh api repos/OWNER/REPO` for 33 repos (stars, forks, pushed_at, default branch); `gh api repos/OWNER/REPO/releases/latest` (fallback `tags?per_page=1`). +- **Issues**: `gh api "repos/OWNER/REPO/issues?state=all&per_page=100&sort=created&direction=desc" --paginate --slurp` for every dedicated MCP-gateway repo (23 repos, 41 k issue+PR records). PRs filtered out locally (`.pull_request == null`), then filtered by an ops/enterprise keyword regex (helm, kubernetes, vault, secrets, otel, prometheus, sso/oidc/saml, rbac, allowlist, rate-limit/quota, multi-tenant, audit/siem, air-gap, docker-hub/image) and ranked locally by `reactions.total_count` then `comments`. `sort=reactions` is search-API only, so ranking was done locally as instructed. +- **Big multi-purpose repos** (litellm, kong, apisix, traefik, cloudflare/agents, composio, mcp-use, portkey): `gh api "search/issues?q= repo:X&sort=reactions&order=desc&per_page=30"` with 4 s spacing (search limit 30/min; never hit an empty result). +- **Discussions**: `gh api graphql` `repository.discussions(first:100, CREATED_AT desc)` with `upvoteCount`, `comments.totalCount`, `bodyText` for 20 repos. +- **Feature matrix**: README keyword grep plus a **file-tree grep** (`git/trees/?recursive=1`) for paths such as `charts/`, `helm`, `vault`, `otel`, `prometheus`, `oidc`, `rbac`, `ratelimit`, `audit`. Tree hits were spot-checked by listing the matching paths (§2 notes cite them). +- **Discovery**: `gh search repos "mcp gateway|mcp proxy|mcp server manager" --stars ">300"` added samanhappy/mcphub, agentic-community/mcp-gateway-registry, TheLunarCompany/lunar, aws/mcp-proxy-for-aws. `envoyproxy/ai-gateway` now redirects to `theagentrouter/agent-router`; `tuananh/hyper-mcp` is archived and lives at `hyper-mcp-rs/hyper-mcp`. `zuplo` and "MCP Manager" were not resolvable to a specific >300★ OSS gateway repo and were skipped; `Kong/kong`, `traefik/traefik`, `ComposioHQ/composio` returned only PRs or ≤3 MCP issues (see §3 "empty lanes"). +- **mcpproxy-go signals**: full issue paginate (274 issues, 989 PRs), 12 discussions, asker profiles via `gh api users/`, 58-user stargazer sample (every 6th stargazer across the full 348-star list, `--paginate` with `application/vnd.github.star+json`). +- Rate limit at end: core 5000/5000 remaining after the run (limits reset mid-run), search never exhausted. Legend: 👍 = `reactions.total_count`, 💬 = comment count, ▲ = discussion upvotes. + +## 2. Competitor matrix + +"Ships" = present in repo tree/README (maintainers built). Stars/last push as of 2026-09-14. + +| repo | stars | last push | last release | helm / k8s | vault / secrets | otel / metrics | sso / oidc | rbac / allowlist | rate-limit | multi-tenant | audit export | notes | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| [IBM/mcp-context-forge](https://github.com/IBM/mcp-context-forge) | 4 468 | 2026-09-14 | v1.0.10 (2026-09-07) | **yes** `charts/mcp-stack`, helm-publish workflow | **yes** `plugins/vault`, `services/token_backends/vault_backend.py` | **yes** ADR-010 Prometheus, `observability-otel.md` | **yes** Entra, ADFS, generic OIDC tutorials, `docker-compose.sso.yml` | **yes** `docs/manage/rbac.md`, team RBAC migrations | **yes** `rate_limit_middleware`, ADR-006 | **yes** teams/private/global scopes (issue #283) | partial (audit in plugins) | Python; 903 open issues; most complete "enterprise" list, but a large share of feature issues are maintainer-authored epics | +| [agentgateway/agentgateway](https://github.com/agentgateway/agentgateway) | 4 841 | 2026-09-14 | v1.5.0 (2026-08-27) | **yes** `controller/install/helm/*` + CRDs (Gateway API) | no (K8s Secrets only) | **yes** `controller/pkg/metrics`, OTEL tracing | **yes** `crates/agentgateway/src/http/oidc/*` (Keycloak, Auth0, Okta providers) | **yes** `mcp/rbac.rs`, CEL policies | **yes** `localratelimit.rs`, `remoteratelimit.rs` | via policies/JWT claims | no first-class export | Rust; Solo.io/Linux Foundation; strongest OSS competitor for K8s-native MCP+LLM gateway | +| [stacklok/toolhive](https://github.com/stacklok/toolhive) | 2 164 | 2026-09-14 | v0.49.0 (2026-09-11) | **yes** operator (`cmd/thv-operator`), helm-publish, CRDs | **yes** 1Password provider, `examples/operator/vault/` | **yes** `thv config otel`, Prometheus path flag | **yes** `MCPOIDCConfig` CRD, OIDC controller | **yes** `pkg/kubernetes/rbac`, vMCP tool include-filter | **yes** `pkg/ratelimit` | namespace-scoped operator (open #2152) | **yes** `runconfig/audit.go` | Go; "enterprise-grade" positioning; closest feature-for-feature to mcpproxy server edition | +| [agentic-community/mcp-gateway-registry](https://github.com/agentic-community/mcp-gateway-registry) | 912 | 2026-09-14 | 1.30.0 (2026-09-09) | **yes** `charts/{registry,auth-server,mcpgw,keycloak-configure}` | partial: `docs/egress-credential-vault.md` (own credential vault, not HashiCorp) | **yes** `configmap-otel.yaml`, metrics-service | **yes** Cognito, Keycloak, Okta, Entra providers | partial (IAM rate-limit groups UI) | **yes** `rate_limiting_config.py`, `IAMRateLimits.tsx` | teams via IdP groups | partial | Python; AWS-community; community doubts adoption (disc #108) | +| [obot-platform/obot](https://github.com/obot-platform/obot) | 1 010 | 2026-09-14 | v0.25.5 (2026-09-09) | **yes** `chart/`, helm workflow | partial: encryption providers (Azure Key Vault, GCP KMS); External-secret request shipped 2026-05 (#6180) | partial | **yes** auth providers (GitHub/Google/Entra/Okta per `docs/configuration/auth-providers.md`) | **yes** ACL rules, groups | **yes** `pkg/api/server/ratelimiter` | **yes** multi-user MCP servers | **yes** `auditlogexport.go` (MCP + LLM audit logs) | Go; "AI Governance Platform"; heavy product scope | +| [docker/mcp-gateway](https://github.com/docker/mcp-gateway) | 1 563 | 2026-08-26 | v0.43.3 (tag) | **no** (no chart; only vendored k8s libs) | Docker Desktop secret store only (users ask to bypass it, #317) | **yes** `docs/telemetry/`, `examples/otel/metrics` | no | catalog-level tool select | no | no | no | Go; CLI plugin; catalog is mandatory (#195, #299 ask to disable) | +| [metatool-ai/metamcp](https://github.com/metatool-ai/metamcp) | 2 659 | 2026-06-22 | v2.4.22 (2025-12-19) | no | no | partial: `mcp-request-audit-logs` DB tables | **yes** OIDC via better-auth (README) | partial: private/public namespaces; RBAC requested (#103, #179) | **yes** `rate-limit.middleware.ts` | partial (multi-user, no per-team RBAC) | DB audit only | TS; docker-compose single image; stale since 2026-06 | +| [samanhappy/mcphub](https://github.com/samanhappy/mcphub) | 2 430 | 2026-09-14 | v1.0.37 (2026-09-13) | no | no | no | **yes** (shipped after #527: built-in OAuth2 server + optional Better Auth) | groups + per-group keys (#107 closed) | partial `rateLimit.ts` | groups | no | TS; very active; largely CN user base | +| [AmoyLab/Unla](https://github.com/AmoyLab/Unla) | 2 225 | 2026-08-27 | v0.10.0 (2026-08-04) | **yes** `deploy/helm`, publish-helm-chart workflow | no | partial `pkg/metrics` | no | tenant/user mgmt UI | no | **yes** `handler/tenant.go`, tenant-management page | no | Go; OpenAPI→MCP converter focus | +| [mcpjungle/MCPJungle](https://github.com/mcpjungle/MCPJungle) | 1 256 | 2026-08-02 | 0.4.6 (2026-08-02) | no | no | **yes** `internal/telemetry/otel*.go` (after disc #48) | **no** (top ask #128) | client allow-lists (`--allow`) | no | no | no | Go; has `enterprise-readiness` label; per-user upstream auth open (#254) | +| [microsoft/mcp-gateway](https://github.com/microsoft/mcp-gateway) | 830 | 2026-09-11 | none | partial: `deployment/k8s/*.yml`, Bicep for AKS (no Helm) | K8s secret env var | no | **yes** Entra app roles (`docs/entra-app-roles.md`) | Entra roles | no | no | no | C#/.NET; Azure-centric; GKE asked (#23) | +| [TheLunarCompany/lunar](https://github.com/TheLunarCompany/lunar) | 493 | 2026-09-10 | lunar-proxy-v0.9.2 (2024-03-21; MCPX unreleased) | **yes** `proxy/deploy/k8s/helm-charts` | no | **yes** `mcpx-server/src/server/prometheus.ts` | no | ACL yaml | **yes** quotas | no | **yes** audit-log persistence | TS; vendor sells "Hive" enterprise tier (disc #58 asks if K8s is community or paid) | +| [1mcp-app/agent](https://github.com/1mcp-app/agent) | 503 | 2026-09-13 | v0.38.0 (2026-09-13) | no | no | no | no | tag-based filtering | no | no | no | TS; aggregator; no enterprise asks in its 517 issues | +| [ravitemer/mcp-hub](https://github.com/ravitemer/mcp-hub) | 516 | 2025-10-24 | v4.2.1 (2025-08-22) | no | no | no | no | no | no | per-user credentials asked (#116) | no | Node; dormant since 2025-10 | +| [hyper-mcp-rs/hyper-mcp](https://github.com/hyper-mcp-rs/hyper-mcp) | 880 | 2026-09-11 | v0.8.3 (2026-06-24) | no | no | no | no | no | no | no | no | Rust/WASM plugin server; not a gateway | +| [sparfenyuk/mcp-proxy](https://github.com/sparfenyuk/mcp-proxy) | 2 751 | 2026-07-20 | v0.12.0 (2026-05-14) | no | no | no | no | no | no | per-user env asked (#120) | no | Python transport bridge only | +| [supercorp-ai/supergateway](https://github.com/supercorp-ai/supergateway) | 2 842 | 2026-09-14 | v3.4.3 (2025-10-09) | no | no | no | no | no | no | multi-user envs asked (#70) | no | TS transport bridge only | +| [tbxark/mcp-proxy](https://github.com/tbxark/mcp-proxy) | 720 | 2026-09-14 | v0.58.0 (2026-08-16) | no | no | no | no | no | no | no | no | Go aggregator; semantic tool filtering asked (#38, 16 💬) | +| [punkpeye/mcp-proxy](https://github.com/punkpeye/mcp-proxy) | 287 | 2026-09-09 | v6.7.16 (2026-09-09) | no | no | no | no | no | no | no | no | TS transport bridge | +| [lasso-security/mcp-gateway](https://github.com/lasso-security/mcp-gateway) | 386 | 2026-01-22 | v1.2.0 (2026-01-21) | no | no | no | no | no | no | no | no | Python security-plugin gateway; 25 issues total, dormant | +| [aws/mcp-proxy-for-aws](https://github.com/aws/mcp-proxy-for-aws) | 352 | 2026-09-14 | v1.6.6 (2026-09-08) | no | AWS creds only | no | IAM/SigV4 | no | no | multi-account (#172) | no | Client-side SigV4 proxy, not a team gateway | +| [theagentrouter/agent-router](https://github.com/theagentrouter/agent-router) (ex envoyproxy/ai-gateway) | 2 066 | 2026-09-13 | v1.1.0 (2026-08-21) | **yes** (Envoy Gateway CRDs, Helm) | K8s Secrets, cloud IAM (IRSA, Azure MI) | **yes** OTel + Prometheus (shipped after #791/#1100) | JWT/OIDC via Envoy Gateway | policy CRDs | **yes** token quotas (`QuotaPolicy`) | namespaces | no | LLM-first; MCPRoute added 2025-10 (#589) | +| [BerriAI/litellm](https://github.com/BerriAI/litellm) | 58 696 | 2026-09-14 | v1.100.1 (2026-09-10) | yes (Helm) | yes (Vault/AWS SM for LLM keys) | yes | yes (enterprise tier) | yes (teams/keys) | yes | yes | yes (enterprise) | MCP gateway is a sub-feature; DCR/OAuth for MCP asked (#13856, 👍9) | +| [apache/apisix](https://github.com/apache/apisix) | 17 118 | 2026-09-14 | 3.18.0 (2026-08-20) | yes | yes (Vault/AWS/GCP secrets) | yes | yes | yes | yes | yes | yes | MCP bridge plugin; MCP-specific asks are bugs (#12138) | +| [Portkey-AI/gateway](https://github.com/Portkey-AI/gateway) | 12 985 | 2026-05-25 | v1.15.2 (2026-01-12) | — | — | — | — | — | — | — | — | MCP directory listings only; no ops asks | +| [Kong/kong](https://github.com/Kong/kong) | 44 134 | 2026-09-07 | 3.9.3 (2026-06-17) | yes | yes | yes | yes | yes | yes | yes | yes | only 3 MCP issues; OTel `_meta` propagation (#14843, 0 👍) | +| [cloudflare/agents](https://github.com/cloudflare/agents) | 5 557 | 2026-09-14 | codemode 0.5.2 (2026-09-11) | n/a (Workers) | n/a | n/a | n/a | n/a | n/a | n/a | n/a | SDK, not a self-hosted gateway; MCP asks are protocol-level | +| [mcp-use/mcp-use](https://github.com/mcp-use/mcp-use) | 10 622 | 2026-09-14 | python-v1.7.1 (2026-09-10) | no | no | no | OAuth adapters | no | no | no | no | framework/SDK; not a gateway | +| [smart-mcp-proxy/mcpproxy-go](https://github.com/smart-mcp-proxy/mcpproxy-go) | **348** (47 forks) | 2026-09-14 | v0.66.1 (2026-09-13) | **no** chart; `Dockerfile` (distroless static) + ghcr image + .deb/.rpm | keyring only (`internal/secret/keyring_provider.go`) | **yes** `/metrics` Prometheus + OTLP traces (`docs/features/observability.md`, off by default) | **yes** server edition: GitHub, Google, Microsoft Entra, generic OIDC (`internal/serveredition`) | agent-token scopes; per-user server sharing | **yes** `max_concurrent_requests`/queue (v0.54.0, #955) | **yes** tenants/agent tokens (server edition) | broker audit (`serveredition/broker/audit.go`) | no Docker Hub listing; single image variant | + +## 3. Top user-requested ops/enterprise features across competitors + +Ranked by reactions, then comments; only user-authored requests (maintainer epics flagged). ≤2-sentence verbatim quotes. + +| # | repo | issue | date | 👍 | 💬 | request | quote (verbatim) | +|---|---|---|---|---|---|---|---| +| 1 | agentgateway | [#239](https://github.com/agentgateway/agentgateway/issues/239) (open) | 2025-07-30 | 24 | 15 | Enterprise SSO (Okta) + per-user credentials to external SaaS MCP | "Environment: Enterprise with 500+ developers using Cursor and other LLM tools … Each user must use their own credentials for external services" | +| 2 | sparfenyuk/mcp-proxy | [#235](https://github.com/sparfenyuk/mcp-proxy/issues/235) (open) | 2026-07-28 | 18 | 12 | Pin dependency for reproducible `uvx` installs (ops stability) | "Unbounded `mcp>=1.17.0` dependency lets `uvx mcp-proxy` resolve `mcp==2.0.0`" | +| 3 | agentgateway | [#1869](https://github.com/agentgateway/agentgateway/issues/1869) (closed 2026-06-03) | 2026-05-19 | 16 | 7 | Forward downstream mTLS client cert as header (enterprise ingress parity) | "Feature Request: Forward downstream client certificate as HTTP header (equivalent to nginx auth-tls-…)" | +| 4 | litellm | [#12367](https://github.com/BerriAI/litellm/issues/12367) (closed 2026-06-25) | 2025-07-07 | 17 | 13 | Custom OAuth2-based provider auth | title: "[Feature]: Add support for custom OAuth2-based LLM provider" | +| 5 | theagentrouter (envoy ai-gw) | [#589](https://github.com/theagentrouter/agent-router/issues/589) (closed 2025-10-03) | 2025-04-26 | 13 | 5 | MCP protocol support in an Envoy-based gateway | title: "[Proposal] Support for MCP protocol" | +| 6 | supergateway | [#38](https://github.com/supercorp-ai/supergateway/issues/38) (closed) | 2025-04-07 | 12 | 9 | Streamable HTTP transport | title: "Support HTTP streaming transport" | +| 7 | agentgateway | [#2351](https://github.com/agentgateway/agentgateway/issues/2351) (closed 2026-08-04) | 2026-06-29 | 12 | 2 | Global rate-limit response headers | "Global rate limit headers missing, no `x-ratelimit-*` headers … I'm in an isolated environment so I can't copy out the raw responses" | +| 8 | litellm | [#13856](https://github.com/BerriAI/litellm/issues/13856) (closed 2025-11-02) | 2025-08-21 | 9 | 8 | MCP gateway OAuth with Dynamic Client Registration | title: "[Feature]: MCP Gateway: Support Authorization flow with Dynamic Client Registration (DCR)" | +| 9 | IBM/mcp-context-forge | [#5306](https://github.com/IBM/mcp-context-forge/issues/5306) (open) | 2026-06-18 | 8 | 1 | JIT SSO user provisioning for headless/token clients | "`SSO_AUTO_CREATE_USERS` … only takes effect during the interactive browser OIDC callback." | +| 10 | theagentrouter | [#2036](https://github.com/theagentrouter/agent-router/issues/2036) (open) | 2026-04-09 | 7 | 2 | OAuth 2.0 Token Exchange (RFC 8693) to SaaS MCP backends | "Enterprises require the ability to securely exchange internal Identit[y]…" (proposal for GitHub Copilot MCP etc.) | +| 11 | docker/mcp-gateway | [#317](https://github.com/docker/mcp-gateway/issues/317) (open) | 2026-01-04 | 6 | 9 | Bypass Docker Desktop secret store; take secrets from env (aws-vault) | "I think it's an anti-pattern to mount your `~/.aws` directory … if a rogue process in the container wants to read your credentials, then _yeesh_." | +| 12 | metamcp | [#202](https://github.com/metatool-ai/metamcp/issues/202) (open) | 2025-11-08 | 6 | 1 | Semantic tool gating (context bloat) | "50+ tools consume 20,000-25,000 tokens (60-80% of context window)" | +| 13 | mcp-use | [#262](https://github.com/mcp-use/mcp-use/issues/262) (closed) | 2025-09-08 | 6 | 18 | Community wishlist thread | title: "💡 I wish mcp-use had ..." (framework; no gateway ops asks) | +| 14 | sparfenyuk/mcp-proxy | [#120](https://github.com/sparfenyuk/mcp-proxy/issues/120) (open) | 2025-10-13 | 5 | 1 | Per-user runtime env vars (multi-tenant agent platform) | "Each user has different runtime environment variables (API keys, region, tenant ID, etc.) which are only known at runtime" | +| 15 | mcpjungle | [#128](https://github.com/mcpjungle/MCPJungle/issues/128) (open, label `enterprise-readiness`) | 2025-09-27 | 5 | 3 | OAuth-based auth (maintainer-authored) | "Not supporting oauth is currently a significant limitation of mcpjungle and we need to address this." | +| 16 | agentgateway | [#2665](https://github.com/agentgateway/agentgateway/issues/2665) (open) | 2026-07-24 | 5 | 2 | K8s-mode governance UI, per-team/user cost analytics | "multi-team engineering org (~300 users). Auth is Okta OIDC/JWT … We enforce per-team and per-user token budgets with global rate limiting" | +| 17 | metamcp | [#179](https://github.com/metatool-ai/metamcp/issues/179) (open) | 2025-09-23 | 5 | 1 | User/role-based access control over servers & endpoints | "I'd love to propose and help implement a feature for user/role-based access control over MCP servers and endpoints." | +| 18 | supergateway | [#13](https://github.com/supercorp-ai/supergateway/issues/13) (open) | 2025-03-13 | 5 | 10 | Multiple MCP servers on one port | title: "Feature request: multiple MCP servers under the same port" | +| 19 | mcphub | [#527](https://github.com/samanhappy/mcphub/issues/527) (closed 2026-05-23) | 2025-12-26 | 4 | 13 | OIDC/SSO login | "admins have to manually create users and manage passwords/resets, which doesn't fit enterprise environments that use centralized identity providers" | +| 20 | ravitemer/mcp-hub | [#116](https://github.com/ravitemer/mcp-hub/issues/116) (open) | 2025-09-02 | 4 | 0 | Per-user credential pass-through headers | "This would allow a single deployment of mcp-hub to handle requests from many different users and allow the MCP server to act on the user's behalf." | +| 21 | supergateway | [#70](https://github.com/supercorp-ai/supergateway/issues/70) (open) | 2025-05-24 | 4 | 1 | Multi-user with different envs per user | "I want to use a set of environments to support different user access mcp sse server." | +| 22 | agentgateway | [#2029](https://github.com/agentgateway/agentgateway/issues/2029) (closed 2026-08-27) | 2026-06-02 | 4 | 7 | OAuth Identity Assertion (Cross-App Access / ID-JAG) | title: "Support OAuth Identity Assertion Authorization Grant (Cross App Access / ID-JAG)" | +| 23 | aws/mcp-proxy-for-aws | [#176](https://github.com/aws/mcp-proxy-for-aws/issues/176) (closed 2026-09-08) | 2026-02-13 | 4 | 3 | Assumed IAM role / chained creds | title: "Support for assumed IAM role (chained credentials) in MCP proxy" | +| 24 | agentgateway | [#1335](https://github.com/agentgateway/agentgateway/issues/1335) (closed 2026-05-21) | 2026-03-24 | 3 | 7 | Okta as native MCP auth provider | "Add `provider: Okta` support for the MCP OAuth 2.1 authentication flow, similar to the existing `provider: Keycloak` and `provider: Auth0`" | +| 25 | docker/mcp-gateway | [#187](https://github.com/docker/mcp-gateway/issues/187) (open) | 2025-10-16 | 3 | 6 | Meta-MCP tool discovery/filtering | "Every message includes tool descriptions for hundreds of tools, consuming thousands of tokens" | +| 26 | docker/mcp-gateway | [#195](https://github.com/docker/mcp-gateway/issues/195) (open) | 2025-10-21 | 3 | 0 | Disable default catalog (approved-server policy) | "disable the default catalog for security purposes since I am working in a heavily regulated industry" | +| 27 | agentic-community | [#189](https://github.com/agentic-community/mcp-gateway-registry/issues/189) (open) | 2025-10-25 | 3 | 5 | Generic OIDC provider (Authentik) | "I use Authentik as my IDP and was wondering if it's possible to use a generic OIDC/OAuth2 provider vs. the branded closed ones." | +| 28 | agentgateway | [#772](https://github.com/agentgateway/agentgateway/issues/772) (closed 2026-03-26) | 2025-12-30 | 3 | 3 | Tool include/exclude independent of authz | "When upstream MCP servers expose many tools, the gateway forwards all tools and then filters via `mcpAuthorization` … Leaks tool names" | +| 29 | IBM/mcp-context-forge | [#283](https://github.com/IBM/mcp-context-forge/issues/283) (closed 2025-09-05; maintainer epic) | 2025-07-06 | 3 | 2 | RBAC user/team/global scopes | "Multi-tenancy enables secure isolation for enterprises, teams, and individual users while maintaining collaboration through controlled sharing." | +| 30 | toolhive | [#306](https://github.com/stacklok/toolhive/issues/306) (closed 2025-05-06, p0) | 2025-04-30 | 3 | 4 | 1Password secrets provider | title: "Add support for a 1Password secrets provider" | +| 31 | mcphub | [#107](https://github.com/samanhappy/mcphub/issues/107) (closed) | 2025-05-19 | 3 | 1 | Per-group / per-server API keys for team use | (zh) "为每个分组或者server创建单独的apikey或者token来提供更精细化的权限管理,便于团队协作使用" | +| 32 | agentgateway | [#2064](https://github.com/agentgateway/agentgateway/issues/2064) (open) | 2026-06-04 | 3 | 0 | Custom OAuth + extra scopes per MCP server (Entra) | "we are using agentgateway as our main gateway for MCPs (with Azure Entra ID) … deployed in k8s on our internal network only" | +| 33 | theagentrouter | [#1571](https://github.com/theagentrouter/agent-router/issues/1571) (open) | 2025-11-25 | 3 | 6 | Token quota with failover | "If a quota is exceeded request is automatically failed over to the next backend ref" | +| 34 | theagentrouter | [#2469](https://github.com/theagentrouter/agent-router/issues/2469) (open) | 2026-08-01 | 3 | 2 | Monthly/billing-period quotas | title: "QuotaPolicy: `duration` enum caps at `1d`, making monthly/billing-period quotas inexpressible" | +| 35 | metamcp | [#103](https://github.com/metatool-ai/metamcp/issues/103) (open) | 2025-07-18 | 2 | 11 | RBAC for MCP servers & namespaces | "every one can access all the mcp servers connected. Is there any plan to provide RBAC" | +| 36 | theagentrouter | [#791](https://github.com/theagentrouter/agent-router/issues/791) (closed 2025-08-12) | 2025-06-27 | 2 | 21 | OpenTelemetry tracing | "Integrate OpenTelemetry to add distributed trace(span & attribute) support" | +| 37 | IBM/mcp-context-forge | [#932](https://github.com/IBM/mcp-context-forge/issues/932) (closed 2025-11-20) | 2025-09-06 | 2 | 0 | Air-gapped support | "Enable MCP Context Forge Gateway to run fully offline in secure, air-gapped environments without external CDN dependencies." | +| 38 | mcpjungle | [#254](https://github.com/mcpjungle/MCPJungle/issues/254) (open) | 2026-05-07 | 1 | 11 | Per-user upstream authentication | "mcpjungle does not support passing user-level authentication to upstream MCP servers, instead it relys on a single global credential" | +| 39 | obot | [#6180](https://github.com/obot-platform/obot/issues/6180) (closed 2026-05-20) | 2026-03-27 | 1 | 5 | External secrets (Vault, AWS SM) via Vault Secrets Operator | "Teams would like to leverage their existing secret store (Vault, AWS Secret Manager, etc) … The API key is managed in Vault and synced to the cluster by the Vault Secrets Operator" | +| 40 | toolhive | [#1249](https://github.com/stacklok/toolhive/issues/1249) (closed 2026-03-04) | 2025-08-01 | 1 | 3 | Operator must not need OS keyring on headless K8s | "i have installed toolhive operator on a k8s server … the pods fails requiring an OS keyring with interactive prompt" | +| 41 | toolhive | [#3493](https://github.com/stacklok/toolhive/issues/3493) (open) | 2026-01-28 | 1 | 6 | Deny-list tool filter (default-allow) | "vMCP tool filtering only supports an include filter (allow list) … no option to exclude specific tools while allowing the rest" | +| 42 | toolhive | [#1063](https://github.com/stacklok/toolhive/issues/1063) (closed 2026-03-04) | 2025-07-14 | 0 | 22 | OpenShift deployment | "We want to be able to deploy toolhive operator and associated MCP servers into OpenShift." | +| 43 | toolhive | [#902](https://github.com/stacklok/toolhive/issues/902) (closed 2025-07-11) | 2025-06-30 | 0 | 39 | EKS operator install troubleshooting (most-commented toolhive issue) | title: "Issue Starting MKP Server on EKS Cluster with Toolhive Operator" | +| 44 | agentic-community | [#625](https://github.com/agentic-community/mcp-gateway-registry/issues/625) (closed 2026-04-22) | 2026-03-09 | 0 | 21 | Helm chart secret wiring bug | "The `registry-secret` … doesn't include `ADMIN_PASSWORD`. The container image expects it as an env var." | +| 45 | IBM/mcp-context-forge | [#5437](https://github.com/IBM/mcp-context-forge/issues/5437) (open) | 2026-06-30 | 0 | 13 | Human-in-the-loop approval for tool execution | title: "Human in the loop Approval for tool execution" | +| 46 | toolhive | [#2152](https://github.com/stacklok/toolhive/issues/2152) (open) | 2025-10-10 | 0 | 1 | Namespace-scoped operator for regulated multi-tenant clusters | "some deployment scenarios — particularly those in highly regulated or multi-tenant setups — call for strong isolation between namespaces" | +| 47 | IBM/mcp-context-forge | [#80](https://github.com/IBM/mcp-context-forge/issues/80) (closed 2025-12-03) | 2025-06-10 | 1 | 3 | Multi-arch (ARM64) image | "The current official image only supports amd64 architecture" | +| 48 | metamcp | [#147](https://github.com/metatool-ai/metamcp/issues/147) (open) | 2025-08-31 | 0 | 10 | Pull from private registry | "a lot of MCP server are not published in official registry so we can just clone the repo and publish ourself (in private registry obiously)" | +| 49 | docker/mcp-gateway | [#299](https://github.com/docker/mcp-gateway/issues/299) (open) | 2025-12-11 | 1 | 3 | Restricted image sources (corporate pull policy) | "In my working environment I am restricted to pull images from some sources" | +| 50 | microsoft/mcp-gateway | [#23](https://github.com/microsoft/mcp-gateway/issues/23) (open) | 2025-09-03 | 1 | 0 | GKE deployment (non-Azure K8s) | title: "Add Support for GKE deployment" (empty body) | + +**Discussions (▲ upvotes / 💬 comments):** + +| repo | discussion | date | ▲ | 💬 | request | quote | +|---|---|---|---|---|---|---| +| IBM/mcp-context-forge | [#324](https://github.com/IBM/mcp-context-forge/discussions/324) | 2025-07-08 | 8 | 1 | OAuth 2.0 client-credentials through an existing API gateway | "My clients has already in place an apigateway that mediates all the interaction with their backend system." | +| agentic-community | [#108](https://github.com/agentic-community/mcp-gateway-registry/discussions/108) | 2025-08-29 | 4 | 2 | Adoption/credibility check | "I've looked at all the available MCP gateway options - this has all the needed features. Except it has all the hallmarks of an entirely vibe-coded project with no real adoption." | +| docker/mcp-gateway | [#180](https://github.com/docker/mcp-gateway/discussions/180) | 2025-10-11 | 4 | 1 | Add servers outside the catalog with governance | "I can't find a way to add tools outside the catalog … governance is important to me :) … I'd happily pay for it if it weren't free." | +| IBM/mcp-context-forge | [#5562](https://github.com/IBM/mcp-context-forge/discussions/5562) | 2026-07-08 | 2 | 1 | Multi-tenant upstream connections | "connect to multiple mcp servers ie confluence, testrail, jira etc for multiple tenants. Each tenants can have their own confuence mcp server." | +| toolhive | [#1998](https://github.com/stacklok/toolhive/discussions/1998) | 2025-09-22 | 2 | 2 | Entra ID token validation via operator | "We use Active Directory internally, specifically Azure EntraID, we also use kubernetes" | +| agentgateway | [#2624](https://github.com/agentgateway/agentgateway/discussions/2624) | 2026-07-22 | 2 | 1 | Shared/global API key store across listeners | title: "Allow binds listeners to share the LLM listener's API keys (shared/global API key store)" | +| IBM/mcp-context-forge | [#5747](https://github.com/IBM/mcp-context-forge/discussions/5747) | 2026-07-22 | 1 | 3 | FIPS mode via Helm value | "Can this be enabled directly via a Helm parameter (e.g., fips.enabled: true or global.fips)?" | +| IBM/mcp-context-forge | [#1477](https://github.com/IBM/mcp-context-forge/discussions/1477) | 2025-11-19 | 1 | 2 | In-place Helm upgrades | "Everytime I had some trouble trying in-place upgrades using the helm chart then I will do a clean installation." | +| mcpjungle | [#48](https://github.com/orgs/mcpjungle/discussions/48) | 2025-08-13 | 1 | 7 | OTel design (contributor) | "Instrument MCPJungle with OTel SDK (Go) → export via OTLP to an OTel Collector → expose a Prometheus-scrape endpoint" | +| TheLunarCompany/lunar | [#58](https://github.com/TheLunarCompany/lunar/discussions/58) | 2026-02-06 | 1 | 0 | K8s scaling — community or paid? | "Does Lunar run in kubernetes … Is this available on the community version, or only with the Enterprise license?" | +| mcphub | [#1145](https://github.com/samanhappy/mcphub/discussions/1145) | 2026-09-08 | 1 | 0 | Per-user/group install ACLs, trusted-plugin marking | "I don't see option as admin to mark certain plugins in market as trusted or not." | +| docker/mcp-gateway | [#490](https://github.com/docker/mcp-gateway/discussions/490) | 2026-05-17 | 1 | 1 | Secrets without Docker Desktop | "docker pass has not been installed … Should this work without Docker Desktop?" | + +**Empty / thin lanes (exact requests):** +- `search/issues?q=mcp repo:Kong/kong` → 3 results, 0 enterprise asks (only [#14843](https://github.com/Kong/kong/issues/14843) OTel `_meta` propagation, 0 👍). +- `search/issues?q=mcp repo:traefik/traefik` → 8 results, all PRs. +- `search/issues?q=mcp self-hosted repo:ComposioHQ/composio` → 8 results, all PRs. +- `search/issues?q=mcp repo:Portkey-AI/gateway` → 19 results; all are "list my MCP server in the directory" or provider bugs. +- `search/issues?q=mcp repo:cloudflare/agents` → 630 results; top are SDK/roadmap ([#2](https://github.com/cloudflare/agents/issues/2) 👍14) and transport bugs, no self-hosting asks (platform is Workers). +- lasso-security/mcp-gateway: 25 issues total, 0 with reactions; 1mcp-app/agent: 517 records, no helm/vault/sso/rbac asks; hyper-mcp: none. + +## 4. mcpproxy-go's own server-edition-related signals + +Repo: 348★, 47 forks, 274 issues (989 PRs), 12 discussions. External-author issues touching server/ops (all others in the keyword set are Dumbris/algis-dumbris-authored): + +| issue | date | closed | 👍 | 💬 | asker (profile) | ask | status | +|---|---|---|---|---|---|---|---| +| [#40 Docker images are needed](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/40) | 2025-08-16 | 2026-05-01 | 0 | 6 | **achetronic** — SRE/developer, YouTube creator, Canarias ES, 184 followers, no company; repos `homelab-ops`, `magec`, `filesystem-mcp` → **homelab K8s** ("I have a K8s cluster where I have deployed both") | Docker image so K8s 1.33 image-volume mounts can front a stdio HomeAssistant MCP | Closed by Dumbris: images on GHCR every release. Commenter **technicalpickles** (Staff Eng @Gusto, 1 147 followers) built slim (distroless) + full images on a branch 2025-09-29 | +| [#1171 Re-enable Docker builds](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1171) | 2026-09-01 | 2026-09-12 | 0 | 0 | **8bitbuddhist** — "Technical marketer … specializing in Kubernetes and Linux", company **@gremlin**, repos `kind-gremlin-demo`, `mcp-servers`, `nixos-hardware` → **K8s vendor employee / homelab** | "Running this as a container requires manually building the image … can you please re-enable the `build-docker` workflow?" | Closed 2026-09-12 (workflow re-enabled) | +| [#955 request queueing / concurrency limit for multi-user deployments](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/955) | 2026-08-05 | 2026-08-09 | 1 | 2 | **zeeid** — "Zeei Developer", 2 followers (individual) | "We run mcpproxy as a shared HTTP service (systemd, headless mode) accessed by multiple concurrent users/agents … risking overload on those upstream resources when usage scales beyond a single user." | Shipped v0.54.0: `max_concurrent_requests`, `queue_size`, `queue_timeout`, per-server defaults | +| [#333 expand secret/env refs in working_dir / data_dir / host_path](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/333) | 2026-03-10 | 2026-03-12 | 0 | 1 | **tjsingleton** — company **Included Health**, Buford GA | `${env:}`/`${keyring:}` not expanded for `working_dir`, `data_dir`, Docker `host_path` | Fixed | +| [#872 upstream_servers list should redact env secrets](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/872) | 2026-07-20 | 2026-07-21 | 0 | 2 | **neylwalecki** — marketing founder, Curitiba BR | "This can expose API keys, bearer tokens, OAuth callback tokens … to an MCP caller that only needs operational server metadata." | Fixed | +| [#820 Completely Delete Agent Tokens](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/820) | 2026-07-07 | 2026-07-09 | 1 | 1 | Eun | agent-token lifecycle | Fixed | +| [#409 core lacks MCPPROXY_KEYRING_WRITE](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/409) | 2026-04-25 | 2026-04-26 | 0 | 1 | jagaliano | keychain secret storage | Fixed | +| [#1013 reconnect has no backoff](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1013) | 2026-08-20 | 2026-08-23 | 0 | 2 | antongulin (@SENIMSOFT, AI QA architect) | ops stability | Fixed | +| [#143 CLI commands for server management](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/143) | 2025-11-19 | 2025-11-27 | 0 | 2 | technicalpickles (@Gusto) | headless management | Shipped (`mcpproxy upstream …`) | +| [#71 Process compose option](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/71) | 2025-10-05 | 2026-05-01 | 0 | 4 | joeblew999 (UbuntuSoftware, offline AI) | alternative process orchestration | Closed | +| [#33 Docker MCP servers stopping immediately](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/33) | 2025-07-29 | 2025-09-14 | 1 | 5 | philipp-winterle | Docker isolation bug | Fixed | + +**Maintainer-built (Dumbris-authored) server-edition hardening, 2026-08-31 → 2026-09-13** — all closed except #1177: [#1180](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1180) `/api/v1/info` leaked admin key to agent tokens; [#1179](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1179) admin can't revoke a tenant's token (closed 2026-09-13); [#1177](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1177) global `auth.MaxTokens` cap lets one tenant exhaust slots (**open**); [#1169](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1169) JWT admin role frozen in claim; [#1168](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1168) agent-token names global namespace; [#1167](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1167) `reveal_secret_headers` for non-admins; [#1161](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1161) every user could read shared-server credentials; [#1148](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1148) quarantine list leaked secrets; [#1143](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/1143) `-slim` uvx image lacks git; [#457](https://github.com/smart-mcp-proxy/mcpproxy-go/issues/457) doctor detects snap-docker for the .deb. Nobody outside the maintainer has filed a helm/vault/otel/SSO/RBAC request against mcpproxy-go — the request in `gh api repos/smart-mcp-proxy/mcpproxy-go/issues?state=all --paginate` filtered for `helm|vault|prometheus|otel|sso|oidc|saml|rbac` returns **zero external-author hits**. + +**Discussions** (12 total; none about server edition): most-commented is [#175 Tracking similar projects](https://github.com/smart-mcp-proxy/mcpproxy-go/discussions/175) (technicalpickles, 💬6) and [#764 Finding MCPProxy MCP servers efficiently](https://github.com/smart-mcp-proxy/mcpproxy-go/discussions/764) (💬5); [#948](https://github.com/smart-mcp-proxy/mcpproxy-go/discussions/948) "It's almost impossible to find … mcpproxy-go" (twardoch, 2026-08-01) is a discoverability complaint. + +## 5. Stargazer-company sample + +`gh api repos/smart-mcp-proxy/mcpproxy-go/stargazers?per_page=100 --paginate` → 348 stargazers; sampled every 6th login (58 users), `gh api users/` each. + +- **20 / 58 (34 %) have a `company` field set.** Companies seen: Included Health, BIK GmbH, Teleport Corp Pty Ltd, WeRoad, @G-Core, @joby, Asseco Cloud, caddi, @zendesk, s3connectedhealth, @SENIMSOFT, Stealth Startup, Ultra Heavy LLC, @TheBloxOfficeLLC, Astride, Freelance, plus 4 joke/self entries (DGAF, David, Ssker Productions, @ClarkQAQ). +- Roughly **12–14 / 58 (≈22 %)** are recognisable employers (cloud/DevOps/health-tech); several bios are explicitly DevOps/SRE/"Data Center / Cloud / DevOps / Automation" (krisiasty @ Asseco Cloud, rmikl @ s3connectedhealth). +- Comparison baseline was not collected for competitors (would need the same sampling per repo); treat 34 % as a crude, un-normalised proxy. + +## 6. Summary + +- **The single loudest ask across every OSS MCP gateway is identity, not infra**: enterprise SSO with *per-user* credentials to upstream/SaaS MCP servers (agentgateway #239 👍24, IBM #5306 👍8, mcphub #527 💬13, mcp-hub #116, mcpjungle #254 💬11, supergateway #70, sparfenyuk #120, agent-router #2036 RFC 8693). mcpproxy's server edition (OIDC/GitHub/Google/Entra login + credential broker) already sits on this demand; per-user upstream OAuth brokering is the differentiator to shout about. +- **Second tier: RBAC / per-team tool allowlists and "only approved servers"** (metamcp #103 💬11 & #179 👍5, agentgateway #772, toolhive #3493, docker #195 "heavily regulated industry", docker disc #180 "governance is important … I'd happily pay"). Users want include *and* exclude lists and a way to disable public catalogs. +- **Helm/K8s is table stakes rather than a feature request**: the competitors users take seriously (IBM, agentgateway, toolhive, obot, Unla, agentic-community, lunar) all ship charts; the asks are about chart *quality* (in-place upgrades IBM disc #1477, secret wiring #625 💬21, OpenShift #1063 💬22, headless keyring #1249, namespace-scoped operators #2152, FIPS via Helm value). Both mcpproxy Docker asks (#40 homelab-K8s SRE, #1171 @gremlin K8s marketer) came from Kubernetes people, and nobody has yet asked mcpproxy for a chart — likely because the image itself only became reliable in 2026-09. +- **Secrets integration demand is real but narrow**: 1Password (toolhive #306, p0), Vault/AWS SM via External-Secrets/VSO (obot #6180), bypass of vendor secret stores in favour of env/aws-vault (docker #317 👍6 💬9), "no OS keyring on servers" (#1249). Nobody asked for SOPS. OTel/Prometheus was requested and then shipped in agent-router (#791 💬21) and mcpjungle (disc #48); there is no unfulfilled high-vote OTel/SIEM/Splunk/Datadog ask anywhere in the set — mcpproxy already has `/metrics` + OTLP (off by default). Rate-limit asks are LLM-gateway-shaped (token quotas, billing periods, `x-ratelimit-*` headers) rather than MCP-shaped; mcpproxy's concurrency queue (#955) is the only MCP-specific one and it came from a single-person "shared systemd service" user. +- **mcpproxy-go's own external signal is thin and homelab/small-team flavoured**: 11 external ops-adjacent issues, max 1 👍, and every enterprise-hardening issue is maintainer-authored; 34 % of sampled stargazers list a company. Competitors' strongest voices are 300–500-developer orgs on Okta/Entra + K8s (agentgateway #239, #2665, #2064). The gap to close for that audience, in order of evidence: per-user upstream OAuth brokering → per-team tool allow/deny lists + approved-server policy → a Helm chart with secret/OIDC wiring → external-secrets hooks (1Password, Vault via ESO) → OTel/SIEM exporters (low pull). diff --git a/docs/research/server-edition-2026-09-14/evidence/hn-reddit.md b/docs/research/server-edition-2026-09-14/evidence/hn-reddit.md new file mode 100644 index 000000000..a1b769de4 --- /dev/null +++ b/docs/research/server-edition-2026-09-14/evidence/hn-reddit.md @@ -0,0 +1,213 @@ +# HN + Reddit demand signals: server-side / team MCP gateway + +Collected 2026-09-14. Scope: what people actually ask for (or build, or reject) when running MCP centrally for a team/org. Product context: MCPProxy server edition (ghcr.io/smart-mcp-proxy/mcpproxy-server). + +Legend for the "who" column: **ASK** = asked for it / described the need · **BUILT** = built it themselves (in-house or side project) · **VENDOR** = vendor/founder selling it · **COUNTER** = does not want a central gateway / prefers something else. + +--- + +## 1. Method, queries, hit counts + +### Hacker News (Algolia API; ids spot-checked against `hacker-news.firebaseio.com/v0/item/.json`) + +Story search `https://hn.algolia.com/api/v1/search?query=&tags=story` (nbHits): + +| query | nbHits | +|---|---| +| "MCP gateway" | 169 | +| "MCP proxy" | 230 | +| "MCP server kubernetes" | 38 | +| "model context protocol enterprise" | 31 | +| "MCP self-hosted" | 156 | +| "mcp registry internal" | 17 | +| "mcp security gateway" | 33 | +| "mcpproxy" | 38 (mostly unrelated: MacProxy, MyProxy, mmproxy; no mcpproxy-go story found) | + +Comment search `...&tags=comment` (nbHits; Algolia typo-tolerance inflates short tokens like "sso"/"helm"): + +| query | nbHits | relevant after reading | +|---|---|---| +| "MCP gateway" (search_by_date, 5 pages = 500 pulled) | 472 | ~45 | +| "MCP proxy enterprise" | 26 | 4 | +| "mcp audit log" | 122 | ~10 | +| "mcp vault secrets" | 34 | 5 | +| "MCP kubernetes" | 366 | ~8 | +| "MCP multi-tenant" | 72 | 4 | +| "MCP oidc" | 72 | 6 | +| "MCP allowlist" | 38 | 3 | +| "MCP registry internal" | 20 | 2 | +| "MCP air-gapped" | 20 | **1** (lukewarm707, 2026-04-10: uses MCP so "an airgapped agent ... can still call online tools" - about agent isolation, not air-gapped gateway installs) | +| "MCP observability otel" | 43 | 2 | +| "MCP compliance" | 612 | ~8 (mostly Who-wants-to-be-hired noise) | + +Comment trees pulled in full (`/api/v1/items/`) for 40 stories, top ones: "MCP is dead?" (48330436, 400 pts, 2026-05-29), "Zero-Touch OAuth for MCP" (48592163, 278 pts, 2026-06-18), "Ask HN: Who is using MCP in production?" (49548600, 198 pts, 2026-09-03), "Claw Patrol" (48462928, 112), "OneCLI credential gateway" (49023427, 110), "IBM MCP Gateway and Registry / ContextForge" (45010524, 73), "MCP Defender" (44128325, 64), "mcpsnoop" (48777144, 64), "HyprMCP" (45521788, 59), "open-edison" (45223102, 51), "The State of MCP Security [pdf]" (48884647, 38), "Armour stdio proxy" (46696348, 23), "5 Knights of the MCP Apocalypse" (46513860, 12), TrueFoundry MCP Gateway (46136222, 10), plus ~25 low-score Show HNs (most 1-8 pts, 0-3 comments - the "million gateways" long tail). + +Observation on volume: **~60 distinct "Show HN: MCP gateway/proxy/firewall" launches since 2025-08**, almost all <10 points. Demand-side threads (Ask HN, "MCP is dead?", Zero-Touch OAuth) carry 10-50x the engagement of any single supply-side launch. + +### Reddit (Arctic Shift archive API; reddit.com itself blocked from this machine) + +Endpoints used: `https://arctic-shift.photon-reddit.com/api/posts/search?subreddit=&query=&limit=100` and `/api/comments/search?link_id=&limit=100`. The API root `/api/` returns 404; the paths above work. Hard rate limit: bursts return `{"error":"Too many requests"}` / `"Timeout. Maybe slow down a bit"` / HTTP 502 - needed ~5s spacing + exponential retry; a full 11x11 subreddit x query matrix was not completable in-session (see table; "-" = not attempted, "n/f" = attempted but rate-limited out before completion). Scores are archive snapshots (lower bound) - used for ordering only. `limit=100` caps, so "100" means >=100. + +| subreddit \ query | mcp gateway | mcp proxy | mcp kubernetes | mcp helm | mcp vault | mcp enterprise | mcp team | mcp self hosted | mcpproxy | mcp audit | mcp sso | +|---|---|---|---|---|---|---|---|---|---|---|---| +| r/mcp | 100 | 100 | 90 | 16 | 89 | 100 | 100 | 100 | 1 | 100 | 32 | +| r/ClaudeAI | n/f | 100 | n/f | - | - | n/f | 100 | 100 | - | - | - | +| r/ClaudeCode | 57 | n/f | - | - | - | n/f | - | - | - | - | - | +| r/selfhosted | 34 | 28 | n/f | n/f | n/f | 17 | - | n/f | - | - | - | +| r/devops | 7 | 8 | n/f | n/f | - | 4 | - | - | - | - | 1 | +| r/kubernetes | 9 | 7 | n/f | n/f | - | 0 | - | - | - | - | - | +| r/platformengineering | 0 | 0 | - | - | - | 2 | - | - | - | - | - | +| r/sysadmin | n/f | n/f | - | - | - | n/f | - | - | - | - | - | +| r/cursor, r/LocalLLaMA, r/AI_Agents | not fetched (rate limit) | | | | | | | | | | | + +The r/mcp "mcpproxy" query returned exactly 1 post (2026-08-13, u/punkpeye "PSA ... mcp-proxy is a simple local proxy that makes old MCP servers compatible with...", about sparfenyuk/mcp-proxy, not mcpproxy-go). **No organic Reddit or HN mention of mcpproxy-go was found in these lanes.** + +Full comment trees pulled for 22 threads (listed inline below). Total unique posts collected: ~600; unique comments: ~450. + +### SearXNG (kubic) +Reachable. `q=MCP gateway helm chart` returned mostly unrelated bank pages plus 3 useful candidates: `github.com/agentic-community/mcp-gateway-registry/blob/main/charts/README.md` (a Helm chart exists for that OSS gateway), `github.com/matthisholleville/mcp-gateway`, and the AWS blog "Governing AI Assets at Scale with MCP Gateway and Registry". Treated as candidates only, not signals. + +--- + +## 2. Signal table + +HN comment URL = `https://news.ycombinator.com/item?id=`. Reddit comment URL = `https://www.reddit.com/r//comments//comment//`. + +| # | source | date | score | who | what they want | verbatim quote | URL | +|---|---|---|---|---|---|---|---| +| 1 | r/mcp post | 2026-09-01 | 41 pts / 59 c | u/Shiz879 · ASK | Central hosting, corporate IdP login, group-based access, queryable per-call log; asks K8s vs VM, OAuth vs tokens, per-server vs per-tool, service-account vs delegated creds, ops cost | "What I want instead is boring and obvious: MCP servers hosted centrally, users authenticate with their corporate identity, access is granted by group membership, and every tool call is logged somewhere I can query." | https://www.reddit.com/r/mcp/comments/1w4oiiv/ | +| 2 | r/mcp comment (thread #1) | 2026-09-01 | 25 | u/Main_Walrus4368 · BUILT | VMs + systemd + OAuth sidecar vs Azure AD; one service account per server; user identity logged per call | "Users hit a lightweight auth sidecar that does the OAuth dance against Azure AD, then drops a short-lived token the MCP server validates on each call. ... Ops burden is maybe a few hours a month, most of that is just rotating the service account secrets." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p79dz4m/ | +| 3 | r/mcp comment (thread #1) | 2026-09-01 | 7 | u/kyngston · BUILT | Kubernetes + Okta | "we run mcp servers on pods in a k8s cluster and use okta oauth authentication" | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7a1884/ | +| 4 | r/mcp comment (thread #1) | 2026-09-02 | 2 | u/Enough-Photo9140 · ASK (compliance) | Immutable append-only audit log binding IdP JWT claims to the tool-execution span; delegated tokens for writes | "If the MCP gateway modifies a downstream record ... via a single shared service account, auditors will flag it unless your gateway emits an immutable, append-only audit log binding the caller's verified IdP JWT claims (sub/email/group) directly to the tool execution span." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7dfl02/ | +| 5 | r/mcp comment (thread #1) | 2026-09-03 | 1 | u/incaroses (AuthPlane maintainer) · VENDOR-adjacent | Per-user downstream authorization, not just attribution (SOX ITGC, PCI 7.x) | "Attribution isn't authorization, and auditors who know the difference will ask." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7ht6y3/ | +| 6 | r/mcp comment (thread #1) | 2026-09-02 | 1 | u/pmoschov (CERN) · BUILT | One gateway (LiteLLM) doing SSO + central MCP registry + group membership + single log point; servers on service VMs | "In front of them sits one LLM gateway (LiteLLM in our case) that does SSO with the corporate identity, holds the MCP registry so clients discover servers centrally, and is the one place tool calls get logged. Access is a group membership on the gateway, so onboarding is adding someone to a group." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7cqjvq/ | +| 7 | r/mcp comment (thread #1) | 2026-09-03 | 1 | u/puffaush · BUILT | EKS + Pulumi + Okta; MCP servers as ordinary services in the existing pipeline | "adding an MCP server isn't a special case, it's just another service going through our normal deploy pipeline, authenticating against our IdP (Okta) like everything else does." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7iny9q/ | +| 8 | r/mcp comment (thread #1) | 2026-09-06 | 1 | u/awhitford · BUILT (on managed gw) | Managed gateway + Entra ID; Agent Skills layered on gateway tools for non-technical users; per-tool policy is a config burden | "Onboarding is: install the corporate plugin (which carries the MCP server spec in a `.mcp.json`), sign in with your Entra ID, done. Nobody hand-edits configs or manages credentials." / "Per-tool is real config burden and it can quietly kill adoption if you're stingy." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p82u6k3/ | +| 9 | r/mcp comment (thread #1) | 2026-09-03 | 1 | u/mcpvault · ASK/BUILT | Per-server access first, per-tool only for mixed-risk servers; delegated user tokens for writes | "I would start with access per server, not per tool. Per-tool policy becomes worthwhile only when one server mixes low-risk read operations with things that can change data or expose sensitive records." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7jx5fr/ | +| 10 | r/mcp comment (thread #1) | 2026-09-02 | 1 | u/Wide-Excitement-1315 (Portablemind) · BUILT/VENDOR | Gotcha: home-minted JWTs leak via `?token=` into reverse-proxy logs -> implement real OAuth 2.1 | "a 90-day bearer credential in a query string leaks straight into your reverse-proxy access logs. We found ours in nginx logs. So we bit the bullet and implemented the actual MCP authorization spec" | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7dsio9/ | +| 11 | r/mcp comment (thread #1) | 2026-09-02 | 1 | u/Ok_Recognition_4630 · BUILT | XAA/ID-JAG + Okta role codes stapled into token; role->tool mapping file; per-user tool list | "If you're doing anything serious you NEED tool-level authz, preferably tuple-level authz. ... RBAC is the only way to do this effectively - 1:1 tool<->group mappings don't scale" | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7anlfr/ | +| 12 | r/mcp post | 2026-09-09 | 10 / 14 c | u/Purple_Morning_8735 · ASK | Whether an AI (LLM) gateway suffices or MCP needs its own gateway: per-server auth, per-agent tool permission, call logging | "But then you get into Auth per server, deciding which agent can call which tool, and logging what actually got called. That feels like a different problem." | https://www.reddit.com/r/mcp/comments/1wc20jx/ | +| 13 | r/mcp comment (thread #12) | 2026-09-10 | 3 | u/organic-humanoid · ASK | Separate policy planes; MCP gateway owns discovery/auth, tool allowlists, audit trail; HITL only for irreversible | "MCP gateway should own server discovery/auth, tool allowlists and the audit trail of what ran." | https://www.reddit.com/r/mcp/comments/1wc20jx/comment/p8upc14/ | +| 14 | r/mcp comment (thread #12) | 2026-09-10 | 1 | u/Basic-Let6828 (sealgate) · VENDOR | Lists SIEM integration as a distinct MCP-gateway job | "c) Integrations with traditional stack (SIEM, etc) d) auth, RBAC, user identity, IdP integrations" | https://www.reddit.com/r/mcp/comments/1wc20jx/comment/p8ylic4/ | +| 15 | r/mcp post | 2026-06-09 | 9 / 20 c | u/One_Camel_7885 · ASK | Open-source gateway for enterprise production; explicitly rejects paid | "Our team is currently exploring a good open source MCP gateway that is being used by organisations for production AI systems." / "currently we are not looking for any paid solutions" | https://www.reddit.com/r/mcp/comments/1u12f3w/ | +| 16 | r/mcp comment (thread #15) | 2026-06-11 | 2 | u/hirstys (Tyk) · VENDOR | Operational model: run as a normal service inside existing K8s/observability/CI; beware open-core paywalled governance | "Does it run as a normal service you can stick in your existing K8s/observability/CI setup, or does it want to own its own world? ... Also check whether it's actually open source or open-core with the governance bits paywalled" | https://www.reddit.com/r/mcp/comments/1u12f3w/comment/oqzwhhe/ | +| 17 | r/mcp comment (thread #15) | 2026-06-09 | 0 | u/Temporary_Bar9501 · ASK (eval checklist) | Transports, OIDC/service identities, per-tool RBAC, HITL/deny-by-default, tamper-evident audit export + SIEM, tool-drift handling, self-hosted/HA/K8s/secrets, fail-closed | "auditability: structured logs, tamper-evident/audit export, SIEM support ... deployment model: self-hosted, HA, Kubernetes, observability, secrets handling ... failure mode: fail-open vs fail-closed" | https://www.reddit.com/r/mcp/comments/1u12f3w/comment/oqmf637/ | +| 18 | r/mcp post | 2026-08-30 | 7 / 19 c | u/Signal-Zone-346 · ASK | Central registry + unified discovery/execution for a platform of agents | "need a centralized way to manage our mcp servers. the manual discovery process is a mess." — reply u/OkCobbler3306 (2): "i been rolling my own with a simple proxy that handles registration, but its not pretty" | https://www.reddit.com/r/mcp/comments/1w2ku89/ | +| 19 | r/mcp comment (thread #18) | 2026-08-31 | 1 | u/EbbCommon9300 · ASK | Concrete demand list | "tool-level allow/deny (not just server-level) - credentials stay in the gateway; agents get a session, not GitHub/Jira/AWS tokens - per-call audit (who, which tool, decision, receipt you can keep) - one place to register/retire servers" | https://www.reddit.com/r/mcp/comments/1w2ku89/comment/p70ea30/ | +| 20 | r/mcp post | 2026-07-16 | 13 / 13 c | u/Background-Job-862 · ASK/BUILT (moved to TrueFoundry) | Proxy != gateway; audit attribution is the tipping point | "Where you actually need a gateway: more than one team touching the same servers, anything customer-facing or regulated, or the moment someone asks 'can you show me every time this tool was called and by whom' and you realize you can't." | https://www.reddit.com/r/mcp/comments/1uye015/ | +| 21 | r/mcp post | 2026-07-21 | 4 / 2 c | u/Background-Job-862 · ASK | SOC 2 audit trail; genuinely self-hosted/hybrid option; notes ContextForge = "you're operating it, no managed compliance story" | "soc 2 audit trail requirements pushed us to look at managed options instead of rolling our own" / "we needed a genuinely self-hosted/hybrid deployment option rather than only a managed saas path" | https://www.reddit.com/r/mcp/comments/1v2r919/ | +| 22 | r/mcp comment (thread #20) | 2026-07-17 | 1 | u/zecureit · ASK (20 yrs regulated) | Security approves a *pattern* (authz model, audit schema, data classes, egress rules); risk-tier tools; stable audit schema | "get security to approve patterns, not integrations." / "risk-tier the tools, not the servers. Read-only on non-sensitive data = fast lane, self-service. Writes or anything touching personal data = full review." | https://www.reddit.com/r/mcp/comments/1uye015/comment/oy21g3f/ | +| 23 | r/ClaudeAI post | 2026-03-26 | 8 / 7 c | u/MittnzZ (IT admin, 75 users) · ASK | Admin panel, permissions, user groups for connectors/MCP/skills; expose internal n8n only | "What's the best solution for managing connectors, MCP, skills, etc. from an 'organizational' perspective? (E.g. an admin panel, permissions, user groups, etc.). I am sure this exists, I just don't know how to find it." | https://www.reddit.com/r/ClaudeAI/comments/1s3yux5/ | +| 24 | r/mcp post | 2025-08-03 | 23 / 36 c | u/Ankit_at_Tripock · VENDOR (Oppie) | Creds off laptops (IT blocked plaintext tokens), non-devs can't edit JSON, per-user instances too costly | "IT took one look at my `claude_desktop_config.json` and said no. Fair point - I was asking people to put GitHub tokens, database passwords, and AWS keys in plaintext files. On every laptop." — top reply (23) u/nore_se_kra: "This is really one of the most stupid ads ive ever seen"; u/tshawkins (3): "Most enterprise security teams would have kittens if they where asked to sign off on a system that did not include robust secrets management." | https://www.reddit.com/r/mcp/comments/1mgrhfa/ | +| 25 | r/mcp post | 2025-08-08 | 7 / 4 c | u/ChoccyPoptart · VENDOR (proposal) | Control plane for Docker MCP Gateways: SSO/OIDC, SCIM, RBAC, OPA policy packs, KMS secrets, SOC2/ISO audit export, Prometheus/Grafana, Terraform/Helm | "Would you self-host this, or only consider a SaaS?" — reply u/an-irish-pretzel: "Self hosted, SaaS is still proving to be a hard sell or non-starter for several compliance use cases." | https://www.reddit.com/r/mcp/comments/1ml8nqp/ | +| 26 | r/mcp post | 2026-08-05 | 3 / 3 c | u/dtembe · ASK (homelab) | Self-hosted web UI that owns server *lifecycle* (catalog, one-step install, upgrade notices, secrets editing, logs, single endpoint); ContextForge doesn't | "It is amazing as a Agent Control Plane ... But it assumes the MCP servers already exist and are running. It does not install them, does not upgrade them, and does not own their lifecycle." | https://www.reddit.com/r/mcp/comments/1vgcrrx/ | +| 27 | r/mcp comment | 2026-08-15 | 3 | u/Neither_Event4902 · ASK | Server-side credential broker; short-lived session token on client; per-request injection; audit line | "Broker pattern: the client holds one short-lived session token; a server-side broker holds the provider creds, does OAuth refresh, injects per request, scopes per tool call, and writes the audit line." | https://www.reddit.com/r/mcp/comments/1voezx0/comment/p3r541p/ | +| 28 | r/mcp post | 2026-08-22 | 2 / 15 c | u/GothamGiver · ASK | Enterprise MCP proxy for long-running tools + traffic observability | "we need a proxy that can handle long running tool executions and provide better observability into the mcp traffic" — reply u/Available_Teaching83 (2): "that is also the only sane place to put an egress allowlist and per-tool auth, and retrofitting that later is painful." | https://www.reddit.com/r/mcp/comments/1vv5lk3/ | +| 29 | r/mcp post | 2026-05-04 | 9 / 24 c | u/tomerlrn · BUILT/VENDOR | Centralize OAuth once; credential injection at dispatch; per-user revocation, rate limiting, audit; stdio is dev-only | "If you're building multiple MCP servers, do NOT implement OAuth in each one. Centralize it." / "Benefits: per-user revocation ..., per-user rate limiting, audit trail of who called what, credential rotation without touching client configs." | https://www.reddit.com/r/mcp/comments/1t3uiwk/ | +| 30 | r/mcp post | 2026-07-18 | 4 / 4 c | u/awca22 · BUILT | Enterprise IdPs (Entra/Okta/Cognito) refuse DCR -> built OAuth bridge in front of MCP server | "most identity providers don't expose one, and that is on purpose: Entra, Okta and Cognito all work on the model that an admin approves every app, nothing self-registers." | https://www.reddit.com/r/mcp/comments/1uzj182/ | +| 31 | r/ClaudeAI post | 2026-07-19 | 2 / 5 c | u/mr---fox · ASK/BUILT | One MCP bridge outside agent sandboxes with per-agent, per-resource permissions | "dynamically assign permissions to agents to MCP tools and resources ... I started building my own, but I'm thinking there's gotta be something already built for this." | https://www.reddit.com/r/ClaudeAI/comments/1v100vf/ | +| 32 | r/mcp post | 2026-07-25 | 32 / 16 c | u/Nearby_Pair_6483 · ASK (independent comparison of 11) | Gap statement; distrust of vendor rankings | "You can plug an AI agent into ten tools and still have no consistent record of who's allowed to do what, no way to see what actually happened after the fact, and no protection if one of those tools turns out to be lying to your AI. That's the gap a gateway sits in." | https://www.reddit.com/r/mcp/comments/1v5xegm/ | +| 33 | r/mcp post | 2026-07-03 | 3 / 7 c | u/SmartWeb2711 · ASK | Multi-tenant tool access control; stateless HTTP | reply u/elef_in_tech: "Separate private networks with scoped secrets make isolation structural instead of something you enforce in app logic." | https://www.reddit.com/r/mcp/comments/1umdbk8/ | +| 34 | r/mcp post | 2026-06-03 | 2 / 5 c | u/MainInteresting5035 · ASK | Hosts honoring the MCP Registry standard; only enterprise tiers do | "The only two which I found were GitHub CoPilot and Kiro in their enterprise tiers. I expected to find many more." | https://www.reddit.com/r/mcp/comments/1tvt0n0/ | +| 35 | HN comment ("MCP is dead?", 400 pts) | 2026-05-30 | - | CharlieDigital · ASK | Keys never seen by dev or agent; one entry point; revoke on offboarding; org-wide templated prompts | "An enterprise has 20 services that each have a secret key (Datadog, Snowflake, etc). ... Put it behind MCP; neither dev nor agent ever sees the key. If developer leaves, revoke one OAuth cred." | https://news.ycombinator.com/item?id=48334918 | +| 36 | HN comment (same thread) | 2026-05-30 | - | zimbatm · ASK | Central MCP backbone with policy + activity log | "For an enterprise-level deployment, it becomes quickly desirable to have a centralized MCP backbone, on which each MCP is attached to. A place you can attach policies to, log activity, and reason about access control." | https://news.ycombinator.com/item?id=48335626 | +| 37 | HN comment (same thread) | 2026-05-30 | - | charrondev · ASK | IT-configured org MCP, OIDC, non-technical users log in as themselves | "You can have your IT department configure an MCP for the org, and your regular non-technical users click a button and login with their account the service. Then they get all the tool calls authenticated as themselves." | https://news.ycombinator.com/item?id=48333218 | +| 38 | HN comment (same thread) | 2026-05-30 | - | notatoad · ASK | Push updates to 300 employees | "if you have 300 employees using ai and you want to share a skill with all of them, and you want to be able to push an update to the skill, mcp provides you with a standard way to do that." | https://news.ycombinator.com/item?id=48331911 | +| 39 | HN comment ("Ask HN: Who is using MCP in production?", 198 pts) | 2026-09-04 | - | hhh · BUILT (agentgateway) | Authorize individual outbound calls from a sandbox | "it all gets accessed thru agentgateway. I don't really like having to use MCP but we don't have a good solution for authorizing individual calls outbound from a sandbox without choosing to just not care about the sandbox." | https://news.ycombinator.com/item?id=49560834 | +| 40 | HN comment (same thread) | 2026-09-04 | - | rcarmo · ASK (works w/ corporates) | MCP as the API-management/audit layer | "it has become (literally) the new API management layer, to isolate and audit connections between systems and prevent people from developing random API clients." | https://news.ycombinator.com/item?id=49561409 | +| 41 | HN comment ("Zero-Touch OAuth for MCP", 278 pts) | 2026-06-18 | - | maxwellg · ASK | IT, not the employee, decides which MCPs may be linked | "As an employee at Acme, I shouldn't decide to link my Acme Google Drive data to Claude or ChatGPT, that should be the decision of my IT Department" | https://news.ycombinator.com/item?id=48593091 | +| 42 | HN comment (same thread) | 2026-06-18 | - | ericchiang · ASK | Central policy over scopes, expiry, device binding | "So instead, you can run centralized infra to validate a user, device, what scopes their requesting and duration, and enforce policies for all your apps?" | https://news.ycombinator.com/item?id=48593179 | +| 43 | HN comment (same thread) | 2026-06-19 | - | programmancer / erebe__ · BUILT | Entra ID has no DCR; proxy the OAuth flow and inject a fixed client_id | erebe__: "we weren't willing to enable DCR. What we ended up doing, was the app proxying the OAuth flow, to inject a hardcoded client_id." | https://news.ycombinator.com/item?id=48596439 | +| 44 | HN comment ("5 Knights of the MCP Apocalypse") | 2026-01-07 | - | zingababba · ASK (evaluating) | Registry/gateway + endpoint enforcement so users can't bypass the org gateway | "MCP registry/gateway, everything kind of sucks at the moment. The other problem is unless you have an extremely good enterprise endpoint approach nothing is going to stop users from not using your orgs MCP gateway." | https://news.ycombinator.com/item?id=46526143 | +| 45 | HN comment (same thread) | 2026-01-07 | - | epec254 · ASK | Gateway in front of every company MCP for PII / prompt-injection checks | "putting a proxy/gateway in front of every MCP used by their company to 'guardrail' data that goes in and out eg checks for sensitive PII, prompt infection, etc?" | https://news.ycombinator.com/item?id=46523621 | +| 46 | HN comment ("The State of MCP Security [pdf]") | 2026-07-12 | - | shitloadofbooks · BUILT | FastMCP proxy behind Entra OAuth, CEL per-tool RBAC, **Helm chart**; distrust of open-core | "so I slopped together an MCP Proxy that uses FastMCP to proxy a list of upstream MCPs behind Entra oauth, with CEL-expressions for per-tool RBAC. ... (3 shot if you count a second prompt to generate the Helm Chart and docs site)" | https://news.ycombinator.com/item?id=48885712 | +| 47 | HN comment (IBM ContextForge, 73 pts) | 2025-08-25 | - | theshrike79 · ASK | Company-level single MCP, central add | "Everyone installs this gateway as their only 'MCP', then at a central location we can add different MCP tools and everyone automatically gains access to them." | https://news.ycombinator.com/item?id=45012257 | +| 48 | HN comment (same thread) | 2025-08-25 | - | qwertox · ASK (skeptic) | Production-ready multi-tenant | quoting IBM's README: "Many of the features required for secure, large-scale, or multi-tenant production deployments are still on the project roadmap" | https://news.ycombinator.com/item?id=45012279 | +| 49 | HN comment (TrueFoundry MCP Gateway) | 2025-12-03 | - | deeptishukla22 · ASK | Auth propagation: short-lived M2M tokens, per-request user metadata, Okta validation | "As soon as the agent backend invokes the MCP server instead of the client, the original user's auth context disappears ... Consistent OAuth2 / Okta validation so both layers trust each other" | https://news.ycombinator.com/item?id=46136355 | +| 50 | HN comment (Armour stdio proxy) | 2026-01-22 | - | kxbnb (keypost) · VENDOR | In-path rate limits, cost caps, argument-level rules | "'can use github.delete but only on branches matching feature-*, and only 3x per hour'" | https://news.ycombinator.com/item?id=46720467 | +| 51 | HN comment (HyprMCP, 59 pts) | 2025-10-09 | - | frumplestlatz · ASK (warning) | Log retention / PII policy for gateway logs | "I would be extremely cautious about what you log from LLMs in a cloud MCP server, who you make those logs available to, data retention policies, etc. They are going to be a PII landmine." (HyprMCP reply: "We'd love to allow orgs to bring their own IdP") | https://news.ycombinator.com/item?id=45523623 | +| 52 | HN comment (mcpsnoop, 64 pts) | 2026-07-04 | - | geraldsterling · ASK | Redaction config for traces | "Would a simple redact config make sense, like keys/patterns to scrub before writing traces?" | https://news.ycombinator.com/item?id=48786304 | +| 53 | HN comment (MCP Security 30 CVEs) | 2026-03-26 | - | salterisp · BUILT (OSS) | OAuth 2.1 + Entra SSO + per-tool RBAC + audit, Docker self-host | "OAuth 2.1 + PKCE, Microsoft Entra SSO, per-tool RBAC, full audit trail on every tool call. The gateway sits in front of your tools so auth and access control are solved once at the platform level rather than per-server. Self-hostable with Docker." | https://news.ycombinator.com/item?id=47528513 | +| 54 | HN comment (Nvidia/Meta open-weights) | 2026-07-24 | - | thewebguyd · ASK | Per-user (not global) MCP permissions in Claude Team | "Claude Team w/ Cowork still only lets you set R/W permissions globally for each MCP connector for the whole team, they still don't offer config on a per-user basis. The enterprise controls are sorely lacking first party." | https://news.ycombinator.com/item?id=49041266 | +| 55 | HN comment (New MCP Roadmap) | 2026-08-22 | - | dayjah · ASK | Workload identity for headless agents, no service-account sprawl, "who" for compliance | "we don't want Service Accounts everywhere because we need to be able to answer 'who' a lot for compliance reasons." | https://news.ycombinator.com/item?id=49400716 | +| 56 | HN comment (Apideck CLI) | 2026-03-18 | - | dtraub · ASK | Central credential management for teams/contractors | "Both work until a contractor leaves and their laptop still has active keys for your repos, your internal docs, and your CRM." | https://news.ycombinator.com/item?id=47427945 | +| 57 | HN comment (Ask HN middleware hooks) | 2026-06-26 | - | pradeep1177 · ASK | Central PII scrubbing before LLM; hooks don't scale across many devs | "how could I scrub the customer data, like name, domain, etc., before sending it to LLM ... hooks are nice, but they are messy to manage/operate for many developers at a time." | https://news.ycombinator.com/item?id=48684149 | +| 58 | HN comment (MCP Won't Solve Enterprise) | 2026-03-10 | - | brianwmunz · ASK | Middleware: OAuth flows, token refresh, rate limiting, per-user schema mapping | "you still need something managing OAuth flows, token refresh, rate limiting, schema mapping per user etc... all the operational stuff." | https://news.ycombinator.com/item?id=47318570 | +| 59 | HN comment (MCP Servers are the new npm) | 2026-03-02 | - | duncankrebs · ASK | Registry linked to LDAP groups, schema validation, audit | "registries of MCP servers ... links MCP servers to LDAP groups and then ... validates its schema contract, audits it and sends the response back." | https://news.ycombinator.com/item?id=47217840 | +| 60 | HN comment (Obot launch) | 2025-08-23 | - | smw355 · VENDOR (OSS on K8s) | Catalog, access control (Google/GitHub/Okta/Entra), audit logs, runtime hosting | "runs on Kubernetes, and is basically a control plane ...: catalog, access control (Google, GitHub Okta, Entra), audit logs, proxy, and the runtime to host the MCPs for users." | https://news.ycombinator.com/item?id=45000006 | +| 61 | HN comment (Go MCP Gateway launch) | 2025-07-26 | - | mholleville · BUILT (OSS, Go) | OAuth2/JWT, fine-grained perms, rate-limiting, **Prometheus metrics** | "Add OAuth2 / JWT auth, fine-grained permissions and (soon) rate-limiting - Built-in Prometheus metrics, structured logs" | https://news.ycombinator.com/item?id=44693739 | +| 62 | HN comment (MCP Defender) | 2025-05-31 | - | meander_water · ASK | Explicit AuthZ policy (Cedar) at a proxy, not LLM-judged security | "the right way to do this is to enforce permissions explicitly through a AuthZ policy. ... All MCP comms from client to server go through an SSE proxy which has AuthN and AuthZ enabled." | https://news.ycombinator.com/item?id=44142455 | +| 63 | HN comment (Windows MCP) | 2025-05-19 | - | JSR_FDED · ASK | Open-source alternative to Windows' centralized MCP policy proxy | "'All MCP client-server interactions are routed through a trusted Windows proxy, enabling centralized enforcement of policies and consent.' ... Hope we get an open source alternative." | https://news.ycombinator.com/item?id=44035453 | +| 64 | HN comment (Chrome DevTools MCP) | 2026-03-15 | - | Torn · ASK | Names MCP's remaining moats | "Multi-tenant auth (many users, dynamic OAuth) - Security sandboxing (restrict what agents can do), credential sandboxing (agents never see secrets)" | https://news.ycombinator.com/item?id=47392518 | +| 65 | HN comment (Claw Patrol, 112 pts) | 2026-06-11 | - | rough-sea (Deno) · BUILT | Wire-level policy because agents route around MCP | "imagine an engineer uses claude to debug an issue, it spawns psql directly, routing around MCP. Wire level interception is the only place a process tree can't escape." | https://news.ycombinator.com/item?id=48497055 | + +--- + +## 3. Frequency tally of requested capabilities + +Counted over the 65 signals above plus the rest of the read comment trees (a signal can count in several rows). "Explicit asks" = someone without a product to sell described needing it. + +| capability | explicit asks | built-it-themselves | vendor pitches | notes | +|---|---|---|---|---| +| **SSO / OIDC / corporate IdP login (Okta, Entra/Azure AD, Keycloak) + group-based access** | 14 | 9 | 8 | The single most common item. Entra-no-DCR is a recurring wall (#30, #43, HN hobofan 48595517). | +| **Per-call audit log with user attribution (SOC 2 / ISO / SOX / PCI)** | 13 | 6 | 7 | "who called what, when" is the stated tipping point from proxy to gateway (#20). Tamper-evident/hash-chained log asked twice (#17, r/ClaudeAI u/Useful_Journalist). | +| **Credentials never on the laptop / credential broker / vault-backed injection** | 12 | 5 | 6 | Named stores: HashiCorp Vault, Infisical, OpenBao, 1Password, AWS SSM, KMS. Nobody asked for a specific Vault *plugin*; they asked that the gateway hold creds and agents get sessions. | +| **Per-tool allow/deny / RBAC (vs per-server)** | 10 | 5 | 6 | Split opinion: #9 and #8 say start per-server, per-tool "can quietly kill adoption"; #11 and #19 say tool-level is mandatory. | +| **Central catalog / registry / "one endpoint, add servers centrally"** | 9 | 4 | 5 | Plus "MCP Registry standard support" (#34). | +| **Kubernetes deployment** | 6 | 6 | 4 | Helm chart explicitly: 3 (#46 generated one, #25 offers Terraform/Helm, agentic-community/mcp-gateway-registry ships one). K8s is assumed by platform teams (#7, #3, r/mcp u/neeltom92, u/mikelevan), not requested as a feature. | +| **Rate limits / quotas / cost caps** | 5 | 2 | 4 | Mostly vendor lists; one real ask for "3x per hour" style rules (#50). | +| **PII / DLP scrubbing, prompt-injection guard, redaction of traces** | 5 | 1 | 4 | #45, #52, #57, #51 (retention). | +| **Observability / metrics export (Prometheus, OTel, logs shipping)** | 4 | 2 | 4 | Prometheus named twice (#25, #61). One user ships gateway logs hourly to a CRM (r/mcp u/loveheaddit). OTel appears mostly in vendor copy. | +| **HITL approval for destructive/irreversible tools** | 4 | 2 | 6 | Strong vendor supply (Preloop, Cordon, Claw Patrol, Peta). | +| **Multi-tenancy** | 3 | 2 | 5 | #33, #48 (IBM not multi-tenant ready), #29. | +| **Self-hosted (not SaaS) as a hard requirement** | 6 | - | - | #15 ("not looking for any paid solutions"), #21, #25 reply, #26, HN freedomben 47737901 ("ship your production logs to a third party ... complete no-go for any compliance scenario"). | +| **Server lifecycle management (install/upgrade/health in a UI)** | 2 | - | 1 | #26 - a gap even ContextForge leaves. | +| **Long-running tools / timeouts (MCP Tasks)** | 1 | - | 1 | #28. | +| **SIEM / Splunk / Datadog export** | 1 (checklist item #17) | 0 | 1 (#14) | Datadog appears only as an *upstream* MCP target, never as an audit sink. | +| **Air-gapped install** | **0** | 0 | 0 | Query made: HN comments "MCP air-gapped" (20 hits, 0 relevant); Reddit posts/comments regex `air.?gap` over ~600 posts + ~450 comments: 1 post (unrelated). | +| **Endpoint enforcement so users can't bypass the org gateway** | 2 | - | 1 | #44, Harmonic pitch in thread #18. | +| **Tool drift / rug-pull re-consent after tools/list changes** | 3 | - | 2 | #17, r/mcp u/GodoPPL ("Surface drift is re-consent, not a silent continue"), #32. | + +--- + +## 4. Counter-signals (don't need / don't want a central gateway, or prefer vendor/first-party) + +| source | date | who | quote | URL | +|---|---|---|---|---| +| HN (IBM ContextForge) | 2025-08-25 | GloriousMEEPT | "I just spin up oauth2proxy to handle authentication with istio gateway. Maybe I should be deploying piles of unknown code instead?" (rebutted by pmig: oauth2proxy lacks DCR) | https://news.ycombinator.com/item?id=45012530 | +| HN (same) | 2025-08-25 | fullstackwife | "For many years we were fine with running DLLs, Java .class deps, npm modules, brew packages etc. why do you think we need so much isolation for left-pad class mcp tools?" | https://news.ycombinator.com/item?id=45011483 | +| HN (same) | 2025-08-26 | CuriouslyC | "I'm not sure a MCP manager has got quite the scope for a SAAS offering, at least not if you're just managing config. There might be a play at the enterprise level if you can integrate deeply with domain policy." | https://news.ycombinator.com/item?id=45028027 | +| HN (OneCLI, 110 pts) | 2026-07-23 | notaharvardmba | "oauth, saml, oidc accomplish the same thing in a way more mature way, so if you're already using SSO just do that instead of adding another point of failure.." | https://news.ycombinator.com/item?id=49025174 | +| HN (same) | 2026-07-23 | oliver236 | "why not just use 1password" | https://news.ycombinator.com/item?id=49027217 | +| HN ("MCP is dead?") | 2026-05-30 | octoberfranklin | "Access control is the operating system's job ... Just use the existing sandboxing infrastructure like bubblewrap, seccomp, etc. I have way more faith in that than in something than some regex-based blocklist." | https://news.ycombinator.com/item?id=48338689 | +| HN (same) | 2026-05-30 | dropofwill | "Just use scopes in the API key the agent uses? ... That's how I use gh, aws, etc." | https://news.ycombinator.com/item?id=48337009 | +| HN (Ask HN prod) | 2026-09-04 | flanked-evergl | "I use almost no MCPs and feel like I'm not missing out on anything, I just use APIs directly or CLIs." | https://news.ycombinator.com/item?id=49562489 | +| HN (Claw Patrol) | 2026-06-12 | oulipo2 | "agents are good at circumventing stuff ('oh, I cannot DROP table, let me just remove all rows', etc). So I'd rather trust the permissions of the original db (eg getting a read-only account)" | https://news.ycombinator.com/item?id=48501865 | +| HN (Zero-Touch OAuth) | 2026-06-19 | ashu1461 | "Looks like something which will be only helpful for bigger companies who have centralised auth." | https://news.ycombinator.com/item?id=48597345 | +| HN (Ask HN prod) | 2026-09-04 | cjonas | MCP-as-gateway "could have been built using open-api" | https://news.ycombinator.com/item?id=49561005 | +| r/mcp (thread #1) | 2026-09-02 | u/Think-Sense9191 (1) | "MCP, MCP I honestly think the AI companies adding more complexity to our flows. You really don't need MCP" | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7dc77x/ | +| r/mcp (thread #1) | 2026-09-02 | u/xFloaty (2) | "I'm not sure why others are overcomplicating it, it's a web server just like any other and this is the best solution if your org has access to k8s and okta." (i.e. no dedicated gateway product needed) | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7bknz5/ | +| r/mcp (Oppie thread) | 2025-08-03 | u/tibbon (11) | "Why not just keep credentials in 1Password and use the cli to access them as needed?" | https://www.reddit.com/r/mcp/comments/1mgrhfa/comment/n6qqmnv/ | +| r/mcp (thread #1) | 2026-09-03 | u/itcadence (1) | Prefers managed vendor: "MintMCP has worked well for us doing the proxy to remote MCPs or hosting them for us. They have SOC 2 Type II." | https://www.reddit.com/r/mcp/comments/1w4oiiv/comment/p7hibim/ | +| r/mcp (#21) | 2026-07-21 | u/Background-Job-862 | Chose managed over OSS because "soc 2 audit trail requirements pushed us to look at managed options instead of rolling our own" | https://www.reddit.com/r/mcp/comments/1v2r919/ | +| HN (Zero-Touch OAuth, 278 pts) | 2026-06-18 | dend (Anthropic) et al. | First-party absorption: Enterprise-Managed Authorization (XAA / ID-JAG) with Okta, Entra in progress - removes the "OAuth relay" part of the gateway value prop for Claude clients | https://news.ycombinator.com/item?id=48593218 | +| HN (IBM thread) | 2025-08-25 | BoredPositron / thecopy | Market saturation: "probably a million people are building the exact same software at the moment" / "im starting to worry its hard to compete with Docker, Microsoft, now IBM..." | https://news.ycombinator.com/item?id=45012150 | + +Pattern in the counter-signals: nobody argues *against central control*; they argue the control should live in existing primitives (IdP scopes, DB roles, OS sandbox, oauth2proxy/istio, 1Password) or in a first-party vendor with a SOC 2 report. The "just use oauth2proxy" line was rebutted in-thread by the DCR problem, which several builders (#30, #43) confirm. + +--- + +## 5. What the HN/Reddit crowd actually wants from a server-side MCP gateway + +1. **The "boring" trio: SSO/IdP login, group-based access, per-call audit with user attribution.** This exact phrasing (#1, 41 pts) is the demand-side canonical post, and every practitioner reply (VMs+systemd, EKS+Okta, CERN+LiteLLM, managed gateway+Entra) converges on it. Compliance language (SOC 2, ISO, SOX ITGC, PCI 7.x, non-repudiation on writes) is what turns "nice" into "required". +2. **Credentials off the endpoint, agents get sessions.** The credential-broker pattern (short-lived session token on the client, gateway holds/refreshes upstream creds, injects per request, writes the audit line) is asked for in near-identical words on both sites. People name Vault/Infisical/OpenBao/1Password as *where creds live*, but the ask is the broker behavior, not a specific integration. +3. **Self-hosted, open-source, runs as a normal service in existing K8s + observability, and not open-core-with-governance-paywalled.** Explicit "not paid", "SaaS is a non-starter for compliance", "logs to a third party = no-go", and "check whether the governance bits are paywalled". Helm/Prometheus are assumed table stakes for platform teams rather than headline asks (Helm: 3 mentions, one user had an LLM generate his own chart). +4. **Tool-level policy with a pragmatic default: per-server first, per-tool for mixed-risk servers, deny/HITL for destructive tools, re-consent on tool drift.** Both "per-tool is mandatory" and "per-tool kills adoption" camps exist; the synthesis people describe is risk-tiering tools (read-only fast lane) and treating a changed `tools/list` as a re-approval event - directly adjacent to MCPProxy's Spec-032 quarantine. +5. **Almost no demand for SIEM/Splunk/Datadog exporters, air-gapped installs, or quotas as headline features** - they show up only in vendor checklists (SIEM: 2 mentions, air-gap: 0). What people do ask for around logging is redaction/retention policy for the gateway's own logs (PII landmine) and a stable, boring audit schema security can approve once. Two real gaps nobody serves well: server *lifecycle* (install/upgrade/health UI - ContextForge explicitly doesn't) and the Entra/Okta-refuse-DCR wall that every self-hoster hits and re-solves by proxying the OAuth flow with a fixed client_id. + +Cross-cutting: there is no organic mention of mcpproxy-go on HN or Reddit in these lanes. The gateway supply side is saturated (~60 Show HN launches, most <10 pts); the demand side is concentrated in a handful of high-engagement threads (#1, "MCP is dead?", Zero-Touch OAuth, Ask HN production) where practitioners describe running boring infra, not buying gateways. + +--- + +## Raw data +`scratchpad/raw/`: `hn_*.json` (story searches), `hnc_*.json` (comment searches), `item_*.json` (HN trees), `hn_comments_flat*.tsv`, `hn_comment_search.tsv`, `rp_*.json` (Arctic Shift post searches), `rc_*.json` (Arctic Shift comment trees), `reddit_all_posts.json`, `reddit_counts2.txt`. diff --git a/docs/research/server-edition-2026-09-14/evidence/internal-inventory.md b/docs/research/server-edition-2026-09-14/evidence/internal-inventory.md new file mode 100644 index 000000000..af28dfb16 --- /dev/null +++ b/docs/research/server-edition-2026-09-14/evidence/internal-inventory.md @@ -0,0 +1,325 @@ +# MCPProxy Server Edition — Internal Inventory (code + docs + telemetry) + +Collected 2026-09-14 from worktree `claude/server-edition-research-993367` (HEAD b39800a89) and Cloudflare D1 `mcpproxy-telemetry`. Read-only; nothing in the repo was modified. File paths are relative to the repo root; line numbers are from this HEAD. + +--- + +## 0. TL;DR + +- **Server edition = one Go build tag (`server`) adding ~8.6k LOC under `internal/serveredition/`** (8,588 non-test lines). What is *wired* today: Google/GitHub/Microsoft OAuth login, BBolt user+session store, HS256 JWT bearer, per-user agent tokens with tenant identity, admin REST (users/sessions/activity/servers/tokens), per-user personal-server CRUD records, an AES-256-GCM credential store + per-user OAuth "connect" flow with an audit sink into the activity log, and a Vue `views/teams/*` UI. +- What is **built but NOT wired** (latent, by the code's own comments): the multi-user MCP `Router`/`ToolFilter`, the `workspace.Manager` (personal servers are never *connected* — they are DB records reachable only via REST), and the whole credential-injection chain (`CredentialResolver`, `TokenExchanger` RFC 8693/Entra OBO, `HeaderInjector` → `Client.SetBrokeredAuth` has **zero production callers**). The docs (`docs/cli/credential-commands.md`) say "the proxy injects it at call time" — the transport supports it, nothing calls it. +- **Distribution**: the *only* server-edition artifact is the Docker image `ghcr.io/smart-mcp-proxy/mcpproxy-server` (public; tags `latest`, `v0.66.0`, `v0.66.1` — re-enabled 2026-09-12 via #1208 after external user #1171 asked). The `.deb`/`.rpm`/tar.gz are the **personal** edition (`matrix.edition != 'server'`; the server matrix entries are commented out). CLAUDE.md's "Docker image, .deb, Linux tar.gz" row is aspirational. +- **Ops surface is edition-neutral and decent**: `/healthz` `/readyz` `/livez`, Prometheus `/metrics` (25 `mcpproxy_*` series, opt-in), OTLP traces (http/grpc, opt-in; server edition adds `user_id`/`profile` span attrs), zap JSON logging, lumberjack rotation, systemd hardening unit, SIGTERM-graceful shutdown with Docker-child cleanup. Missing: syslog/log shipping, SIEM push, audit-log export beyond `GET /api/v1/activity/export`, external secret managers, per-tenant quotas/rate limits, HA. +- **Telemetry demand signal is tiny and pre-dates the public image**: 46 server-edition anonymous_ids ever, but only **9 distinct IPs / 3 countries** — realistically ~4–5 self-built deployments, 2 active in the last 30 days (8 installs/30d after CI filter vs 608 personal). Zero payload fields for multiuser/users/OAuth-provider exist, so "is multi-user actually on?" is **unmeasurable** today. The much bigger signal: **362 personal-edition installs (86 IPs) ran inside containers in 90d, 113 of them long-lived (≥24h uptime)** — ~10x the server-edition operator base runs the *personal* binary as a container/headless service. + +--- + +## 1. Capability matrix + +Status legend: **shipped** = wired end-to-end in production build; **partial** = code exists but not wired / gaps; **missing** = nothing in repo. + +### 1a. Identity, sessions, tokens + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| OAuth login: Google | shipped | `internal/serveredition/auth/oauth_providers.go:66-80` | OIDC+PKCE; `access_type=offline` when `store_idp_tokens` | +| OAuth login: GitHub | shipped | `oauth_providers.go:82-93` | No OIDC, no PKCE; primary-email fetch via `/user/emails` | +| OAuth login: Microsoft/Entra | shipped | `oauth_providers.go:95-112` | `tenant_id` (default `common`); `offline_access` scope | +| **Generic OIDC (Okta/Keycloak/Auth0)** | **missing** | `oauth_providers.go:60-64` registry has exactly 3 keys; `config/server_edition_config.go:64-67` validator rejects others | Spec 029 US1 scenario 6 promised "generic provider" — not built | +| SAML | missing | no hits | — | +| GitHub org / Google Workspace group gating | missing | only `allowed_domains` (`server_edition_config.go:31`) | Spec 029 US1 scenario 5 (GitHub org allowlist) not built | +| Email domain allowlist | shipped | `server_edition_config.go:31`, checked in `auth/oauth_handler.go` | — | +| Admin role | shipped (config-driven) | `server_edition_config.go:41-48` `IsAdminEmail`; hot-reloadable via `ServerEditionConfigProvider` (`setup.go:130-141`, fixes #1169) | Only two roles: admin / user. No RBAC beyond that | +| Session store | shipped | `auth/session_store.go` (cookie `mcpproxy_session`, HttpOnly, SameSite=Lax) on BBolt via `users/store.go` | **`Secure` flag hardcoded false** — `setup.go:115` `NewSessionManager(userStore, sessionTTL, false) // secure=false for localhost`. Behind an HTTPS reverse proxy the cookie is still sent without `Secure` | +| JWT bearer (user) | shipped | `auth/jwt_tokens.go:32-70` HS256, claims sub/email/display_name/role/provider/exp/iat/jti; key from `internal/auth/agent_token.go:134-160` (`/hmac.key`, generated if absent) | JWT only accepted by the server-edition REST middleware (`auth/middleware.go:182`); `/mcp` uses agent tokens | +| Agent tokens with tenant identity | shipped | `internal/auth/agent_token.go:45` `UserID`; owner gate + scope resolver installed first in `setup.go:47-100` (fail-closed) | Fixes #1168/#1169/#1179 landed 2026-09-01..02 | +| Token scope narrowed to entitlement | shipped | `api/user_handlers.go` `NarrowTokenServerScope` (via `setup.go:93`) | Snapshot at mint/auth time, not live per call (doc §"Scope is a snapshot") | +| Per-tenant token quota | **missing** | `internal/auth/agent_token.go:32` `MaxTokens = 100` global | Open issue **#1177** | +| Session revocation, user disable | shipped | admin routes below; `SetAgentTokenOwnerGate` | — | + +### 1b. Multi-tenancy / isolation + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| Shared (admin) servers visible to all users | shipped | `api/admin_handlers.go:119-123`, `SetServerShared` in `serveredition_wire.go:41` | `shared` flag on ServerConfig | +| Personal per-user servers (records) | partial | `api/user_handlers.go:112-117` CRUD into BBolt | **Never connected**: `workspace.NewManager` and `multiuser.NewRouter` have no production caller (`multiuser/router.go:42-56` "NOT YET WIRED … LATENT"; doc `docs/development/server-edition-multiuser-auth.md:243`) | +| Per-user MCP routing / tool filtering | partial | `multiuser/router.go`, `multiuser/tool_filter.go` exist; unused | Today isolation on `/mcp` rests **only** on agent-token `allowed_servers` scope | +| Per-user activity attribution | shipped | `storage/activity_models.go:237` `UserID`; `api/user_activity.go`, `multiuser/activity.go` | Admin sees all via `/admin/activity` | +| Per-user credential store (AES-256-GCM in BBolt) | shipped | `broker/bbolt_aes.go:55-94`; key = `MCPPROXY_CRED_KEY` env **or** `server_edition.credential_encryption_key` (`broker/credential_store.go:133-138`); base64 32 bytes; store silently *disabled* when absent | No KMS/keyring; key lives in env or config file | +| IdP subject-token capture at login | shipped (opt-in) | `store_idp_tokens` (`server_edition_config.go:23`), `docs/features/idp-token-storage.md` | Off by default | +| Per-user OAuth "connect" to upstream (Path B) | shipped | `api/credential_handlers.go:84-96` list/delete/connect/callback; `api/connector_provider.go` → `broker.NewOAuthConnector` | CLI `mcpproxy credential …` (`cmd/mcpproxy/credential_cmd.go`) | +| Token exchange (RFC 8693) / Entra OBO | partial | `broker/token_exchanger.go` complete; `NewTokenExchanger` has **no production caller** | — | +| **Injecting the brokered credential on upstream calls** | **partial/unwired** | transport supports it (`internal/transport/broker_auth.go`, `upstream/core/connection_http.go:21-44` fail-closed), but `Client.SetBrokeredAuth` (`connection_http.go:175`) and `broker.NewCredentialResolver` / `HeaderInjector` have **zero callers** outside tests | So "each user's own credential is used for the shared upstream" does not happen yet | +| Policy hook seam | partial | `broker/credential_resolver.go:101-122` `PolicyHook` (allow-all default) | Placeholder for OPA/etc. | +| Broker audit trail | shipped | `broker/audit.go` → `api/broker_audit.go:42-70` writes `ActivityTypeCredentialBroker` records via `SaveActivityAsync` | Lands in the same BBolt activity log; no external sink | +| Profiles (URL-scoped server subsets) | shipped (edition-neutral) | `config.go:255`, `docs/features/profiles.md` `/mcp/p/` | Not tied to users/teams | +| Teams / groups / org units | missing | `users/models.go` has User+Session only | Spec 029 "teams of 2-50" never got a Team entity | + +### 1c. Admin API (server edition, all under `/api/v1`, session-or-JWT auth, mounted outside the API-key group — `setup.go:209-216`) + +| Route | File | +|---|---| +| `GET /auth/login`, `GET /auth/callback` (public) | `setup.go:160-161` | +| `POST /auth/logout`, `GET /auth/me`, `POST /auth/token` | `setup.go:211`, `api/auth_endpoints.go:46-47` | +| `GET /admin/users`, `POST /admin/users/{id}/enable|disable` | `api/admin_handlers.go:113-115` | +| `GET /admin/tokens`, `POST /admin/users/{id}/tokens/revoke`, `POST /admin/users/{id}/tokens/{name}/revoke` | `admin_handlers.go:110-112` | +| `GET /admin/activity`, `GET /admin/sessions`, `GET /admin/dashboard` | `admin_handlers.go:116-118` | +| `GET /admin/servers`, `POST /admin/servers/{name}/shared|enable|disable|restart` | `admin_handlers.go:119-123` | +| `GET|POST /user/servers`, `GET|PUT|DELETE /user/servers/{name}`, `POST …/enable` | `api/user_handlers.go:112-117` | +| `GET|POST /user/tokens`, `DELETE /user/tokens/{name}[/permanent]`, `POST …/regenerate` | `user_handlers.go:120-124` | +| `GET /user/activity`, `GET /user/diagnostics` | `api/user_activity.go:43-44` | +| `GET /user/credentials`, `DELETE /user/credentials/{server}`, `GET …/{server}/connect|callback` | `api/credential_handlers.go:84-87` | + +Note (doc `server-edition-multiuser-auth.md:254`): these routes are invisible to `swag`/OAS coverage/CI lint because they need `-tags server`. Web UI: `frontend/src/views/teams/{Login,AdminDashboard,AdminUsers,AdminServers,UserServers,UserTokens,UserActivity,UserDiagnostics}.vue`. + +### 1d. Observability + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| Prometheus `/metrics` | shipped (opt-in `observability.metrics.enabled`) | `internal/observability/metrics.go`; mounted `httpapi/server.go:725`, `server/server.go:2422` | 25 series: `mcpproxy_tool_calls_total`, `_tool_call_duration_seconds`, `_tool_calls_rejected_total`, `_concurrency_active/_queue_depth`, `_servers_total/_connected/_quarantined`, `_tools_total`, `_index_documents_total`, `_oauth_refresh_*`, `_actor_*`, `_supervisor_*`, `_storage_operations_total`, `_docker_containers_active`, `_http_requests_total/_duration_seconds`, `_quarantine_events_total`, `_uptime_seconds`. **No per-user/tenant labels** (by design, cardinality) | +| Grafana dashboard | shipped | `contrib/grafana/mcpproxy-dashboard.json` | — | +| OpenTelemetry traces (OTLP http/grpc, sampling) | shipped (opt-in) | `observability/tracing.go`; `docs/features/observability.md:99-134` | Server edition adds `user_id` + `profile` span attributes (`server/observability_edition_server.go`) | +| OTel **metrics/logs** export | missing | only `otlptrace` exporters in `go.mod:35-39` | — | +| Structured JSON logs | shipped | `config.go:613` `logging.json_format`; zap | To file (lumberjack rotation `max_size/max_backups/max_age/compress`) and/or console | +| Log shipping (syslog, fluent, Loki push) | missing | no hits for syslog/otlplog | Container users rely on stdout scraping; `enable_console` must be on | +| Activity log (audit) storage | shipped | BBolt; retention `activity_retention_days=90`, `activity_max_records=100000`, `activity_max_size_mb` (`config.go:469-474`) | Single node, single file | +| Activity export API | shipped | `GET /api/v1/activity/export` (`httpapi/server.go:952`); CLI `mcpproxy activity export`; SIEM recipe in `docs/features/sensitive-data-detection.md:360` (pull-based curl loop) | No push/webhook/streaming sink | +| Health/readiness/liveness | shipped | `/healthz` `/readyz` `/livez` `/ready` `/health` (`httpapi/server.go:735-747`, unauthenticated list `server/server.go:2410`) | Fine for K8s probes | +| Request IDs | shipped | `X-Request-Id` on all responses (CLAUDE.md, activity `--request-id`) | — | + +### 1e. Secrets + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| `${env:VAR}` refs in config strings | shipped | `internal/secret/env_provider.go`; Spec 034 (17/17 tasks) expands in all string fields | — | +| `${keyring:NAME}` refs | shipped | `internal/secret/keyring_provider.go` (zalando/go-keyring) | **Useless in distroless/headless containers** — no D-Bus Secret Service; env is the only practical provider there | +| File-based secret refs (`${file:/run/secrets/x}`) | missing | only `env`/`keyring` registered in `secret/resolver.go:16` | K8s/Docker secrets have to be re-exported as env vars | +| Vault / AWS SM / GCP SM / 1Password / SOPS | missing | no hits in `go.mod`/`internal` | — | +| Credential encryption key sourcing | partial | env `MCPPROXY_CRED_KEY` or plaintext in config (`credential_store.go:133`) | No KMS envelope, no rotation tooling | +| OAuth client secret sourcing | partial | `server_edition.oauth.client_secret` in JSON; `${env:}` expansion applies | Fine for GitOps if `${env:}` used | +| Secret masking in API/logs | shipped | `reveal_secret_headers` admin-gated (#1167 fixed); sensitive-data detection | — | + +### 1f. Limits, quotas, resilience + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| Global concurrency cap + queue | shipped | `config.go:277-279` `max_concurrent_requests/queue_size/queue_timeout` (+ env); `runtime/concurrency_rejections.go`; #955 closed | Aggregate only | +| Per-server concurrency | shipped | `config.go:723-725`, `server_concurrency_defaults` | — | +| **Per-user / per-token rate limit or quota** | **missing** | no `rate`/`tollbooth`/`httprate` in `go.mod`; limiter is server-scoped | Nothing stops one tenant from consuming the whole queue | +| Per-tenant agent-token cap | missing | #1177 open | — | +| Personal-server count cap | shipped | `max_user_servers` (default 20) | Only meaningful once workspaces are wired | +| Graceful shutdown | shipped | `docs/operations/shutdown-behavior.md` (SIGTERM→9s→SIGKILL for children; Docker cleanup 30s; process groups) | Fits `docker stop`/K8s `terminationGracePeriodSeconds` ≥ 40s | +| TLS in-process, mTLS, HSTS | shipped | `config.go:589-592`, `MCPPROXY_TLS_ENABLED`, `MCPPROXY_CERTS_DIR` | Self-signed generation; no ACME | +| Reverse-proxy awareness | partial | `trusted_hosts` (`config.go:380`, `docs/operations/reverse-proxy.md`); `X-Forwarded-Proto` honoured only in `api/connector_provider.go:131` | No trusted-proxies / `X-Forwarded-For` real-IP handling for session `IPAddress` | + +### 1g. Deployment & configuration + +| Capability | Status | Evidence | Notes | +|---|---|---|---| +| Docker image (multi-arch amd64/arm64, distroless static) | shipped | `Dockerfile`; `release.yml:1232-1286` `build-docker` (stable tags only, gated on qa-gate) | Public on GHCR since v0.66.0 (2026-09-12). Only `latest`, `v0.66.0`, `v0.66.1` exist | +| Server-edition tarball | missing | `release.yml:232-247` matrix entries commented out "uncomment when server MVP is ready" | — | +| `.deb`/`.rpm` + systemd unit | shipped **(personal edition)** | `release.yml:755-759` `if: matrix.edition != 'server'`; `packaging/linux/nfpm.yaml`, `mcpproxy.service` (hardened: `ProtectSystem=strict`, `NoNewPrivileges`, `User=mcpproxy`) | There is no server-edition deb | +| Helm chart / K8s manifests / docker-compose | missing | only `bench/docker-compose.yml` (benchmark rig); grep of docs for kubernetes/helm hits only observability.md prose | — | +| Docs: Docker run | shipped | `docs/getting-started/installation.md:368-400` | Warns: mount at `/root/.mcpproxy`; do NOT use `MCPPROXY_DATA`/`--data-dir` in the container (config never read, API key rotates every boot); `MCPPROXY_DATA_DIR` "not implemented at all" | +| Docs: server_edition config | partial | `docs/development/server-edition-multiuser-auth.md`, `docs/features/idp-token-storage.md`, `docs/cli/credential-commands.md` | `docs/configuration.md` has **no** `server_edition` section (grep = 0 hits) | +| Env-var config | partial | viper `SetEnvPrefix("MCPP")`+`AutomaticEnv` (`config/loader.go:194-198`) for flat top-level keys; explicit `MCPPROXY_*`: `LISTEN, API_KEY, DATA, TLS_ENABLED, TLS_REQUIRE_CLIENT_CERT, CERTS_DIR, TRUSTED_HOSTS, MAX_CONCURRENT_REQUESTS, QUEUE_SIZE, QUEUE_TIMEOUT, HTTP_READ/WRITE/IDLE_TIMEOUT, TOOL_RESPONSE_MODE, DIRECT_TOOL_RESPONSE_MODE, TELEMETRY, DISABLE_AUTO_UPDATE, ALLOW_PRERELEASE_UPDATES, TPA_BUNDLE_PATH, AUTO_BASELINE_SCAN, CRED_KEY, HOME, DISABLE_OAUTH`, plus `HEADLESS` | Nested blocks (`server_edition.*`, `observability.*`, `mcpServers`) are **file-only**; use `${env:}` refs inside the JSON for secrets | +| Config fully file-driven (GitOps) | partial | JSON file + hot-reload file watcher | But the daemon **writes back** to the config file (auto-generated API key `main.go:611,648`, UI edits, quarantine state) — a read-only ConfigMap mount breaks the API-key bootstrap unless `MCPPROXY_API_KEY` is set | +| State/persistence | partial | `~/.mcpproxy/{config.db (BBolt), index.bleve/, hmac.key, logs/}`; `storage/bbolt.go:43` exclusive lock, 10s timeout, exit code 3 | **Single-writer, single-node.** Two replicas on one RWX volume = the second exits 3; two replicas on separate volumes = split users/sessions/tokens/activity. No HA story | +| Edition self-identification | shipped | `cmd/mcpproxy/edition.go` + `edition_teams.go`; `/api/v1/status.edition` (`httpapi/server.go:1174`); `mcpproxy version` | — | +| Telemetry reports edition | shipped | `telemetry.go:158` `Edition` column in D1 `heartbeats.edition` | **But no field for server_edition.enabled / user count / provider** (`feature_flags.go:14-43` has none) — adoption of multi-user is invisible | + +--- + +## 2. What a K8s/Docker operator hits on day 1 + +1. **State dir is `/root/.mcpproxy` and must be a volume** — config.db (BBolt), `index.bleve/`, `hmac.key` (JWT + agent-token HMAC — losing it invalidates every token), `logs/`. Docs explicitly say do not relocate with `MCPPROXY_DATA`/`--data-dir` because the config in the new dir is never read and the API key is regenerated each boot (`installation.md:386-390`). +2. **BBolt = single writer, exclusive file lock** (`storage/bbolt.go:43`, exit code 3). `replicas: 2` is not possible; rolling updates need `strategy: Recreate` or a 10s lock-wait race. No external DB option, no leader election. +3. **API key bootstrap**: if `MCPPROXY_API_KEY` is unset the daemon generates one, logs it at WARN with a banner (`main.go:591-600`) and **writes it into the config file** (`main.go:611`). With distroless there is **no shell** to `cat` the file — you read it from `kubectl logs` or set the env var up front (which the docs recipe does). +4. **No shell in the image** (`gcr.io/distroless/static-debian12`) — `mcpproxy doctor`, `mcpproxy upstream list` etc. must be run as `kubectl exec … mcpproxy ` (works since it is the same static binary) and `ENTRYPOINT` swallows subcommands (`docker run … version` needs `--entrypoint`, per memory note). No `npx`/`uvx`/`docker` inside → **stdio upstreams cannot run in the container**; only HTTP/SSE upstreams, or Docker-isolation via a mounted socket (which distroless cannot drive either — the `docker` CLI is absent). +5. **Config is JSON-file-only for the interesting blocks**: `server_edition.*`, `observability.*`, `mcpServers` cannot be set via env. A ConfigMap works, but must be writable (or the API key must come from env) because the daemon writes back. Secrets must be `${env:NAME}` refs — `${keyring:}` has no backend in a container and there is no `${file:}` for `/run/secrets`. +6. **Secrets at rest**: the per-user credential store needs `MCPPROXY_CRED_KEY` (base64 32 B) or it is *silently disabled* (`bbolt_aes.go:61-64` logs a WARN once). No KMS integration. +7. **Session cookie `Secure=false` is hardcoded** (`setup.go:115`) — behind an ingress with TLS this is a finding an auditor will flag. `trusted_hosts` must list the public hostname (`docs/operations/reverse-proxy.md`). `X-Forwarded-For` is not used for session IPs. +8. **Health probes exist and are unauthenticated** (`/healthz`, `/readyz`, `/livez`) — good. `/metrics` is on the same listener, unauthenticated like `/mcp` — needs a NetworkPolicy or sidecar. +9. **Multi-user is not what the docs imply**: after login a user can mint an agent token scoped to shared servers and call them, and admins can manage users/tokens. But personal servers are never connected, per-user credential injection never fires, and there is no per-tenant quota/rate limit. `require_mcp_auth` must be `true` or `/mcp` is open to anyone who can reach the pod (telemetry shows 17 of 46 server installs with `require_mcp_auth=0`). +10. **Only three IdPs (Google/GitHub/Microsoft)** — no generic OIDC, so Okta/Keycloak/Authentik shops are out. +11. **Image tags**: only two versions exist on GHCR (`v0.66.0`, `v0.66.1`); RCs publish no image; Renovate/ArgoCD Image Updater will see `latest` move on every stable release. + +--- + +## 3. Telemetry (Cloudflare D1 `mcpproxy-telemetry`, queried 2026-09-14) + +### 3.0 Schema facts + +- `heartbeats` has an `edition` **column** (default `'personal'`) plus `payload_json`. Server rows have **no** `machine_id` (column or payload): 0/168 rows; personal rows 7,093/24,989. Dedup key therefore = `COALESCE(NULLIF(json_extract(payload_json,'$.machine_id'),''), NULLIF(machine_id,''), anonymous_id)`. +- Distinct top-level payload keys across server rows: `anonymous_id version edition os arch go_version server_count connected_server_count tool_count uptime_hours routing_mode quarantine_enabled timestamp schema_version anonymous_id_created_at current_version previous_version last_startup_outcome surface_requests upstream_tool_call_count_bucket rest_endpoint_calls feature_flags server_protocol_counts env_kind env_markers activation launch_source autostart_enabled diagnostics builtin_tool_calls wizard_* error_category_counts days_since_install active_days_30d last_error_code previous_shutdown web_ui_opened`. +- `feature_flags` keys: `enable_socket enable_web_ui enable_prompts require_mcp_auth enable_code_execution quarantine_enabled sensitive_data_detection_enabled oauth_provider_types docker_available docker_isolation_enabled docker_cli_source deep_scan_enabled`. **No `server_edition`, `multiuser`, `users_count`, `oauth_provider` (IdP) field exists** — `LIKE '%multiuser%' OR '%server_edition%' OR '%users_count%' OR '%teams%'` over server payloads = 0 rows. Question (c) is unanswerable from data. +- Container signal that *does* exist: `env_kind='container'` and `env_markers.is_container` (`/.dockerenv`, `/run/.containerenv`, `$container`). No k8s/cgroup/hostname field. + +### 3.1 CI filter (used as `WITH … hb` prefix for every query below) + +```sql +WITH bad AS ( + SELECT DISTINCT anonymous_id FROM heartbeats + WHERE env_kind IN ('ci','ci_inferred','cloud_ide','cloud_ide_inferred') OR version NOT LIKE 'v%'), +gt AS ( + SELECT anonymous_id, SUM(CASE WHEN env_kind='interactive' THEN 1 ELSE 0 END) inter, COUNT(*) n + FROM heartbeats WHERE env_kind IN ('interactive','headless','container','ci','cloud_ide') GROUP BY anonymous_id), +rescued AS (SELECT anonymous_id FROM gt WHERE inter=n), +excluded AS (SELECT anonymous_id FROM bad WHERE anonymous_id NOT IN (SELECT anonymous_id FROM rescued)), +hb AS ( + SELECT h.*, COALESCE(NULLIF(json_extract(payload_json,'$.machine_id'),''), NULLIF(machine_id,''), anonymous_id) AS install_key + FROM heartbeats h WHERE anonymous_id NOT IN (SELECT anonymous_id FROM excluded)) +``` + +Excluded: 2,171 anonymous_ids, **0 of them server-edition**. + +### 3.2 (a) Distinct installs by edition + +```sql + SELECT edition, + COUNT(DISTINCT CASE WHEN created_at >= datetime('now','-14 days') THEN install_key END) d14, + COUNT(DISTINCT CASE WHEN created_at >= datetime('now','-30 days') THEN install_key END) d30, + COUNT(DISTINCT CASE WHEN created_at >= datetime('now','-90 days') THEN install_key END) d90, + COUNT(DISTINCT install_key) all_time FROM hb GROUP BY edition +``` + +| edition | 14d | 30d | 90d | all time | first seen | +|---|---|---|---|---|---| +| personal | 467 | 608 | 1,341 | 2,493 | 2026-03-23 | +| server | **6** | **8** | 37 | 46 | 2026-05-30 | + +**Dedup reality check** (no machine_id for server rows, containers without volumes get a fresh anonymous_id per recreate): + +```sql +SELECT COUNT(DISTINCT ip_address) ips, COUNT(DISTINCT country) countries, COUNT(DISTINCT anonymous_id) ids +FROM heartbeats WHERE edition='server' +``` +→ **9 IPs, 3 countries (US, CA, DE), 46 ids**. Clustering by (country, arch, version, server_count) shows three long-running lines: US/amd64 with 9 servers that upgraded every release v0.34→v0.52.1 (1 IP, 2026-05-30→08-06, then gone), US/arm64 v0.40.0 with 3 servers (1 IP, 11 anonymous_ids = repeated container recreation, 06-17→09-13, still alive), and CA/amd64 **v0.33.1** with 7 servers (3 IPs, 08-19→09-13, still alive). Plus 4–5 one-shot try-outs. **All of these pre-date the public image (v0.66.0, 2026-09-12) — every server-edition install to date was self-built** (`go build -tags server` / own Dockerfile), consistent with #1171's author. + +### 3.3 (b) OS/arch/env_kind of server installs (90d) + +```sql + SELECT os, arch, env_kind, COUNT(DISTINCT install_key) installs_90d, COUNT(DISTINCT ip_address) ips_90d +FROM hb WHERE edition='server' AND created_at >= datetime('now','-90 days') GROUP BY 1,2,3 +``` + +| os/arch | env_kind | installs | IPs | +|---|---|---|---| +| linux/amd64 | container | 23 | 6 | +| linux/arm64 | container | 14 | 2 | + +100% Linux, 100% `container`. No macOS/Windows server builds, no bare-metal/headless server installs. + +### 3.4 (c) Multi-user enabled? + +**Not measurable** — no payload field (see 3.0). Proxy signals from `feature_flags`: + +```sql + SELECT json_extract(payload_json,'$.feature_flags.require_mcp_auth') require_mcp_auth, + json_extract(payload_json,'$.feature_flags.enable_web_ui') web_ui, + json_extract(payload_json,'$.feature_flags.docker_isolation_enabled') docker_iso, + json_extract(payload_json,'$.routing_mode') routing, COUNT(DISTINCT install_key) installs +FROM hb WHERE edition='server' GROUP BY 1,2,3,4 +``` + +| require_mcp_auth | web_ui | docker_iso | installs | +|---|---|---|---| +| 0 | 1 | 0 | 17 | +| 1 | 1 | null | 14 | +| 1 | 1 | 0 | 15 | + +`oauth_provider_types` = `[]` on every server row (that field is *upstream* OAuth, not IdP). `connected_client_count` is null on all server rows. + +### 3.5 (d) Container signals — the real story + +```sql + SELECT edition, COUNT(DISTINCT install_key) container_installs_90d FROM hb +WHERE (env_kind='container' OR json_extract(payload_json,'$.env_markers.is_container')=1) + AND created_at >= datetime('now','-90 days') GROUP BY edition +``` + +| edition | container installs 90d | distinct IPs | +|---|---|---| +| personal | **362** | **86** | +| server | 37 | 8 | + +Personal-in-container breakdown (90d): + +```sql + SELECT CASE WHEN mu>=24 THEN 'uptime>=24h' WHEN mu>=1 THEN '1-23h' ELSE '<1h' END bucket, + COUNT(*) installs, SUM(rows) rows, COUNT(DISTINCT ip) ips +FROM (SELECT install_key, MAX(uptime_hours) mu, COUNT(*) rows, MIN(ip_address) ip FROM hb + WHERE edition='personal' AND env_kind='container' AND created_at >= datetime('now','-90 days') GROUP BY install_key) GROUP BY 1 +``` + +| bucket | installs | heartbeat rows | IPs | +|---|---|---|---| +| uptime ≥ 24h (long-lived service) | **113** | 1,086 | 32 | +| 1–23h | 1 | 1 | 1 | +| < 1h (ephemeral / recreated) | 248 | 284 | 33 | + +Arch: arm64 213 / amd64 150. Personal `headless` (Linux, not container) adds another 153 long-lived installs. Personal env_kind mix 90d: interactive 648, container 362, headless 336. + +Caveat: some "container" personal installs may be agent sandboxes/devcontainers rather than ops deployments; the CI filter already drops `ci_inferred`/`cloud_ide`. The ≥24h-uptime bucket is the defensible "someone runs this as a service" number. + +### 3.6 (e) Weekly trend, server edition (CI-filtered) + +```sql + SELECT strftime('%Y-W%W', created_at) week, COUNT(*) heartbeats, COUNT(DISTINCT install_key) installs, + COUNT(DISTINCT ip_address) ips, GROUP_CONCAT(DISTINCT version) versions +FROM hb WHERE edition='server' GROUP BY 1 ORDER BY 1 +``` + +| week | heartbeats | installs | IPs | versions | +|---|---|---|---|---| +| 2026-W21 | 4 | 4 | 2 | v0.34.0 | +| W22 | 10 | 5 | 1 | v0.34.0, v0.37.0, v0.38.0 | +| W23 | 8 | 2 | 1 | v0.38.0, v0.38.1 | +| W24 | 16 | 8 | 2 | v0.38.1, v0.40.0, v0.41.2, v0.43.x | +| W25 | 16 | 6 | 2 | v0.43.1, v0.40.0, v0.44.0, v0.45.0, v0.46.0 | +| W26 | 14 | 2 | 2 | v0.46.0, v0.40.0 | +| W27 | 18 | 8 | 3 | v0.46.0, v0.40.0, v0.47.0, v0.48.0 | +| W28 | 15 | 9 | 3 | v0.48.x, v0.40.0, v0.50.0, v0.51.0 | +| W29 | 8 | 3 | 1 | v0.51.0, v0.52.1 | +| W30 | 7 | 1 | 1 | v0.52.1 | +| W31 | 4 | 1 | 1 | v0.52.1 | +| W32 | 1 | 1 | 1 | v0.55.0 | +| W33 | 6 | 2 | 1 | v0.33.1 | +| W34 | 13 | 3 | 2 | v0.33.1, v0.40.0 | +| W35 | 14 | 3 | 2 | v0.40.0, v0.33.1 | +| W36 | 14 | 5 | 4 | v0.40.0, v0.33.1 | + +Flat at 1–4 IPs/week for four months; no uptick yet from the v0.66.0 public image (too recent — 2 days). For contrast, personal-in-container was 14→30 IPs/week over the same period (W24: 9, W30: 19, W36: 30). + +### 3.7 Release asset downloads + +- `external_release_downloads` has **no Docker/GHCR/server rows** (`asset_name LIKE '%docker%' OR '%server%'` = 0). GHCR pull counts are not tracked anywhere; the GHCR packages API needs `read:packages` scope (403 with the current `gh` token). Anonymous registry query confirms the image is public with tags `latest, v0.66.0, v0.66.1`. +- Cumulative by package type (latest D1 snapshot): dmg 5,549 · linux tar.gz 5,373 · zip 3,994 · macos tar.gz 3,676 · exe 2,106 · other 1,694 · **deb 601** · **rpm 384**. +- Per-release (`gh api repos/smart-mcp-proxy/mcpproxy-go/releases?per_page=10`, 2026-09-14; personal edition — there is no server-edition asset): + +| release | date | deb amd64 | deb arm64 | rpm x86_64 | rpm aarch64 | linux tar.gz amd64 | linux tar.gz arm64 | dmg arm64 | dmg amd64 | win zip | +|---|---|---|---|---|---|---|---|---|---|---| +| v0.66.1 | 09-13 | 3 | 2 | 2 | 2 | 26 (+3 `latest`) | 7 (+1) | 27 | 6 | 6 (+4) | +| v0.66.0 | 09-12 | 9 | 2 | 1 | 1 | 14 (+3) | 5 (+2) | 8 | 3 | 2 (+5) | +| v0.65.0 | 09-05 | 11 | 7 | 3 | 4 | 57 (+18) | 15 (+4) | 71 | 10 | 18 (+44) | +| v0.64.0 | 09-02 | 4 | 12 | 8 | 3 | 31 (+11) | 9 (+3) | 64 | 7 | 6 (+15) | +| v0.63.0 | 08-30 | 3 | 3 | 3 | 3 | 38 (+14) | 41 (+8) | 71 | 9 | 8 (+24) | + +Linux tar.gz consistently out-downloads the deb ~4–6x and roughly matches the macOS DMG — Linux/headless is a real audience, but it arrives via tarball (and Homebrew/apt repos, not counted here), not via the server edition. + +--- + +## 4. Half-built / gap summary for the ops/enterprise capabilities under consideration + +| Under consideration | Today | Gap to "shippable" | +|---|---|---| +| SSO for any IdP | 3 hardcoded providers | Generic OIDC discovery provider (+ tests); it's ~1 file in `oauth_providers.go` plus validator | +| True multi-user MCP (per-user servers, per-user creds) | REST records + broker store, injection unwired | Wire `workspace.Manager`/`Router`/`ToolFilter` into `/mcp`; call `SetBrokeredAuth` from a per-(user,server) client pool (`Router.BrokeredConnectionKey` already designed) | +| Teams/RBAC | admin/user only | Team entity, server→team grants, role model | +| Quotas / rate limits per tenant | global concurrency only; #1177 | Per-user limiter keyed on `AuthContext`; per-user token cap | +| Audit export | pull `GET /activity/export`, 90d BBolt | Push sink (webhook/OTLP logs/syslog), immutable retention | +| Secrets | `${env:}` only in containers | `${file:}` provider; optional Vault/cloud-SM providers; KMS for `MCPPROXY_CRED_KEY` | +| K8s-native | Docker image only | Helm chart, `Secure` cookie/`X-Forwarded-*` handling, read-only config mode, env for nested config, documented probe/grace settings | +| HA | BBolt single writer | Either an external store (SQLite→Postgres/Redis for users/sessions/tokens/activity) or an explicit "single replica, Recreate" contract | +| Server-edition packages | Docker only | Un-comment matrix entries; decide whether deb ships server edition | +| Measure adoption | `edition` only | Add `server_edition_enabled`, `idp_provider`, `user_count_bucket`, `is_k8s` to heartbeat | diff --git a/docs/research/server-edition-2026-09-14/evidence/web-vendors.md b/docs/research/server-edition-2026-09-14/evidence/web-vendors.md new file mode 100644 index 000000000..47c738a17 --- /dev/null +++ b/docs/research/server-edition-2026-09-14/evidence/web-vendors.md @@ -0,0 +1,160 @@ +# Server-side / team MCP gateway — web, X-embed, vendor & analyst signals + +Collected 2026-09-14. Scope: what organisations want from a self-hosted / team MCP gateway, and what vendors ship and charge. Companion collectors cover GitHub issues and HN/Reddit separately. + +Legend for "who": **P** = practitioner asked/reported · **V** = vendor claim · **A** = analyst / security / government guidance · **M** = protocol maintainer. + +--- + +## 1. Method + queries + +**Lanes and access outcomes** + +| Lane | What was done | Outcome | +|---|---|---| +| 1. X/Twitter (indirect) | `simonwillison.net/tags/model-context-protocol` fetched; kaxil.substack, latent.space, apideck, firecrawl, aiengineering.report searched; `curl -sI` on the one X status found | Simon's 2026 tag page has **no** embedded enterprise/gateway tweets (only datasette-mcp / stateless-MCP posts). Kaxil's post embeds 3 tweets (Garry Tan ×2, Simon Willison) — text recovered from the embed; `https://x.com/kaxil/status/2041315551796953187` returned HTTP 200 (existence only, text unrecoverable directly). latent.space / apideck / firecrawl / aiengineering.report: **nothing gateway-specific found** (queries listed below). | +| 2. Web / blogs / forums | WebSearch + WebFetch on dev.to, medium, InfoQ, The New Stack, security vendors, NSA/CISA | Rich. NSA CSI PDF blocked (media.defense.gov and nsa.gov both 403/HTML-challenge to fetch and curl) → quoted via ReedSmith's law-firm summary. lobste.rs / forums.docker.com: **no relevant threads surfaced**. Reddit skipped per lane rules. | +| 3. Vendor landscape + pricing | Product/pricing/README pages for ~22 vendors | Most fetched. 404s: Kong docs path (used Kong blog instead), Cloudflare portals doc (used blog + changelog), Zuplo docs+product pages, Portkey MCP doc (used pricing page), Obot /pricing (used README), Lasso product page (used GitHub), Apigee MCP overview (both old and redirected URL 404). Glama /pricing and Smithery /pricing render no prices. | +| 4. kubic SearXNG | `http://kubic.home.arpa:30081/search?q=MCP+gateway+enterprise+self-hosted&format=json&engines=google` | Reachable; results polluted with unrelated Bing filler; only two usable candidates (scalekit.com OSS-gateways post, MintMCP self-hosted post — the latter fetched directly). Treated as candidates only. | + +**WebSearch queries run (30):** "MCP gateway" enterprise 2026 · MCP gateway kubernetes helm chart operator · MCP server Vault secrets management gateway credentials · MCP audit log SIEM Splunk Datadog gateway · MCP OpenTelemetry tracing gateway observability · "MCP gateway" pricing per seat · "shadow MCP" OR "MCP server sprawl" enterprise governance · "MCP gateway" comparison 2026 ToolHive agentgateway Docker MCP Gateway ContextForge · internal MCP registry platform engineering approved servers · NSA CISA MCP guidance · simonwillison.net model-context-protocol MCP gateway enterprise 2026 · Gartner "AI gateway" MCP 2026 · kaxil.substack.com MCP enterprise gateway tweet · latent.space MCP gateway enterprise 2026 tweet · InfoQ OR "The New Stack" MCP gateway enterprise governance 2026 · Invariant Labs OR "Noma Security" OR Zenity MCP enterprise gateway guidance 2026 · MintMCP "self-hosted" MCP gateways 2026 · Trend Micro OR "Unit 42" OR Wiz "MCP" security enterprise recommendations gateway 2026 · Cloudflare "MCP server portals" Zero Trust pricing · "tool-call approval" OR "human-in-the-loop" MCP gateway · air-gapped MCP gateway offline install enterprise · Docker MCP Gateway enterprise "Docker Hub" MCP catalog pricing team features · dev.to OR medium.com "MCP gateway" self-hosted team "we built" · Kong AI Gateway MCP "ai-mcp-proxy" docs · apideck OR firecrawl OR "aiengineering.report" MCP gateway tweets roundup 2026 · Glama MCP gateway pricing OR Smithery enterprise pricing · Stacklok ToolHive enterprise pricing · lobste.rs OR "forums.docker.com" MCP gateway proxy self-hosted · "MCP" gateway "Prometheus" metrics "Grafana" dashboard · Gravitee "2026 State of AI Agent Security" · "per-team" OR "per-user" MCP tool allowlist gateway "SCIM" OR "Okta" OR "Entra" · Azure API Management MCP pricing "AI gateway" tier · Composio security incident May 2026 MCP. + +**Fetch failures to note:** Unit 42 and Trend Micro MCP URLs guessed → 404 (no verified Unit 42 / Trend Micro MCP-gateway guidance included). Invariant Labs: search returned nothing gateway-specific. Zenity: only vendor-comparison listicles, not included. + +--- + +## 2. Signal table + +| # | Source | Date | Who | Capability wanted | Verbatim quote | URL | +|---|---|---|---|---|---|---| +| 1 | MCP 2026 Roadmap — David Soria Parra (lead maintainer) | 2026-03-09 | M | Audit trails, SSO auth, gateway behaviour, config portability | "Enterprises are deploying MCP and running into a predictable set of problems: audit trails, SSO-integrated auth, gateway behavior, and configuration portability." | https://blog.modelcontextprotocol.io/posts/2026-mcp-roadmap/ | +| 2 | MCP 2026 Roadmap (same) | 2026-03-09 | M | Registry / offline discovery | "Second, a standard metadata format, that can be served via `.well-known`, so that server capabilities are discoverable without a live connection." | same | +| 3 | WorkOS — Maria Paktiti, "Everything your team needs to know about MCP in 2026" | 2026-03-26 | V (summarising roadmap) | Audit → SIEM/APM | "No standardized audit trail. Teams building production MCP deployments are inventing their own logging, tracing, and compliance infrastructure." | https://workos.com/blog/everything-your-team-needs-to-know-about-mcp-in-2026 | +| 4 | WorkOS (same) | 2026-03-26 | V | Gateway/proxy semantics | "Enterprises running MCP behind API gateways, security proxies, or load balancers face undefined behavior around authorization propagation, session affinity, and inspection boundaries." | same | +| 5 | Snowflake Engineering — Pratyus Patnaik, Sr Director Eng | 2026-09-02 | **P** | Credential broker (no secrets on laptops) | "Modern gateway architectures intercept tool executions at runtime and inject authorized credentials on the fly" | https://www.snowflake.com/en/blog/engineering/enterprise-mcp-gateway-ai-agent-governance/ | +| 6 | Snowflake (same) | 2026-09-02 | **P** | Per-user delegated authz | "the gateway should ensure the agent acts strictly within the permission scope of the user it represents" | same | +| 7 | Snowflake (same) | 2026-09-02 | **P** | Central approved-tool registry + RBAC | "IT and security teams control what is available, who can access it and under what conditions" | same | +| 8 | Snowflake (same) | 2026-09-02 | **P** | DLP on prompts + tool outputs | "inspecting both prompts and tool outputs — stripping PII, proprietary code snippets and confidential tokens" | same | +| 9 | Snowflake (same) | 2026-09-02 | **P** | Audit of full agent trajectory + cost budgets | "capture the full agent trajectory: not just which API calls were made...but what the agent was trying to accomplish" | same | +| 10 | Kaxil Naik (Astronomer), "MCP Sucks (Until It Doesn't)" | 2026-04-07 | **P** | Scoped per-team tokens, audit, central policy | "Scoped tokens per team or role. Audit logs showing which agent called which tool and when." / "You can update access policies without pushing changes to every client." | https://kaxil.substack.com/p/mcp-vs-cli-vs-rest (X: https://x.com/kaxil/status/2041315551796953187 — HTTP 200, exists) | +| 11 | Kaxil (same) | 2026-04-07 | **P** | Security boundary on infra, not laptops | "The security boundary lives on your infrastructure instead of on every developer's laptop." | same | +| 12 | Garry Tan (@garrytan) tweet, embedded in Kaxil's post | ~2026-04 | **P** | (negative signal: MCP overhead) | "MCP sucks honestly... I got sick of Claude in Chrome via MCP and vibe coded a CLI wrapper for Playwright tonight in 30 minutes" | embed at kaxil.substack.com/p/mcp-vs-cli-vs-rest — **original X URL not recovered; text from embed only** | +| 13 | Garry Tan (@garrytan) follow-up, embedded in Kaxil's post | ~2026-04 | **P** | Lightweight, purpose-built MCP | "I changed my mind. MCP can be wonderful. It just needs to be light and purpose-built and engineered instead of a shitty shim" | same caveat | +| 14 | Simon Willison (@simonw) tweet, embedded in Kaxil's post | ~2026-04 | **P** | Context pollution fix → many servers | "This is great - context pollution is why I rarely used MCP, now that it's solved there's no reason not to hook up dozens or even hundreds of MCPs" | same caveat | +| 15 | dev.to — Varshith V Hegde, eval for a mid-size financial-services client | 2026-05-08 | **P** | Self-host / VPC hard requirement, audit, RBAC, residency | CISO question: "who can see what tools our agents are calling?" / "Managed-only gateways require you to trust a vendor's infrastructure with your agent's tool calls" / "you can deploy it inside your own VPC or fully on-premises, which was a hard requirement" | https://dev.to/varshithvhegde/best-mcp-gateways-for-enterprise-teams-in-2026-5fk8 | +| 16 | Manveer Chawla, hands-on comparison of 12 gateways | 2026-07-30 | **P** | Reusable multi-user auth; external IdP that works | "After about 70 minutes, I still hadn't created a reusable gateway where different users could authenticate." (Composio) / "Setting up a custom external identity provider didn't work." (TrueFoundry) | https://manveerc.substack.com/p/best-mcp-gateways | +| 17 | InfoQ — Nik Kale, "Securing MCP in Production: Defense-in-Depth beyond the Gateway" | 2026-07-29 | **P/A** | Gateway = authn/authz, audit, rate limit, policy; plus what it can't do | Gateways "authenticate clients, authorize requests against policy", "maintain audit trails and request logs", "provide rate limiting functionality"; but a gateway "does not detect when the tool definitions a team approved last week change" | https://www.infoq.com/articles/securing-mcp-production-gateway/ | +| 18 | InfoQ (same) — anecdote | 2026-07-29 | **P** | Secure-by-default management plane | "While assessing the MCP, we discovered that our testing harness was listening on an internal network with no authentication. It was a twenty minute job to shut it down. The default was open." | same | +| 19 | The New Stack — Amanda Rueda | 2026-07-14 | **P/A** | Audit with identity + authority by design | "In regulated environments, 'the AI did it' is not a sufficient audit entry. Teams need to answer what the agent did, on whose behalf, and under what authority." | https://thenewstack.io/mcp-enterprise-agent-governance/ | +| 20 | IBM ContextForge issue #932 — AmshegaR | 2025-09-06 (closed) | **P** | Air-gapped install | "Many enterprise and government organizations require air-gapped deployments for security compliance." / "Currently, the admin UI and Swagger fail to function properly due to CDN dependencies" | https://github.com/IBM/mcp-context-forge/issues/932 | +| 21 | Metorial — Karim Rahme, post-Composio-breach checklist | 2026-05-22 | V (competitor) | Self-host, per-connection isolation, trace + revoke | "Can we deploy our own MCP servers? Can we inspect or self-host the platform?" / "Can we trace every tool call?" and "Can we revoke a single user connection?" | https://metorial.com/blog/composio-security-incident-mcp-security | +| 22 | Composio May-2026 incident (via dev.to Sapnesh Naik; Material Security report) | 2026-05-21 | **P** (incident) | Credential isolation / broker | "An attacker gained a foothold in an internal agentic tool, escalated through the sandboxed execution environment, and reached an auxiliary credential cache." ~5,241 API keys + 5,001 GitHub connections exposed | https://dev.to/sapnesh_naik_ngo/top-5-mcp-gateways-for-ai-agents-in-your-product-in-2026-49h8 ; https://composio.dev/blog/composio-may-2026-security-incident | +| 23 | WorkOS — Maria Paktiti, "The tools that caught shadow IT can't see MCP sprawl" | 2026-08-10 | V | Per-call identity + argument logging, daily inventory | "Every tool call attributable to a specific agent identity and logged with its arguments and outcome" / "The earlier risk was that shadow AI exposed your data. The risk now is that it operates on it." | https://workos.com/blog/mcp-sprawl-invisible-to-shadow-it-tools | +| 24 | Stacklok — Scott Buchanan, "Shadow MCP" | 2026-05-04 | V | Approved registry + K8s auto-discovery | "Admins and security teams can define which servers are approved, who can use them, and how." / "Stacklok's Kubernetes operator discovers MCP servers running in your cluster and surfaces them in the catalog automatically." | https://stacklok.com/blog/shadow-mcp-the-ai-governance-problem-hiding-in-plain-sight/ | +| 25 | Qualys — Krishna Anumalasetty | 2026-03-20 | A (security vendor) | Inventory of localhost/high-port servers; log discovery + invocation | "MCP services dodge traditional visibility for several reasons. They sometimes bind to localhost instead of network interfaces, can be configured to listen on random high ports." Cites Astrix: "53% of servers rely on static secrets" | https://blog.qualys.com/product-tech/2026/03/19/mcp-servers-shadow-it-ai-qualys-totalai-2026 | +| 26 | Datadog Security — Mallory Mooney, "MCP security risks: SIEM detection rules" | 2025-11-03 | A | Log schema for SIEM | Servers should emit "Successful and failed authentication attempts", "Tool registrations, updates, and other configuration changes", "Tool invocations, including call parameters and errors" | https://www.datadoghq.com/blog/mcp-detection-rules/ | +| 27 | Wiz — Rami McCarthy, MCP research briefing | 2025-04-17 | A | Central proxy for audit; binary allowlisting | "Centralizing MCP Server usage through a proxy will allow a single point of control for audit logging and monitoring" / "Binary allowlisting is a helpful hardening measure against related threats" | https://www.wiz.io/blog/mcp-security-research-briefing | +| 28 | Noma Security launch (Agentic Access Control) | 2026-06-02 | V | Inventory + Approved/Review/Blocked states, tool-granular policy | "Security teams configure each agent and MCP connection in one of three states: Approved, Requires Review, or Blocked." / "approve or block individual tools rather than entire systems" | https://www.noma.security/blog/noma-launches-agentic-access-control-to-govern-ai-agents-and-mcp-servers-across-the-enterprise | +| 29 | Cloudflare — Kenny Johnson, MCP Server Portals | 2025-08-26 | V | Single endpoint, Access SSO policy, aggregated logs | "Server Portals aggregate all MCP request logs into a single place, giving you the visibility needed to audit activity." / "enforce the same granular access policies for your AI connections that you do for your human users." | https://blog.cloudflare.com/zero-trust-mcp-server-portals/ | +| 30 | InfoQ — Matt Foster on Cloudflare's MCP reference architecture | 2026-04-22 | A (press) | Remote, centrally-managed servers | "Cloudflare argues locally deployed MCP servers represent a significant security liability, as they often rely on unvetted software and lack centralized oversight." | https://www.infoq.com/news/2026/04/cloudflare-mcp/ | +| 31 | InfoQ — Steef-Jan Wiggers, stateless MCP | 2026-08-12 | A (press) | Gateway can act per-method via headers | "A gateway, rate limiter or WAF can read those headers and act on them, per method or per tool, using the same primitives it already applies to every other API." | https://www.infoq.com/news/2026/08/mcp-stateless-gateway/ | +| 32 | Zuplo — "Martyn", what the best MCP gateways do | 2026-06-05 | V | SCIM first-class; JWT-claim authz; full request log | "SCIM provisioning should be a first-class feature, not a 'contact sales' add-on." / "JWT claims from your IDP should drive per-tenant, per-role, per-team authorization decisions at the gateway edge." | https://zuplo.com/blog/what-the-best-mcp-gateways-do-in-2026 | +| 33 | Composio (dev.to) buyer's guide | 2026 (page shows 2024 date — likely misdated) | V | Per-team scoped endpoint + SSO; SCIM | "Every team gets a unique, scoped MCP endpoint... SSO authenticates. Only the tools their team is authorized to use appear" / "Without SCIM, MCP gateway access management becomes a manual operation at every organizational boundary event." | https://dev.to/composiodev/the-enterprise-mcp-gateway-buyers-guide-sso-scim-audit-and-governance-requirements-ho7 | +| 34 | TrueFoundry — Boyu Wang, "The Human Gate" | 2026-08-14 | V | Tool-call approval workflow at gateway | "MCP recommends human control but does not define a universal approval protocol." / "the Gateway holds the call instead of invoking the downstream tool." | https://www.truefoundry.com/blog/mcp-tool-approval-human-gate-call-path | +| 35 | TrueFoundry — Naman Monga, HITL vs Kong | 2026-08-21 | V | Approval hold for irreversible actions | "One authorized mistake can become a P1, trigger blanket removal of agent write access, and stall the wider agent program." / Kong's controls "do not support a native approval workflow that can hold an otherwise permitted tool call while a human decides." | https://www.truefoundry.com/blog/human-in-the-loop-mcp-truefoundry-vs-kong | +| 36 | Speakeasy — Nolan Sullivan, "Choosing an MCP gateway" | 2026-02-04 | V | IdP token brokering; argument-level policy; audit | "Developers should authenticate once at the identity provider, such as Okta, and the gateway should broker tokens to each MCP server" / "The months of work are the identity provider integration, argument-level policy on tool calls, audit logging that stands up to review" | https://www.speakeasy.com/blog/choosing-an-mcp-gateway | +| 37 | Lunar.dev — Eyal Solomon, OSS gateways compared | 2026-04-06 | V (competitor) | Gaps in Docker/Microsoft gateways | Docker MCP: "There are no audit trails, no tool-level access control, and no identity-aware policy enforcement." / Microsoft: "no tool-level RBAC or agent-identity attribution built in" | https://www.lunar.dev/post/the-best-open-source-mcp-gateways-in-2026 | +| 38 | MintMCP — self-hosted gateways | 2026-06-05 | V | Self-host = creds inside boundary | "Self-hosted gateways keep traffic, execution, and credential handling inside your own infrastructure boundary." / "Complete audit trails, tracking every tool call, authentication event, and data access, support compliance reporting requirements." | https://www.mintmcp.com/blog/mcp-gateways-self-hosted-deployments | +| 39 | Docker — MCP Enterprise Gateway product page | 2026 (undated) | V | IdP→group→policy→credential-inject→record | "It authenticates the user through your identity provider, resolves which servers and tools that user's groups can reach, evaluates policy for the specific call, injects the credentials the call needs, routes it to the server, and records the decision." Customer (unnamed, "hundreds of millions of monthly users") "retired a homegrown MCP proxy for a governed gateway" | https://www.docker.com/products/mcp-enterprise-gateway/ | +| 40 | Docker (same) | 2026 | V | Air-gapped K8s appliance | "Private Kubernetes with no outbound connection. Catalogs, server images, and policy load from inside your network." (marked "Coming soon") | same | +| 41 | Kong — Alex Drag, Enterprise MCP Gateway launch | 2025-10-14 | V | OAuth 2.1, tool ACLs, observability — paid only | "Without comprehensive observability, platform teams operate blindly, unable to track which tools agents are invoking." / "an enterprise-only solution that leverages paid plugins" | https://konghq.com/blog/product-releases/enterprise-mcp-gateway | +| 42 | Microsoft Learn — APIM AI Gateway tier (preview) | 2026-07-23 | V | Governed MCP endpoint, token/request rate limits, OTel, Entra | "Apply governance controls such as token rate limits, request rate limits, content safety, and IP filters." / "Publish approved MCP tools for AI agents." / "Pricing and the business model will be announced later in the preview." | https://learn.microsoft.com/en-us/azure/api-management/ai-gateway-overview | +| 43 | Gravitee — Jorge Ruiz, State of AI Agent Security 2026 (n≈900) | 2026-02-04 | A (vendor survey) | Governance/enforcement gap | "88% of organizations reported confirmed or suspected AI agent security incidents in the last year"; only "14.4% reporting all AI Agents going live with full security/IT approval"; 45.6% rely on shared API keys | https://www.gravitee.io/blog/state-of-ai-agent-security-2026-report-when-adoption-outpaces-control | +| 44 | Practical DevSecOps — Varun Kumar, MCP stats roundup | 2026-06-26 | A (secondary) | Secrets hygiene, agent identity | "GitGuardian: 24,008 secrets found in MCP-related config files on public GitHub; 2,117 still valid" / "Only 23% have a formal enterprise-wide agent identity strategy" (CSA/Strata, Feb 2026) | https://www.practical-devsecops.com/mcp-security-statistics-2026-report/ | +| 45 | Zuplo — "Nate", Gartner 75% claim | 2026-03-26 | A (via vendor; Gartner report name not cited — links K2View) | MCP in API gateways as table stakes | "75% of API gateway vendors will integrate MCP features" by end-2026; "70% of software engineering teams building multimodel applications will use AI gateways" by 2028 | https://zuplo.com/blog/gartner-75-percent-api-gateways-mcp | +| 46 | Permit.io — Or Weis | 2026-03-18 | V | Drop-in proxy adding authn/authz/consent/audit | "A drop-in proxy between MCP clients and MCP servers that adds authentication, authorization, consent, and audit to every tool call, with no SDK, no agent rewrites." | https://permit.substack.com/p/mcp-isnt-dead-its-becoming-enterprise | +| 47 | Tyk docs — Grafana dashboard for MCP traffic | 2026 (undated) | V | OTLP metrics, per-tool latency, error by code | "Tyk exports metrics via OTLP (not a Prometheus scrape endpoint directly)." Panels: request rate by JSON-RPC method, error rate, top tools; P95 per-tool latency, per-session usage | https://tyk.io/docs/ai-management/mcp-gateway/how-to-grafana-mcp-dashboard | +| 48 | hoop.dev — Coleman Nye | 2026-06-18 | V | Immutable audit → Datadog | "Regulatory frameworks, internal security policies, and incident‑response teams all demand immutable audit logging." | https://hoop.dev/blog/audit-logging-for-mcp-servers-on-datadog | + +**Tweets proven to exist but unread:** none beyond #10 (Kaxil's status, whose text is the article title). Garry Tan / Simon Willison tweet texts (#12–14) come from Kaxil's Substack embeds; their X URLs were not recoverable. + +--- + +## 3. Vendor matrix + +"—" = not found in fetched material (not proof of absence). "Ent" = gated to a paid/enterprise tier. Sources in the notes column. + +| Vendor | OSS / SaaS | Pricing | Helm/K8s | Vault/secrets | OTel/metrics | SSO/OIDC | RBAC/allowlist | Rate-limit | Multi-tenant | Audit export | DLP | Notes + URL | +|---|---|---|---|---|---|---|---|---|---|---|---|---| +| **Docker MCP Gateway / Catalog / Enterprise Gateway** | OSS CLI gateway (Apache) + commercial Enterprise Gateway | OSS "no platform fees"; Enterprise = "Talk to sales", undisclosed | Enterprise: "Managed in your cloud" now; air-gapped private-K8s appliance "coming soon" | Enterprise: "Credentials are read at call time from the store that already holds them" (no products named on page; a search snippet listed Vault/AWS SM/GCP SM/Azure KV as commercial-only — **unverified**) | OSS: "built-in logging and call-tracing" | Enterprise: IdP auth | Enterprise: group→server/tool resolution + per-call policy | — | Enterprise "Docker-managed cloud (multi-tenant)" coming soon | Enterprise "records the decision" | — | OSS gateway per Lunar: "no audit trails, no tool-level access control". https://www.docker.com/products/mcp-enterprise-gateway/ ; https://docs.docker.com/ai/mcp-gateway/ | +| **Kong AI Gateway (MCP)** | Commercial (Kong Gateway Enterprise self-hosted or Konnect SaaS) | Enterprise/Konnect licence; "enterprise-only solution that leverages paid plugins" | Yes (Kong on K8s) | — | Yes; MCP-specific logging of session IDs, JSON-RPC methods, payloads, latency (3.12) | OAuth 2.1 via `ai-mcp-oauth2` | Consumer/Consumer-Group ACLs on MCP tools | Token- and request-based | Via consumers/workspaces | Yes (logging plugins) | PII controls (AI plugins) | No native HITL approval hold (per TrueFoundry). https://konghq.com/blog/product-releases/enterprise-mcp-gateway ; https://developer.konghq.com/mcp/ | +| **Solo agentgateway** | OSS Apache-2.0 (Linux Foundation); Solo Enterprise for agentgateway | OSS free; enterprise undisclosed | Yes (kgateway); Solo docs "Install in air-gapped environments" | — | Yes | JWT/OIDC | CEL policies "match on any request attribute" | Yes | Yes | — | — | https://agentgateway.dev/docs/ ; https://docs.solo.io/agentgateway/2.3.x/install/airgap/ | +| **Envoy AI Gateway → "Agent Router" (AAIF)** | OSS | Free | Helm/K8s (v1.1) | — | "OpenTelemetry tracing and Prometheus metrics for all MCP requests" | "Native enforcement of OAuth authentication flows" | "fine-grained access control using JWT claims, scopes, and CEL expressions"; tool filtering exact/regex | Envoy rate limiting | Tenant-scoped via JWT claims | — | — | Rebranded; multiplexes servers with prefixed tool names. https://theagentrouter.ai/docs/capabilities/mcp/ | +| **Cloudflare MCP Server Portals (Cloudflare One) + Agents SDK** | SaaS | Portals in Open Beta; "up to 50 free seats"; then Cloudflare One per-user pricing | n/a (cloud-only) | — | Portal logs | Cloudflare Access (any IdP) | Per-user Access policies; ≤40 remote HTTP servers per portal; stdio not supported | — | Yes | "aggregate all MCP request logs into a single place" | — | Willow's comparison: no on-prem/air-gap. https://blog.cloudflare.com/zero-trust-mcp-server-portals/ ; https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/secure-mcp-servers/ | +| **Zuplo** | SaaS (managed / dedicated) | Tiers not fetched (docs 404) | — | — | — | JWT/OIDC | JWT-claim authz | Yes (API gateway heritage) | Yes | Yes | — | Blog: "SCIM provisioning should be a first-class feature, not a 'contact sales' add-on." https://zuplo.com/blog/what-the-best-mcp-gateways-do-in-2026 | +| **Portkey** | OSS gateway + SaaS | OSS free; Developer free (10k logs/mo); Production $49/mo (100k logs); Enterprise custom | Yes (self-host/VPC = Ent) | — | Yes | **Ent** | **Ent** (RBAC) | Yes | Yes | **Ent** (audit logs, data export) | Custom guardrails **Ent** | https://portkey.ai/pricing | +| **LiteLLM MCP Gateway** | OSS (MIT) + Enterprise licence | OSS free; Enterprise (custom) | Helm yes | — | Prometheus/OTel | **Ent** ("SSO/SAML") | Per-key/team/org tool permissions (OSS); guardrails **Ent** | Budgets/limits per key | Teams/orgs (**Ent** multi-team mgmt) | **Ent** (audit logs) | Guardrails **Ent** | https://docs.litellm.ai/docs/mcp | +| **IBM ContextForge** | OSS Apache-2.0 (v1.0.0-RC-3 referenced) | Free | Helm `charts/mcp-stack`; multi-cluster | `AUTH_ENCRYPTION_SECRET`; vault "less documented" (Lunar) | OTel → Phoenix/Jaeger/Zipkin; Prometheus | JWT, OAuth2, Keycloak SSO | RBAC in Admin UI; Cedar (per Lunar) | Built-in | User-level; no org model documented | Audit trails in logs | 40+ plugins incl. PII filters | Air-gap issue #932 closed. https://github.com/IBM/mcp-context-forge | +| **Obot** | OSS MIT (+ managed service) | Free OSS; /pricing 404 | K8s "recommended for production/multi-tenant"; Helm in repo | K8s secret bindings; OAuth cred mgmt | — (not in README) | Configurable IdPs | "Apply policies based on individual users or identity-provider groups"; scoped API keys | — | Yes | Correlated audit with "Scheduled export" | — | Git-backed registries. https://github.com/obot-platform/obot | +| **Stacklok ToolHive (+Operator)** | OSS Apache-2.0 + Stacklok Enterprise | OSS free; Enterprise "licensed as an annual subscription", price undisclosed | Operator + CRDs (MCPServer, MCPRemoteProxy, VirtualMCPServer, MCPRegistry) | K8s secrets | MCPTelemetryConfig (OTel/Prometheus) | OIDC (OSS); "Turnkey IdP integration (Okta, Entra ID)" **Ent** | Cedar policy (OSS); "IdP group to ToolHive role mapping" **Ent** | — | Via operator | Audit logging | — | Ent adds hardened images, backported Sev0-3 patches, SLA. https://docs.stacklok.com/toolhive/enterprise ; https://docs.stacklok.com/toolhive/guides-k8s/intro | +| **Lasso MCP Gateway** | OSS MIT + paid Lasso plugin | Free; Lasso guardrails need paid API key | — | — | — | — | — | — | — | Dashboard/risk scoring | Basic secret masking + Presidio PII free; "prompt injection detection, sensitive data leakage prevention" paid | Scans servers "before loading" (reputation + tool-description). https://github.com/lasso-security/mcp-gateway | +| **Composio** | SaaS | Hobby free 100k calls/mo (3 members); Pro $29/mo + $0.0003/call overage; Enterprise custom (new pricing from 2026-08-15) | Self-host **Ent** | Customer-managed KMS **Ent** | — | SSO/SCIM **Ent** | Per-team toolkit allow/blocklists | API rate limits by tier | Yes | Custom log retention **Ent** | BAA $0.0003/call; ZDR $0.0001/call (per dev.to) | May-2026 breach: 5,241 keys + 5,001 GitHub connections. https://composio.dev/pricing | +| **Glama** | SaaS registry/gateway | Free browse; paid team/enterprise (no prices on /pricing) | — | — | — | — | — | — | — | — | — | https://glama.ai/ | +| **Smithery** | SaaS hosting | Free tier; custom quotes; **acquired by Arcade.dev** (banner) | — | — | — | — | — | — | — | — | — | https://smithery.ai/pricing | +| **MCP Manager** | SaaS (+ self-host Ent) | Core $135/mo (10 servers) · Plus $400 · Professional $668 · Enterprise custom | Multi-instance self-hosted **Ent** | — | "OTel logging" **Ent** | SSO/SCIM **Ent** | RBAC + internal registry all tiers; custom roles Pro/Ent | — | Multiple workspaces **Ent** | Log retention 30d/90d/custom; HIPAA logging **Ent** | PII detection (Presidio) Pro+ | Local (stdio) server support **Ent**. https://mcpmanager.ai/pricing-plans/ | +| **Microsoft MCP Gateway (GitHub)** | OSS MIT | Free | K8s StatefulSets + headless services | Azure Key Vault (per Lunar) | Azure Monitor/App Insights | Entra ID | Roles `mcp.admin`/`mcp.engineer`; "no tool-level RBAC" (Lunar) | — | Session-affinity routing | Via Azure Monitor | — | https://github.com/microsoft/mcp-gateway | +| **Azure APIM AI Gateway tier** | SaaS (preview) | "at no cost in public preview"; pricing TBA | n/a | Managed identity / provider keys held by gateway | OTel GenAI conventions; token metrics | Entra ID (admin) + runtime keys | Publish "approved MCP tools" | Token + request rate limits | Yes | OTLP destinations | Content safety | Private Link + VNet in preview. https://learn.microsoft.com/en-us/azure/api-management/ai-gateway-overview | +| **AWS AgentCore Gateway** | SaaS | "$0.005 per 1,000 invocations"; Search "$0.025 per 1,000"; "$0.02 per 100 tools indexed per month" | n/a | AWS Secrets Manager (platform) | CloudWatch | IAM / OAuth (inbound) | IAM policies | — | Yes | CloudTrail | — | https://aws.amazon.com/bedrock/agentcore/pricing/ | +| **Google Apigee MCP** | SaaS | Apigee tiers | n/a | — | — | — | — | — | — | — | — | **Overview page 404 at both URLs**; not verified. | +| **TrueFoundry** | SaaS + self-host (VPC/on-prem/air-gap documented) | Developer free 50k req/mo; Pro $499/mo; Pro Plus $2,999/mo (per Speakeasy) | Yes (K8s/VPC) | — | Yes | Yes | Yes | Budgets | Yes | Yes | — | Native tool-call approval hold (Slack/PagerDuty/Teams). https://www.truefoundry.com/docs/ai-gateway/mcp/mcp-tool-approval | +| **Lunar MCPX** | OSS MIT core + enterprise | Free core | Yes | "vault-backed" | Prometheus | **Ent** | Yes | — | Yes | "immutable" | — | Gartner "Representative Vendor" claim (vendor-stated). https://www.lunar.dev/post/the-best-open-source-mcp-gateways-in-2026 | +| **Willow** | SaaS | Free ≤5 users/5 integrations; Startup $15/seat; Enterprise gates SCIM + guardrails | — | — | — | Yes | Yes | — | Yes | — | Guardrails **Ent** | https://withwillow.ai/compare/willow-vs-cloudflare ; pricing per Speakeasy | +| **Arcade.dev** | SaaS | Hobby free; Growth "$25 per month plus usage"; $0.01/tool call, $0.10/auth event (per dev.to) | Self-host **Ent** | — | — | Yes | Yes | — | Yes | Yes | Yes | Tool-level auth only when hosted on Arcade runtime (Chawla). | +| **Noma Security** | SaaS security platform | Undisclosed ($100M raised) | — | — | — | — | Approved/Review/Blocked per tool/agent/user/team/env | — | — | — | — | Discovery-first, not a data-plane gateway. | + +--- + +## 4. Security / compliance guidance → implied must-haves + +| Guidance | Date | Control implied | Verbatim / paraphrase | URL | +|---|---|---|---|---| +| **NSA CSI "MCP: Security Design Considerations for AI-Driven Automation"** (primary PDF blocked to fetch; quoted via ReedSmith, Ryan J. Fitzpatrick, 2026-06-04) | 2026-05-20 (published; PDF dated 2026-06-02) | **Audit logging** with who/what/result | "Maintain comprehensive activity logs: All actions taken by MCP tools should be logged in detail, including what tool was requested, by whom, and what resulted." | https://www.reedsmith.com/our-insights/blogs/viewpoints/102mvg9/nsa-publishes-security-guidance-on-designing-ai-systems-with-model-context-protoc/ (primary: https://media.defense.gov/2026/Jun/02/2003943289/-1/-1/0/CSI_MCP_SECURITY.PDF — 403) | +| NSA (same) | | **Least privilege / per-server allowlists** | "Grant only the minimum access necessary: If an MCP tool does not need access to sensitive files, internal networks, or other resources, then access should be explicitly blocked." | same | +| NSA (same) | | **Token expiry/revocation → credential broker** | "Credential reuse risk: MCP systems often lack proper expiration or revocation controls for authentication tokens, meaning a stolen or intercepted credential could be reused." | same | +| NSA (same) | | **Sandboxing / isolation** (→ Docker isolation) | Confine automated actions "within strict permission boundaries and isolated from other processes." | same | +| NSA (same) | | **Human approval for tool calls** | "Lack of human approval steps: Some MCP implementations do not require human sign-off before taking actions." | same | +| NSA (same) | | **Trust-zone segmentation** (gateway as boundary) | "Separate systems and data by trust level" with "clear boundaries between different components of an MCP environment". Also flags DoS/overload risk (→ rate limits) without prescribing a control. | same | +| **Five Eyes joint agentic-AI paper** (CISA/NSA/ACSC/CCCS/NCSC-NZ/NCSC-UK) | 2026-05-01 | Governance of third-party integrations, auditability | Reported by ExecutiveGov as covering "access control, prompt handling, tool execution, agent permissions, auditability, and governance of third-party integrations" (not fetched directly). | https://www.executivegov.com/articles/nsa-model-context-protocol-deployment | +| **Datadog Security Labs** | 2025-11-03 | Structured log schema exportable to SIEM; anomaly detection on call spikes / permission-denied | Emit "Tool invocations, including call parameters and errors"; "Track any sudden increases in call errors or permission denied events" | https://www.datadoghq.com/blog/mcp-detection-rules/ | +| **Wiz** | 2025-04-17 | Central proxy; binary allowlist; inventory | "Centralizing MCP Server usage through a proxy will allow a single point of control for audit logging and monitoring" | https://www.wiz.io/blog/mcp-security-research-briefing | +| **Qualys** | 2026-03-20 | Inventory of localhost/high-port servers; log capability discovery and invocation; separate discovery vs invocation privileges | "Even a read-only MCP endpoint can leak internal system names, tool schemas, resource paths, and namespaces." | https://blog.qualys.com/product-tech/2026/03/19/mcp-servers-shadow-it-ai-qualys-totalai-2026 | +| **InfoQ defense-in-depth (Nik Kale)** | 2026-07-29 | Gateway ≠ complete: needs tool-definition drift detection (→ MCPProxy Spec-032 rug-pull hashes), management-plane auth | "does not detect when the tool definitions a team approved last week change" | https://www.infoq.com/articles/securing-mcp-production-gateway/ | +| **Gravitee survey (n≈900)** | 2026-02-04 | Agent identity as first-class principal; continuous enforcement | 45.6% "rely on shared API keys"; 88% incidents | https://www.gravitee.io/blog/state-of-ai-agent-security-2026-report-when-adoption-outpaces-control | +| **Gartner (via Zuplo, second-hand)** | 2026-03-26 | MCP support in API gateways = table stakes | "75% of API gateway vendors will integrate MCP features" by end-2026 | https://zuplo.com/blog/gartner-75-percent-api-gateways-mcp | + +**Mapping to MCPProxy candidate capabilities** + +| Candidate | Verdict from evidence | Strongest signals | +|---|---|---| +| Helm chart / K8s operator | **Validate — table stakes for self-host buyers.** Every OSS peer ships Helm (ContextForge, ToolHive operator+CRDs, agentgateway, Agent Router, Microsoft, Obot). Air-gap requires mirrored images + chart. | #20, #24, Solo airgap docs, matrix | +| Vault / secrets-manager integration | **Validate — but as "credential broker that keeps secrets off laptops" first; named-vault backends second.** Docker Enterprise's whole pitch is call-time credential injection; Snowflake asks for it explicitly; Composio breach + Astrix 53%-static-secrets + GitGuardian 24k leaked MCP secrets make it the headline. | #5, #22, #25, #39, #44 | +| Log/audit exporters (OTel / SIEM) | **Validate — highest-frequency ask across all three lanes.** Roadmap #1 gap; NSA; Datadog schema; Zuplo field list; MCP Manager gates OTel to Enterprise (i.e. people pay for it). | #1, #3, #26, #32, NSA | +| Prometheus metrics | **Validate (cheap).** Agent Router/ContextForge/MCPX ship it; Tyk goes OTLP-only and users then need a collector. | #47, matrix | +| SSO / OIDC / SAML | **Validate — but note OIDC is "free tier" everywhere; turnkey Okta/Entra + SCIM group mapping is what gets gated to paid.** | #16, #32, #33, Stacklok Ent, LiteLLM Ent, Portkey Ent | +| RBAC + per-team tool allowlists | **Validate.** Universal; Lunar dings Docker and Microsoft for lacking tool-level RBAC. | #7, #10, #33, #37 | +| Rate limits / quotas | **Validate (medium).** Kong/APIM/Agent Router have it; NSA names DoS; Snowflake wants per-user cost budgets. Less often the *decision* driver. | #9, #42, NSA | +| Multi-tenancy | **Partial — "per-user servers" already covers most asks; org/workspace-level tenancy is an Enterprise-tier feature at MCP Manager/LiteLLM.** ContextForge lacks it and is still adopted. | matrix | +| Air-gapped install | **Validate for gov/regulated; ship as "no outbound deps + image bundle", not a separate SKU.** Docker markets it as "coming soon"; ContextForge issue; Solo docs. | #20, #40 | +| Central approved-server policy / registry | **Validate — the "shadow MCP" narrative is the 2026 marketing consensus** (Stacklok, WorkOS, Qualys, Noma, Snowflake). Approved/Review/Blocked states map onto MCPProxy quarantine. | #7, #23–25, #28 | +| DLP / sensitive-data redaction | **Validate — MCPProxy already has detection; redaction on both directions is asked by Snowflake and gated to Pro/Ent at MCP Manager, paid at Lasso.** | #8, matrix | +| Tool-call approval workflows | **Validate (differentiator).** NSA calls out missing human sign-off; TrueFoundry built a product line on it and points at Kong's gap. Fits MCPProxy's existing quarantine/approve UX. | #34, #35, NSA | + +--- + +## 5. Summary — what orgs pay for vs expect free + +1. **Free is expected for the data plane:** proxying, OIDC/JWT login, per-key or per-team tool allowlists, container isolation, basic logs, Helm chart. Every serious OSS peer (ContextForge, ToolHive, agentgateway, Agent Router, Obot, LiteLLM, Docker's CLI gateway) ships these at $0; Docker's own OSS gateway gets criticised precisely for missing audit + tool-level RBAC. +2. **Money changes hands for identity plumbing and evidence:** turnkey Okta/Entra + SCIM group→role mapping, org-wide audit logs with retention windows, OTel/SIEM export, HIPAA/BAA-grade logging. These are gated to Enterprise at Stacklok, LiteLLM, Portkey, MCP Manager ($135→$668/mo then custom), Composio, Kong (paid plugins only), Willow ($15/seat; SCIM+guardrails Ent). +3. **Self-hosting itself is a paid feature at SaaS vendors** (Composio, Arcade, Portkey, MCP Manager "multi-instance self-hosted" Ent) — and a hard requirement for regulated buyers (fin-services eval, Snowflake, NSA). An OSS gateway that self-hosts *with* the enterprise-tier features is the gap MCPProxy's server edition sits in. +4. **Credential brokering is the 2026 headline, driven by incidents:** Composio's May breach (5,241 keys), GitGuardian's 24k leaked MCP secrets, Astrix's 53% static secrets, NSA's "credential reuse risk". Docker's Enterprise Gateway pitch is literally "injects the credentials the call needs… records the decision." Named vault backends matter less than "secrets never reach mcp.json". +5. **Emerging paid differentiators, still rare:** gateway-held human-approval for irreversible tool calls (TrueFoundry vs Kong), tool-definition drift detection (InfoQ says gateways don't do it — MCPProxy's Spec-032 already does), per-user cost budgets, and air-gapped appliances (Docker "coming soon"). Pricing models are unsettled: per-seat ($15), per-tool-call ($0.0003–$0.01), per-1k-invocations ($0.005 AWS), flat tiers ($135–$2,999/mo), or "talk to sales".