A community-driven registry for the Claude Code ecosystem. Not affiliated with Anthropic.
Are you the author? Sign in to claim
Secure mcp infrastructure to audit and control every data access by AI agents with minimal efforts
Self-hosting ready security gateway for Model Context Protocol (MCP) servers with authentication, policy-based access control, tool filtering, and comprehensive audit logging for AI agents, Claude Desktop, VS Code, and custom LLM applications.
Secure MCP Gateway is an enterprise-grade security and management layer for Model Context Protocol servers, enabling organizations to safely expose MCP tools to AI agents, LLMs, and users while maintaining complete control over access, permissions, and compliance.
Without the Gateway:
AI Agent → MCP Server → Unrestricted Tool Access ❌
With Secure MCP Gateway:
AI Agent → Gateway (Auth + Policy + Audit) → Controlled MCP Access ✅
# Clone the repository
git clone https://github.com/datacline/secure-mcp-gateway.git
cd secure-mcp-gateway
# (Optional) Set API keys for MCP catalog visibility
# Required only if you want to see public MCP servers in the catalog
export POSTMAN_API_KEY="your_postman_api_key_here"
# Start all services (Gateway, Keycloak, PostgreSQL, Policy Engine, Frontend)
docker-compose up -d
# Wait 30 seconds for services to initialize
# Check that the gateway is ready
curl http://localhost:8000/actuator/health
# Open the Web UI in your browser
open http://localhost:5173
# Or manually navigate to: http://localhost:5173
Note:
Once all services are running, access them at:
| Service | URL | Description |
|---|---|---|
| Web UI | http://localhost:5173 | 👈 Start here! Main management interface (No login required) |
| Gateway API | http://localhost:8000 | REST API for MCP operations |
| Keycloak Admin | http://localhost:8080 | User and authentication management (admin / admin) |
| Policy Engine | http://localhost:9000 | Policy evaluation service (Internal) |
Getting Started:
After running docker-compose up -d, follow these steps:
Option 1: Use the Web UI (Recommended for beginners)
# Open the Web UI
open http://localhost:5173
# No login required! From the UI you can:
# - View and configure MCP servers
# - Create MCP groups
# - Manage policies
# - Test tool access
Option 2: Integrate with Claude Desktop See Test with Claude Desktop section below
Option 3: Use the API directly
# Get an authentication token first
TOKEN=$(curl -X POST http://localhost:8080/realms/mcp-gateway/protocol/openid-connect/token \
-d "client_id=mcp-gateway-client" \
-d "username=testuser" \
-d "password=testpass" \
-d "grant_type=password" | jq -r '.access_token')
# List MCP servers
curl http://localhost:8000/mcp/servers \
-H "Authorization: Bearer $TOKEN"
Add to your Claude Desktop config:
{
"mcpServers": {
"secure-gateway": {
"url": "http://localhost:8000/mcp/group/1/mcp",
"transport": {
"type": "http"
}
}
}
}
Install the MCP extension and configure:
{
"mcp.servers": [
{
"name": "Secure Gateway",
"url": "http://localhost:8000/mcp/group/1/mcp"
}
]
}
smcp CLIThe project also ships an npm CLI package named @datacline/smcp for common gateway, group, and server workflows.
Install globally:
npm install -g @datacline/smcp
smcp --help
Run without global install:
npx @datacline/smcp commands
Run from this repo while developing:
npm install
npm run smcp -- commands
Examples:
# Local runtime helpers
smcp gateway start
smcp gateway logs
# API-backed commands
smcp server list
smcp group list
smcp group create engineering --description "Engineering tools" --servers github,slack
By default, smcp targets http://localhost:8000 for API-backed commands. Override with:
export SMCP_GATEWAY_URL="http://your-host:8000"
┌─────────────────────────────────────────────────────────────┐
│ Secure MCP Gateway │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Frontend │ │ Java Gateway│ │ Policy Engine │ │
│ │ (React/TS) │ │ (Spring Boot)│ │ (Go) │ │
│ │ Port 5173 │ │ Port 8000 │ │ Port 9000 │ │
│ └──────────────┘ └──────────────┘ └─────────────────┘ │
│ │ │ │ │
│ └──────────────────┴───────────────────┘ │
│ │ │
│ ┌──────────────────────────┼──────────────────────────┐ │
│ │ │ │ │
│ │ ┌────────────────┐ ┌───┴────────────┐ ┌────────┴─┐ │
│ │ │ Keycloak │ │ PostgreSQL │ │ STDIO │ │
│ │ │ (Auth) │ │ (Database) │ │ Proxy │ │
│ │ │ Port 8080 │ │ Port 5432 │ │ Port 8081│ │
│ │ └────────────────┘ └────────────────┘ └──────────┘ │
│ └─────────────────────────────────────────────────────────┘
└─────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
┌───────▼────────┐ ┌───────▼────────┐ ┌──────▼──────────┐
│ Group: Team1 │ │ Group: Team2 │ │ Group: Team3 │
│ /mcp/group/1/ │ │ /mcp/group/2/ │ │ /mcp/group/3/ │
│ mcp │ │ mcp │ │ mcp │
└────────────────┘ └────────────────┘ └─────────────────┘
│ │ │
┌───┴────┐ ┌────┴────┐ ┌────┴────┐
│ GitHub │ │ Notion │ │ AWS │
│ Slack │ │ Gmail │ │ Docker │
│ Jira │ │ Drive │ │ K8s │
└────────┘ └─────────┘ └─────────┘
Challenge: Deploy Claude Desktop to 1,000 employees with access to internal tools (GitHub, Jira, Confluence) while ensuring:
Solution:
# Create groups by department
Engineering Group:
- GitHub MCP (read/write code)
- Jira MCP (create issues)
- Slack MCP (send messages)
Management Group:
- Notion MCP (view reports)
- Calendar MCP (schedule)
- Gmail MCP (read-only)
# Apply policies
Policy: "engineering-read-only"
Resources: github:*
Tools: [list_repos, get_pr, search_code] # No delete/force-push
Policy: "management-view-only"
Resources: notion:*
Tools: [get_page, search_pages] # No create/update
Challenge: SaaS platform wants to offer AI assistants to customers, each with their own MCP servers and data isolation.
Solution:
Challenge: 50 developers need access to 20+ MCP servers, but configuration is complex and error-prone.
Solution:
http://gateway/mcp/group/dev/mcpChallenge: Financial services company needs complete audit trail of all AI agent actions for SOC2/GDPR compliance.
Solution:
Challenge: Want to test new MCP server with beta users before company-wide release.
Solution:
Beta Group (10 users):
- New Experimental MCP Server
- Policy: Allow all tools, log everything
Production Group (All users):
- Stable MCP Servers only
- Policy: Strict access control
# Clone repository
git clone https://github.com/datacline/secure-mcp-gateway.git
cd secure-mcp-gateway
# Configure environment (optional)
cp .env.example .env
nano .env # Edit as needed
# Start all services with one command
docker-compose up -d
# Wait 30 seconds for initialization, then open the UI
open http://localhost:5173
# Or check service status
docker-compose ps
# View logs if needed
docker-compose logs -f mcp-gateway-java
docker-compose logs -f policy-engine
This single command starts all services:
cd server-java
./mvnw clean install
docker build -t mcp-gateway-java .
docker run -p 8000:8000 -e POLICY_ENGINE_URL=http://host.docker.internal:9000 mcp-gateway-java
cd policy-engine-go
go build -o policy-engine
./policy-engine
cd frontend
npm install
npm run dev
# Terminal 1: Java Gateway
cd server-java
./mvnw spring-boot:run
# Terminal 2: Policy Engine
cd policy-engine-go
go run main.go
# Terminal 3: Frontend
cd frontend
npm run dev
# Terminal 4: Keycloak (Docker)
docker-compose up -d keycloak postgres
# Gateway Configuration
SERVER_PORT=8000
GATEWAY_HOST=localhost
POLICY_ENGINE_URL=http://localhost:9000
# Database
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/mcp_gateway
SPRING_DATASOURCE_USERNAME=mcp_user
SPRING_DATASOURCE_PASSWORD=mcp_password
# Authentication
AUTH_ENABLED=true
KEYCLOAK_URL=http://localhost:8080
KEYCLOAK_REALM=mcp-gateway
SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUER_URI=http://localhost:8080/realms/mcp-gateway
# MCP Servers
MCP_SERVERS_CONFIG=/app/mcp_servers.yaml
MIGRATE_YAML_TO_DB=true
# Audit Logging
AUDIT_LOG_FILE=/app/logs/audit.json
AUDIT_TO_STDOUT=true
AUDIT_TO_DATABASE=true
# External Credentials
GITHUB_MCP_PAT=your_github_token
NOTION_TOKEN=your_notion_token
File: server-java/mcp_servers.yaml
servers:
- name: github
url: https://api.github.com/mcp
type: http
auth_method: bearer
credential: ${GITHUB_MCP_PAT}
description: GitHub MCP Server
- name: notion
url: http://localhost:8081/mcp
type: http
auth_method: bearer
credential: ${NOTION_TOKEN}
description: Notion MCP Server
- name: local-filesystem
type: stdio
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/directory"]
description: Local filesystem access
MCP Groups allow you to organize multiple MCP servers into logical collections that act as a single unified endpoint.
Via Web UI:
Via API:
curl -X POST http://localhost:8000/mcp/groups \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "Engineering Team",
"description": "Development tools",
"serverNames": ["github", "slack", "jira"]
}'
# Response includes: gateway_url: "http://localhost:8000/mcp/group/1/mcp"
Restrict which tools are exposed from each server:
curl -X PUT http://localhost:8000/mcp/groups/1/servers/github/tools \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"tools": ["create_issue", "list_repos", "get_pr"]
}'
Groups enforce policy restrictions automatically:
Server has: 50 tools
Policy allows: 10 tools
Group config: 5 tools
Result: 5 tools (intersection)
Formula: Available Tools = Server Tools ∩ Policy-Allowed ∩ Group-Configured
See server-java/MCP_GROUPS_COMPLETE_GUIDE.md for complete documentation.
Policies use the Unified Policy format:
{
"policy_id": "engineering-github-access",
"name": "Engineering GitHub Access",
"description": "Allow engineers to manage code but not delete repos",
"status": "active",
"priority": 100,
"policy_rules": [
{
"rule_id": "github-allow",
"description": "Allow code management tools",
"actions": [{"type": "allow"}],
"conditions": {
"user_roles": ["engineer", "senior-engineer"]
}
}
],
"resources": [
{"resource_type": "mcp_server", "resource_id": "github"},
{"resource_type": "tool", "resource_id": "github:create_issue"},
{"resource_type": "tool", "resource_id": "github:list_repos"},
{"resource_type": "tool", "resource_id": "github:create_pr"},
{"resource_type": "tool", "resource_id": "github:merge_pr"}
]
}
Via Web UI:
Via API:
curl -X POST http://localhost:9000/api/v1/unified/policies \
-H "Content-Type: application/json" \
-d @policy.json
# List all groups
GET /mcp/groups
# Get group by ID
GET /mcp/groups/{id}
# Create group
POST /mcp/groups
Body: {"name": "Team", "serverNames": ["github"]}
# Update group
PUT /mcp/groups/{id}
Body: {"serverNames": ["github", "slack"]}
# Delete group
DELETE /mcp/groups/{id}
# Configure tools for server in group
PUT /mcp/groups/{id}/servers/{serverName}/tools
Body: {"tools": ["create_issue", "list_repos"]}
# Get policy-allowed tools
GET /mcp/servers/{serverName}/policy-allowed-tools
# Group gateway (MCP protocol)
POST /mcp/group/{id}/mcp
Body: {"jsonrpc": "2.0", "method": "tools/list", "id": 1}
# Individual server (MCP protocol)
POST /mcp/{serverName}
Body: {"jsonrpc": "2.0", "method": "tools/list", "id": 1}
# List MCP servers
GET /mcp/servers
# Get server details
GET /mcp/servers/{name}
# Register new server
POST /mcp/servers
Body: {"name": "github", "url": "...", "type": "http"}
# Update server
PUT /mcp/servers/{name}
# Delete server
DELETE /mcp/servers/{name}
# Convert STDIO to HTTP
POST /mcp/servers/{name}/convert-to-http
See server-java/README.md for complete API documentation.
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"engineering-tools": {
"url": "http://localhost:8000/mcp/group/1/mcp",
"transport": {
"type": "http"
}
}
}
}
.vscode/mcp.json:
{
"servers": [
{
"name": "Secure Gateway",
"url": "http://localhost:8000/mcp/group/1/mcp"
}
]
}
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
const transport = new SSEClientTransport(
new URL("http://localhost:8000/mcp/group/1/mcp")
);
const client = new Client({
name: "my-app",
version: "1.0.0",
}, {
capabilities: {}
});
await client.connect(transport);
// List available tools
const result = await client.request({
method: "tools/list"
}, ListToolsResultSchema);
// Call a tool
const response = await client.request({
method: "tools/call",
params: {
name: "create_issue",
arguments: {
title: "Bug report",
body: "Description here"
}
}
}, CallToolResultSchema);
Authorization: Bearer <token>✅ DO:
AUTH_ENABLED=true)❌ DON'T:
All tool invocations are logged with:
Example audit log:
{
"timestamp": "2026-02-14T19:30:00Z",
"user": "john.doe",
"action": "mcp.tool.call",
"server": "github",
"tool": "create_issue",
"arguments": {
"title": "Bug report",
"repository": "my-repo"
},
"result": "success",
"duration_ms": 234,
"ip": "192.168.1.100"
}
# Check Docker logs
docker-compose logs -f mcp-gateway-java
# Common issues:
# 1. Port 8000 already in use
docker-compose down
lsof -ti:8000 | xargs kill -9
docker-compose up -d
# 2. Database connection failed
docker-compose up -d postgres
docker-compose restart mcp-gateway-java
# 3. Policy engine not reachable
docker-compose up -d policy-engine
docker-compose restart mcp-gateway-java
# Note: Policy Engine URL is now http://policy-engine:9000 (internal service name)
# 1. Check Policy Engine connection
docker logs mcp-gateway-java | grep "Policy Engine client initialized"
# Should show: http://host.docker.internal:9000
# 2. Verify policies exist
curl http://localhost:9000/api/v1/unified/resources/mcp_server/github/policies?active=true
# 3. Check debug endpoint
curl http://localhost:8000/mcp/servers/github/tool-availability-debug?group_id=1
# 4. View gateway logs
docker logs mcp-gateway-java | grep "Policy"
# 1. Test server directly
curl -X POST http://mcp-server-url/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# 2. Check authentication
# Ensure bearer token is set in mcp_servers.yaml
# 3. For STDIO servers, convert to HTTP
# Use the Web UI or:
curl -X POST http://localhost:8000/mcp/servers/my-stdio-server/convert-to-http
# 1. Check browser console for errors
# 2. Verify frontend is calling correct endpoint
# Should be: /mcp/servers/{name}/policy-allowed-tools
# NOT: /mcp/servers/{name}/tools
# 3. Clear browser cache
# 4. Rebuild frontend
cd frontend && npm run build
See server-java/TROUBLESHOOTING.md for more solutions.
We welcome contributions! Please read our Contributing Guide for details on:
# Fork and clone
git clone https://github.com/YOUR_USERNAME/secure-mcp-gateway.git
cd secure-mcp-gateway
# Create branch
git checkout -b feature/amazing-feature
# Start services
docker-compose up -d
# Make changes, test, commit
git commit -m "feat: add amazing feature"
git push origin feature/amazing-feature
# Open Pull Request
See CONTRIBUTING.md for complete guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
MCP gateway, Model Context Protocol, AI agent security, Claude MCP, LLM tools, MCP server proxy, OAuth2 MCP, MCP authentication, policy-based access control, MCP groups, tool filtering, STDIO to HTTP, enterprise AI, MCP management, secure AI agents, AI compliance, MCP audit logging, VS Code MCP, Claude Desktop, MCP server management, multi-tenant MCP, RBAC for AI, AI tool governance
Made with ❤️ for the MCP community
Star ⭐ this repo if you find it useful!
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Secure MCP server for MySQL database interaction, queries, and schema management
English-first Korean equity intelligence MCP — DART filings, foreign-holder 5%-rule flows, activist filings, KRX news. F