# SPDX-License-Identifier: AGPL-3.0-only # Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0 import sqlite3 import threading from datetime import datetime, timezone from typing import Optional from utils.paths import studio_db_path, ensure_dir _schema_lock = threading.Lock() _schema_ready = False def _ensure_schema(conn: sqlite3.Connection) -> None: conn.execute("PRAGMA journal_mode=WAL") conn.execute( """ CREATE TABLE IF NOT EXISTS mcp_servers ( id TEXT NOT NULL PRIMARY KEY, display_name TEXT NOT NULL, url TEXT NOT NULL, headers_json TEXT, is_enabled INTEGER NOT NULL DEFAULT 1, use_oauth INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ) """ ) # Backfill use_oauth for pre-existing DBs. cols = {r["name"] for r in conn.execute("PRAGMA table_info(mcp_servers)").fetchall()} if "use_oauth" not in cols: conn.execute("ALTER TABLE mcp_servers ADD COLUMN use_oauth INTEGER NOT NULL DEFAULT 0") def get_connection() -> sqlite3.Connection: global _schema_ready db_path = studio_db_path() ensure_dir(db_path.parent) conn = sqlite3.connect(str(db_path)) conn.row_factory = sqlite3.Row if not _schema_ready: with _schema_lock: if not _schema_ready: try: _ensure_schema(conn) _schema_ready = True except Exception: conn.close() raise return conn def create_server( id: str, display_name: str, url: str, headers_json: Optional[str] = None, is_enabled: bool = True, use_oauth: bool = False, ) -> None: now = datetime.now(timezone.utc).isoformat() conn = get_connection() try: conn.execute( """ INSERT INTO mcp_servers (id, display_name, url, headers_json, is_enabled, use_oauth, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) """, ( id, display_name, url, headers_json, int(is_enabled), int(use_oauth), now, now, ), ) conn.commit() finally: conn.close() def update_server(id: str, changes: dict) -> bool: """Apply column updates and bump ``updated_at``. Returns True on a hit.""" if not changes: return False bool_cols = {"is_enabled", "use_oauth"} sets, params = [], [] for col, value in changes.items(): sets.append(f"{col} = ?") params.append(int(value) if col in bool_cols else value) sets.append("updated_at = ?") params.extend([datetime.now(timezone.utc).isoformat(), id]) conn = get_connection() try: cursor = conn.execute( f"UPDATE mcp_servers SET {', '.join(sets)} WHERE id = ?", params, ) conn.commit() return cursor.rowcount > 0 finally: conn.close() def delete_server(id: str) -> bool: conn = get_connection() try: cursor = conn.execute("DELETE FROM mcp_servers WHERE id = ?", (id,)) conn.commit() return cursor.rowcount > 0 finally: conn.close() def get_server(id: str) -> Optional[dict]: conn = get_connection() try: row = conn.execute("SELECT * FROM mcp_servers WHERE id = ?", (id,)).fetchone() return dict(row) if row else None finally: conn.close() def list_servers() -> list[dict]: conn = get_connection() try: rows = conn.execute("SELECT * FROM mcp_servers ORDER BY created_at").fetchall() return [dict(row) for row in rows] finally: conn.close()