Production-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 โ
- No authentication
- No authorization
- No audit trail
- No policy enforcement
- No tool filtering
- No centralized management
With Secure MCP Gateway:
AI Agent โ Gateway (Auth + Policy + Audit) โ Controlled MCP Access โ
- โ JWT/OAuth2 Authentication - Keycloak integration
- โ Policy-Based Access Control - Fine-grained permissions per tool
- โ MCP Groups - Organize servers by team/role
- โ Tool Filtering - Restrict which tools users can access
- โ Audit Logging - Complete compliance trail
- โ STDIO to HTTP Conversion - Use any MCP server
- โ Web UI - Easy management interface
- โ Multi-Tenancy - Isolate access by user/team
- JWT Authentication with JWKS validation
- OAuth2/OIDC integration (Keycloak, Auth0, Okta)
- Policy Engine for fine-grained access control
- Role-Based Access Control (RBAC)
- Tool-level permissions - Control access to individual MCP tools
- Audit logging to database, files, and stdout
- MCP Groups - Organize multiple servers into logical collections
- STDIO to HTTP Conversion - Run local MCP servers as HTTP endpoints
- Tool Configuration - Show/hide specific tools per group
- Server Discovery - Auto-detect and register MCP servers
- Health Checks - Monitor server availability
- Failover Support - Automatic retry and error handling
- Policy Precedence - Security policies override group configurations
- Unified Policy Format - Supports enhanced and unified policies
- Dynamic Filtering - Tools filtered based on user context
- UI Integration - Frontend shows only policy-allowed tools
- Mismatch Detection - Warns when configurations violate policies
- Web Dashboard - Manage servers, groups, and policies
- Real-time Monitoring - View active connections and requests
- User Management - Create users, assign roles
- Policy Editor - Visual policy creation and testing
- Audit Viewer - Search and analyze audit logs
- Docker Compose - One-command setup
- Hot Reload - Development mode with auto-restart
- API Documentation - Comprehensive REST API docs
- CLI Tool - Command-line management interface
- Examples - Sample configurations for common use cases
- VS Code Integration - Use with VS Code MCP extension
- Quick Start
- Architecture
- Use Cases
- Installation
- Configuration
- MCP Groups
- Policy Management
- API Reference
- Client Integration
- Security
- Troubleshooting
- Contributing
- Docker & Docker Compose
- Git
- (Optional) Node.js 18+ for frontend development
- (Optional) Java 21+ for backend development
- (Optional) Go 1.21+ for policy engine development
# Clone the repository
git clone https://github.com/datacline/secure-mcp-gateway.git
cd secure-mcp-gateway
# Start all services (Gateway, Keycloak, PostgreSQL, Policy Engine, Frontend)
docker-compose up -d
# Wait 30 seconds for services to initialize, then test
curl http://localhost:8000/actuator/health| Service | URL | Credentials |
|---|---|---|
| Gateway API | http://localhost:8000 | JWT token required |
| Web UI | http://localhost:5173 | testuser / testpass |
| Keycloak Admin | http://localhost:8080 | admin / admin |
| Policy Engine | http://localhost:9000 | Internal service |
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"
}
]
}โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 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 โ
โโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโ
- Java Gateway (Spring Boot) - Core proxy, authentication, MCP protocol
- Policy Engine (Go) - Policy evaluation, access control decisions
- Frontend (React/TypeScript) - Web UI for management
- Keycloak - Identity provider, OAuth2/OIDC
- PostgreSQL - Data storage (servers, groups, policies, audit logs)
- STDIO Proxy - Converts STDIO MCP servers to HTTP
Challenge: Deploy Claude Desktop to 1,000 employees with access to internal tools (GitHub, Jira, Confluence) while ensuring:
- Only authorized users access sensitive tools
- Developers can't delete production resources
- All actions are audited for compliance
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/updateChallenge: SaaS platform wants to offer AI assistants to customers, each with their own MCP servers and data isolation.
Solution:
- Create separate groups per customer
- Apply tenant-specific policies
- Isolate audit logs by tenant
- Custom gateway URLs per customer
Challenge: 50 developers need access to 20+ MCP servers, but configuration is complex and error-prone.
Solution:
- One central gateway with all servers
- VS Code connects to
http://gateway/mcp/group/dev/mcp - Developers get auto-configured access to approved tools
- IT team manages servers centrally
Challenge: Financial services company needs complete audit trail of all AI agent actions for SOC2/GDPR compliance.
Solution:
- All MCP tool invocations logged to database
- Audit logs include: user, timestamp, tool, arguments, result
- Export audit logs to SIEM systems
- Policy violations automatically blocked and logged
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
docker-compose up -d
# Check status
docker-compose ps
# View logs
docker-compose logs -f mcp-gateway-javacd 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-javacd policy-engine-go
go build -o policy-engine
./policy-enginecd 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_tokenFile: 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 accessMCP Groups allow you to organize multiple MCP servers into logical collections that act as a single unified endpoint.
Via Web UI:
- Navigate to http://localhost:5173/mcp-servers
- Click "Create Group"
- Add servers and configure tools
- Use the generated gateway URL
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:
- Navigate to Policy Engine UI (http://localhost:9000)
- Create new unified policy
- Add resources (servers and tools)
- Set conditions and actions
Via API:
curl -X POST http://localhost:9000/api/v1/unified/policies \
-H "Content-Type: application/json" \
-d @policy.json- Active policies only - Draft/suspended policies ignored
- Most restrictive wins - Intersection of all applicable policies
- Policy > Group - Policy restrictions override group configurations
- Fail-safe - On error, deny all access
# 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-httpSee 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);- User logs in to Keycloak (or OAuth2 provider)
- Receives JWT token with user info and roles
- Includes token in requests:
Authorization: Bearer <token> - Gateway validates token signature using JWKS
- Policy engine evaluates user's permissions
- Request allowed/denied based on policy
โ DO:
- Enable authentication in production (
AUTH_ENABLED=true) - Use HTTPS in production
- Rotate secrets regularly
- Review audit logs
- Apply least-privilege policies
- Use environment variables for secrets
โ DON'T:
- Commit secrets to git
- Disable authentication in production
- Use default passwords
- Grant wildcard permissions without policies
- Expose gateway directly to internet without firewall
All tool invocations are logged with:
- User: Who invoked the tool
- Timestamp: When it was invoked
- Tool: Which tool was called
- Arguments: What parameters were passed
- Result: Success/failure and response
- Duration: How long it took
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
# Ensure POLICY_ENGINE_URL=http://host.docker.internal:9000# 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 buildSee server-java/TROUBLESHOOTING.md for more solutions.
We welcome contributions! Please read our Contributing Guide for details on:
- ๐ How to report bugs
- ๐ก Suggesting enhancements
- ๐ง Development setup
- ๐ Coding standards
- โ Testing guidelines
- ๐ Pull request process
# 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
cd server-java && docker-compose up -d
# Make changes, test, commit
git commit -m "feat: add amazing feature"
git push origin feature/amazing-feature
# Open Pull RequestSee CONTRIBUTING.md for complete guidelines.
- Server README - Java Gateway documentation
- MCP Groups Guide - Complete groups workflow
- Policy Engine - Policy management
- Frontend - Web UI documentation
- VS Code Integration - VS Code setup
- Quick Start - Getting started guide
- Troubleshooting - Common issues
- โ JWT/OAuth2 authentication
- โ MCP Groups
- โ Policy-based access control
- โ STDIO to HTTP conversion
- โ Web UI
- โ Audit logging
- ๐ Rate limiting per user/group
- ๐ Caching layer for tool responses
- ๐ Webhook support for audit events
- ๐ Multi-region deployment
- ๐ Grafana/Prometheus metrics
- ๐ SAML authentication support
- ๐ฎ AI-powered policy recommendations
- ๐ฎ Tool usage analytics and insights
- ๐ฎ Custom MCP server templates
- ๐ฎ Marketplace for MCP servers
- ๐ฎ Mobile app for management
This project is licensed under the MIT License - see the LICENSE file for details.
- Model Context Protocol - MCP specification
- Anthropic - Claude and MCP development
- Spring Boot - Java framework
- Keycloak - Identity and access management
- React - Frontend framework
- Documentation: docs/
- Contributing: CONTRIBUTING.md
- Issues: GitHub Issues
- Discussions: GitHub Discussions
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!