UI Theme Management
August 22, 2025 ยท View on GitHub
Overview
MCP CLI features a comprehensive theme system that controls the visual appearance of all UI components. The theme system is designed to be internally managed - application code doesn't need to be theme-aware, as all theme handling happens automatically within the UI components.
Available Themes
MCP CLI includes five built-in themes:
1. Default Theme
- Colors: Standard terminal colors with cyan/blue/magenta accents
- Icons: Full emoji and symbol support (๐ฌ, ๐ค, ๐ง, โ, โ)
- Decorations: Rich boxes, panels, and formatting
- Use Case: Modern terminals with full Unicode support
2. Dark Theme
- Colors: Bright variants optimized for dark backgrounds
- Icons: Full emoji and symbol support
- Decorations: Enhanced contrast for dark terminals
- Use Case: Dark terminal backgrounds
3. Light Theme
- Colors: Dark variants optimized for light backgrounds
- Icons: Full emoji and symbol support
- Decorations: Adjusted contrast for light terminals
- Use Case: Light terminal backgrounds
4. Minimal Theme
- Colors: No colors - plain white text only
- Icons: No emojis - basic ASCII characters (-, >, [x])
- Decorations: No boxes or panels - plain text output
- Use Case: Compatibility mode, screen readers, or logging
5. Terminal Theme
- Colors: Basic ANSI colors only (8-color palette)
- Icons: No emojis - basic ASCII characters
- Decorations: Simple boxes using ASCII characters
- Use Case: Legacy terminals or SSH sessions
Theme Architecture
Core Components
Theme Class (src/mcp_cli/ui/theme.py)
The main theme class that combines colors, icons, and styles:
from mcp_cli.ui.theme import Theme, set_theme, get_theme
# Set a theme globally
set_theme("minimal")
# Get the current theme
theme = get_theme()
# Access theme properties
print(theme.name) # "minimal"
print(theme.colors.success) # Color for success messages
print(theme.icons.check) # Icon for checkmarks
ColorScheme Class
Defines color mappings for different UI elements:
@dataclass
class ColorScheme:
# Status colors
success: str = "green"
error: str = "red"
warning: str = "yellow"
info: str = "cyan"
# Text styles
normal: str = "white"
emphasis: str = "bold"
# UI element colors
primary: str = "cyan"
secondary: str = "blue"
accent: str = "magenta"
# Semantic colors
user: str = "yellow"
assistant: str = "blue"
tool: str = "magenta"
Icons Class
Defines icons and symbols used in the UI:
@dataclass
class Icons:
# Status icons
success: str = "โ"
error: str = "โ"
warning: str = "โ "
# Mode indicators
chat: str = "๐ฌ"
interactive: str = "โก"
# Special
robot: str = "๐ค"
user: str = "๐ค"
tool: str = "๐ง"
Using Themes
Setting a Theme
Themes can be set programmatically or through command-line options:
# In Python code
from mcp_cli.ui.theme import set_theme
# Set theme at application start
set_theme("dark")
# Change theme during runtime
set_theme("minimal")
# Via environment variable (future support)
export MCP_CLI_THEME=minimal
mcp-cli chat --server sqlite
Theme-Agnostic Code
The key principle is that application code should not check themes. UI components handle theme differences internally:
โ Good - Theme-Agnostic Code
from mcp_cli.ui import output, display_code, display_diff
# Just use the components - they handle themes internally
output.success("Operation completed!")
display_code(my_code, "python", title="Example")
display_diff(old_code, new_code, title="Changes")
โ Bad - Theme-Aware Code
# Don't do this!
theme = get_theme()
if theme.name == "minimal":
print(f"Code: {code}")
else:
console.print(Syntax(code, "python"))
Theme Features
Automatic Degradation
UI components automatically adapt based on the theme:
| Feature | Default | Dark | Light | Minimal | Terminal |
|---|---|---|---|---|---|
| Colors | โ Full | โ Full | โ Full | โ None | โ Basic |
| Emojis | โ Yes | โ Yes | โ Yes | โ No | โ No |
| Boxes/Panels | โ Rich | โ Rich | โ Rich | โ None | โ Simple |
| Syntax Highlighting | โ Yes | โ Yes | โ Yes | โ No | โ Basic |
| Markdown Rendering | โ Full | โ Full | โ Full | โ Plain | โ Basic |
| Progress Bars | โ Rich | โ Rich | โ Rich | โ Text | โ Simple |
Theme Helper Methods
Themes provide helper methods for checking capabilities:
theme = get_theme()
# Check theme capabilities
if theme.is_minimal():
# Theme has no decorations
pass
if theme.should_show_banners():
# Theme supports decorative banners
pass
if theme.should_show_icons():
# Theme supports emojis/icons
pass
if theme.should_show_boxes():
# Theme supports boxes/panels
pass
Examples
Example 1: Running Demo Scripts
The repository includes several demo scripts that showcase UI and terminal capabilities. Following our package management guidelines, use uv run to execute them:
# Interactive UI demo with theme switching
uv run examples/ui_demo.py
# Quick test of all UI components
uv run examples/ui_quick_test.py default
uv run examples/ui_quick_test.py minimal
uv run examples/ui_quick_test.py terminal
# Code-focused UI demo
uv run examples/ui_code_demo.py
# Theme independence demonstration
uv run examples/ui_theme_independence.py
# Terminal management demo (NEW)
uv run examples/ui_terminal_demo.py
Example 2: Theme Switching in Chat Mode
# In chat mode, use slash commands
/theme minimal # Switch to minimal theme
/theme dark # Switch to dark theme
/theme default # Back to default
Example 3: Custom Theme Creation
from mcp_cli.ui.theme import Theme, ColorScheme, Icons, use_theme
# Create a custom color scheme
class CustomColorScheme(ColorScheme):
def __init__(self):
super().__init__(
success="bright_green",
error="bright_red",
primary="bright_cyan",
accent="bright_magenta"
)
# Create a custom theme
custom_theme = Theme("custom")
custom_theme.colors = CustomColorScheme()
# Use the custom theme
use_theme(custom_theme)
Component-Specific Styling
Different UI components receive theme-appropriate styling:
User Messages
- Default/Dark/Light: Colored border with emoji icon (๐ค You)
- Minimal: Plain text with "You:" prefix
- Terminal: Simple border with "You:" label
Assistant Messages
- Default/Dark/Light: Colored border with robot emoji (๐ค Assistant)
- Minimal: Plain text with "Assistant:" prefix
- Terminal: Simple border with "Assistant:" label
Tool Calls
- Default/Dark/Light: Colored panel with tool emoji (๐ง Tool Invocation)
- Minimal: Plain text with tool name and arguments
- Terminal: Simple box with tool information
Code Display
- Default/Dark/Light: Syntax highlighting with line numbers
- Minimal: Plain text code block
- Terminal: Basic highlighting if supported
Best Practices
1. Let UI Components Handle Themes
Never check theme names in application code. UI components know how to render themselves appropriately.
2. Use Semantic Methods
Instead of checking colors directly, use semantic methods:
output.success("Done!") # Green in default, plain in minimal
output.error("Failed!") # Red in default, plain in minimal
output.info("Processing...") # Cyan in default, plain in minimal
3. Tables and Rich Components
Always create Rich components normally - the UI system handles conversion:
# โ
CORRECT - Theme-agnostic
from rich.table import Table
table = Table(title="Results")
table.add_column("Name")
table.add_column("Status")
table.add_row("Test 1", "โ
Passed")
ui.print_table(table) # Automatically handles all themes
# โ WRONG - Don't check themes
if theme.name == "minimal":
print("Name Status")
print("Test 1 Passed")
else:
# Create Rich table...
The print_table method automatically:
- Displays Rich formatting for default/dark/light themes
- Converts to aligned plain text for minimal theme
- Converts to simple ASCII for terminal theme
4. Test Across Themes
Use the demo scripts to test your UI across all themes:
# Test all themes automatically
uv run examples/ui_theme_independence.py
# Test terminal integration
uv run examples/ui_terminal_demo.py
Theme Configuration
Global Theme Setting
The theme is set globally and affects all UI components:
from mcp_cli.ui.theme import set_theme
# At application start
set_theme("minimal") # All UI components now use minimal theme
Theme Persistence
Theme settings can be persisted (future feature):
# ~/.mcp-cli/config.yaml
ui:
theme: minimal
show_timestamps: true
compact_mode: false
Troubleshooting
Issue: Emojis Not Displaying
- Solution: Switch to
minimalorterminaltheme - Command:
set_theme("minimal")
Issue: Colors Not Showing
- Cause: Terminal doesn't support colors
- Solution: Use
minimaltheme for plain text
Issue: Boxes/Borders Corrupted
- Cause: Terminal doesn't support Unicode
- Solution: Use
terminaltheme for ASCII-only output
Issue: Output Too Verbose
- Solution:
minimaltheme removes all decorations
Future Enhancements
Planned theme system improvements:
- Custom Theme Loading: Load themes from YAML/JSON files
- Theme Detection: Auto-detect terminal capabilities
- Per-Component Overrides: Override theme for specific components
- Theme Inheritance: Create themes that extend existing ones
- Dynamic Theme Switching: Change themes without restart
- Terminal Capability Detection: Automatically choose best theme
Related Documentation
- UI Components Guide - Overview of all UI components
- Output System - Detailed output system documentation
- Prompts and Input - Interactive prompt system
- Code Display - Code rendering and syntax highlighting