Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Give agents more agency

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    CuriousLearner

    schema-visualizer

    CuriousLearner/schema-visualizer
    Design
    20
    1 installs

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Generate database schema diagrams, ERDs, and documentation from database schemas.

    SKILL.md

    Schema Visualizer Skill

    Generate database schema diagrams, ERDs, and documentation from database schemas.

    Instructions

    You are a database schema visualization expert. When invoked:

    1. Analyze Database Schema:

      • Inspect database structure (tables, columns, types)
      • Identify relationships (foreign keys, references)
      • Detect indexes and constraints
      • Understand data model patterns
    2. Generate Visualizations:

      • Create Entity Relationship Diagrams (ERD)
      • Generate Mermaid diagrams for documentation
      • Produce schema documentation in various formats
      • Show table relationships and cardinality
    3. Detect Schema from Code:

      • Parse ORM models (Prisma, TypeORM, SQLAlchemy)
      • Extract schema from migration files
      • Analyze database dump files
      • Read CREATE TABLE statements
    4. Provide Insights:

      • Identify missing indexes
      • Suggest normalization improvements
      • Highlight potential performance issues
      • Recommend relationship optimizations

    Supported Formats

    • Diagrams: Mermaid ERD, PlantUML, dbdiagram.io
    • Documentation: Markdown tables, JSON schema, YAML
    • Schema Sources: SQL dumps, ORM models, migration files, live database connection

    Usage Examples

    @schema-visualizer
    @schema-visualizer --from-prisma schema.prisma
    @schema-visualizer --from-migrations
    @schema-visualizer --format mermaid
    @schema-visualizer --analyze-relationships
    

    Mermaid ERD Examples

    Basic E-Commerce Schema

    erDiagram
        USERS ||--o{ ORDERS : places
        USERS {
            int id PK
            string username
            string email UK
            string password_hash
            boolean active
            timestamp created_at
            timestamp updated_at
        }
    
        ORDERS ||--|{ ORDER_ITEMS : contains
        ORDERS {
            int id PK
            int user_id FK
            decimal total_amount
            string status
            timestamp created_at
            timestamp updated_at
        }
    
        PRODUCTS ||--o{ ORDER_ITEMS : "ordered in"
        PRODUCTS {
            int id PK
            string name
            text description
            decimal price
            int stock_quantity
            int category_id FK
            timestamp created_at
            timestamp updated_at
        }
    
        ORDER_ITEMS {
            int id PK
            int order_id FK
            int product_id FK
            int quantity
            decimal price
        }
    
        CATEGORIES ||--o{ PRODUCTS : contains
        CATEGORIES {
            int id PK
            string name
            int parent_id FK "NULL allowed"
            timestamp created_at
        }
    
        USERS ||--o{ REVIEWS : writes
        PRODUCTS ||--o{ REVIEWS : receives
        REVIEWS {
            int id PK
            int user_id FK
            int product_id FK
            int rating
            text comment
            timestamp created_at
        }
    

    Multi-Tenant SaaS Application

    erDiagram
        ORGANIZATIONS ||--o{ USERS : employs
        ORGANIZATIONS {
            int id PK
            string name
            string slug UK
            string plan
            timestamp created_at
        }
    
        USERS ||--o{ PROJECTS : creates
        USERS {
            int id PK
            int organization_id FK
            string email UK
            string name
            string role
            timestamp created_at
        }
    
        PROJECTS ||--o{ TASKS : contains
        PROJECTS {
            int id PK
            int organization_id FK
            int owner_id FK
            string name
            text description
            string status
            timestamp created_at
        }
    
        TASKS ||--o{ COMMENTS : has
        TASKS {
            int id PK
            int project_id FK
            int assignee_id FK
            string title
            text description
            string priority
            string status
            timestamp due_date
            timestamp created_at
        }
    
        USERS ||--o{ COMMENTS : writes
        COMMENTS {
            int id PK
            int task_id FK
            int user_id FK
            text content
            timestamp created_at
        }
    
        USERS ||--o{ TASKS : "assigned to"
    

    Blog Platform Schema

    erDiagram
        USERS ||--o{ POSTS : authors
        USERS ||--o{ COMMENTS : writes
        USERS {
            int id PK
            string username UK
            string email UK
            string bio
            string avatar_url
            timestamp created_at
        }
    
        POSTS ||--o{ COMMENTS : receives
        POSTS ||--o{ POST_TAGS : has
        POSTS {
            int id PK
            int author_id FK
            string title
            string slug UK
            text content
            string status
            timestamp published_at
            timestamp created_at
            timestamp updated_at
        }
    
        COMMENTS ||--o{ COMMENTS : replies
        COMMENTS {
            int id PK
            int post_id FK
            int user_id FK
            int parent_id FK "NULL allowed"
            text content
            timestamp created_at
        }
    
        TAGS ||--o{ POST_TAGS : tagged
        TAGS {
            int id PK
            string name UK
            string slug UK
        }
    
        POST_TAGS {
            int post_id FK
            int tag_id FK
        }
    

    Schema Documentation Formats

    Markdown Table Format

    # Database Schema Documentation
    
    ## Users Table
    
    | Column | Type | Constraints | Description |
    |--------|------|-------------|-------------|
    | id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique user identifier |
    | username | VARCHAR(50) | UNIQUE, NOT NULL | User's login name |
    | email | VARCHAR(255) | UNIQUE, NOT NULL | User's email address |
    | password_hash | VARCHAR(255) | NOT NULL | Bcrypt hashed password |
    | active | BOOLEAN | DEFAULT true | Account active status |
    | created_at | TIMESTAMP | DEFAULT NOW() | Account creation time |
    | updated_at | TIMESTAMP | DEFAULT NOW() | Last update time |
    
    **Indexes:**
    - `idx_users_email` on (email)
    - `idx_users_username` on (username)
    
    **Foreign Keys:**
    - None
    
    ---
    
    ## Orders Table
    
    | Column | Type | Constraints | Description |
    |--------|------|-------------|-------------|
    | id | INTEGER | PRIMARY KEY, AUTO_INCREMENT | Unique order identifier |
    | user_id | INTEGER | FOREIGN KEY (users.id), NOT NULL | Reference to user |
    | total_amount | DECIMAL(10,2) | NOT NULL | Order total amount |
    | status | VARCHAR(20) | NOT NULL, DEFAULT 'pending' | Order status |
    | created_at | TIMESTAMP | DEFAULT NOW() | Order creation time |
    | updated_at | TIMESTAMP | DEFAULT NOW() | Last update time |
    
    **Indexes:**
    - `idx_orders_user_id` on (user_id)
    - `idx_orders_status` on (status)
    - `idx_orders_created_at` on (created_at)
    
    **Foreign Keys:**
    - `fk_orders_user_id` FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    
    **Check Constraints:**
    - `chk_orders_total_amount` CHECK (total_amount >= 0)
    - `chk_orders_status` CHECK (status IN ('pending', 'processing', 'completed', 'cancelled'))
    

    JSON Schema Format

    {
      "database": "ecommerce",
      "tables": {
        "users": {
          "columns": {
            "id": {
              "type": "INTEGER",
              "primaryKey": true,
              "autoIncrement": true,
              "nullable": false
            },
            "username": {
              "type": "VARCHAR(50)",
              "unique": true,
              "nullable": false
            },
            "email": {
              "type": "VARCHAR(255)",
              "unique": true,
              "nullable": false
            },
            "active": {
              "type": "BOOLEAN",
              "default": true,
              "nullable": false
            },
            "created_at": {
              "type": "TIMESTAMP",
              "default": "NOW()",
              "nullable": false
            }
          },
          "indexes": [
            {
              "name": "idx_users_email",
              "columns": ["email"],
              "unique": true
            }
          ],
          "foreignKeys": []
        },
        "orders": {
          "columns": {
            "id": {
              "type": "INTEGER",
              "primaryKey": true,
              "autoIncrement": true
            },
            "user_id": {
              "type": "INTEGER",
              "nullable": false
            },
            "total_amount": {
              "type": "DECIMAL(10,2)",
              "nullable": false
            },
            "status": {
              "type": "VARCHAR(20)",
              "default": "pending"
            }
          },
          "indexes": [
            {
              "name": "idx_orders_user_id",
              "columns": ["user_id"]
            }
          ],
          "foreignKeys": [
            {
              "name": "fk_orders_user_id",
              "column": "user_id",
              "references": {
                "table": "users",
                "column": "id"
              },
              "onDelete": "CASCADE",
              "onUpdate": "CASCADE"
            }
          ]
        }
      }
    }
    

    Extracting Schema from ORM Models

    From Prisma Schema

    // schema.prisma
    model User {
      id        Int      @id @default(autoincrement())
      email     String   @unique
      username  String   @unique
      active    Boolean  @default(true)
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
    
      orders    Order[]
      reviews   Review[]
    
      @@index([email])
      @@map("users")
    }
    
    model Order {
      id          Int      @id @default(autoincrement())
      userId      Int
      totalAmount Decimal  @db.Decimal(10, 2)
      status      String   @default("pending")
      createdAt   DateTime @default(now())
    
      user  User         @relation(fields: [userId], references: [id], onDelete: Cascade)
      items OrderItem[]
    
      @@index([userId])
      @@index([status])
      @@map("orders")
    }
    

    Generated Visualization:

    erDiagram
        USERS ||--o{ ORDERS : "has many"
        USERS ||--o{ REVIEWS : "has many"
    
        USERS {
            int id PK
            string email UK
            string username UK
            boolean active
            datetime created_at
            datetime updated_at
        }
    
        ORDERS {
            int id PK
            int user_id FK
            decimal total_amount
            string status
            datetime created_at
        }
    

    From TypeORM Entities

    // user.entity.ts
    @Entity('users')
    export class User {
      @PrimaryGeneratedColumn()
      id: number;
    
      @Column({ unique: true })
      email: string;
    
      @Column({ unique: true })
      username: string;
    
      @Column({ default: true })
      active: boolean;
    
      @CreateDateColumn()
      createdAt: Date;
    
      @UpdateDateColumn()
      updatedAt: Date;
    
      @OneToMany(() => Order, order => order.user)
      orders: Order[];
    
      @Index()
      @Column()
      organizationId: number;
    }
    
    // order.entity.ts
    @Entity('orders')
    export class Order {
      @PrimaryGeneratedColumn()
      id: number;
    
      @Column()
      userId: number;
    
      @Column('decimal', { precision: 10, scale: 2 })
      totalAmount: number;
    
      @Column({ default: 'pending' })
      status: string;
    
      @ManyToOne(() => User, user => user.orders, { onDelete: 'CASCADE' })
      @JoinColumn({ name: 'userId' })
      user: User;
    
      @OneToMany(() => OrderItem, item => item.order)
      items: OrderItem[];
    }
    

    From SQLAlchemy Models

    # models.py
    from sqlalchemy import Column, Integer, String, Boolean, DECIMAL, DateTime, ForeignKey
    from sqlalchemy.orm import relationship
    from datetime import datetime
    
    class User(Base):
        __tablename__ = 'users'
    
        id = Column(Integer, primary_key=True, autoincrement=True)
        email = Column(String(255), unique=True, nullable=False, index=True)
        username = Column(String(50), unique=True, nullable=False)
        active = Column(Boolean, default=True)
        created_at = Column(DateTime, default=datetime.utcnow)
        updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
        # Relationships
        orders = relationship('Order', back_populates='user', cascade='all, delete-orphan')
        reviews = relationship('Review', back_populates='user')
    
    class Order(Base):
        __tablename__ = 'orders'
    
        id = Column(Integer, primary_key=True, autoincrement=True)
        user_id = Column(Integer, ForeignKey('users.id', ondelete='CASCADE'), nullable=False, index=True)
        total_amount = Column(DECIMAL(10, 2), nullable=False)
        status = Column(String(20), default='pending', index=True)
        created_at = Column(DateTime, default=datetime.utcnow)
    
        # Relationships
        user = relationship('User', back_populates='orders')
        items = relationship('OrderItem', back_populates='order')
    

    Schema Analysis Features

    Relationship Cardinality Detection

    # Relationship Analysis
    
    ## One-to-Many Relationships
    - Users → Orders (One user can have many orders)
    - Products → OrderItems (One product can be in many orders)
    - Categories → Products (One category can have many products)
    
    ## Many-to-Many Relationships
    - Posts ↔ Tags (Through post_tags junction table)
    - Users ↔ Roles (Through user_roles junction table)
    
    ## One-to-One Relationships
    - Users → UserProfiles (One user has one profile)
    

    Missing Indexes Detection

    # Schema Health Report
    
    ## Missing Indexes
    
    ⚠️ **High Priority:**
    - `orders.user_id` - Foreign key without index (impacts JOIN performance)
    - `order_items.product_id` - Foreign key without index
    
    ⚠️ **Medium Priority:**
    - `users.email` - Frequently used in WHERE clauses
    - `products.category_id` - Used in JOIN operations
    
    ## Suggested Index Additions:
    
    ```sql
    CREATE INDEX idx_orders_user_id ON orders(user_id);
    CREATE INDEX idx_order_items_product_id ON order_items(product_id);
    CREATE INDEX idx_users_email ON users(email);
    CREATE INDEX idx_products_category_id ON products(category_id);
    
    -- Composite index for common query pattern
    CREATE INDEX idx_orders_user_status ON orders(user_id, status);
    

    Normalization Analysis

    # Database Normalization Report
    
    ## Current Normalization Level: 3NF
    
    ### First Normal Form (1NF) ✓
    - All tables have primary keys
    - No repeating groups
    - Atomic values in all columns
    
    ### Second Normal Form (2NF) ✓
    - All tables in 1NF
    - No partial dependencies on composite keys
    
    ### Third Normal Form (3NF) ✓
    - All tables in 2NF
    - No transitive dependencies
    
    ### Potential Improvements:
    
    **Denormalization Opportunities (for performance):**
    - Add `user_name` to `orders` table to avoid JOIN for display
    - Cache `order_count` in `users` table
    - Store `product_name` in `order_items` for historical accuracy
    
    **Further Normalization Suggestions:**
    - Extract address fields from `users` to separate `addresses` table
    - Split `products.description` to separate `product_details` table if frequently unused
    

    dbdiagram.io Format

    // Use dbdiagram.io to visualize this schema
    
    Table users {
      id int [pk, increment]
      username varchar(50) [unique, not null]
      email varchar(255) [unique, not null]
      password_hash varchar(255) [not null]
      active boolean [default: true]
      created_at timestamp [default: `now()`]
      updated_at timestamp [default: `now()`]
    
      Indexes {
        email [unique]
        username [unique]
      }
    }
    
    Table orders {
      id int [pk, increment]
      user_id int [not null, ref: > users.id]
      total_amount decimal(10,2) [not null]
      status varchar(20) [default: 'pending']
      created_at timestamp [default: `now()`]
      updated_at timestamp [default: `now()`]
    
      Indexes {
        user_id
        status
        created_at
      }
    }
    
    Table products {
      id int [pk, increment]
      name varchar(255) [not null]
      description text
      price decimal(10,2) [not null]
      stock_quantity int [default: 0]
      category_id int [ref: > categories.id]
      created_at timestamp [default: `now()`]
    
      Indexes {
        category_id
        (name, category_id) [name: 'idx_product_category']
      }
    }
    
    Table order_items {
      id int [pk, increment]
      order_id int [not null, ref: > orders.id]
      product_id int [not null, ref: > products.id]
      quantity int [not null]
      price decimal(10,2) [not null]
    
      Indexes {
        order_id
        product_id
      }
    }
    
    Table categories {
      id int [pk, increment]
      name varchar(100) [unique, not null]
      parent_id int [ref: > categories.id]
      created_at timestamp [default: `now()`]
    }
    
    Table reviews {
      id int [pk, increment]
      user_id int [not null, ref: > users.id]
      product_id int [not null, ref: > products.id]
      rating int [not null, note: '1-5']
      comment text
      created_at timestamp [default: `now()`]
    
      Indexes {
        (user_id, product_id) [unique]
        product_id
      }
    }
    

    PlantUML Format

    @startuml
    
    entity "users" as users {
      *id : int <<PK>>
      --
      *username : varchar(50) <<UK>>
      *email : varchar(255) <<UK>>
      *password_hash : varchar(255)
      active : boolean
      created_at : timestamp
      updated_at : timestamp
    }
    
    entity "orders" as orders {
      *id : int <<PK>>
      --
      *user_id : int <<FK>>
      *total_amount : decimal(10,2)
      status : varchar(20)
      created_at : timestamp
      updated_at : timestamp
    }
    
    entity "products" as products {
      *id : int <<PK>>
      --
      *name : varchar(255)
      description : text
      *price : decimal(10,2)
      stock_quantity : int
      category_id : int <<FK>>
      created_at : timestamp
    }
    
    entity "order_items" as order_items {
      *id : int <<PK>>
      --
      *order_id : int <<FK>>
      *product_id : int <<FK>>
      *quantity : int
      *price : decimal(10,2)
    }
    
    entity "categories" as categories {
      *id : int <<PK>>
      --
      *name : varchar(100)
      parent_id : int <<FK>>
      created_at : timestamp
    }
    
    users ||--o{ orders
    orders ||--|{ order_items
    products ||--o{ order_items
    categories ||--o{ products
    categories ||--o{ categories : "parent/child"
    
    @enduml
    

    Schema Comparison

    # Schema Comparison: Production vs Staging
    
    ## New Tables in Staging:
    - `notifications` - User notification system
    - `audit_logs` - Activity tracking
    
    ## Modified Tables:
    
    ### users
    **Added columns:**
    - `last_login_at` (timestamp)
    - `email_verified` (boolean)
    
    **Removed columns:**
    - `legacy_id` (deprecated)
    
    ### orders
    **Modified columns:**
    - `total_amount`: DECIMAL(8,2) → DECIMAL(10,2) (increased precision)
    
    **Added indexes:**
    - `idx_orders_created_at` on (created_at)
    
    ## Migration Script:
    
    ```sql
    -- Add new columns
    ALTER TABLE users ADD COLUMN last_login_at TIMESTAMP;
    ALTER TABLE users ADD COLUMN email_verified BOOLEAN DEFAULT false;
    ALTER TABLE users DROP COLUMN legacy_id;
    
    -- Modify column type
    ALTER TABLE orders ALTER COLUMN total_amount TYPE DECIMAL(10,2);
    
    -- Add new index
    CREATE INDEX idx_orders_created_at ON orders(created_at);
    
    -- Create new tables
    CREATE TABLE notifications (
      id SERIAL PRIMARY KEY,
      user_id INTEGER NOT NULL REFERENCES users(id),
      type VARCHAR(50) NOT NULL,
      message TEXT NOT NULL,
      read BOOLEAN DEFAULT false,
      created_at TIMESTAMP DEFAULT NOW()
    );
    

    Best Practices

    1. Always visualize before making changes - Understand impact
    2. Document relationship cardinality - One-to-many, many-to-many
    3. Include indexes in diagrams - Performance consideration
    4. Show foreign key constraints - Data integrity
    5. Use consistent naming conventions - Improve readability
    6. Version control schema changes - Track evolution
    7. Generate diagrams from code - Keep in sync
    8. Include constraints and checks - Business rules
    9. Document enum values - Valid states
    10. Keep diagrams up to date - Living documentation

    Tools Integration

    Generate from Database

    # PostgreSQL - using pg_dump
    pg_dump -s -d mydb > schema.sql
    
    # MySQL - schema only
    mysqldump --no-data mydb > schema.sql
    
    # Using SchemaSpy (generates HTML visualization)
    java -jar schemaspy.jar -t pgsql -db mydb -u user -p password -o output
    
    # Using DBeaver (export ERD)
    # File → Export → Database Structure → ERD
    

    Generate from ORM

    # Prisma - generate ERD
    npx prisma generate
    npx prisma studio
    
    # TypeORM - generate migration
    npx typeorm migration:generate -n InitialSchema
    
    # Django - generate ERD
    python manage.py graph_models -a -o erd.png
    
    # Rails - generate ERD
    bundle exec rails erd
    

    Notes

    • Update diagrams when schema changes
    • Include constraints and indexes in visualization
    • Use consistent colors for entity types
    • Generate documentation automatically from schema
    • Version control schema visualization files
    • Consider using database documentation tools (SchemaSpy, dbdocs)
    • Keep ERDs readable - split large schemas into logical domains
    Recommended Servers
    tldraw
    tldraw
    Airtable
    Airtable
    ThinAir Data
    ThinAir Data
    Repository
    curiouslearner/devkit
    Files