aios-core
Version:
Synkra AIOS: AI-Orchestrated System for Full Stack Development - Core Framework
809 lines (700 loc) • 28 kB
YAML
tool:
schema_version: 2.0
id: supabase
type: mcp
name: Supabase Platform Management
version: 1.0.0
description: Supabase project and database management with SQL execution, migrations, RLS policies, and real-time subscriptions
knowledge_strategy: executable
executable_knowledge:
validators:
# Validator for execute_sql
- id: validate-execute-sql
validates: execute_sql
language: javascript
checks:
- required_fields: [project_id, query]
- sql_injection_prevention: true
function: |
(function() {
const errors = [];
// 1. Required fields
if (!args.args.project_id) {
errors.push("project_id is required");
}
if (!args.args.query) {
errors.push("query is required");
}
// 2. Validate project_id format (proj_xxx)
if (args.args.project_id && !/^proj_[a-z0-9_]+$/i.test(args.args.project_id)) {
errors.push("project_id must match format: proj_[id]");
}
// 3. Basic SQL injection prevention
if (args.args.query) {
const query = args.args.query.toLowerCase();
// Check for dangerous patterns
if (query.includes('drop table') || query.includes('drop database')) {
errors.push("DROP operations not allowed via execute_sql - use apply_migration");
}
// Check for DDL operations
if (query.match(/\b(create|alter|drop)\s+(table|index|view|function|trigger)/)) {
errors.push("DDL operations not allowed in execute_sql - use apply_migration instead");
}
}
return {
valid: errors.length === 0,
errors: errors
};
})();
# Validator for apply_migration
- id: validate-apply-migration
validates: apply_migration
language: javascript
checks:
- required_fields: [project_id, name, query]
- migration_name_format: snake_case
function: |
(function() {
const errors = [];
// 1. Required fields
if (!args.args.project_id) {
errors.push("project_id is required");
}
if (!args.args.name) {
errors.push("name is required");
}
if (!args.args.query) {
errors.push("query is required");
}
// 2. Validate migration name format (snake_case)
if (args.args.name && !/^[a-z0-9_]+$/.test(args.args.name)) {
errors.push("migration name must be snake_case (lowercase letters, numbers, underscores only)");
}
// 3. Check for hardcoded IDs in data migrations
if (args.args.query && args.args.query.match(/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i)) {
errors.push("WARNING: Migration contains hardcoded UUID - consider using generated IDs instead");
}
return {
valid: errors.length === 0,
errors: errors
};
})();
# Validator for create_branch
- id: validate-create-branch
validates: create_branch
language: javascript
checks:
- required_fields: [project_id, confirm_cost_id]
- branch_name_format: true
function: |
(function() {
const errors = [];
// 1. Required fields
if (!args.args.project_id) {
errors.push("project_id is required");
}
if (!args.args.confirm_cost_id) {
errors.push("confirm_cost_id is required - call confirm_cost first");
}
// 2. Validate branch name if provided
if (args.args.name && !/^[a-z0-9-]+$/.test(args.args.name)) {
errors.push("branch name must be lowercase letters, numbers, and hyphens only");
}
return {
valid: errors.length === 0,
errors: errors
};
})();
# Validator for deploy_edge_function
- id: validate-deploy-edge-function
validates: deploy_edge_function
language: javascript
checks:
- required_fields: [project_id, name, files]
- file_structure: true
function: |
(function() {
const errors = [];
// 1. Required fields
if (!args.args.project_id) {
errors.push("project_id is required");
}
if (!args.args.name) {
errors.push("name is required");
}
if (!args.args.files) {
errors.push("files array is required");
}
// 2. Validate files structure
if (args.args.files) {
if (!Array.isArray(args.args.files)) {
errors.push("files must be an array");
} else {
args.args.files.forEach((file, index) => {
if (!file.name) {
errors.push(`files[${index}] missing required 'name' field`);
}
if (!file.content) {
errors.push(`files[${index}] missing required 'content' field`);
}
});
}
}
// 3. Check for entrypoint
if (args.args.entrypoint_path && !args.args.entrypoint_path.endsWith('.ts')) {
errors.push("entrypoint_path should be a TypeScript file (.ts)");
}
return {
valid: errors.length === 0,
errors: errors
};
})();
# Validator for create_project
- id: validate-create-project
validates: create_project
language: javascript
checks:
- required_fields: [name, region, organization_id, confirm_cost_id]
- region_validation: true
function: |
(function() {
const errors = [];
// 1. Required fields
if (!args.args.name) {
errors.push("name is required");
}
if (!args.args.region) {
errors.push("region is required");
}
if (!args.args.organization_id) {
errors.push("organization_id is required");
}
if (!args.args.confirm_cost_id) {
errors.push("confirm_cost_id is required - call confirm_cost first");
}
// 2. Validate region
const validRegions = [
'us-west-1', 'us-east-1', 'us-east-2', 'ca-central-1',
'eu-west-1', 'eu-west-2', 'eu-west-3', 'eu-central-1', 'eu-central-2', 'eu-north-1',
'ap-south-1', 'ap-southeast-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-southeast-2',
'sa-east-1'
];
if (args.args.region && !validRegions.includes(args.args.region)) {
errors.push(`region must be one of: ${validRegions.join(', ')}`);
}
return {
valid: errors.length === 0,
errors: errors
};
})();
helpers:
- id: build-select-query
language: javascript
runtime: isolated_vm
description: "Build SELECT query with RLS considerations"
function: |
(function() {
const { table, columns, where, orderBy, limit, checkRLS } = args;
if (!table) {
return { error: 'Table name is required' };
}
let query = 'SELECT ';
query += columns && columns.length > 0 ? columns.join(', ') : '*';
query += ` FROM ${table}`;
if (where && typeof where === 'object') {
const conditions = Object.entries(where)
.map(([key, value]) => {
if (typeof value === 'string') {
return `${key} = '${value}'`;
}
return `${key} = ${value}`;
})
.join(' AND ');
query += ` WHERE ${conditions}`;
}
if (orderBy) {
query += ` ORDER BY ${orderBy}`;
}
if (limit) {
query += ` LIMIT ${limit}`;
}
return {
query: query,
requiresRLS: checkRLS !== false,
hint: checkRLS !== false ? 'Ensure RLS policies are enabled on this table' : null
};
})();
- id: build-insert-query
language: javascript
runtime: isolated_vm
description: "Build INSERT query with RLS validation"
function: |
(function() {
const { table, data, returning } = args;
if (!table) {
return { error: 'Table name is required' };
}
if (!data || typeof data !== 'object') {
return { error: 'Data object is required' };
}
const columns = Object.keys(data);
const values = Object.values(data).map(v => {
if (typeof v === 'string') {
return `'${v}'`;
}
if (v === null) {
return 'NULL';
}
return v;
});
let query = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${values.join(', ')})`;
if (returning) {
query += ` RETURNING ${returning === true ? '*' : returning}`;
}
return {
query: query,
requiresRLS: true,
hint: 'Ensure user has INSERT permissions via RLS policy'
};
})();
- id: build-update-query
language: javascript
runtime: isolated_vm
description: "Build UPDATE query with RLS validation"
function: |
(function() {
const { table, data, where, returning } = args;
if (!table) {
return { error: 'Table name is required' };
}
if (!data || typeof data !== 'object') {
return { error: 'Data object is required' };
}
if (!where || typeof where !== 'object') {
return { error: 'WHERE condition is required for UPDATE' };
}
const setClauses = Object.entries(data).map(([key, value]) => {
if (typeof value === 'string') {
return `${key} = '${value}'`;
}
if (value === null) {
return `${key} = NULL`;
}
return `${key} = ${value}`;
});
const whereClauses = Object.entries(where).map(([key, value]) => {
if (typeof value === 'string') {
return `${key} = '${value}'`;
}
return `${key} = ${value}`;
});
let query = `UPDATE ${table} SET ${setClauses.join(', ')} WHERE ${whereClauses.join(' AND ')}`;
if (returning) {
query += ` RETURNING ${returning === true ? '*' : returning}`;
}
return {
query: query,
requiresRLS: true,
hint: 'Ensure user has UPDATE permissions via RLS policy'
};
})();
- id: validate-rls-policy
language: javascript
runtime: isolated_vm
description: "Validate RLS policy syntax and structure"
function: |
(function() {
const { policy, table, operation } = args;
if (!policy || typeof policy !== 'object') {
return { valid: false, errors: ['Policy object is required'] };
}
const errors = [];
// Check required fields
if (!policy.name) {
errors.push('Policy name is required');
}
if (!table) {
errors.push('Table name is required');
}
if (!operation) {
errors.push('Operation is required (SELECT, INSERT, UPDATE, DELETE, ALL)');
}
// Validate operation
const validOperations = ['SELECT', 'INSERT', 'UPDATE', 'DELETE', 'ALL'];
if (operation && !validOperations.includes(operation.toUpperCase())) {
errors.push(`Operation must be one of: ${validOperations.join(', ')}`);
}
// Check for USING clause (required for SELECT, UPDATE, DELETE, ALL)
if (!policy.using && ['SELECT', 'UPDATE', 'DELETE', 'ALL'].includes(operation?.toUpperCase())) {
errors.push('USING clause is required for this operation');
}
// Check for WITH CHECK clause (required for INSERT, UPDATE)
if (!policy.withCheck && ['INSERT', 'UPDATE'].includes(operation?.toUpperCase())) {
errors.push('WITH CHECK clause recommended for this operation');
}
return {
valid: errors.length === 0,
errors: errors,
warnings: policy.withCheck ? [] : ['Consider adding WITH CHECK clause for additional security']
};
})();
- id: format-realtime-subscription
language: javascript
runtime: isolated_vm
description: "Format real-time subscription configuration"
function: |
(function() {
const { table, event, filter, schema } = args;
if (!table) {
return { error: 'Table name is required' };
}
const events = event ? (Array.isArray(event) ? event : [event]) : ['INSERT', 'UPDATE', 'DELETE'];
const config = {
event: events.join(','),
schema: schema || 'public',
table: table
};
if (filter) {
config.filter = filter;
}
return {
channel: `${schema || 'public'}:${table}`,
config: config,
example: `
const channel = supabase
.channel('${schema || 'public'}:${table}')
.on('postgres_changes', ${JSON.stringify(config, null, 2)}, (payload) => {
console.log('Change received!', payload)
})
.subscribe()
`
};
})();
- id: validate-table-permissions
language: javascript
runtime: isolated_vm
description: "Validate table permissions and RLS status"
function: |
(function() {
const { table, hasRLS, policies } = args;
if (!table) {
return { error: 'Table name is required' };
}
const warnings = [];
const recommendations = [];
// Check if RLS is enabled
if (hasRLS === false) {
warnings.push('RLS is disabled - table data is publicly accessible');
recommendations.push('Enable RLS with: ALTER TABLE ' + table + ' ENABLE ROW LEVEL SECURITY');
}
// Check if policies exist
if (hasRLS && (!policies || policies.length === 0)) {
warnings.push('RLS is enabled but no policies exist - table is inaccessible');
recommendations.push('Create at least one RLS policy to allow access');
}
// Check for overly permissive policies
if (policies && Array.isArray(policies)) {
policies.forEach(policy => {
if (policy.using === 'true' || policy.using === '(true)') {
warnings.push(`Policy '${policy.name}' allows access to all rows`);
}
if (policy.operation === 'ALL' && (policy.using === 'true' || !policy.using)) {
warnings.push(`Policy '${policy.name}' allows all operations without restrictions`);
}
});
}
return {
table: table,
rlsEnabled: hasRLS === true,
policyCount: policies ? policies.length : 0,
warnings: warnings,
recommendations: recommendations,
isSecure: hasRLS && policies && policies.length > 0
};
})();
- id: parse-postgres-error
language: javascript
runtime: isolated_vm
description: "Parse and format Postgres error messages"
function: |
(function() {
const { error, query } = args;
if (!error) {
return null;
}
const result = {
message: error.message || 'Unknown error',
code: error.code || null,
hint: null,
context: query ? `Query: ${query.substring(0, 100)}...` : null
};
// Common Postgres error codes
const errorMap = {
'23505': 'Unique constraint violation',
'23503': 'Foreign key constraint violation',
'23502': 'Not null constraint violation',
'23514': 'Check constraint violation',
'42P01': 'Table does not exist',
'42703': 'Column does not exist',
'42501': 'Insufficient privilege (check RLS policies)',
'42883': 'Function does not exist'
};
if (error.code && errorMap[error.code]) {
result.hint = errorMap[error.code];
}
// RLS-specific hints
if (error.code === '42501' || error.message?.includes('permission denied')) {
result.hint = 'Permission denied - check RLS policies and user authentication';
result.rlsHint = 'Ensure user is authenticated and RLS policy allows this operation';
}
return result;
})();
- id: generate-migration-name
language: javascript
runtime: isolated_vm
description: "Generate timestamped migration name"
function: |
(function() {
const { description } = args;
if (!description) {
return { error: 'Description is required' };
}
// Convert to snake_case
const snakeCase = description
.toLowerCase()
.replace(/[^a-z0-9]+/g, '_')
.replace(/^_|_$/g, '');
// Generate timestamp (YYYYMMDDHHMMSS format)
const now = new Date();
const timestamp = now.toISOString()
.replace(/[-:T.]/g, '')
.substring(0, 14);
const migrationName = `${timestamp}_${snakeCase}`;
return {
name: migrationName,
timestamp: timestamp,
description: snakeCase,
example: `apply_migration({ name: "${migrationName}", query: "..." })`
};
})();
api_complexity:
rls_policy_patterns:
- pattern: authenticated_user
description: "Allow access only to authenticated users"
example: |
USING (auth.uid() IS NOT NULL)
use_case: "Restrict access to logged-in users only"
- pattern: user_owned_rows
description: "Users can only access their own rows"
example: |
USING (auth.uid() = user_id)
use_case: "Private user data (profiles, settings)"
- pattern: role_based_access
description: "Access based on user role"
example: |
USING (
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid()
AND role IN ('admin', 'editor')
)
)
use_case: "Admin panels, content management"
- pattern: team_member_access
description: "Access for team/organization members"
example: |
USING (
EXISTS (
SELECT 1 FROM team_members
WHERE team_id = projects.team_id
AND user_id = auth.uid()
)
)
use_case: "Collaborative workspaces, multi-tenant apps"
realtime_subscription_patterns:
- pattern: table_changes
description: "Subscribe to all changes on a table"
config: |
{
event: '*',
schema: 'public',
table: 'messages'
}
use_case: "Real-time chat, activity feeds"
- pattern: filtered_changes
description: "Subscribe to specific rows"
config: |
{
event: 'INSERT',
schema: 'public',
table: 'messages',
filter: 'room_id=eq.123'
}
use_case: "Room-specific updates, filtered feeds"
- pattern: user_specific_changes
description: "Subscribe to user's own data"
config: |
{
event: '*',
schema: 'public',
table: 'notifications',
filter: 'user_id=eq.[USER_ID]'
}
use_case: "User notifications, personal updates"
auth_integration_quirks:
- quirk: auth_uid_null
description: "auth.uid() returns NULL for unauthenticated requests"
impact: "RLS policies using auth.uid() will block anonymous access"
solution: "Use separate policies for authenticated and anonymous users"
- quirk: jwt_token_expiry
description: "JWT tokens expire after configured duration (default 1 hour)"
impact: "Long-running operations may fail mid-execution"
solution: "Implement token refresh logic in client applications"
- quirk: rls_bypass_service_role
description: "Service role key bypasses RLS policies"
impact: "Backend operations ignore RLS - can access all data"
solution: "Never expose service role key to clients - use anon/user keys only"
- quirk: policy_evaluation_order
description: "Multiple policies are OR'd together (any match grants access)"
impact: "Cannot create deny policies - all policies must grant access"
solution: "Design policies to be restrictive by default"
anti_patterns:
- pattern: missing_rls_policies
description: "Enabling RLS without creating policies"
category: security
severity: high
wrong: |
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- ❌ No policies created - table is now inaccessible
correct: |
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view own profile"
ON users FOR SELECT
USING (auth.uid() = id);
CREATE POLICY "Users can update own profile"
ON users FOR UPDATE
USING (auth.uid() = id);
-- ✅ RLS enabled with appropriate policies
rationale: "RLS without policies makes tables completely inaccessible. Always create policies after enabling RLS."
- pattern: overly_permissive_policies
description: "Using USING (true) for all operations"
category: security
severity: critical
wrong: |
CREATE POLICY "Allow all"
ON sensitive_data FOR ALL
USING (true);
-- ❌ Allows anyone to do anything
correct: |
CREATE POLICY "Allow authenticated users"
ON sensitive_data FOR SELECT
USING (auth.uid() IS NOT NULL AND auth.uid() = user_id);
-- ✅ Restricts access to authenticated users and their own data
rationale: "USING (true) defeats the purpose of RLS. Always implement meaningful access controls."
- pattern: hardcoded_uuids_in_migrations
description: "Hardcoding UUIDs in data migrations"
category: migrations
severity: medium
wrong: |
-- ❌ Hardcoded UUID will fail if record doesn't exist
INSERT INTO projects (id, name, owner_id)
VALUES ('123e4567-e89b-12d3-a456-426614174000', 'My Project', '...');
correct: |
-- ✅ Generate UUIDs or use RETURNING clause
INSERT INTO projects (name, owner_id)
VALUES ('My Project', (SELECT id FROM users WHERE email = 'admin@example.com'))
RETURNING id;
rationale: "Hardcoded UUIDs cause migration failures across environments. Use generated IDs or lookups."
- pattern: ddl_in_execute_sql
description: "Running DDL operations via execute_sql"
category: migrations
severity: high
wrong: |
execute_sql({
query: "CREATE TABLE users (id uuid, name text)"
})
-- ❌ DDL not tracked in migrations
correct: |
apply_migration({
name: "create_users_table",
query: "CREATE TABLE users (id uuid PRIMARY KEY DEFAULT uuid_generate_v4(), name text NOT NULL)"
})
-- ✅ DDL tracked in migrations table
rationale: "DDL operations must be tracked via migrations for version control and rollback capability."
examples:
execute_sql:
- scenario: success
description: "Execute SELECT query with RLS"
input:
project_id: "proj_abc123"
query: "SELECT * FROM posts WHERE user_id = auth.uid()"
output:
rows: [{ id: 1, title: "My Post", user_id: "user_xyz" }]
count: 1
- scenario: failure_invalid_param
description: "Missing required project_id"
input:
query: "SELECT * FROM posts"
error:
code: VALIDATION_ERROR
message: "project_id is required"
validator: validate-execute-sql
- scenario: failure_ddl_operation
description: "Attempting DDL via execute_sql"
input:
project_id: "proj_abc123"
query: "CREATE TABLE test (id int)"
error:
code: VALIDATION_ERROR
message: "DDL operations not allowed in execute_sql - use apply_migration instead"
validator: validate-execute-sql
apply_migration:
- scenario: success
description: "Apply migration to create table"
input:
project_id: "proj_abc123"
name: "create_posts_table"
query: |
CREATE TABLE posts (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
title text NOT NULL,
content text,
user_id uuid REFERENCES auth.users(id),
created_at timestamptz DEFAULT now()
);
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Users can view own posts"
ON posts FOR SELECT
USING (auth.uid() = user_id);
output:
migration_id: "mig_xyz789"
status: "applied"
- scenario: failure_invalid_param
description: "Invalid migration name format"
input:
project_id: "proj_abc123"
name: "CreatePostsTable"
query: "CREATE TABLE posts (id int)"
error:
code: VALIDATION_ERROR
message: "migration name must be snake_case (lowercase letters, numbers, underscores only)"
validator: validate-apply-migration
mcp_specific:
server_command: "https://mcp.supabase.com/mcp"
transport: sse
auth: oauth
query_parameters:
- name: project_ref
required: false
description: "Scope server to specific project (recommended)"
- name: read_only
required: false
description: "Restrict to read-only operations (recommended)"
- name: features
required: false
description: "Specify which tool groups to enable"
health_check:
method: tool_call
command: list_projects
expected_response: "Array of projects or organization prompt"
timeout_ms: 10000