One MCP endpoint · every tool · full policy control

The gateway between your agents
and everything they touch

Lian MCP Gateway is a dynamic MCP server and policy engine. It learns your systems, exposes them as tools over API or upstream MCP, and enforces exactly who is allowed to do what — with a full audit trail of every call.

Lian MCP Gateway — product demo

Connects agents to the tools they already run

GitHub Jenkins Redash Slack Grafana Brave Search Any REST API Any upstream MCP

HOW IT WORKS

One endpoint. Three moves.

No hardcoded tools. You teach the gateway your systems once, and every agent gets them — scoped to their identity.

01

Connect an app

Pick a ready MCP server from the catalog, let the AI build a bridge in a chat, or map a REST endpoint. Credentials stay on the app, never exposed.

02

Set the policy

Federate identity via OAuth or SAML (Google Workspace, Azure AD). Grant per-group, per-app — or down to a single tool. A no-grant app stays public.

03

Point your agent

Agents connect to /mcp/{app}. They see only the tools they're allowed to run — and every call is logged with the exact arguments.

WHY A GATEWAY

Control, not just connectivity

MCP that manages MCPs

A single server that fronts many target systems. A path segment selects the app — one connection, your whole stack.

Two tool sources, one registry

Expose a product's REST API or proxy an upstream MCP — uniformly. Fill the gaps an upstream MCP leaves with the product's own API.

RBAC to the tool

Group → app grants, nullable down to a single tool. Unauthorized tools vanish from tools/list; blocked calls return a clean error.

Full audit log

One row per call — allowed and denied: who, which app/tool, the LLM's exact arguments, the decision and the outcome. Nothing happens off the record.

Identity & secrets handled

OAuth + SAML federation. Per-user upstream tokens stored AES-256-GCM encrypted, enrolled right in the login flow — works even in ChatGPT.

Build tools with AI

Chat with the LLM to design a bridge, import an OpenAPI spec, or warm a catalog server. Every new tool is a proposal you approve before it goes live.

UNDER THE HOOD

Built to sit in the critical path

Go backend. React console. MySQL.

  • Streamable HTTP MCP — JSON-RPC 2.0 at POST /mcp/{app}, dynamic enabled-only tool lists, live tools/list_changed push.
  • API executor — path templating with auth injection: none, bearer, header, query or basic.
  • SAML SP + OAuth broker — federates to Google & Azure, reads group claims, authorizes group → app.
  • Admin console — apps, access control, authentication, catalog, audit and a live log viewer over SSE.
agent → gateway → your system
# one endpoint, the app is in the path
POST /mcp/jenkins
Authorization: Bearer <federated-token>

{
  "method": "tools/call",
  "params": {
    "name": "last_build",
    "arguments": { "job": "deploy" }
  }
}

# gateway: check group → app → tool,
# inject the right credential, call upstream,
# write the audit row, return the result.

STEP-BY-STEP GUIDE

From empty console to a live, governed tool

Everything happens in the admin console — the left sidebar is your map: Dashboard · Apps · MCP Management · Access control · Authentication · Audit · Logs · Settings.

Do this first. The AI features (Build-with-AI chat and the Tool Builder) call a model, so they do nothing until you add an API key under Settings. No key → the chat and "build tools" buttons return an error. Add it once and every AI feature lights up.

https://pav.lian.co.il/ — Settings

LLM provider

Powers Build-with-AI and the Tool Builder. The key is write-only.
Anthropic
claude-opus-4-8
sk-ant-•••••••••••••••• ← paste & Save
https://pav.lian.co.il
Save settings
1 SETTINGS

Turn on the AI (add your token)

The gateway is model-agnostic — bring your own Anthropic or OpenAI key. It's stored encrypted and never returned by the API (you only ever see "stored").

  1. Open Settings in the sidebar.
  2. Pick a provider (Anthropic / OpenAI) and a model.
  3. Paste your API key and press Save — this is the token the AI needs.
  4. While you're here, set the Public base URL (e.g. https://pav.lian.co.il) — OAuth & SAML endpoints are built from it.
https://pav.lian.co.il/ — Apps › New app

New app — how do you want to build it?

Every app becomes an MCP server the gateway runs for you.
🤖 Build with the AI (chat, no config)
Describe the system; the AI writes/launches a bridge and imports its tools.
🔌 Connect an existing MCP server (manual)
Point to an npx/uvx package or a running server; fill its env.
🏬 From catalog
Pick a ready server (GitHub, Slack, Grafana…) and just fill credentials.
2 APPS → NEW APP

Add an application

An "app" is any system you want agents to reach. Three ways in — all end up as an MCP server with its tools imported into the registry.

  1. Go to Apps → New app.
  2. Build with the AI: chat (next step) and the AI designs the bridge.
  3. From catalog: choose a ready server and enter its credentials — secrets live only on the created app.
  4. If a bridge fails to start, the app is still created — open it under Apps to set env values and restart.
https://pav.lian.co.il/ — Apps › Build with the AI
Connect our Jenkins at jenkins.lian.co.il — list jobs and trigger builds.
I'll build a stdio bridge with list_jobs, job_info, trigger_build. It needs a Jenkins user + API token (env). Ready to create?
Yes, create it.
Create app & start bridge ✓ 3 tools imported
3 BUILD WITH THE AI

Let the AI wire it up

Describe the system in plain language. The AI picks a strategy — reuse a published npx/uvx MCP package, or write a small Node bridge — and asks for whatever credentials it needs.

  1. Tell it what to connect and what the agent should do.
  2. Review the proposed tools, then Create app & start bridge.
  3. The gateway starts the subprocess and imports its tools automatically.
  4. Prefer HTTP mapping? Build tools with AI turns an OpenAPI spec or docs into tools you approve before they go live.
