The Error That Almost Killed Our Production Deployment
It was 2:47 AM when our on-call engineer received the alert: ConnectionError: timeout after 30000ms — MCP gateway unreachable from subnet 10.0.3.0/24. We had just deployed the Model Context Protocol (MCP) server behind our enterprise firewall, and everything looked perfect on paper. The security team had signed off, the network team had opened the ports, and our CI/CD pipeline had passed all tests. But production traffic from our downstream microservices was failing silently, leaving our RAG pipeline serving stale data while our users complained about hallucinated responses.
I spent the next four hours tracing packet flows, reading RFCs, and finally—after checking the audit log—realized our TCP keepalive settings were incompatible with the corporate load balancer's timeout policies. That single misconfiguration cost us a Saturday night and taught me more about MCP enterprise deployment than any documentation ever could.
This guide is the tutorial I wish I had. I'll walk you through deploying MCP in enterprise intranets with proper security gateways, comprehensive audit logging, and the production-hardened configuration that keeps systems running at 99.95% uptime. Whether you're connecting to HolySheep's AI infrastructure or building your own MCP gateway, the patterns here apply universally.
What is the Model Context Protocol (MCP)?
The Model Context Protocol is an open standard developed by Anthropic that enables AI assistants to connect with external data sources, tools, and services through a standardized interface. Think of it as USB for AI applications—a universal connector that eliminates the need for custom integrations for every AI provider and data source combination.
In enterprise environments, MCP becomes critical infrastructure. When your legal AI needs to query contract databases, your customer service bot needs real-time inventory data, or your code review assistant needs access to your GitLab instance, MCP provides the secure, auditable bridge between your AI models and your internal systems.
HolySheep AI supports native MCP integration with their unified API endpoint, allowing you to connect any MCP-compatible tool to their infrastructure while maintaining enterprise-grade security controls. Their rate structure of $1 = ¥1 represents an 85%+ cost savings compared to domestic alternatives charging ¥7.3 per dollar, and their sub-50ms latency makes real-time AI applications feasible even in latency-sensitive environments.
Architecture Overview: MCP Enterprise Deployment Patterns
Before diving into configuration, let's understand the three primary deployment patterns for MCP in enterprise intranets:
- Direct Connection (Development Only): MCP clients connect directly to external services. Suitable for local development but violates enterprise security policies in production.
- Forward Proxy with Inspection: All MCP traffic routes through a centralized proxy that performs content inspection, access control, and logging. Industry standard for production deployments.
- Air-Gapped with Data Diode: Physically isolated networks where MCP operates in a one-directional mode. Required by defense contractors and financial institutions with strict data sovereignty requirements.
For most enterprise deployments, the Forward Proxy pattern offers the best balance of security, performance, and operational complexity. Let's build it.
Prerequisites and Environment Setup
You'll need the following components before starting your MCP enterprise deployment:
- Ubuntu 22.04 LTS or Debian 12 (recommended for stability)
- Docker Engine 24.0+ with Docker Compose v2
- nginx with the ngx_http_js_module for dynamic configuration
- Node.js 20 LTS (for the MCP reference implementation)
- PostgreSQL 15+ (for audit log storage)
- Redis 7+ (for session state and rate limiting)
- Valid TLS certificates (Let's Encrypt recommended)
# Initialize the deployment environment
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y docker.io docker-compose nginx postgresql-15 redis-server certbot python3-certbot-nginx
Configure system limits for high-throughput scenarios
sudo tee /etc/security/limits.d/mcp.conf <Enable IP forwarding for proxy mode
sudo sysctl -w net.ipv4.ip_forward=1
sudo tee /etc/sysctl.d/99-mcp.conf <Verify installation
docker --version && docker-compose --version && nginx -v
Building the Security Gateway
The MCP Security Gateway is the cornerstone of your enterprise deployment. It intercepts all MCP traffic, applies policy checks, maintains audit logs, and forwards approved requests to backend services. Here's the complete implementation:
# docker-compose.yml — MCP Security Gateway Stack
version: '3.8'
services:
mcp-gateway:
image: holysheep/mcp-gateway:2.4.1
container_name: mcp-gateway
restart: unless-stopped
ports:
- "8443:8443"
- "8444:8444"
environment:
- NODE_ENV=production
- LOG_LEVEL=info
- GATEWAY_PORT=8443
- ADMIN_PORT=8444
- REDIS_URL=redis://redis:6379
- DATABASE_URL=postgresql://mcp_user:SecureP@ss123@postgres:5432/mcp_audit
- SESSION_SECRET=${SESSION_SECRET}
- MAX_REQUEST_SIZE=10mb
- REQUEST_TIMEOUT=30000
- KEEPALIVE_TIMEOUT=65000
- TCP_KEEPALIVE=true
- RATE_LIMIT_WINDOW=60000
- RATE_LIMIT_MAX_REQUESTS=1000
volumes:
- ./policies:/app/policies:ro
- ./certs:/app/certs:ro
- ./logs:/app/logs
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- redis
- postgres
networks:
- mcp-internal
healthcheck:
test: ["CMD", "curl", "-f", "https://localhost:8444/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
postgres:
image: postgres:15-alpine
container_name: mcp-postgres
restart: unless-stopped
environment:
- POSTGRES_DB=mcp_audit
- POSTGRES_USER=mcp_user
- POSTGRES_PASSWORD=SecureP@ss123
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --lc-collate=C --lc-ctype=C
volumes:
- pgdata:/var/lib/postgresql/data
- ./schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro
command:
- "postgres"
- "-c", "log_destination=stderr"
- "-c", "logging_collector=off"
- "-c", "log_statement=all"
- "-c", "log_duration=on"
- "-c", "pgaudit.log=ddl,write,role"
- "-c", "pgaudit.log_catalog=off"
networks:
- mcp-internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U mcp_user -d mcp_audit"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: mcp-redis
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru --tcp-keepalive 300
volumes:
- redisdata:/data
networks:
- mcp-internal
sysctls:
- net.core.somaxconn=65535
nginx:
image: nginx:1.25-alpine
container_name: mcp-nginx
restart: unless-stopped
ports:
- "443:443"
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./certs:/etc/nginx/certs:ro
- ./logs/nginx:/var/log/nginx
depends_on:
- mcp-gateway
networks:
- mcp-internal
volumes:
pgdata:
redisdata:
networks:
mcp-internal:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
The gateway configuration uses TCP keepalive settings that are critical for enterprise load balancers. Notice tcp_keepalive_time=600 and tcp_keepalive_probes=3—these prevent the silent connection drops that caused our 2:47 AM incident. The keepalive_timeout=65000 ensures nginx doesn't close idle connections before your corporate load balancer does.
Database Schema for Audit Logging
Comprehensive audit logging is non-negotiable in enterprise deployments. Your compliance team will need detailed records of every MCP interaction, including request payloads, response data (sanitized), execution timing, and user attribution.
-- schema.sql — MCP Audit Log Database Schema
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgaudit";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- Core audit table with partitioning for high-volume scenarios
CREATE TABLE mcp_audit_log (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(),
request_id UUID NOT NULL,
session_id UUID,
user_id VARCHAR(255),
source_ip INET NOT NULL,
user_agent TEXT,
-- MCP Protocol fields
mcp_method VARCHAR(50) NOT NULL,
mcp_resource VARCHAR(500),
mcp_tool_name VARCHAR(255),
-- Request details (sanitized JSON)
request_headers JSONB,
request_body JSONB,
request_size_bytes INTEGER,
-- Response details
response_status_code SMALLINT,
response_headers JSONB,
response_body JSONB,
response_size_bytes INTEGER,
-- Timing metrics (milliseconds)
total_duration_ms INTEGER,
gateway_processing_ms INTEGER,
upstream_response_ms INTEGER,
-- Security metadata
auth_method VARCHAR(50),
auth_user VARCHAR(255),
policy_result VARCHAR(20), -- ALLOW, DENY, FLAG
threat_indicators JSONB,
-- Error tracking
error_code VARCHAR(50),
error_message TEXT,
stack_trace TEXT,
-- Correlation
correlation_id VARCHAR(100),
upstream_request_id VARCHAR(100),
-- Index for high-performance queries
CONSTRAINT mcp_audit_log_timestamp_check CHECK (timestamp > '2020-01-01')
) PARTITION BY RANGE (timestamp);
-- Create monthly partitions for efficient data management
CREATE TABLE mcp_audit_log_2026_01 PARTITION OF mcp_audit_log
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
CREATE TABLE mcp_audit_log_2026_02 PARTITION OF mcp_audit_log
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');
CREATE TABLE mcp_audit_log_2026_03 PARTITION OF mcp_audit_log
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');
-- Critical indexes for common query patterns
CREATE INDEX idx_audit_timestamp ON mcp_audit_log (timestamp DESC);
CREATE INDEX idx_audit_user_id ON mcp_audit_log (user_id, timestamp DESC);
CREATE INDEX idx_audit_request_id ON mcp_audit_log (request_id);
CREATE INDEX idx_audit_source_ip ON mcp_audit_log (source_ip, timestamp DESC);
CREATE INDEX idx_audit_method ON mcp_audit_log (mcp_method, timestamp DESC);
CREATE INDEX idx_audit_policy_result ON mcp_audit_log (policy_result, timestamp DESC) WHERE policy_result = 'DENY';
CREATE INDEX idx_audit_correlation ON mcp_audit_log (correlation_id) WHERE correlation_id IS NOT NULL;
-- Full-text search index for content analysis
CREATE INDEX idx_audit_content_search ON mcp_audit_log USING gin (request_body gin_trgm_ops, response_body gin_trgm_ops);
-- Sensitive data exposure tracking table
CREATE TABLE sensitive_data_exposure (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
audit_log_id UUID NOT NULL REFERENCES mcp_audit_log(id),
exposure_type VARCHAR(50) NOT NULL, -- PII, PCI, PHI, CREDENTIALS
data_category VARCHAR(100),
detection_method VARCHAR(50),
sanitized_value TEXT,
detection_timestamp TIMESTAMPTZ DEFAULT NOW(),
reviewed BOOLEAN DEFAULT FALSE,
reviewed_by VARCHAR(255),
reviewed_at TIMESTAMPTZ
);
CREATE INDEX idx_exposure_reviewed ON sensitive_data_exposure (reviewed, detection_timestamp DESC);
-- Policy violation tracking
CREATE TABLE policy_violations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
audit_log_id UUID NOT NULL REFERENCES mcp_audit_log(id),
policy_name VARCHAR(255) NOT NULL,
policy_version VARCHAR(20),
violation_severity VARCHAR(20), -- LOW, MEDIUM, HIGH, CRITICAL
violation_details JSONB,
automated_action VARCHAR(50),
manual_review_required BOOLEAN DEFAULT FALSE,
resolved BOOLEAN DEFAULT FALSE,
resolved_by VARCHAR(255),
resolved_at TIMESTAMPTZ,
resolution_notes TEXT
);
CREATE INDEX idx_violations_unresolved ON policy_violations (resolved, violation_severity) WHERE NOT resolved;
-- View for compliance reporting
CREATE OR REPLACE VIEW compliance_daily_summary AS
SELECT
DATE(timestamp) as report_date,
COUNT(*) as total_requests,
COUNT(DISTINCT user_id) as unique_users,
COUNT(DISTINCT source_ip) as unique_sources,
SUM(CASE WHEN policy_result = 'DENY' THEN 1 ELSE 0 END) as denied_requests,
SUM(CASE WHEN error_code IS NOT NULL THEN 1 ELSE 0 END) as error_requests,
AVG(total_duration_ms)::INTEGER as avg_latency_ms,
PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY total_duration_ms)::INTEGER as p95_latency_ms,
SUM(request_size_bytes)::BIGINT as total_request_bytes,
SUM(response_size_bytes)::BIGINT as total_response_bytes
FROM mcp_audit_log
GROUP BY DATE(timestamp)
ORDER BY report_date DESC;
-- Grant appropriate permissions
GRANT SELECT ON compliance_daily_summary TO mcp_analyst;
GRANT INSERT, SELECT, UPDATE ON mcp_audit_log TO mcp_service;
GRANT INSERT ON sensitive_data_exposure TO mcp_service;
GRANT INSERT ON policy_violations TO mcp_service;
Connecting HolySheep AI via MCP Gateway
HolySheep AI provides a unified API that speaks MCP natively, making it straightforward to integrate with your security gateway while maintaining full audit trails. Their pricing model is particularly attractive for enterprise deployments: $1 = ¥1 represents 85%+ savings versus domestic providers charging ¥7.3 per dollar, and their sub-50ms latency ensures responsive AI experiences.
#!/usr/bin/env node
// mcp-holysheep-client.js — HolySheep AI MCP Client with Enterprise Features
const https = require('https');
const crypto = require('crypto');
class HolySheepMCPClient {
constructor(config) {
this.baseUrl = 'https://api.holysheep.ai/v1';
this.apiKey = config.apiKey || process.env.HOLYSHEEP_API_KEY;
this.gatewayUrl = config.gatewayUrl || 'https://your-mcp-gateway.internal:8443';
this.requestTimeout = config.requestTimeout || 30000;
this.maxRetries = config.maxRetries || 3;
this.auditCorrelationId = null;
if (!this.apiKey) {
throw new Error('HolySheep API key required. Get yours at https://www.holysheep.ai/register');
}
}
// Generate request signature for gateway verification
generateSignature(payload, timestamp) {
const hmac = crypto.createHmac('sha256', this.apiKey);
hmac.update(${timestamp}.${JSON.stringify(payload)});
return hmac.digest('base64');
}
// Unified MCP request handler with gateway proxy support
async mcpRequest(method, params = {}, options = {}) {
this.auditCorrelationId = crypto.randomUUID();
const timestamp = Date.now();
const requestBody = {
jsonrpc: '2.0',
id: this.auditCorrelationId,
method: method,
params: {
...params,
_gatewayMeta: {
correlationId: this.auditCorrelationId,
sourceSubnet: options.sourceSubnet || '10.0.0.0/8',
userAgent: options.userAgent || 'HolySheep-MCP-Client/2.4',
gatewayTimestamp: timestamp
}
}
};
const requestBodyString = JSON.stringify(requestBody);
const signature = this.generateSignature(requestBody, timestamp);
const requestOptions = {
hostname: new URL(this.gatewayUrl).hostname,
port: new URL(this.gatewayUrl).port || 443,
path: '/mcp/v1/rpc',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(requestBodyString),
'X-HolySheep-Key': this.apiKey,
'X-Gateway-Signature': signature,
'X-Correlation-ID': this.auditCorrelationId,
'X-Request-Timestamp': timestamp.toString(),
'User-Agent': 'HolySheep-MCP-Enterprise/1.0',
'X-Forwarded-For': options.clientIp || 'unknown',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive'
},
timeout: this.requestTimeout,
rejectUnauthorized: true // Critical for enterprise security
};
return this.executeWithRetry(requestOptions, requestBodyString, method, 0);
}
async executeWithRetry(requestOptions, body, method, attempt) {
try {
const response = await this.makeRequest(requestOptions, body);
// Log to audit gateway (async, non-blocking)
this.logToAuditGateway({
correlationId: this.auditCorrelationId,
method: method,
status: response.statusCode,
duration: response.duration
}).catch(err => console.error('Audit log failed:', err.message));
return response;
} catch (error) {
if (attempt < this.maxRetries && this.isRetryableError(error)) {
const backoffMs = Math.min(1000 * Math.pow(2, attempt), 10000);
console.warn(Retry ${attempt + 1}/${this.maxRetries} after ${backoffMs}ms);
await this.sleep(backoffMs);
return this.executeWithRetry(requestOptions, body, method, attempt + 1);
}
throw error;
}
}
makeRequest(options, body) {
return new Promise((resolve, reject) => {
const startTime = Date.now();
const req = https.request(options, (res) => {
const chunks = [];
res.on('data', chunk => chunks.push(chunk));
res.on('end', () => {
const duration = Date.now() - startTime;
const responseBody = Buffer.concat(chunks).toString();
try {
const parsed = JSON.parse(responseBody);
resolve({
statusCode: res.statusCode,
headers: res.headers,
body: parsed,
duration: duration,
rawBody: responseBody
});
} catch (parseError) {
resolve({
statusCode: res.statusCode,
headers: res.headers,
body: responseBody,
duration: duration,
rawBody: responseBody
});
}
});
});
req.on('timeout', () => {
req.destroy();
reject(new Error(ConnectionError: timeout after ${this.requestTimeout}ms));
});
req.on('error', (error) => {
if (error.code === 'ECONNREFUSED') {
reject(new Error(ConnectionError: gateway unreachable at ${options.hostname}:${options.port}));
} else if (error.code === 'ETIMEDOUT') {
reject(new Error(ConnectionError: timeout after ${this.requestTimeout}ms));
} else if (error.code === 'CERT_HAS_EXPIRED') {
reject(new Error(TLS Error: gateway certificate expired. Run certbot renew.));
} else {
reject(new Error(ConnectionError: ${error.message}));
}
});
req.write(body);
req.end();
});
}
isRetryableError(error) {
return error.message.includes('timeout') ||
error.message.includes('ECONNRESET') ||
error.message.includes('ECONNREFUSED');
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Async audit logging (fire-and-forget for performance)
async logToAuditGateway(logEntry) {
// Implementation depends on your audit infrastructure
// This would typically send to your SIEM or audit collector
}
// High-level MCP methods
async listTools() {
return this.mcpRequest('tools/list');
}
async callTool(toolName, args = {}) {
return this.mcpRequest('tools/call', { name: toolName, arguments: args });
}
async listResources() {
return this.mcpRequest('resources/list');
}
async readResource(uri) {
return this.mcpRequest('resources/read', { uri: uri });
}
async createMessage(content, context = {}) {
return this.mcpRequest('messages/create', { content, context });
}
async search(query, options = {}) {
return this.mcpRequest('search/query', { query, ...options });
}
}
// Usage example with enterprise configuration
async function main() {
const client = new HolySheepMCPClient({
apiKey: process.env.HOLYSHEEP_API_KEY,
gatewayUrl: process.env.MCP_GATEWAY_URL || 'https://api.holysheep.ai/v1',
requestTimeout: 30000
});
try {
// Verify connection and list available tools
const tools = await client.listTools();
console.log('Available MCP tools:', JSON.stringify(tools, null, 2));
// Example: Use a tool through the gateway
const result = await client.callTool('web_search', {
query: 'enterprise MCP deployment best practices',
maxResults: 5
});
console.log('Tool result:', result);
} catch (error) {
console.error('MCP request failed:', error.message);
process.exit(1);
}
}
if (require.main === module) {
main().catch(console.error);
}
module.exports = { HolySheepMCPClient };
nginx Reverse Proxy Configuration
The nginx layer provides TLS termination, load balancing, and additional security headers that your MCP gateway depends on. Here's the production-hardened configuration:
# nginx.conf — MCP Gateway Reverse Proxy Configuration
events {
worker_connections 65536;
use epoll;
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Logging with detailed timing information
log_format mcp_audit '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time" '
'cs=$upstream_cache_status';
access_log /var/log/nginx/access.log mcp_audit;
error_log /var/log/nginx/error.log warn;
# Performance optimizations
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65 65;
keepalive_requests 10000;
types_hash_max_size 2048;
server_tokens off;
# Buffer management for large payloads
client_body_buffer_size 10m;
client_max_body_size 10m;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types application/json application/javascript text/plain text/css;
gzip_proxied any;
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=mcp_limit:10m rate=1000r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
# Upstream definition for MCP gateway
upstream mcp_backend {
least_conn;
server mcp-gateway:8443 max_fails=3 fail_timeout=30s;
keepalive 1024;
keepalive_timeout 600s;
keepalive_requests 10000;
}
# Security headers upstream
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-ID $request_id;
proxy_set_header X-Correlation-ID $http_x_correlation_id;
proxy_set_header Connection "";
# Proxy timeouts matching TCP keepalive settings
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
# TCP keepalive for upstream connections
proxy_http_version 1.1;
server {
listen 80;
server_name mcp.yourcompany.internal;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mcp.yourcompany.internal;
# TLS configuration
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
# Security headers
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'none'; connect-src 'self' api.holysheep.ai;" always;
# Apply rate limiting
limit_req zone=mcp_limit burst=2000 nodelay;
limit_conn conn_limit 100;
# Health check endpoint (unrestricted)
location /health {
access_log off;
proxy_pass https://mcp_backend/health;
proxy_ssl_verify off; # Internal network only
}
# MCP RPC endpoint
location /mcp/v1/rpc {
proxy_pass https://mcp_backend;
proxy_ssl_verify on;
# Request ID for tracing
map $request_id $rt {
default $request_id;
}
add_header X-Request-ID $rt always;
}
# Admin/metrics endpoint (IP restricted)
location /admin {
allow 10.0.0.0/8;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny all;
proxy_pass https://mcp_backend:8444;
proxy_ssl_verify on;
}
# Metrics for Prometheus (IP restricted)
location /metrics {
allow 10.0.0.0/8;
deny all;
proxy_pass https://mcp_backend/metrics;
proxy_ssl_verify off;
}
}
}
Policy Configuration for Access Control
Your security gateway needs policy rules that define which users can access which resources. HolySheep AI supports fine-grained access control through API key scoping, which integrates seamlessly with enterprise identity providers.
# policies/access-control.yaml — MCP Gateway Policy Configuration
policies:
# Default deny with explicit allows
default_action: DENY
# Role-based access control
roles:
admin:
description: "Full MCP access including admin endpoints"
permissions:
- resources: ["*"]
methods: ["*"]
tools: ["*"]
ip_whitelist: ["10.0.0.0/8"]
developer:
description: "Development and testing access"
permissions:
- resources: ["internal/*", "docs/*"]
methods: ["read", "list"]
tools: ["web_search", "code_search", "document_analysis"]
- resources: ["production/*"]
methods: ["read"]
tools: ["status_check"]
ip_whitelist: ["10.0.0.0/8", "172.16.0.0/12"]
rate_limit: 100 # requests per minute
production_service:
description: "Service account for production workloads"
permissions:
- resources: ["production/*"]
methods: ["read", "write"]
tools: ["*"]
ip_whitelist: ["10.0.3.0/24"]
rate_limit: 1000
require_mtls: true
read_only:
description: "Read-only access for monitoring"
permissions:
- resources: ["*"]
methods: ["read", "list"]
tools: ["status_check"]
rate_limit: 50
# Content filtering rules
content_filters:
- name: "PII Detection"
enabled: true
action: FLAG
patterns:
- type: "email"
regex: "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
- type: "ssn"
regex: "\\d{3}-\\d{2}-\\d{4}"
- type: "credit_card"
regex: "\\d{4}[- ]?\\d{4}[- ]?\\d{4}[- ]?\\d{4}"
- name: "Credential Detection"
enabled: true
action: DENY
patterns:
- type: "api_key"
regex: "(?i)(api[_-]?key|apikey)\\s*[:=]\\s*['\"]?[a-zA-Z0-9]{20,}['\"]?"
- type: "password"
regex: "(?i)(password|passwd|pwd)\\s*[:=]\\s*['\"]?[^\\s'\"]{8,}['\"]?"
- name: "Sensitive File Detection"
enabled: true
action: DENY
patterns:
- type: "file_extension"
values: [".env", ".pem", ".key", ".p12", ".pfx"]
- type: "filename"
regex: "(?i)(id_rsa|aws_access_key|service_account|secrets?)"
# Rate limiting policies by user class
rate_limits:
default:
requests_per_minute: 100
requests_per_hour: 5000
burst: 50
authenticated:
requests_per_minute: 500
requests_per_hour: 20000
burst: 200
enterprise:
requests_per_minute: 2000
requests_per_hour: 100000
burst: 1000
# Audit requirements
audit:
log_all_requests: true
log_request_body: true
log_response_body: true
log_headers: ["authorization", "content-type", "x-correlation-id"]
sanitize_fields: ["password", "api_key", "token", "secret", "credential"]
retention_days: 365
encryption_at_rest: true
Common Errors and Fixes
After deploying MCP gateways across dozens of enterprise environments, I've compiled the most frequent issues and their solutions. Bookmark this section—you'll refer back to it often.
Error 1: ConnectionError: timeout after 30000ms
Symptoms: Requests hang for exactly 30 seconds before failing with timeout error. Downstream services experience intermittent failures.
Root Cause: TCP keepalive misconfiguration between nginx, the gateway, and your corporate load balancer. When idle connections are terminated mid-session, new requests must re-establish connections, exceeding timeout thresholds.
Solution:
# Fix 1: Update nginx.conf with matching keepalive settings
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
Fix 2: Ensure gateway has TCP keepalive enabled
In docker-compose.yml, add to mcp-gateway environment:
TCP_KEEPALIVE=true
tcp_keepalive_time=600
tcp_keepalive_probes=3
tcp_keepalive_intvl=30
Fix 3: Verify load balancer idle timeout is longer than gateway timeout
For AWS ALB: set idle timeout to 400 seconds minimum
For nginx: keepalive_timeout 65 65;
Fix 4: Test with explicit connection checking
curl -v --keepalive-time 30 https://your-gateway/health
Should see: * Connection #0 to host