MCP Security
This guide covers security considerations and best practices for the MCP server.
Authentication
Section titled “Authentication”Client Keys (Recommended)
Section titled “Client Keys (Recommended)”Create client keys with minimal required scopes:
# Read-only access for AI assistantsfluxbase clientkeys create --name "AI Reader" \ --scopes "read:tables,read:storage"
# Limited write accessfluxbase clientkeys create --name "AI Writer" \ --scopes "read:tables,write:tables"Service Keys (Admin Only)
Section titled “Service Keys (Admin Only)”Service keys bypass Row Level Security and have full access. Use only for:
- Administrative operations
- Trusted backend services
- Development/debugging
Never expose service keys to client applications or AI assistants in untrusted environments.
Authorization Layers
Section titled “Authorization Layers”1. Scope-Based Access
Section titled “1. Scope-Based Access”Each MCP tool requires specific scopes:
# Example: Restrict to read-only operationsmcp: allowed_tools: - query_table - list_objects - download_object2. Row Level Security (RLS)
Section titled “2. Row Level Security (RLS)”All database operations respect PostgreSQL RLS policies:
-- Users can only see their own dataCREATE POLICY user_isolation ON public.orders FOR SELECT USING (user_id = current_setting('request.jwt.claims')::json->>'sub');MCP queries execute within the user’s security context.
3. Tool Whitelisting
Section titled “3. Tool Whitelisting”Restrict available tools in production:
mcp: allowed_tools: - query_table # Allow reads - search_vectors # Allow vector search # - insert_record # Block writes # - delete_record # Block deletes4. Resource Whitelisting
Section titled “4. Resource Whitelisting”Restrict available resources:
mcp: allowed_resources: - "fluxbase://schema/tables" - "fluxbase://functions" # Exclude sensitive resourcesSQL Injection Prevention
Section titled “SQL Injection Prevention”The MCP server prevents SQL injection through:
- Identifier Validation - Table and column names validated against
^[a-zA-Z_][a-zA-Z0-9_]*$ - Parameterized Queries - All values use prepared statements
- Schema Cache - Table/column existence verified before query execution
- Quoting - Identifiers properly quoted and escaped
Safe Defaults
Section titled “Safe Defaults”Mandatory Filters
Section titled “Mandatory Filters”update_record and delete_record require a filter parameter:
// This will fail - no filter provided{ "name": "delete_record", "arguments": {"table": "users"}}
// This works - filter specified{ "name": "delete_record", "arguments": { "table": "users", "filter": {"id": "eq.123"} }}Query Limits
Section titled “Query Limits”- Maximum 1000 rows per query
- Maximum 10MB file download
- Maximum 100 vector search results
Rate Limiting
Section titled “Rate Limiting”Configure per-client rate limits:
mcp: rate_limit_per_min: 100 # 100 requests per minute per clientAudit Logging
Section titled “Audit Logging”MCP operations are logged with:
- Client key ID/name
- User ID and role
- Tool/resource accessed
- Timestamp
Enable debug logging for detailed traces:
logging: level: debugBest Practices
Section titled “Best Practices”1. Principle of Least Privilege
Section titled “1. Principle of Least Privilege”Create dedicated client keys with minimal scopes:
# For a chatbot that only needs to search knowledge basefluxbase clientkeys create --name "Support Bot" \ --scopes "read:vectors"2. Separate Keys per Application
Section titled “2. Separate Keys per Application”Don’t share client keys between applications:
fluxbase clientkeys create --name "Mobile App - Production"fluxbase clientkeys create --name "Web App - Production"fluxbase clientkeys create --name "AI Assistant - Production"3. Rotate Keys Regularly
Section titled “3. Rotate Keys Regularly”Rotate client keys periodically:
# Create new keyfluxbase clientkeys create --name "AI Assistant - 2024-Q2"
# Update application configuration# Then revoke old keyfluxbase clientkeys delete "old-key-id"4. Monitor Usage
Section titled “4. Monitor Usage”Review MCP access patterns:
SELECT client_key_name, COUNT(*) as requests, DATE_TRUNC('hour', created_at) as hourFROM auth.audit_logWHERE path LIKE '/mcp%'GROUP BY 1, 3ORDER BY 3 DESC;5. Restrict in Production
Section titled “5. Restrict in Production”Disable unnecessary features in production:
mcp: enabled: true allowed_tools: - query_table - search_vectors allowed_resources: - "fluxbase://schema/tables"Common Attack Vectors
Section titled “Common Attack Vectors”Prevented Attacks
Section titled “Prevented Attacks”| Attack | Prevention |
|---|---|
| SQL Injection | Parameterized queries, identifier validation |
| Unauthorized Access | Scope-based access control |
| Data Leakage | Row Level Security |
| Bulk Deletion | Mandatory filters |
| Resource Exhaustion | Query limits, rate limiting |
Configuration Mistakes to Avoid
Section titled “Configuration Mistakes to Avoid”- Don’t use service keys for AI assistants - Use scoped client keys instead
- Don’t disable RLS - Always use RLS in production
- Don’t allow all tools - Whitelist only required tools
- Don’t expose internal schemas - Non-admin users can’t see system tables
- Don’t skip rate limiting - Configure appropriate limits
Monitoring and Alerts
Section titled “Monitoring and Alerts”Set up alerts for:
- Unusual query patterns
- Failed authentication attempts
- Rate limit violations
- Access to sensitive tables
-- Example: Alert on failed authSELECT COUNT(*)FROM auth.audit_logWHERE path LIKE '/mcp%' AND status_code = 401 AND created_at > NOW() - INTERVAL '1 hour';