https://pav.lian.co.il/ — Authentication
OverviewOAuth / OIDC providersSAML identity providers

Add OIDC provider

MCP clients log in through the gateway, which federates to your IdP.
https://accounts.google.com
xxxx.apps.googleusercontent.com
••••••••
https://pav.lian.co.il/oauth/callback/google
Save provider
4 AUTHENTICATION

Set up OAuth login

The gateway is its own OAuth Authorization Server for MCP clients (Claude, Cursor, ChatGPT) and federates the actual login to your OIDC provider or SAML IdP (Google Workspace, Azure AD).

  1. Set the Public base URL in Settings first — every endpoint derives from it.
  2. Under Authentication → OAuth / OIDC providers, add issuer + client ID/secret.
  3. Register the shown redirect URI (/oauth/callback/{provider}) at the IdP.
  4. Done — a client hitting /mcp/ gets a 401 that kicks off the login automatically. SAML? Use the SAML identity providers tab and import its metadata.
https://pav.lian.co.il/oauth/enroll — after login

Link your tool accounts

Shown once, right after you log in — stored encrypted, keyed to you.
leave blank to keep
paste token…
Save & continue
5 PER-USER TOKENS

Who's the identity upstream?

Each app has a credential mode. In gateway mode the gateway uses one stored token for everyone. In user mode each caller acts as themselves upstream — and this screen collects their token during the normal login.

  1. Set the mode per app (gateway vs user) when you create/edit it.
  2. User-mode apps show an enrolment page right after OAuth login — no custom headers, works in ChatGPT.
  3. Tokens are AES-256-GCM encrypted and never returned by the API.
  4. Admins can pre-fill them under Access control → Per-user upstream tokens.
https://pav.lian.co.il/ — Access control › Rules
UsersGroupsRules

Grant: group → app → tool

A restricted app needs a matching grant; a no-grant app is public.
devops
jenkins
trigger_build
Add rule
devops → jenkins → all tools
6 ACCESS CONTROL

Decide who can do what

RBAC is group-based and goes all the way down to a single tool. Groups come from the IdP assertion or can be assigned by hand.

  1. Users — everyone who logged in, with their group snapshot.
  2. Groups — assign manual groups on top of IdP groups.
  3. Rules — group → app (whole app) or group → app → tool (one tool).
  4. Unauthorized tools disappear from tools/list; a blocked call returns -32001.
https://pav.lian.co.il/ — Audit

Audit trail

One row per tools/call — allowed and denied alike.
UserApp · ToolArgsDecision
dana@lianjenkins · trigger_build{job:"deploy"}allow
omer@liangithub · delete_repo{repo:"core"}deny
dana@lianredash · run_query{id:42}allow
7 CONNECT & AUDIT

Point the agent — and watch everything

Give your MCP client one URL. It logs in once and sees every app it's allowed to use; each app's tools are namespaced <app>__<tool>.

  1. Aggregate surface: https://pav.lian.co.il/mcp/ — one login, all authorized apps.
  2. Or a single app: /mcp/{app-slug}.
  3. The Audit tab logs who / which tool / the LLM's exact arguments / the decision / the outcome.
  4. Logs streams activity live; Dashboard shows the overview.

RUN IT YOURSELF

Up and running with Docker

A single self-contained image runs everything — the Go gateway, the admin console, and the npx/node/python3 runtimes for local bridges. The only thing you bring is a MySQL database (or let the full stack bundle one).

Quickest — pull the published image
# the image is on Docker Hub
docker pull avnersib/mcp-gateway

docker run -d --name mcp-gateway \
  --env-file .env -p 8120:8120 \
  -v mcpgw-data:/app/data \
  avnersib/mcp-gateway

# .env → MCPGW_DB_*, MCPGW_BASE_URL, MCPGW_ADMIN_USER/PASS
# console → http://<host>:8120/   ·   MCP → /mcp/

Option A — bring your own MySQL

  • One container next to a MySQL you already run.
  • The gateway creates its own mcpgw_ tables on first boot — no manual migrations.
  • Serves the console + MCP on :8120; put your TLS proxy in front.
Option A — your MySQL
# 1. create the database (once)
CREATE DATABASE mcpgw CHARACTER SET utf8mb4;
GRANT ALL ON mcpgw.* TO 'mcpgw'@'%' IDENTIFIED BY '…';

# 2. configure
cp .env.example .env   # set DB_*, BASE_URL, ADMIN_*

# 3. run
docker compose up -d --build

# console → http://<host>:8120/  ·  MCP → /mcp/

Option B — full self-contained stack

  • Gateway + bundled MySQL 8.4 — nothing external, just Docker.
  • The DB has a healthcheck the gateway waits on before booting.
  • First login = MCPGW_ADMIN_USER / PASS from your .env.
Option B — bundled MySQL
# build the whole project from scratch
cp .env.full.example .env
# set MCPGW_DOMAIN + DB / root / admin passwords

docker compose -f docker-compose.full.yml up -d --build

# starts:  db (mysql:8.4)  +  gateway (:8120)
# tables auto-created on first boot

TLS: the container serves plain HTTP on :8120. Terminate TLS with nginx / Caddy / Traefik / a cloud LB and forward to it. Set MCPGW_BASE_URL to your public HTTPS URL — it's the OAuth issuer and what redirect URIs are built from. For the long-lived MCP stream use proxy_buffering off; proxy_read_timeout 3600s;.

READY WHEN YOU ARE

Give your agents reach — on your terms

Connect the first app in minutes. Scope it, audit it, and never wonder what your agents did again.

Open the admin console

OPEN SOURCE

MIT Licensed

Free to use, copy, modify and distribute — in your own products, commercial or not.

LICENSE
MIT License

Copyright (c) 2026 Avner

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.