Skip to main content
Glama
schema.sql12.8 kB
-- Database Schema for AI MCP Gateway -- Version: 1.0.0 -- Description: Creates tables for conversations, messages, context summaries, and LLM call logs -- Enable UUID extension CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Conversations table CREATE TABLE IF NOT EXISTS conversations ( id VARCHAR(255) PRIMARY KEY, user_id VARCHAR(255), project_id VARCHAR(255), mode VARCHAR(50) DEFAULT 'web', metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_message_at TIMESTAMP, message_count INTEGER DEFAULT 0, total_cost DECIMAL(10, 6) DEFAULT 0.00 ); -- Index for faster lookups CREATE INDEX IF NOT EXISTS idx_conversations_user_id ON conversations(user_id); CREATE INDEX IF NOT EXISTS idx_conversations_project_id ON conversations(project_id); CREATE INDEX IF NOT EXISTS idx_conversations_created_at ON conversations(created_at DESC); -- Messages table CREATE TABLE IF NOT EXISTS messages ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), conversation_id VARCHAR(255) NOT NULL REFERENCES conversations(id) ON DELETE CASCADE, role VARCHAR(50) NOT NULL CHECK (role IN ('user', 'assistant', 'system', 'tool')), content TEXT NOT NULL, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, tokens_input INTEGER DEFAULT 0, tokens_output INTEGER DEFAULT 0 ); -- Index for faster message retrieval CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages(conversation_id); CREATE INDEX IF NOT EXISTS idx_messages_created_at ON messages(created_at DESC); CREATE INDEX IF NOT EXISTS idx_messages_role ON messages(role); -- Context summaries table CREATE TABLE IF NOT EXISTS context_summaries ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), conversation_id VARCHAR(255) NOT NULL REFERENCES conversations(id) ON DELETE CASCADE, version INTEGER DEFAULT 1, summary JSONB NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, message_count_at_summary INTEGER DEFAULT 0 ); -- Index for faster summary retrieval CREATE INDEX IF NOT EXISTS idx_context_summaries_conversation_id ON context_summaries(conversation_id); CREATE INDEX IF NOT EXISTS idx_context_summaries_version ON context_summaries(conversation_id, version DESC); -- LLM calls table (for cost tracking and analytics) CREATE TABLE IF NOT EXISTS llm_calls ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), conversation_id VARCHAR(255) REFERENCES conversations(id) ON DELETE SET NULL, model_id VARCHAR(255) NOT NULL, provider VARCHAR(50) NOT NULL, layer VARCHAR(10) NOT NULL, input_tokens INTEGER DEFAULT 0, output_tokens INTEGER DEFAULT 0, estimated_cost DECIMAL(10, 6) DEFAULT 0.00, actual_cost DECIMAL(10, 6), duration_ms INTEGER, success BOOLEAN DEFAULT true, error_message TEXT, cached BOOLEAN DEFAULT false, cross_check_used BOOLEAN DEFAULT false, escalated BOOLEAN DEFAULT false, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Indexes for analytics CREATE INDEX IF NOT EXISTS idx_llm_calls_conversation_id ON llm_calls(conversation_id); CREATE INDEX IF NOT EXISTS idx_llm_calls_model_id ON llm_calls(model_id); CREATE INDEX IF NOT EXISTS idx_llm_calls_layer ON llm_calls(layer); CREATE INDEX IF NOT EXISTS idx_llm_calls_created_at ON llm_calls(created_at DESC); CREATE INDEX IF NOT EXISTS idx_llm_calls_success ON llm_calls(success); -- Routing hints table (for optimization) CREATE TABLE IF NOT EXISTS routing_hints ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), project_id VARCHAR(255), task_pattern TEXT, recommended_layer VARCHAR(10), recommended_model VARCHAR(255), success_rate DECIMAL(5, 4), avg_cost DECIMAL(10, 6), usage_count INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_routing_hints_project_id ON routing_hints(project_id); -- Todo items table (for code agent) CREATE TABLE IF NOT EXISTS todo_items ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), conversation_id VARCHAR(255) NOT NULL REFERENCES conversations(id) ON DELETE CASCADE, title VARCHAR(500) NOT NULL, description TEXT, status VARCHAR(50) DEFAULT 'not-started' CHECK (status IN ('not-started', 'in-progress', 'completed')), priority INTEGER DEFAULT 0, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, completed_at TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_todo_items_conversation_id ON todo_items(conversation_id); CREATE INDEX IF NOT EXISTS idx_todo_items_status ON todo_items(status); -- Function to update updated_at timestamp CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; -- Triggers for auto-updating updated_at CREATE TRIGGER update_conversations_updated_at BEFORE UPDATE ON conversations FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_context_summaries_updated_at BEFORE UPDATE ON context_summaries FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_routing_hints_updated_at BEFORE UPDATE ON routing_hints FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_todo_items_updated_at BEFORE UPDATE ON todo_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- View for conversation statistics CREATE OR REPLACE VIEW conversation_stats AS SELECT c.id, c.user_id, c.project_id, c.created_at, c.message_count, c.total_cost, COUNT(DISTINCT m.id) as actual_message_count, COUNT(DISTINCT l.id) as llm_call_count, SUM(l.estimated_cost) as calculated_cost, AVG(l.duration_ms) as avg_response_time_ms FROM conversations c LEFT JOIN messages m ON c.id = m.conversation_id LEFT JOIN llm_calls l ON c.id = l.conversation_id GROUP BY c.id, c.user_id, c.project_id, c.created_at, c.message_count, c.total_cost; -- View for model performance CREATE OR REPLACE VIEW model_performance AS SELECT model_id, provider, layer, COUNT(*) as total_calls, SUM(CASE WHEN success THEN 1 ELSE 0 END) as successful_calls, ROUND(AVG(duration_ms)::numeric, 2) as avg_duration_ms, SUM(input_tokens) as total_input_tokens, SUM(output_tokens) as total_output_tokens, SUM(estimated_cost) as total_cost, SUM(CASE WHEN cached THEN 1 ELSE 0 END) as cache_hits FROM llm_calls GROUP BY model_id, provider, layer; -- Comments for documentation COMMENT ON TABLE conversations IS 'Stores conversation metadata and tracking'; COMMENT ON TABLE messages IS 'Stores all messages in conversations'; COMMENT ON TABLE context_summaries IS 'Stores compressed context summaries for long conversations'; COMMENT ON TABLE llm_calls IS 'Logs all LLM API calls for cost tracking and analytics'; COMMENT ON TABLE routing_hints IS 'Stores learned routing patterns for optimization'; COMMENT ON TABLE todo_items IS 'Stores TODO items for code agent tasks'; -- ============================================ -- Model and Layer Configuration Tables -- ============================================ -- Model configurations table CREATE TABLE IF NOT EXISTS model_configs ( id VARCHAR(255) PRIMARY KEY, provider VARCHAR(50) NOT NULL, api_model_name VARCHAR(255) NOT NULL, layer VARCHAR(10) NOT NULL CHECK (layer IN ('L0', 'L1', 'L2', 'L3')), relative_cost INTEGER DEFAULT 0, price_per_1k_input_tokens DECIMAL(10, 6) DEFAULT 0, price_per_1k_output_tokens DECIMAL(10, 6) DEFAULT 0, context_window INTEGER DEFAULT 8192, enabled BOOLEAN DEFAULT true, capabilities JSONB DEFAULT '{"code": true, "general": true, "reasoning": false}', metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_model_configs_provider ON model_configs(provider); CREATE INDEX IF NOT EXISTS idx_model_configs_layer ON model_configs(layer); CREATE INDEX IF NOT EXISTS idx_model_configs_enabled ON model_configs(enabled); -- Layer configurations table CREATE TABLE IF NOT EXISTS layer_configs ( layer VARCHAR(10) PRIMARY KEY CHECK (layer IN ('L0', 'L1', 'L2', 'L3')), enabled BOOLEAN DEFAULT true, model_ids TEXT[], -- Array of model IDs for this layer fallback_models TEXT[], -- Fallback model names metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Task-specific model preferences CREATE TABLE IF NOT EXISTS task_model_preferences ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), task_type VARCHAR(50) NOT NULL CHECK (task_type IN ('chat', 'code', 'analyze', 'create_project')), model_ids TEXT[] NOT NULL, -- Ordered list of preferred models enabled BOOLEAN DEFAULT true, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_task_model_preferences_task_type ON task_model_preferences(task_type); CREATE INDEX IF NOT EXISTS idx_task_model_preferences_enabled ON task_model_preferences(enabled); -- Triggers for auto-updating updated_at CREATE TRIGGER update_model_configs_updated_at BEFORE UPDATE ON model_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_layer_configs_updated_at BEFORE UPDATE ON layer_configs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_task_model_preferences_updated_at BEFORE UPDATE ON task_model_preferences FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- Comments COMMENT ON TABLE model_configs IS 'Stores LLM model configurations including pricing and capabilities'; COMMENT ON TABLE layer_configs IS 'Stores layer enable/disable state and model assignments'; COMMENT ON TABLE task_model_preferences IS 'Stores task-specific model preferences (chat, code, analyze, etc.)'; -- ============================================ -- Terminal Connection Profiles -- ============================================ -- Terminal connection profiles table (for saving SSH/Telnet connection configs) CREATE TABLE IF NOT EXISTS terminal_connections ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(255) NOT NULL, type VARCHAR(20) NOT NULL CHECK (type IN ('ssh', 'telnet', 'local')), host VARCHAR(255), port INTEGER DEFAULT 22, username VARCHAR(255), auth_type VARCHAR(20) DEFAULT 'password' CHECK (auth_type IN ('password', 'private_key', 'agent', 'none')), -- Note: For security, passwords/private keys should be stored securely or referenced from a secrets manager -- This is a simplified implementation for development encrypted_credentials TEXT, -- Encrypted password or private key (optional) is_default BOOLEAN DEFAULT false, notes TEXT, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_terminal_connections_type ON terminal_connections(type); CREATE INDEX IF NOT EXISTS idx_terminal_connections_is_default ON terminal_connections(is_default); CREATE TRIGGER update_terminal_connections_updated_at BEFORE UPDATE ON terminal_connections FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); COMMENT ON TABLE terminal_connections IS 'Stores saved terminal connection profiles for quick reconnection'; -- ============================================ -- Admin Users (for authentication) -- ============================================ CREATE TABLE IF NOT EXISTS admin_users ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), username VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, -- bcrypt hash email VARCHAR(255), display_name VARCHAR(255), role VARCHAR(50) DEFAULT 'admin' CHECK (role IN ('admin', 'viewer', 'operator')), is_active BOOLEAN DEFAULT true, last_login TIMESTAMP, metadata JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE UNIQUE INDEX IF NOT EXISTS idx_admin_users_username ON admin_users(username); CREATE TRIGGER update_admin_users_updated_at BEFORE UPDATE ON admin_users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); COMMENT ON TABLE admin_users IS 'Stores admin dashboard user accounts for authentication';

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/babasida246/ai-mcp-gateway'

If you have feedback or need assistance with the MCP directory API, please join our Discord server